mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-23 02:44:41 +03:00
Compare commits
42 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d99134be83 | |||
| a339bd791a | |||
| 1ca531971f | |||
| 77b0c6f040 | |||
| eb62221ff0 | |||
| a3169da877 | |||
| a93c30a2f2 | |||
| ae0d644269 | |||
| c8a3c74556 | |||
| a449d8bab0 | |||
| a4f82db53d | |||
| 92fc218205 | |||
| adf428cbef | |||
| cb28c0b770 | |||
| c74a17a498 | |||
| 9b7f7f02e9 | |||
| cb115edfc6 | |||
| 0ee7a08627 | |||
| 5ee79af41f | |||
| feb0fa6b38 | |||
| 7c0618bdb7 | |||
| 3ff9e4f8ac | |||
| 211868b5d0 | |||
| e45ca514e8 | |||
| f52d9b6f42 | |||
| 837e426c1f | |||
| 426d07d64c | |||
| 692f78045e | |||
| 245850b66c | |||
| 1abf68b7ae | |||
| 846a4cc089 | |||
| e01e3a4e12 | |||
| 6e79bcd356 | |||
| ef2156c66e | |||
| f28cd347c4 | |||
| c12b5829e1 | |||
| 425f7895dd | |||
| d91778e31f | |||
| cb549c7425 | |||
| f9a2d94c95 | |||
| 6af79c92dd | |||
| c5bbd80cb9 |
@@ -1,10 +1,10 @@
|
||||
Meta: 1
|
||||
Name: zfs
|
||||
Branch: 1.0
|
||||
Version: 2.1.12
|
||||
Version: 2.1.14
|
||||
Release: 1
|
||||
Release-Tags: relext
|
||||
License: CDDL
|
||||
Author: OpenZFS
|
||||
Linux-Maximum: 6.3
|
||||
Linux-Maximum: 6.5
|
||||
Linux-Minimum: 3.10
|
||||
|
||||
@@ -597,8 +597,6 @@ zfs_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *data)
|
||||
*/
|
||||
if (nvlist_lookup_string(nvl, dp->dd_prop, &path) != 0 ||
|
||||
strcmp(dp->dd_compare, path) != 0) {
|
||||
zed_log_msg(LOG_INFO, " %s: no match (%s != vdev %s)",
|
||||
__func__, dp->dd_compare, path);
|
||||
return;
|
||||
}
|
||||
if (dp->dd_new_vdev_guid != 0 && dp->dd_new_vdev_guid != guid) {
|
||||
|
||||
@@ -415,6 +415,11 @@ zfs_retire_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl,
|
||||
FM_EREPORT_PAYLOAD_ZFS_VDEV_GUID, &vdev_guid) != 0)
|
||||
return;
|
||||
|
||||
if (vdev_guid == 0) {
|
||||
fmd_hdl_debug(hdl, "Got a zero GUID");
|
||||
return;
|
||||
}
|
||||
|
||||
if (spare) {
|
||||
int nspares = find_and_remove_spares(zhdl, vdev_guid);
|
||||
fmd_hdl_debug(hdl, "%d spares removed", nspares);
|
||||
|
||||
@@ -21,6 +21,7 @@ dist_zedexec_SCRIPTS = \
|
||||
scrub_finish-notify.sh \
|
||||
statechange-led.sh \
|
||||
statechange-notify.sh \
|
||||
statechange-slot_off.sh \
|
||||
vdev_clear-led.sh \
|
||||
vdev_attach-led.sh \
|
||||
pool_import-led.sh \
|
||||
@@ -39,6 +40,7 @@ zedconfdefaults = \
|
||||
scrub_finish-notify.sh \
|
||||
statechange-led.sh \
|
||||
statechange-notify.sh \
|
||||
statechange-slot_off.sh \
|
||||
vdev_clear-led.sh \
|
||||
vdev_attach-led.sh \
|
||||
pool_import-led.sh \
|
||||
|
||||
Executable
+64
@@ -0,0 +1,64 @@
|
||||
#!/bin/sh
|
||||
# shellcheck disable=SC3014,SC2154,SC2086,SC2034
|
||||
#
|
||||
# Turn off disk's enclosure slot if it becomes FAULTED.
|
||||
#
|
||||
# Bad SCSI disks can often "disappear and reappear" causing all sorts of chaos
|
||||
# as they flip between FAULTED and ONLINE. If
|
||||
# ZED_POWER_OFF_ENCLOUSRE_SLOT_ON_FAULT is set in zed.rc, and the disk gets
|
||||
# FAULTED, then power down the slot via sysfs:
|
||||
#
|
||||
# /sys/class/enclosure/<enclosure>/<slot>/power_status
|
||||
#
|
||||
# We assume the user will be responsible for turning the slot back on again.
|
||||
#
|
||||
# Note that this script requires that your enclosure be supported by the
|
||||
# Linux SCSI Enclosure services (SES) driver. The script will do nothing
|
||||
# if you have no enclosure, or if your enclosure isn't supported.
|
||||
#
|
||||
# Exit codes:
|
||||
# 0: slot successfully powered off
|
||||
# 1: enclosure not available
|
||||
# 2: ZED_POWER_OFF_ENCLOUSRE_SLOT_ON_FAULT disabled
|
||||
# 3: vdev was not FAULTED
|
||||
# 4: The enclosure sysfs path passed from ZFS does not exist
|
||||
# 5: Enclosure slot didn't actually turn off after we told it to
|
||||
|
||||
[ -f "${ZED_ZEDLET_DIR}/zed.rc" ] && . "${ZED_ZEDLET_DIR}/zed.rc"
|
||||
. "${ZED_ZEDLET_DIR}/zed-functions.sh"
|
||||
|
||||
if [ ! -d /sys/class/enclosure ] ; then
|
||||
# No JBOD enclosure or NVMe slots
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "${ZED_POWER_OFF_ENCLOUSRE_SLOT_ON_FAULT}" != "1" ] ; then
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if [ "$ZEVENT_VDEV_STATE_STR" != "FAULTED" ] ; then
|
||||
exit 3
|
||||
fi
|
||||
|
||||
if [ ! -f "$ZEVENT_VDEV_ENC_SYSFS_PATH/power_status" ] ; then
|
||||
exit 4
|
||||
fi
|
||||
|
||||
# Turn off the slot and wait for sysfs to report that the slot is off.
|
||||
# It can take ~400ms on some enclosures and multiple retries may be needed.
|
||||
for i in $(seq 1 20) ; do
|
||||
echo "off" | tee "$ZEVENT_VDEV_ENC_SYSFS_PATH/power_status"
|
||||
|
||||
for j in $(seq 1 5) ; do
|
||||
if [ "$(cat $ZEVENT_VDEV_ENC_SYSFS_PATH/power_status)" == "off" ] ; then
|
||||
break 2
|
||||
fi
|
||||
sleep 0.1
|
||||
done
|
||||
done
|
||||
|
||||
if [ "$(cat $ZEVENT_VDEV_ENC_SYSFS_PATH/power_status)" != "off" ] ; then
|
||||
exit 5
|
||||
fi
|
||||
|
||||
zed_log_msg "powered down slot $ZEVENT_VDEV_ENC_SYSFS_PATH for $ZEVENT_VDEV_PATH"
|
||||
@@ -143,3 +143,8 @@ ZED_SYSLOG_SUBCLASS_EXCLUDE="history_event"
|
||||
# Disabled by default, 1 to enable and 0 to disable.
|
||||
#ZED_SYSLOG_DISPLAY_GUIDS=1
|
||||
|
||||
##
|
||||
# Power off the drive's slot in the enclosure if it becomes FAULTED. This can
|
||||
# help silence misbehaving drives. This assumes your drive enclosure fully
|
||||
# supports slot power control via sysfs.
|
||||
#ZED_POWER_OFF_ENCLOUSRE_SLOT_ON_FAULT=1
|
||||
|
||||
+135
-3
@@ -16,12 +16,63 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV_GET_BY_PATH], [
|
||||
])
|
||||
])
|
||||
|
||||
dnl #
|
||||
dnl # 6.5.x API change,
|
||||
dnl # blkdev_get_by_path() takes 4 args
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV_GET_BY_PATH_4ARG], [
|
||||
ZFS_LINUX_TEST_SRC([blkdev_get_by_path_4arg], [
|
||||
#include <linux/fs.h>
|
||||
#include <linux/blkdev.h>
|
||||
], [
|
||||
struct block_device *bdev __attribute__ ((unused)) = NULL;
|
||||
const char *path = "path";
|
||||
fmode_t mode = 0;
|
||||
void *holder = NULL;
|
||||
struct blk_holder_ops h;
|
||||
|
||||
bdev = blkdev_get_by_path(path, mode, holder, &h);
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_BLKDEV_GET_BY_PATH], [
|
||||
AC_MSG_CHECKING([whether blkdev_get_by_path() exists])
|
||||
AC_MSG_CHECKING([whether blkdev_get_by_path() exists and takes 3 args])
|
||||
ZFS_LINUX_TEST_RESULT([blkdev_get_by_path], [
|
||||
AC_MSG_RESULT(yes)
|
||||
], [
|
||||
ZFS_LINUX_TEST_ERROR([blkdev_get_by_path()])
|
||||
AC_MSG_RESULT(no)
|
||||
AC_MSG_CHECKING([whether blkdev_get_by_path() exists and takes 4 args])
|
||||
ZFS_LINUX_TEST_RESULT([blkdev_get_by_path_4arg], [
|
||||
AC_DEFINE(HAVE_BLKDEV_GET_BY_PATH_4ARG, 1,
|
||||
[blkdev_get_by_path() exists and takes 4 args])
|
||||
AC_MSG_RESULT(yes)
|
||||
], [
|
||||
ZFS_LINUX_TEST_ERROR([blkdev_get_by_path()])
|
||||
])
|
||||
])
|
||||
])
|
||||
|
||||
dnl #
|
||||
dnl # 6.5.x API change
|
||||
dnl # blk_mode_t was added as a type to supercede some places where fmode_t
|
||||
dnl # is used
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV_BLK_MODE_T], [
|
||||
ZFS_LINUX_TEST_SRC([blk_mode_t], [
|
||||
#include <linux/fs.h>
|
||||
#include <linux/blkdev.h>
|
||||
], [
|
||||
blk_mode_t m __attribute((unused)) = (blk_mode_t)0;
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_BLKDEV_BLK_MODE_T], [
|
||||
AC_MSG_CHECKING([whether blk_mode_t is defined])
|
||||
ZFS_LINUX_TEST_RESULT([blk_mode_t], [
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_BLK_MODE_T, 1, [blk_mode_t is defined])
|
||||
], [
|
||||
AC_MSG_RESULT(no)
|
||||
])
|
||||
])
|
||||
|
||||
@@ -41,12 +92,35 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV_PUT], [
|
||||
])
|
||||
])
|
||||
|
||||
dnl #
|
||||
dnl # 6.5.x API change.
|
||||
dnl # blkdev_put() takes (void* holder) as arg 2
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV_PUT_HOLDER], [
|
||||
ZFS_LINUX_TEST_SRC([blkdev_put_holder], [
|
||||
#include <linux/fs.h>
|
||||
#include <linux/blkdev.h>
|
||||
], [
|
||||
struct block_device *bdev = NULL;
|
||||
void *holder = NULL;
|
||||
|
||||
blkdev_put(bdev, holder);
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_BLKDEV_PUT], [
|
||||
AC_MSG_CHECKING([whether blkdev_put() exists])
|
||||
ZFS_LINUX_TEST_RESULT([blkdev_put], [
|
||||
AC_MSG_RESULT(yes)
|
||||
], [
|
||||
ZFS_LINUX_TEST_ERROR([blkdev_put()])
|
||||
AC_MSG_CHECKING([whether blkdev_put() accepts void* as arg 2])
|
||||
ZFS_LINUX_TEST_RESULT([blkdev_put_holder], [
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_BLKDEV_PUT_HOLDER, 1,
|
||||
[blkdev_put() accepts void* as arg 2])
|
||||
], [
|
||||
ZFS_LINUX_TEST_ERROR([blkdev_put()])
|
||||
])
|
||||
])
|
||||
])
|
||||
|
||||
@@ -103,6 +177,33 @@ AC_DEFUN([ZFS_AC_KERNEL_BLKDEV_CHECK_DISK_CHANGE], [
|
||||
])
|
||||
])
|
||||
|
||||
dnl #
|
||||
dnl # 6.5.x API change
|
||||
dnl # disk_check_media_change() was added
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV_DISK_CHECK_MEDIA_CHANGE], [
|
||||
ZFS_LINUX_TEST_SRC([disk_check_media_change], [
|
||||
#include <linux/fs.h>
|
||||
#include <linux/blkdev.h>
|
||||
], [
|
||||
struct block_device *bdev = NULL;
|
||||
bool error;
|
||||
|
||||
error = disk_check_media_change(bdev->bd_disk);
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_BLKDEV_DISK_CHECK_MEDIA_CHANGE], [
|
||||
AC_MSG_CHECKING([whether disk_check_media_change() exists])
|
||||
ZFS_LINUX_TEST_RESULT([disk_check_media_change], [
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_DISK_CHECK_MEDIA_CHANGE, 1,
|
||||
[disk_check_media_change() exists])
|
||||
], [
|
||||
AC_MSG_RESULT(no)
|
||||
])
|
||||
])
|
||||
|
||||
dnl #
|
||||
dnl # bdev_kobj() is introduced from 5.12
|
||||
dnl #
|
||||
@@ -443,9 +544,34 @@ AC_DEFUN([ZFS_AC_KERNEL_BLKDEV_GET_ERESTARTSYS], [
|
||||
])
|
||||
])
|
||||
|
||||
dnl #
|
||||
dnl # 6.5.x API change
|
||||
dnl # BLK_STS_NEXUS replaced with BLK_STS_RESV_CONFLICT
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV_BLK_STS_RESV_CONFLICT], [
|
||||
ZFS_LINUX_TEST_SRC([blk_sts_resv_conflict], [
|
||||
#include <linux/blkdev.h>
|
||||
],[
|
||||
blk_status_t s __attribute__ ((unused)) = BLK_STS_RESV_CONFLICT;
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_BLKDEV_BLK_STS_RESV_CONFLICT], [
|
||||
AC_MSG_CHECKING([whether BLK_STS_RESV_CONFLICT is defined])
|
||||
ZFS_LINUX_TEST_RESULT([blk_sts_resv_conflict], [
|
||||
AC_DEFINE(HAVE_BLK_STS_RESV_CONFLICT, 1, [BLK_STS_RESV_CONFLICT is defined])
|
||||
AC_MSG_RESULT(yes)
|
||||
], [
|
||||
AC_MSG_RESULT(no)
|
||||
])
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV], [
|
||||
ZFS_AC_KERNEL_SRC_BLKDEV_GET_BY_PATH
|
||||
ZFS_AC_KERNEL_SRC_BLKDEV_GET_BY_PATH_4ARG
|
||||
ZFS_AC_KERNEL_SRC_BLKDEV_PUT
|
||||
ZFS_AC_KERNEL_SRC_BLKDEV_PUT_HOLDER
|
||||
ZFS_AC_KERNEL_SRC_BLKDEV_REREAD_PART
|
||||
ZFS_AC_KERNEL_SRC_BLKDEV_INVALIDATE_BDEV
|
||||
ZFS_AC_KERNEL_SRC_BLKDEV_LOOKUP_BDEV
|
||||
@@ -458,6 +584,9 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKDEV], [
|
||||
ZFS_AC_KERNEL_SRC_BLKDEV_ISSUE_SECURE_ERASE
|
||||
ZFS_AC_KERNEL_SRC_BLKDEV_BDEV_KOBJ
|
||||
ZFS_AC_KERNEL_SRC_BLKDEV_PART_TO_DEV
|
||||
ZFS_AC_KERNEL_SRC_BLKDEV_DISK_CHECK_MEDIA_CHANGE
|
||||
ZFS_AC_KERNEL_SRC_BLKDEV_BLK_STS_RESV_CONFLICT
|
||||
ZFS_AC_KERNEL_SRC_BLKDEV_BLK_MODE_T
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_BLKDEV], [
|
||||
@@ -476,4 +605,7 @@ AC_DEFUN([ZFS_AC_KERNEL_BLKDEV], [
|
||||
ZFS_AC_KERNEL_BLKDEV_ISSUE_SECURE_ERASE
|
||||
ZFS_AC_KERNEL_BLKDEV_BDEV_KOBJ
|
||||
ZFS_AC_KERNEL_BLKDEV_PART_TO_DEV
|
||||
ZFS_AC_KERNEL_BLKDEV_DISK_CHECK_MEDIA_CHANGE
|
||||
ZFS_AC_KERNEL_BLKDEV_BLK_STS_RESV_CONFLICT
|
||||
ZFS_AC_KERNEL_BLKDEV_BLK_MODE_T
|
||||
])
|
||||
|
||||
@@ -49,12 +49,42 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS_RELEASE_VOID], [
|
||||
], [], [])
|
||||
])
|
||||
|
||||
dnl #
|
||||
dnl # 5.9.x API change
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS_RELEASE_1ARG], [
|
||||
ZFS_LINUX_TEST_SRC([block_device_operations_release_void_1arg], [
|
||||
#include <linux/blkdev.h>
|
||||
|
||||
void blk_release(struct gendisk *g) {
|
||||
(void) g;
|
||||
return;
|
||||
}
|
||||
|
||||
static const struct block_device_operations
|
||||
bops __attribute__ ((unused)) = {
|
||||
.open = NULL,
|
||||
.release = blk_release,
|
||||
.ioctl = NULL,
|
||||
.compat_ioctl = NULL,
|
||||
};
|
||||
], [], [])
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS_RELEASE_VOID], [
|
||||
AC_MSG_CHECKING([whether bops->release() is void])
|
||||
AC_MSG_CHECKING([whether bops->release() is void and takes 2 args])
|
||||
ZFS_LINUX_TEST_RESULT([block_device_operations_release_void], [
|
||||
AC_MSG_RESULT(yes)
|
||||
],[
|
||||
ZFS_LINUX_TEST_ERROR([bops->release()])
|
||||
AC_MSG_RESULT(no)
|
||||
AC_MSG_CHECKING([whether bops->release() is void and takes 1 arg])
|
||||
ZFS_LINUX_TEST_RESULT([block_device_operations_release_void_1arg], [
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE([HAVE_BLOCK_DEVICE_OPERATIONS_RELEASE_1ARG], [1],
|
||||
[Define if release() in block_device_operations takes 1 arg])
|
||||
],[
|
||||
ZFS_LINUX_TEST_ERROR([bops->release()])
|
||||
])
|
||||
])
|
||||
])
|
||||
|
||||
@@ -92,6 +122,7 @@ AC_DEFUN([ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS_REVALIDATE_DISK], [
|
||||
AC_DEFUN([ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS], [
|
||||
ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS_CHECK_EVENTS
|
||||
ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS_RELEASE_VOID
|
||||
ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS_RELEASE_1ARG
|
||||
ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS_REVALIDATE_DISK
|
||||
])
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
AC_DEFUN([ZFS_AC_KERNEL_SRC_COPY_SPLICE_READ], [
|
||||
dnl #
|
||||
dnl # Kernel 6.5 - generic_file_splice_read was removed in favor
|
||||
dnl # of copy_splice_read for the .splice_read member of the
|
||||
dnl # file_operations struct.
|
||||
dnl #
|
||||
ZFS_LINUX_TEST_SRC([has_copy_splice_read], [
|
||||
#include <linux/fs.h>
|
||||
|
||||
struct file_operations fops __attribute__((unused)) = {
|
||||
.splice_read = copy_splice_read,
|
||||
};
|
||||
],[])
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_COPY_SPLICE_READ], [
|
||||
AC_MSG_CHECKING([whether copy_splice_read() exists])
|
||||
ZFS_LINUX_TEST_RESULT([has_copy_splice_read], [
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_COPY_SPLICE_READ, 1,
|
||||
[copy_splice_read exists])
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
])
|
||||
])
|
||||
@@ -0,0 +1,27 @@
|
||||
dnl #
|
||||
dnl # Linux 6.5 removes register_sysctl_table
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_KERNEL_SRC_REGISTER_SYSCTL_TABLE], [
|
||||
ZFS_LINUX_TEST_SRC([has_register_sysctl_table], [
|
||||
#include <linux/sysctl.h>
|
||||
|
||||
static struct ctl_table dummy_table[] = {
|
||||
{}
|
||||
};
|
||||
|
||||
],[
|
||||
struct ctl_table_header *h
|
||||
__attribute((unused)) = register_sysctl_table(dummy_table);
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_REGISTER_SYSCTL_TABLE], [
|
||||
AC_MSG_CHECKING([whether register_sysctl_table exists])
|
||||
ZFS_LINUX_TEST_RESULT([has_register_sysctl_table], [
|
||||
AC_MSG_RESULT([yes])
|
||||
AC_DEFINE(HAVE_REGISTER_SYSCTL_TABLE, 1,
|
||||
[register_sysctl_table exists])
|
||||
],[
|
||||
AC_MSG_RESULT([no])
|
||||
])
|
||||
])
|
||||
@@ -6,8 +6,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_VFS_IOV_ITER], [
|
||||
#include <linux/fs.h>
|
||||
#include <linux/uio.h>
|
||||
],[
|
||||
int type __attribute__ ((unused)) =
|
||||
ITER_IOVEC | ITER_KVEC | ITER_BVEC | ITER_PIPE;
|
||||
int type __attribute__ ((unused)) = ITER_KVEC;
|
||||
])
|
||||
|
||||
ZFS_LINUX_TEST_SRC([iov_iter_advance], [
|
||||
@@ -93,6 +92,14 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_VFS_IOV_ITER], [
|
||||
struct iov_iter iter = { 0 };
|
||||
__attribute__((unused)) enum iter_type i = iov_iter_type(&iter);
|
||||
])
|
||||
|
||||
ZFS_LINUX_TEST_SRC([iter_iov], [
|
||||
#include <linux/fs.h>
|
||||
#include <linux/uio.h>
|
||||
],[
|
||||
struct iov_iter iter = { 0 };
|
||||
__attribute__((unused)) const struct iovec *iov = iter_iov(&iter);
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_VFS_IOV_ITER], [
|
||||
@@ -201,4 +208,19 @@ AC_DEFUN([ZFS_AC_KERNEL_VFS_IOV_ITER], [
|
||||
AC_DEFINE(HAVE_VFS_IOV_ITER, 1,
|
||||
[All required iov_iter interfaces are available])
|
||||
])
|
||||
|
||||
dnl #
|
||||
dnl # Kernel 6.5 introduces the iter_iov() function that returns the
|
||||
dnl # __iov member of an iov_iter*. The iov member was renamed to this
|
||||
dnl # __iov member, and is intended to be accessed via the helper
|
||||
dnl # function now.
|
||||
dnl #
|
||||
AC_MSG_CHECKING([whether iter_iov() is available])
|
||||
ZFS_LINUX_TEST_RESULT([iter_iov], [
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_ITER_IOV, 1,
|
||||
[iter_iov() is available])
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
])
|
||||
])
|
||||
|
||||
@@ -148,6 +148,8 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [
|
||||
ZFS_AC_KERNEL_SRC_FILEMAP
|
||||
ZFS_AC_KERNEL_SRC_WRITEPAGE_T
|
||||
ZFS_AC_KERNEL_SRC_RECLAIMED
|
||||
ZFS_AC_KERNEL_SRC_REGISTER_SYSCTL_TABLE
|
||||
ZFS_AC_KERNEL_SRC_COPY_SPLICE_READ
|
||||
case "$host_cpu" in
|
||||
powerpc*)
|
||||
ZFS_AC_KERNEL_SRC_CPU_HAS_FEATURE
|
||||
@@ -275,6 +277,8 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [
|
||||
ZFS_AC_KERNEL_FILEMAP
|
||||
ZFS_AC_KERNEL_WRITEPAGE_T
|
||||
ZFS_AC_KERNEL_RECLAIMED
|
||||
ZFS_AC_KERNEL_REGISTER_SYSCTL_TABLE
|
||||
ZFS_AC_KERNEL_COPY_SPLICE_READ
|
||||
case "$host_cpu" in
|
||||
powerpc*)
|
||||
ZFS_AC_KERNEL_CPU_HAS_FEATURE
|
||||
|
||||
@@ -69,7 +69,7 @@ __zfs_match_snapshot()
|
||||
else
|
||||
if [ "$cur" != "" ] && __zfs_list_datasets "$cur" &> /dev/null
|
||||
then
|
||||
$__ZFS_CMD list -H -o name -s name -t filesystem -r "$cur" | tail -n +2
|
||||
$__ZFS_CMD list -H -o name -s name -t filesystem,volume -r "$cur" | tail -n +2
|
||||
# We output the base dataset name even though we might be
|
||||
# completing a command that can only take a snapshot, because it
|
||||
# prevents bash from considering the completion finished when it
|
||||
|
||||
+2
-26
@@ -43,32 +43,8 @@ config ZFS
|
||||
If unsure, say N.
|
||||
EOF
|
||||
|
||||
add_after()
|
||||
{
|
||||
FILE="$1"
|
||||
MARKER="$2"
|
||||
NEW="$3"
|
||||
|
||||
while IFS='' read -r LINE
|
||||
do
|
||||
printf "%s\n" "$LINE"
|
||||
|
||||
if [ -n "$MARKER" ] && [ "$LINE" = "$MARKER" ]
|
||||
then
|
||||
printf "%s\n" "$NEW"
|
||||
MARKER=''
|
||||
if IFS='' read -r LINE
|
||||
then
|
||||
[ "$LINE" != "$NEW" ] && printf "%s\n" "$LINE"
|
||||
fi
|
||||
fi
|
||||
done < "$FILE" > "$FILE.new"
|
||||
|
||||
mv "$FILE.new" "$FILE"
|
||||
}
|
||||
|
||||
add_after "$KERNEL_DIR/fs/Kconfig" 'if BLOCK' 'source "fs/zfs/Kconfig"'
|
||||
add_after "$KERNEL_DIR/fs/Makefile" 'endif' 'obj-$(CONFIG_ZFS) += zfs/'
|
||||
sed -i '/source "fs\/ext2\/Kconfig\"/i\source "fs/zfs/Kconfig"' "$KERNEL_DIR/fs/Kconfig"
|
||||
echo 'obj-$(CONFIG_ZFS) += zfs/' >> "$KERNEL_DIR/fs/Makefile"
|
||||
|
||||
echo "$0: done. now you can build the kernel with ZFS support." >&2
|
||||
echo "$0: make sure you enable ZFS support (CONFIG_ZFS) before building." >&2
|
||||
|
||||
@@ -170,7 +170,11 @@ bi_status_to_errno(blk_status_t status)
|
||||
return (ENOLINK);
|
||||
case BLK_STS_TARGET:
|
||||
return (EREMOTEIO);
|
||||
#ifdef HAVE_BLK_STS_RESV_CONFLICT
|
||||
case BLK_STS_RESV_CONFLICT:
|
||||
#else
|
||||
case BLK_STS_NEXUS:
|
||||
#endif
|
||||
return (EBADE);
|
||||
case BLK_STS_MEDIUM:
|
||||
return (ENODATA);
|
||||
@@ -204,7 +208,11 @@ errno_to_bi_status(int error)
|
||||
case EREMOTEIO:
|
||||
return (BLK_STS_TARGET);
|
||||
case EBADE:
|
||||
#ifdef HAVE_BLK_STS_RESV_CONFLICT
|
||||
return (BLK_STS_RESV_CONFLICT);
|
||||
#else
|
||||
return (BLK_STS_NEXUS);
|
||||
#endif
|
||||
case ENODATA:
|
||||
return (BLK_STS_MEDIUM);
|
||||
case EILSEQ:
|
||||
@@ -326,6 +334,9 @@ zfs_check_media_change(struct block_device *bdev)
|
||||
return (0);
|
||||
}
|
||||
#define vdev_bdev_reread_part(bdev) zfs_check_media_change(bdev)
|
||||
#elif defined(HAVE_DISK_CHECK_MEDIA_CHANGE)
|
||||
#define vdev_bdev_reread_part(bdev) disk_check_media_change(bdev->bd_disk)
|
||||
#define zfs_check_media_change(bdev) disk_check_media_change(bdev->bd_disk)
|
||||
#else
|
||||
/*
|
||||
* This is encountered if check_disk_change() and bdev_check_media_change()
|
||||
@@ -376,6 +387,12 @@ vdev_lookup_bdev(const char *path, dev_t *dev)
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(HAVE_BLK_MODE_T)
|
||||
#define blk_mode_is_open_write(flag) ((flag) & BLK_OPEN_WRITE)
|
||||
#else
|
||||
#define blk_mode_is_open_write(flag) ((flag) & FMODE_WRITE)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Kernels without bio_set_op_attrs use bi_rw for the bio flags.
|
||||
*/
|
||||
|
||||
@@ -38,7 +38,7 @@ typedef unsigned long ulong_t;
|
||||
typedef unsigned long long u_longlong_t;
|
||||
typedef long long longlong_t;
|
||||
|
||||
typedef unsigned long intptr_t;
|
||||
typedef long intptr_t;
|
||||
typedef unsigned long long rlim64_t;
|
||||
|
||||
typedef struct task_struct kthread_t;
|
||||
|
||||
@@ -146,4 +146,16 @@ zfs_uio_iov_iter_init(zfs_uio_t *uio, struct iov_iter *iter, offset_t offset,
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_ITER_IOV)
|
||||
#define zfs_uio_iter_iov(iter) iter_iov((iter))
|
||||
#else
|
||||
#define zfs_uio_iter_iov(iter) (iter)->iov
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_IOV_ITER_TYPE)
|
||||
#define zfs_uio_iov_iter_type(iter) iov_iter_type((iter))
|
||||
#else
|
||||
#define zfs_uio_iov_iter_type(iter) (iter)->type
|
||||
#endif
|
||||
|
||||
#endif /* SPL_UIO_H */
|
||||
|
||||
@@ -1762,7 +1762,8 @@ zfs_prop_set_list(zfs_handle_t *zhp, nvlist_t *props)
|
||||
nvlist_t *nvl;
|
||||
int nvl_len = 0;
|
||||
int added_resv = 0;
|
||||
zfs_prop_t prop = 0;
|
||||
zfs_prop_t prop;
|
||||
boolean_t nsprop = B_FALSE;
|
||||
nvpair_t *elem;
|
||||
|
||||
(void) snprintf(errbuf, sizeof (errbuf),
|
||||
@@ -1809,6 +1810,7 @@ zfs_prop_set_list(zfs_handle_t *zhp, nvlist_t *props)
|
||||
elem = nvlist_next_nvpair(nvl, elem)) {
|
||||
|
||||
prop = zfs_name_to_prop(nvpair_name(elem));
|
||||
nsprop |= zfs_is_namespace_prop(prop);
|
||||
|
||||
assert(cl_idx < nvl_len);
|
||||
/*
|
||||
@@ -1909,8 +1911,7 @@ zfs_prop_set_list(zfs_handle_t *zhp, nvlist_t *props)
|
||||
* if one of the options handled by the generic
|
||||
* Linux namespace layer has been modified.
|
||||
*/
|
||||
if (zfs_is_namespace_prop(prop) &&
|
||||
zfs_is_mounted(zhp, NULL))
|
||||
if (nsprop && zfs_is_mounted(zhp, NULL))
|
||||
ret = zfs_mount(zhp, MNTOPT_REMOUNT, 0);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -13,10 +13,10 @@
|
||||
|
||||
|
||||
#define sizeCclosure(n) (cast(int, sizeof(CClosure)) + \
|
||||
cast(int, sizeof(TValue)*((n)-1)))
|
||||
cast(int, sizeof(TValue)*((n))))
|
||||
|
||||
#define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \
|
||||
cast(int, sizeof(TValue *)*((n)-1)))
|
||||
cast(int, sizeof(TValue *)*((n))))
|
||||
|
||||
|
||||
LUAI_FUNC Proto *luaF_newproto (lua_State *L);
|
||||
|
||||
@@ -514,14 +514,14 @@ typedef struct UpVal {
|
||||
typedef struct CClosure {
|
||||
ClosureHeader;
|
||||
lua_CFunction f;
|
||||
TValue upvalue[1]; /* list of upvalues */
|
||||
TValue upvalue[]; /* list of upvalues */
|
||||
} CClosure;
|
||||
|
||||
|
||||
typedef struct LClosure {
|
||||
ClosureHeader;
|
||||
struct Proto *p;
|
||||
UpVal *upvals[1]; /* list of upvalues */
|
||||
UpVal *upvals[]; /* list of upvalues */
|
||||
} LClosure;
|
||||
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ typedef struct zfs_dbgmsg {
|
||||
list_node_t zdm_node;
|
||||
time_t zdm_timestamp;
|
||||
int zdm_size;
|
||||
char zdm_msg[1]; /* variable length allocation */
|
||||
char zdm_msg[];
|
||||
} zfs_dbgmsg_t;
|
||||
|
||||
list_t zfs_dbgmsgs;
|
||||
@@ -159,7 +159,7 @@ __zfs_dbgmsg(char *buf)
|
||||
|
||||
DTRACE_PROBE1(zfs__dbgmsg, char *, buf);
|
||||
|
||||
size = sizeof (zfs_dbgmsg_t) + strlen(buf);
|
||||
size = sizeof (zfs_dbgmsg_t) + strlen(buf) + 1;
|
||||
zdm = kmem_zalloc(size, KM_SLEEP);
|
||||
zdm->zdm_size = size;
|
||||
zdm->zdm_timestamp = gethrestime_sec();
|
||||
|
||||
@@ -1020,9 +1020,19 @@ spl_cache_grow(spl_kmem_cache_t *skc, int flags, void **obj)
|
||||
ASSERT0(flags & ~KM_PUBLIC_MASK);
|
||||
ASSERT(skc->skc_magic == SKC_MAGIC);
|
||||
ASSERT((skc->skc_flags & KMC_SLAB) == 0);
|
||||
might_sleep();
|
||||
|
||||
*obj = NULL;
|
||||
|
||||
/*
|
||||
* Since we can't sleep attempt an emergency allocation to satisfy
|
||||
* the request. The only alterative is to fail the allocation but
|
||||
* it's preferable try. The use of KM_NOSLEEP is expected to be rare.
|
||||
*/
|
||||
if (flags & KM_NOSLEEP)
|
||||
return (spl_emergency_alloc(skc, flags, obj));
|
||||
|
||||
might_sleep();
|
||||
|
||||
/*
|
||||
* Before allocating a new slab wait for any reaping to complete and
|
||||
* then return so the local magazine can be rechecked for new objects.
|
||||
|
||||
@@ -46,6 +46,10 @@ static unsigned long table_min = 0;
|
||||
static unsigned long table_max = ~0;
|
||||
|
||||
static struct ctl_table_header *spl_header = NULL;
|
||||
#ifndef HAVE_REGISTER_SYSCTL_TABLE
|
||||
static struct ctl_table_header *spl_kmem = NULL;
|
||||
static struct ctl_table_header *spl_kstat = NULL;
|
||||
#endif
|
||||
static struct proc_dir_entry *proc_spl = NULL;
|
||||
static struct proc_dir_entry *proc_spl_kmem = NULL;
|
||||
static struct proc_dir_entry *proc_spl_kmem_slab = NULL;
|
||||
@@ -624,6 +628,7 @@ static struct ctl_table spl_table[] = {
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dohostid,
|
||||
},
|
||||
#ifdef HAVE_REGISTER_SYSCTL_TABLE
|
||||
{
|
||||
.procname = "kmem",
|
||||
.mode = 0555,
|
||||
@@ -634,9 +639,11 @@ static struct ctl_table spl_table[] = {
|
||||
.mode = 0555,
|
||||
.child = spl_kstat_table,
|
||||
},
|
||||
#endif
|
||||
{},
|
||||
};
|
||||
|
||||
#ifdef HAVE_REGISTER_SYSCTL_TABLE
|
||||
static struct ctl_table spl_dir[] = {
|
||||
{
|
||||
.procname = "spl",
|
||||
@@ -648,21 +655,64 @@ static struct ctl_table spl_dir[] = {
|
||||
|
||||
static struct ctl_table spl_root[] = {
|
||||
{
|
||||
.procname = "kernel",
|
||||
.mode = 0555,
|
||||
.child = spl_dir,
|
||||
.procname = "kernel",
|
||||
.mode = 0555,
|
||||
.child = spl_dir,
|
||||
},
|
||||
{}
|
||||
};
|
||||
#endif
|
||||
|
||||
static void spl_proc_cleanup(void)
|
||||
{
|
||||
remove_proc_entry("kstat", proc_spl);
|
||||
remove_proc_entry("slab", proc_spl_kmem);
|
||||
remove_proc_entry("kmem", proc_spl);
|
||||
remove_proc_entry("taskq-all", proc_spl);
|
||||
remove_proc_entry("taskq", proc_spl);
|
||||
remove_proc_entry("spl", NULL);
|
||||
|
||||
#ifndef HAVE_REGISTER_SYSCTL_TABLE
|
||||
if (spl_kstat) {
|
||||
unregister_sysctl_table(spl_kstat);
|
||||
spl_kstat = NULL;
|
||||
}
|
||||
if (spl_kmem) {
|
||||
unregister_sysctl_table(spl_kmem);
|
||||
spl_kmem = NULL;
|
||||
}
|
||||
#endif
|
||||
if (spl_header) {
|
||||
unregister_sysctl_table(spl_header);
|
||||
spl_header = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
spl_proc_init(void)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
#ifdef HAVE_REGISTER_SYSCTL_TABLE
|
||||
spl_header = register_sysctl_table(spl_root);
|
||||
if (spl_header == NULL)
|
||||
return (-EUNATCH);
|
||||
#else
|
||||
spl_header = register_sysctl("kernel/spl", spl_table);
|
||||
if (spl_header == NULL)
|
||||
return (-EUNATCH);
|
||||
|
||||
spl_kmem = register_sysctl("kernel/spl/kmem", spl_kmem_table);
|
||||
if (spl_kmem == NULL) {
|
||||
rc = -EUNATCH;
|
||||
goto out;
|
||||
}
|
||||
spl_kstat = register_sysctl("kernel/spl/kstat", spl_kstat_table);
|
||||
if (spl_kstat == NULL) {
|
||||
rc = -EUNATCH;
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
|
||||
proc_spl = proc_mkdir("spl", NULL);
|
||||
if (proc_spl == NULL) {
|
||||
@@ -703,15 +753,8 @@ spl_proc_init(void)
|
||||
goto out;
|
||||
}
|
||||
out:
|
||||
if (rc) {
|
||||
remove_proc_entry("kstat", proc_spl);
|
||||
remove_proc_entry("slab", proc_spl_kmem);
|
||||
remove_proc_entry("kmem", proc_spl);
|
||||
remove_proc_entry("taskq-all", proc_spl);
|
||||
remove_proc_entry("taskq", proc_spl);
|
||||
remove_proc_entry("spl", NULL);
|
||||
unregister_sysctl_table(spl_header);
|
||||
}
|
||||
if (rc)
|
||||
spl_proc_cleanup();
|
||||
|
||||
return (rc);
|
||||
}
|
||||
@@ -719,13 +762,5 @@ out:
|
||||
void
|
||||
spl_proc_fini(void)
|
||||
{
|
||||
remove_proc_entry("kstat", proc_spl);
|
||||
remove_proc_entry("slab", proc_spl_kmem);
|
||||
remove_proc_entry("kmem", proc_spl);
|
||||
remove_proc_entry("taskq-all", proc_spl);
|
||||
remove_proc_entry("taskq", proc_spl);
|
||||
remove_proc_entry("spl", NULL);
|
||||
|
||||
ASSERT(spl_header != NULL);
|
||||
unregister_sysctl_table(spl_header);
|
||||
spl_proc_cleanup();
|
||||
}
|
||||
|
||||
@@ -74,9 +74,22 @@ typedef struct dio_request {
|
||||
struct bio *dr_bio[0]; /* Attached bio's */
|
||||
} dio_request_t;
|
||||
|
||||
#ifdef HAVE_BLK_MODE_T
|
||||
static blk_mode_t
|
||||
#else
|
||||
static fmode_t
|
||||
#endif
|
||||
vdev_bdev_mode(spa_mode_t spa_mode)
|
||||
{
|
||||
#ifdef HAVE_BLK_MODE_T
|
||||
blk_mode_t mode = 0;
|
||||
|
||||
if (spa_mode & SPA_MODE_READ)
|
||||
mode |= BLK_OPEN_READ;
|
||||
|
||||
if (spa_mode & SPA_MODE_WRITE)
|
||||
mode |= BLK_OPEN_WRITE;
|
||||
#else
|
||||
fmode_t mode = 0;
|
||||
|
||||
if (spa_mode & SPA_MODE_READ)
|
||||
@@ -84,6 +97,7 @@ vdev_bdev_mode(spa_mode_t spa_mode)
|
||||
|
||||
if (spa_mode & SPA_MODE_WRITE)
|
||||
mode |= FMODE_WRITE;
|
||||
#endif
|
||||
|
||||
return (mode);
|
||||
}
|
||||
@@ -191,12 +205,47 @@ vdev_disk_kobj_evt_post(vdev_t *v)
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(HAVE_BLKDEV_GET_BY_PATH_4ARG)
|
||||
/*
|
||||
* Define a dummy struct blk_holder_ops for kernel versions
|
||||
* prior to 6.5.
|
||||
*/
|
||||
struct blk_holder_ops {};
|
||||
#endif
|
||||
|
||||
static struct block_device *
|
||||
vdev_blkdev_get_by_path(const char *path, spa_mode_t mode, void *holder,
|
||||
const struct blk_holder_ops *hops)
|
||||
{
|
||||
#ifdef HAVE_BLKDEV_GET_BY_PATH_4ARG
|
||||
return (blkdev_get_by_path(path,
|
||||
vdev_bdev_mode(mode) | BLK_OPEN_EXCL, holder, hops));
|
||||
#else
|
||||
return (blkdev_get_by_path(path,
|
||||
vdev_bdev_mode(mode) | FMODE_EXCL, holder));
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
vdev_blkdev_put(struct block_device *bdev, spa_mode_t mode, void *holder)
|
||||
{
|
||||
#ifdef HAVE_BLKDEV_PUT_HOLDER
|
||||
return (blkdev_put(bdev, holder));
|
||||
#else
|
||||
return (blkdev_put(bdev, vdev_bdev_mode(mode) | FMODE_EXCL));
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
vdev_disk_open(vdev_t *v, uint64_t *psize, uint64_t *max_psize,
|
||||
uint64_t *logical_ashift, uint64_t *physical_ashift)
|
||||
{
|
||||
struct block_device *bdev;
|
||||
#ifdef HAVE_BLK_MODE_T
|
||||
blk_mode_t mode = vdev_bdev_mode(spa_mode(v->vdev_spa));
|
||||
#else
|
||||
fmode_t mode = vdev_bdev_mode(spa_mode(v->vdev_spa));
|
||||
#endif
|
||||
hrtime_t timeout = MSEC2NSEC(zfs_vdev_open_timeout_ms);
|
||||
vdev_disk_t *vd;
|
||||
|
||||
@@ -246,15 +295,15 @@ vdev_disk_open(vdev_t *v, uint64_t *psize, uint64_t *max_psize,
|
||||
reread_part = B_TRUE;
|
||||
}
|
||||
|
||||
blkdev_put(bdev, mode | FMODE_EXCL);
|
||||
vdev_blkdev_put(bdev, mode, zfs_vdev_holder);
|
||||
}
|
||||
|
||||
if (reread_part) {
|
||||
bdev = blkdev_get_by_path(disk_name, mode | FMODE_EXCL,
|
||||
zfs_vdev_holder);
|
||||
bdev = vdev_blkdev_get_by_path(disk_name, mode,
|
||||
zfs_vdev_holder, NULL);
|
||||
if (!IS_ERR(bdev)) {
|
||||
int error = vdev_bdev_reread_part(bdev);
|
||||
blkdev_put(bdev, mode | FMODE_EXCL);
|
||||
vdev_blkdev_put(bdev, mode, zfs_vdev_holder);
|
||||
if (error == 0) {
|
||||
timeout = MSEC2NSEC(
|
||||
zfs_vdev_open_timeout_ms * 2);
|
||||
@@ -299,8 +348,8 @@ vdev_disk_open(vdev_t *v, uint64_t *psize, uint64_t *max_psize,
|
||||
hrtime_t start = gethrtime();
|
||||
bdev = ERR_PTR(-ENXIO);
|
||||
while (IS_ERR(bdev) && ((gethrtime() - start) < timeout)) {
|
||||
bdev = blkdev_get_by_path(v->vdev_path, mode | FMODE_EXCL,
|
||||
zfs_vdev_holder);
|
||||
bdev = vdev_blkdev_get_by_path(v->vdev_path, mode,
|
||||
zfs_vdev_holder, NULL);
|
||||
if (unlikely(PTR_ERR(bdev) == -ENOENT)) {
|
||||
/*
|
||||
* There is no point of waiting since device is removed
|
||||
@@ -376,8 +425,8 @@ vdev_disk_close(vdev_t *v)
|
||||
return;
|
||||
|
||||
if (vd->vd_bdev != NULL) {
|
||||
blkdev_put(vd->vd_bdev,
|
||||
vdev_bdev_mode(spa_mode(v->vdev_spa)) | FMODE_EXCL);
|
||||
vdev_blkdev_put(vd->vd_bdev, spa_mode(v->vdev_spa),
|
||||
zfs_vdev_holder);
|
||||
}
|
||||
|
||||
rw_destroy(&vd->vd_lock);
|
||||
|
||||
@@ -118,6 +118,7 @@ typedef struct {
|
||||
spa_t *se_spa; /* pool spa */
|
||||
uint64_t se_objsetid; /* snapshot objset id */
|
||||
struct dentry *se_root_dentry; /* snapshot root dentry */
|
||||
krwlock_t se_taskqid_lock; /* scheduled unmount taskqid lock */
|
||||
taskqid_t se_taskqid; /* scheduled unmount taskqid */
|
||||
avl_node_t se_node_name; /* zfs_snapshots_by_name link */
|
||||
avl_node_t se_node_objsetid; /* zfs_snapshots_by_objsetid link */
|
||||
@@ -144,6 +145,7 @@ zfsctl_snapshot_alloc(const char *full_name, const char *full_path, spa_t *spa,
|
||||
se->se_objsetid = objsetid;
|
||||
se->se_root_dentry = root_dentry;
|
||||
se->se_taskqid = TASKQID_INVALID;
|
||||
rw_init(&se->se_taskqid_lock, NULL, RW_DEFAULT, NULL);
|
||||
|
||||
zfs_refcount_create(&se->se_refcount);
|
||||
|
||||
@@ -160,6 +162,7 @@ zfsctl_snapshot_free(zfs_snapentry_t *se)
|
||||
zfs_refcount_destroy(&se->se_refcount);
|
||||
kmem_strfree(se->se_name);
|
||||
kmem_strfree(se->se_path);
|
||||
rw_destroy(se->se_taskqid_lock);
|
||||
|
||||
kmem_free(se, sizeof (zfs_snapentry_t));
|
||||
}
|
||||
@@ -335,7 +338,9 @@ snapentry_expire(void *data)
|
||||
return;
|
||||
}
|
||||
|
||||
rw_enter(&se->se_taskqid_lock, RW_WRITER);
|
||||
se->se_taskqid = TASKQID_INVALID;
|
||||
rw_exit(&se->se_taskqid_lock);
|
||||
(void) zfsctl_snapshot_unmount(se->se_name, MNT_EXPIRE);
|
||||
zfsctl_snapshot_rele(se);
|
||||
|
||||
@@ -359,8 +364,18 @@ snapentry_expire(void *data)
|
||||
static void
|
||||
zfsctl_snapshot_unmount_cancel(zfs_snapentry_t *se)
|
||||
{
|
||||
if (taskq_cancel_id(system_delay_taskq, se->se_taskqid) == 0) {
|
||||
se->se_taskqid = TASKQID_INVALID;
|
||||
int err = 0;
|
||||
rw_enter(&se->se_taskqid_lock, RW_WRITER);
|
||||
err = taskq_cancel_id(system_delay_taskq, se->se_taskqid);
|
||||
/*
|
||||
* if we get ENOENT, the taskq couldn't be found to be
|
||||
* canceled, so we can just mark it as invalid because
|
||||
* it's already gone. If we got EBUSY, then we already
|
||||
* blocked until it was gone _anyway_, so we don't care.
|
||||
*/
|
||||
se->se_taskqid = TASKQID_INVALID;
|
||||
rw_exit(&se->se_taskqid_lock);
|
||||
if (err == 0) {
|
||||
zfsctl_snapshot_rele(se);
|
||||
}
|
||||
}
|
||||
@@ -371,14 +386,29 @@ zfsctl_snapshot_unmount_cancel(zfs_snapentry_t *se)
|
||||
static void
|
||||
zfsctl_snapshot_unmount_delay_impl(zfs_snapentry_t *se, int delay)
|
||||
{
|
||||
ASSERT3S(se->se_taskqid, ==, TASKQID_INVALID);
|
||||
|
||||
if (delay <= 0)
|
||||
return;
|
||||
|
||||
zfsctl_snapshot_hold(se);
|
||||
rw_enter(&se->se_taskqid_lock, RW_WRITER);
|
||||
/*
|
||||
* If this condition happens, we managed to:
|
||||
* - dispatch once
|
||||
* - want to dispatch _again_ before it returned
|
||||
*
|
||||
* So let's just return - if that task fails at unmounting,
|
||||
* we'll eventually dispatch again, and if it succeeds,
|
||||
* no problem.
|
||||
*/
|
||||
if (se->se_taskqid != TASKQID_INVALID) {
|
||||
rw_exit(&se->se_taskqid_lock);
|
||||
zfsctl_snapshot_rele(se);
|
||||
return;
|
||||
}
|
||||
se->se_taskqid = taskq_dispatch_delay(system_delay_taskq,
|
||||
snapentry_expire, se, TQ_SLEEP, ddi_get_lbolt() + delay * HZ);
|
||||
rw_exit(&se->se_taskqid_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -30,7 +30,7 @@ typedef struct zfs_dbgmsg {
|
||||
procfs_list_node_t zdm_node;
|
||||
uint64_t zdm_timestamp;
|
||||
int zdm_size;
|
||||
char zdm_msg[1]; /* variable length allocation */
|
||||
char zdm_msg[]; /* variable length allocation */
|
||||
} zfs_dbgmsg_t;
|
||||
|
||||
procfs_list_t zfs_dbgmsgs;
|
||||
@@ -134,7 +134,7 @@ __set_error(const char *file, const char *func, int line, int err)
|
||||
void
|
||||
__zfs_dbgmsg(char *buf)
|
||||
{
|
||||
int size = sizeof (zfs_dbgmsg_t) + strlen(buf);
|
||||
int size = sizeof (zfs_dbgmsg_t) + strlen(buf) + 1;
|
||||
zfs_dbgmsg_t *zdm = kmem_zalloc(size, KM_SLEEP);
|
||||
zdm->zdm_size = size;
|
||||
zdm->zdm_timestamp = gethrestime_sec();
|
||||
|
||||
@@ -198,7 +198,7 @@ zfs_open(struct inode *ip, int mode, int flag, cred_t *cr)
|
||||
ZFS_VERIFY_ZP(zp);
|
||||
|
||||
/* Honor ZFS_APPENDONLY file attribute */
|
||||
if ((mode & FMODE_WRITE) && (zp->z_pflags & ZFS_APPENDONLY) &&
|
||||
if (blk_mode_is_open_write(mode) && (zp->z_pflags & ZFS_APPENDONLY) &&
|
||||
((flag & O_APPEND) == 0)) {
|
||||
ZFS_EXIT(zfsvfs);
|
||||
return (SET_ERROR(EPERM));
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
static int
|
||||
zpl_common_open(struct inode *ip, struct file *filp)
|
||||
{
|
||||
if (filp->f_mode & FMODE_WRITE)
|
||||
if (blk_mode_is_open_write(filp->f_mode))
|
||||
return (-EACCES);
|
||||
|
||||
return (generic_file_open(ip, filp));
|
||||
|
||||
@@ -294,15 +294,10 @@ zpl_uio_init(zfs_uio_t *uio, struct kiocb *kiocb, struct iov_iter *to,
|
||||
#if defined(HAVE_VFS_IOV_ITER)
|
||||
zfs_uio_iov_iter_init(uio, to, pos, count, skip);
|
||||
#else
|
||||
#ifdef HAVE_IOV_ITER_TYPE
|
||||
zfs_uio_iovec_init(uio, to->iov, to->nr_segs, pos,
|
||||
iov_iter_type(to) & ITER_KVEC ? UIO_SYSSPACE : UIO_USERSPACE,
|
||||
zfs_uio_iovec_init(uio, zfs_uio_iter_iov(to), to->nr_segs, pos,
|
||||
zfs_uio_iov_iter_type(to) & ITER_KVEC ?
|
||||
UIO_SYSSPACE : UIO_USERSPACE,
|
||||
count, skip);
|
||||
#else
|
||||
zfs_uio_iovec_init(uio, to->iov, to->nr_segs, pos,
|
||||
to->type & ITER_KVEC ? UIO_SYSSPACE : UIO_USERSPACE,
|
||||
count, skip);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1147,7 +1142,11 @@ const struct file_operations zpl_file_operations = {
|
||||
.read_iter = zpl_iter_read,
|
||||
.write_iter = zpl_iter_write,
|
||||
#ifdef HAVE_VFS_IOV_ITER
|
||||
#ifdef HAVE_COPY_SPLICE_READ
|
||||
.splice_read = copy_splice_read,
|
||||
#else
|
||||
.splice_read = generic_file_splice_read,
|
||||
#endif
|
||||
.splice_write = iter_file_splice_write,
|
||||
#endif
|
||||
#else
|
||||
|
||||
@@ -492,7 +492,11 @@ out:
|
||||
}
|
||||
|
||||
static int
|
||||
#ifdef HAVE_BLK_MODE_T
|
||||
zvol_open(struct gendisk *disk, blk_mode_t flag)
|
||||
#else
|
||||
zvol_open(struct block_device *bdev, fmode_t flag)
|
||||
#endif
|
||||
{
|
||||
zvol_state_t *zv;
|
||||
int error = 0;
|
||||
@@ -507,10 +511,14 @@ retry:
|
||||
/*
|
||||
* Obtain a copy of private_data under the zvol_state_lock to make
|
||||
* sure that either the result of zvol free code path setting
|
||||
* bdev->bd_disk->private_data to NULL is observed, or zvol_free()
|
||||
* disk->private_data to NULL is observed, or zvol_os_free()
|
||||
* is not called on this zv because of the positive zv_open_count.
|
||||
*/
|
||||
#ifdef HAVE_BLK_MODE_T
|
||||
zv = disk->private_data;
|
||||
#else
|
||||
zv = bdev->bd_disk->private_data;
|
||||
#endif
|
||||
if (zv == NULL) {
|
||||
rw_exit(&zvol_state_lock);
|
||||
return (SET_ERROR(-ENXIO));
|
||||
@@ -590,14 +598,15 @@ retry:
|
||||
}
|
||||
}
|
||||
|
||||
error = -zvol_first_open(zv, !(flag & FMODE_WRITE));
|
||||
error = -zvol_first_open(zv, !(blk_mode_is_open_write(flag)));
|
||||
|
||||
if (drop_namespace)
|
||||
mutex_exit(&spa_namespace_lock);
|
||||
}
|
||||
|
||||
if (error == 0) {
|
||||
if ((flag & FMODE_WRITE) && (zv->zv_flags & ZVOL_RDONLY)) {
|
||||
if ((blk_mode_is_open_write(flag)) &&
|
||||
(zv->zv_flags & ZVOL_RDONLY)) {
|
||||
if (zv->zv_open_count == 0)
|
||||
zvol_last_close(zv);
|
||||
|
||||
@@ -612,14 +621,25 @@ retry:
|
||||
rw_exit(&zv->zv_suspend_lock);
|
||||
|
||||
if (error == 0)
|
||||
#ifdef HAVE_BLK_MODE_T
|
||||
disk_check_media_change(disk);
|
||||
#else
|
||||
zfs_check_media_change(bdev);
|
||||
#endif
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
static void
|
||||
zvol_release(struct gendisk *disk, fmode_t mode)
|
||||
#ifdef HAVE_BLOCK_DEVICE_OPERATIONS_RELEASE_1ARG
|
||||
zvol_release(struct gendisk *disk)
|
||||
#else
|
||||
zvol_release(struct gendisk *disk, fmode_t unused)
|
||||
#endif
|
||||
{
|
||||
#if !defined(HAVE_BLOCK_DEVICE_OPERATIONS_RELEASE_1ARG)
|
||||
(void) unused;
|
||||
#endif
|
||||
zvol_state_t *zv;
|
||||
boolean_t drop_suspend = B_TRUE;
|
||||
|
||||
|
||||
+45
-28
@@ -946,7 +946,7 @@ static void l2arc_hdr_restore(const l2arc_log_ent_phys_t *le,
|
||||
l2arc_dev_t *dev);
|
||||
|
||||
/* L2ARC persistence write I/O routines. */
|
||||
static void l2arc_log_blk_commit(l2arc_dev_t *dev, zio_t *pio,
|
||||
static uint64_t l2arc_log_blk_commit(l2arc_dev_t *dev, zio_t *pio,
|
||||
l2arc_write_callback_t *cb);
|
||||
|
||||
/* L2ARC persistence auxiliary routines. */
|
||||
@@ -8415,7 +8415,7 @@ l2arc_write_eligible(uint64_t spa_guid, arc_buf_hdr_t *hdr)
|
||||
static uint64_t
|
||||
l2arc_write_size(l2arc_dev_t *dev)
|
||||
{
|
||||
uint64_t size, dev_size, tsize;
|
||||
uint64_t size;
|
||||
|
||||
/*
|
||||
* Make sure our globals have meaningful values in case the user
|
||||
@@ -8432,18 +8432,23 @@ l2arc_write_size(l2arc_dev_t *dev)
|
||||
if (arc_warm == B_FALSE)
|
||||
size += l2arc_write_boost;
|
||||
|
||||
/* We need to add in the worst case scenario of log block overhead. */
|
||||
size += l2arc_log_blk_overhead(size, dev);
|
||||
if (dev->l2ad_vdev->vdev_has_trim && l2arc_trim_ahead > 0) {
|
||||
/*
|
||||
* Trim ahead of the write size 64MB or (l2arc_trim_ahead/100)
|
||||
* times the writesize, whichever is greater.
|
||||
*/
|
||||
size += MAX(64 * 1024 * 1024,
|
||||
(size * l2arc_trim_ahead) / 100);
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure the write size does not exceed the size of the cache
|
||||
* device. This is important in l2arc_evict(), otherwise infinite
|
||||
* iteration can occur.
|
||||
*/
|
||||
dev_size = dev->l2ad_end - dev->l2ad_start;
|
||||
tsize = size + l2arc_log_blk_overhead(size, dev);
|
||||
if (dev->l2ad_vdev->vdev_has_trim && l2arc_trim_ahead > 0)
|
||||
tsize += MAX(64 * 1024 * 1024,
|
||||
(tsize * l2arc_trim_ahead) / 100);
|
||||
|
||||
if (tsize >= dev_size) {
|
||||
if (size > dev->l2ad_end - dev->l2ad_start) {
|
||||
cmn_err(CE_NOTE, "l2arc_write_max or l2arc_write_boost "
|
||||
"plus the overhead of log blocks (persistent L2ARC, "
|
||||
"%llu bytes) exceeds the size of the cache device "
|
||||
@@ -8452,8 +8457,19 @@ l2arc_write_size(l2arc_dev_t *dev)
|
||||
dev->l2ad_vdev->vdev_guid, L2ARC_WRITE_SIZE);
|
||||
size = l2arc_write_max = l2arc_write_boost = L2ARC_WRITE_SIZE;
|
||||
|
||||
if (l2arc_trim_ahead > 1) {
|
||||
cmn_err(CE_NOTE, "l2arc_trim_ahead set to 1");
|
||||
l2arc_trim_ahead = 1;
|
||||
}
|
||||
|
||||
if (arc_warm == B_FALSE)
|
||||
size += l2arc_write_boost;
|
||||
|
||||
size += l2arc_log_blk_overhead(size, dev);
|
||||
if (dev->l2ad_vdev->vdev_has_trim && l2arc_trim_ahead > 0) {
|
||||
size += MAX(64 * 1024 * 1024,
|
||||
(size * l2arc_trim_ahead) / 100);
|
||||
}
|
||||
}
|
||||
|
||||
return (size);
|
||||
@@ -9074,22 +9090,9 @@ l2arc_evict(l2arc_dev_t *dev, uint64_t distance, boolean_t all)
|
||||
|
||||
buflist = &dev->l2ad_buflist;
|
||||
|
||||
/*
|
||||
* We need to add in the worst case scenario of log block overhead.
|
||||
*/
|
||||
distance += l2arc_log_blk_overhead(distance, dev);
|
||||
if (vd->vdev_has_trim && l2arc_trim_ahead > 0) {
|
||||
/*
|
||||
* Trim ahead of the write size 64MB or (l2arc_trim_ahead/100)
|
||||
* times the write size, whichever is greater.
|
||||
*/
|
||||
distance += MAX(64 * 1024 * 1024,
|
||||
(distance * l2arc_trim_ahead) / 100);
|
||||
}
|
||||
|
||||
top:
|
||||
rerun = B_FALSE;
|
||||
if (dev->l2ad_hand >= (dev->l2ad_end - distance)) {
|
||||
if (dev->l2ad_hand + distance > dev->l2ad_end) {
|
||||
/*
|
||||
* When there is no space to accommodate upcoming writes,
|
||||
* evict to the end. Then bump the write and evict hands
|
||||
@@ -9283,7 +9286,7 @@ out:
|
||||
*/
|
||||
ASSERT3U(dev->l2ad_hand + distance, <, dev->l2ad_end);
|
||||
if (!dev->l2ad_first)
|
||||
ASSERT3U(dev->l2ad_hand, <, dev->l2ad_evict);
|
||||
ASSERT3U(dev->l2ad_hand, <=, dev->l2ad_evict);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9549,7 +9552,13 @@ l2arc_write_buffers(spa_t *spa, l2arc_dev_t *dev, uint64_t target_sz)
|
||||
uint64_t asize = vdev_psize_to_asize(dev->l2ad_vdev,
|
||||
psize);
|
||||
|
||||
if ((write_asize + asize) > target_sz) {
|
||||
/*
|
||||
* If the allocated size of this buffer plus the max
|
||||
* size for the pending log block exceeds the evicted
|
||||
* target size, terminate writing buffers for this run.
|
||||
*/
|
||||
if (write_asize + asize +
|
||||
sizeof (l2arc_log_blk_phys_t) > target_sz) {
|
||||
full = B_TRUE;
|
||||
mutex_exit(hash_lock);
|
||||
break;
|
||||
@@ -9669,8 +9678,14 @@ l2arc_write_buffers(spa_t *spa, l2arc_dev_t *dev, uint64_t target_sz)
|
||||
* arcstat_l2_{size,asize} kstats are updated
|
||||
* internally.
|
||||
*/
|
||||
if (l2arc_log_blk_insert(dev, hdr))
|
||||
l2arc_log_blk_commit(dev, pio, cb);
|
||||
if (l2arc_log_blk_insert(dev, hdr)) {
|
||||
/*
|
||||
* l2ad_hand will be adjusted in
|
||||
* l2arc_log_blk_commit().
|
||||
*/
|
||||
write_asize +=
|
||||
l2arc_log_blk_commit(dev, pio, cb);
|
||||
}
|
||||
|
||||
zio_nowait(wzio);
|
||||
}
|
||||
@@ -10820,7 +10835,7 @@ l2arc_dev_hdr_update(l2arc_dev_t *dev)
|
||||
* This function allocates some memory to temporarily hold the serialized
|
||||
* buffer to be written. This is then released in l2arc_write_done.
|
||||
*/
|
||||
static void
|
||||
static uint64_t
|
||||
l2arc_log_blk_commit(l2arc_dev_t *dev, zio_t *pio, l2arc_write_callback_t *cb)
|
||||
{
|
||||
l2arc_log_blk_phys_t *lb = &dev->l2ad_log_blk;
|
||||
@@ -10933,6 +10948,8 @@ l2arc_log_blk_commit(l2arc_dev_t *dev, zio_t *pio, l2arc_write_callback_t *cb)
|
||||
dev->l2ad_log_ent_idx = 0;
|
||||
dev->l2ad_log_blk_payload_asize = 0;
|
||||
dev->l2ad_log_blk_payload_start = 0;
|
||||
|
||||
return (asize);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+12
-10
@@ -1533,17 +1533,19 @@ receive_handle_existing_object(const struct receive_writer_arg *rwa,
|
||||
}
|
||||
|
||||
/*
|
||||
* The dmu does not currently support decreasing nlevels
|
||||
* or changing the number of dnode slots on an object. For
|
||||
* non-raw sends, this does not matter and the new object
|
||||
* can just use the previous one's nlevels. For raw sends,
|
||||
* however, the structure of the received dnode (including
|
||||
* nlevels and dnode slots) must match that of the send
|
||||
* side. Therefore, instead of using dmu_object_reclaim(),
|
||||
* we must free the object completely and call
|
||||
* dmu_object_claim_dnsize() instead.
|
||||
* The dmu does not currently support decreasing nlevels or changing
|
||||
* indirect block size if there is already one, same as changing the
|
||||
* number of of dnode slots on an object. For non-raw sends this
|
||||
* does not matter and the new object can just use the previous one's
|
||||
* parameters. For raw sends, however, the structure of the received
|
||||
* dnode (including indirects and dnode slots) must match that of the
|
||||
* send side. Therefore, instead of using dmu_object_reclaim(), we
|
||||
* must free the object completely and call dmu_object_claim_dnsize()
|
||||
* instead.
|
||||
*/
|
||||
if ((rwa->raw && drro->drr_nlevels < doi->doi_indirection) ||
|
||||
if ((rwa->raw && ((doi->doi_indirection > 1 &&
|
||||
indblksz != doi->doi_metadata_block_size) ||
|
||||
drro->drr_nlevels < doi->doi_indirection)) ||
|
||||
dn_slots != doi->doi_dnodesize >> DNODE_SHIFT) {
|
||||
err = dmu_free_long_object(rwa->os, drro->drr_object);
|
||||
if (err != 0)
|
||||
|
||||
+26
-17
@@ -1773,7 +1773,14 @@ dnode_try_claim(objset_t *os, uint64_t object, int slots)
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks if the dnode contains any uncommitted dirty records.
|
||||
* Checks if the dnode itself is dirty, or is carrying any uncommitted records.
|
||||
* It is important to check both conditions, as some operations (eg appending
|
||||
* to a file) can dirty both as a single logical unit, but they are not synced
|
||||
* out atomically, so checking one and not the other can result in an object
|
||||
* appearing to be clean mid-way through a commit.
|
||||
*
|
||||
* Do not change this lightly! If you get it wrong, dmu_offset_next() can
|
||||
* detect a hole where there is really data, leading to silent corruption.
|
||||
*/
|
||||
boolean_t
|
||||
dnode_is_dirty(dnode_t *dn)
|
||||
@@ -1781,7 +1788,8 @@ dnode_is_dirty(dnode_t *dn)
|
||||
mutex_enter(&dn->dn_mtx);
|
||||
|
||||
for (int i = 0; i < TXG_SIZE; i++) {
|
||||
if (multilist_link_active(&dn->dn_dirty_link[i])) {
|
||||
if (multilist_link_active(&dn->dn_dirty_link[i]) ||
|
||||
!list_is_empty(&dn->dn_dirty_records[i])) {
|
||||
mutex_exit(&dn->dn_mtx);
|
||||
return (B_TRUE);
|
||||
}
|
||||
@@ -1891,7 +1899,7 @@ dnode_set_blksz(dnode_t *dn, uint64_t size, int ibs, dmu_tx_t *tx)
|
||||
if (ibs == dn->dn_indblkshift)
|
||||
ibs = 0;
|
||||
|
||||
if (size >> SPA_MINBLOCKSHIFT == dn->dn_datablkszsec && ibs == 0)
|
||||
if (size == dn->dn_datablksz && ibs == 0)
|
||||
return (0);
|
||||
|
||||
rw_enter(&dn->dn_struct_rwlock, RW_WRITER);
|
||||
@@ -1914,24 +1922,25 @@ dnode_set_blksz(dnode_t *dn, uint64_t size, int ibs, dmu_tx_t *tx)
|
||||
if (ibs && dn->dn_nlevels != 1)
|
||||
goto fail;
|
||||
|
||||
/* resize the old block */
|
||||
err = dbuf_hold_impl(dn, 0, 0, TRUE, FALSE, FTAG, &db);
|
||||
if (err == 0) {
|
||||
dbuf_new_size(db, size, tx);
|
||||
} else if (err != ENOENT) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
dnode_setdblksz(dn, size);
|
||||
dnode_setdirty(dn, tx);
|
||||
dn->dn_next_blksz[tx->tx_txg&TXG_MASK] = size;
|
||||
if (size != dn->dn_datablksz) {
|
||||
/* resize the old block */
|
||||
err = dbuf_hold_impl(dn, 0, 0, TRUE, FALSE, FTAG, &db);
|
||||
if (err == 0) {
|
||||
dbuf_new_size(db, size, tx);
|
||||
} else if (err != ENOENT) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
dnode_setdblksz(dn, size);
|
||||
dn->dn_next_blksz[tx->tx_txg & TXG_MASK] = size;
|
||||
if (db)
|
||||
dbuf_rele(db, FTAG);
|
||||
}
|
||||
if (ibs) {
|
||||
dn->dn_indblkshift = ibs;
|
||||
dn->dn_next_indblkshift[tx->tx_txg&TXG_MASK] = ibs;
|
||||
dn->dn_next_indblkshift[tx->tx_txg & TXG_MASK] = ibs;
|
||||
}
|
||||
/* release after we have fixed the blocksize in the dnode */
|
||||
if (db)
|
||||
dbuf_rele(db, FTAG);
|
||||
|
||||
rw_exit(&dn->dn_struct_rwlock);
|
||||
return (0);
|
||||
|
||||
@@ -270,7 +270,7 @@ typedef struct indirect_split {
|
||||
*/
|
||||
indirect_child_t *is_good_child;
|
||||
|
||||
indirect_child_t is_child[1]; /* variable-length */
|
||||
indirect_child_t is_child[];
|
||||
} indirect_split_t;
|
||||
|
||||
/*
|
||||
|
||||
@@ -468,6 +468,9 @@ vdev_config_generate(spa_t *spa, vdev_t *vd, boolean_t getstats,
|
||||
if (vd->vdev_isspare)
|
||||
fnvlist_add_uint64(nv, ZPOOL_CONFIG_IS_SPARE, 1);
|
||||
|
||||
if (flags & VDEV_CONFIG_L2CACHE)
|
||||
fnvlist_add_uint64(nv, ZPOOL_CONFIG_ASHIFT, vd->vdev_ashift);
|
||||
|
||||
if (!(flags & (VDEV_CONFIG_SPARE | VDEV_CONFIG_L2CACHE)) &&
|
||||
vd == vd->vdev_top) {
|
||||
fnvlist_add_uint64(nv, ZPOOL_CONFIG_METASLAB_ARRAY,
|
||||
|
||||
+19
-9
@@ -23,6 +23,7 @@
|
||||
* Copyright (c) 2016 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2019 by Lawrence Livermore National Security, LLC.
|
||||
* Copyright (c) 2021 Hewlett Packard Enterprise Development LP
|
||||
* Copyright 2023 RackTop Systems, Inc.
|
||||
*/
|
||||
|
||||
#include <sys/spa.h>
|
||||
@@ -572,6 +573,7 @@ vdev_trim_ranges(trim_args_t *ta)
|
||||
uint64_t extent_bytes_max = ta->trim_extent_bytes_max;
|
||||
uint64_t extent_bytes_min = ta->trim_extent_bytes_min;
|
||||
spa_t *spa = vd->vdev_spa;
|
||||
int error = 0;
|
||||
|
||||
ta->trim_start_time = gethrtime();
|
||||
ta->trim_bytes_done = 0;
|
||||
@@ -591,19 +593,32 @@ vdev_trim_ranges(trim_args_t *ta)
|
||||
uint64_t writes_required = ((size - 1) / extent_bytes_max) + 1;
|
||||
|
||||
for (uint64_t w = 0; w < writes_required; w++) {
|
||||
int error;
|
||||
|
||||
error = vdev_trim_range(ta, VDEV_LABEL_START_SIZE +
|
||||
rs_get_start(rs, ta->trim_tree) +
|
||||
(w *extent_bytes_max), MIN(size -
|
||||
(w * extent_bytes_max), extent_bytes_max));
|
||||
if (error != 0) {
|
||||
return (error);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
done:
|
||||
/*
|
||||
* Make sure all TRIMs for this metaslab have completed before
|
||||
* returning. TRIM zios have lower priority over regular or syncing
|
||||
* zios, so all TRIM zios for this metaslab must complete before the
|
||||
* metaslab is re-enabled. Otherwise it's possible write zios to
|
||||
* this metaslab could cut ahead of still queued TRIM zios for this
|
||||
* metaslab causing corruption if the ranges overlap.
|
||||
*/
|
||||
mutex_enter(&vd->vdev_trim_io_lock);
|
||||
while (vd->vdev_trim_inflight[0] > 0) {
|
||||
cv_wait(&vd->vdev_trim_io_cv, &vd->vdev_trim_io_lock);
|
||||
}
|
||||
mutex_exit(&vd->vdev_trim_io_lock);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -922,11 +937,6 @@ vdev_trim_thread(void *arg)
|
||||
}
|
||||
|
||||
spa_config_exit(spa, SCL_CONFIG, FTAG);
|
||||
mutex_enter(&vd->vdev_trim_io_lock);
|
||||
while (vd->vdev_trim_inflight[0] > 0) {
|
||||
cv_wait(&vd->vdev_trim_io_cv, &vd->vdev_trim_io_lock);
|
||||
}
|
||||
mutex_exit(&vd->vdev_trim_io_lock);
|
||||
|
||||
range_tree_destroy(ta.trim_tree);
|
||||
|
||||
|
||||
+6
-2
@@ -418,12 +418,16 @@ zil_parse(zilog_t *zilog, zil_parse_blk_func_t *parse_blk_func,
|
||||
lr_t *lr = (lr_t *)lrp;
|
||||
reclen = lr->lrc_reclen;
|
||||
ASSERT3U(reclen, >=, sizeof (lr_t));
|
||||
if (lr->lrc_seq > claim_lr_seq)
|
||||
if (lr->lrc_seq > claim_lr_seq) {
|
||||
arc_buf_destroy(abuf, &abuf);
|
||||
goto done;
|
||||
}
|
||||
|
||||
error = parse_lr_func(zilog, lr, arg, txg);
|
||||
if (error != 0)
|
||||
if (error != 0) {
|
||||
arc_buf_destroy(abuf, &abuf);
|
||||
goto done;
|
||||
}
|
||||
ASSERT3U(max_lr_seq, <, lr->lrc_seq);
|
||||
max_lr_seq = lr->lrc_seq;
|
||||
lr_count++;
|
||||
|
||||
@@ -42,4 +42,4 @@ gensymbols:
|
||||
@OBJDUMP@ -t lib/zstd.o | awk '$$2 == "g" && !/ zfs_/ {print "#define\t" $$6 " zfs_" $$6}' | sort >> include/zstd_compat_wrapper.h
|
||||
|
||||
checksymbols:
|
||||
@OBJDUMP@ -t lib/zstd.o | awk '/file format/ {print} $$2 == "g" && !/ zfs_/ {++ret; print} END {exit ret}'
|
||||
@OBJDUMP@ -t lib/zstd.o | awk '/file format/ {print} $$2 == "g" && (!/ zfs_/ && !/ __pfx_zfs_/) {++ret; print} END {exit ret}'
|
||||
|
||||
@@ -68,46 +68,9 @@ fi
|
||||
%defattr(-,root,root)
|
||||
/usr/src/%{module}-%{version}
|
||||
|
||||
%post
|
||||
for POSTINST in /usr/lib/dkms/common.postinst; do
|
||||
if [ -f $POSTINST ]; then
|
||||
$POSTINST %{module} %{version}
|
||||
exit $?
|
||||
fi
|
||||
echo "WARNING: $POSTINST does not exist."
|
||||
done
|
||||
echo -e "ERROR: DKMS version is too old and %{module} was not"
|
||||
echo -e "built with legacy DKMS support."
|
||||
echo -e "You must either rebuild %{module} with legacy postinst"
|
||||
echo -e "support or upgrade DKMS to a more current version."
|
||||
exit 1
|
||||
|
||||
%preun
|
||||
# Are we doing an upgrade?
|
||||
if [ "$1" = "1" -o "$1" = "upgrade" ] ; then
|
||||
# Yes we are. Are we upgrading to a new ZFS version?
|
||||
NEWEST_VER=$(dkms status zfs | tr -d , | sort -r -V | awk '/installed/{print $2; exit}')
|
||||
if [ "$NEWEST_VER" != "%{version}" ] ; then
|
||||
# Yes, it's a new ZFS version. We'll uninstall the old module
|
||||
# later on in this script.
|
||||
true
|
||||
else
|
||||
# No, it's probably an upgrade of the same ZFS version
|
||||
# to a new distro (zfs-dkms-0.7.12.fc28->zfs-dkms-0.7.12.fc29).
|
||||
# Don't remove our modules, since the rebuild for the new
|
||||
# distro will automatically delete the old modules.
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
dkms remove -m %{module} -v %{version} --all
|
||||
|
||||
%posttrans
|
||||
/usr/lib/dkms/common.postinst %{module} %{version}
|
||||
|
||||
# If we're here then we're doing an uninstall (not upgrade).
|
||||
CONFIG_H="/var/lib/dkms/%{module}/%{version}/*/*/%{module}_config.h"
|
||||
SPEC_META_ALIAS="@PACKAGE@-@VERSION@-@RELEASE@"
|
||||
DKMS_META_ALIAS=`cat $CONFIG_H 2>/dev/null |
|
||||
awk -F'"' '/META_ALIAS\s+"/ { print $2; exit 0 }'`
|
||||
if [ "$SPEC_META_ALIAS" = "$DKMS_META_ALIAS" ]; then
|
||||
echo -e
|
||||
echo -e "Uninstall of %{module} module ($SPEC_META_ALIAS) beginning:"
|
||||
dkms remove -m %{module} -v %{version} --all %{!?not_rpm:--rpm_safe_upgrade}
|
||||
fi
|
||||
exit 0
|
||||
|
||||
@@ -164,8 +164,8 @@ summary = {
|
||||
# reasons listed above can be used.
|
||||
#
|
||||
known = {
|
||||
'casenorm/mixed_none_lookup_ci': ['FAIL', '7633'],
|
||||
'casenorm/mixed_formd_lookup_ci': ['FAIL', '7633'],
|
||||
'casenorm/mixed_none_lookup_ci': ['FAIL', 7633],
|
||||
'casenorm/mixed_formd_lookup_ci': ['FAIL', 7633],
|
||||
'cli_root/zfs_unshare/zfs_unshare_002_pos': ['SKIP', na_reason],
|
||||
'cli_root/zfs_unshare/zfs_unshare_006_pos': ['SKIP', na_reason],
|
||||
'cli_root/zpool_import/import_rewind_device_replaced':
|
||||
@@ -175,7 +175,7 @@ known = {
|
||||
'privilege/setup': ['SKIP', na_reason],
|
||||
'refreserv/refreserv_004_pos': ['FAIL', known_reason],
|
||||
'rootpool/setup': ['SKIP', na_reason],
|
||||
'rsend/rsend_008_pos': ['SKIP', '6066'],
|
||||
'rsend/rsend_008_pos': ['SKIP', 6066],
|
||||
'vdev_zaps/vdev_zaps_007_pos': ['FAIL', known_reason],
|
||||
}
|
||||
|
||||
@@ -193,10 +193,10 @@ if sys.platform.startswith('freebsd'):
|
||||
})
|
||||
elif sys.platform.startswith('linux'):
|
||||
known.update({
|
||||
'casenorm/mixed_formd_lookup': ['FAIL', '7633'],
|
||||
'casenorm/mixed_formd_delete': ['FAIL', '7633'],
|
||||
'casenorm/sensitive_formd_lookup': ['FAIL', '7633'],
|
||||
'casenorm/sensitive_formd_delete': ['FAIL', '7633'],
|
||||
'casenorm/mixed_formd_lookup': ['FAIL', 7633],
|
||||
'casenorm/mixed_formd_delete': ['FAIL', 7633],
|
||||
'casenorm/sensitive_formd_lookup': ['FAIL', 7633],
|
||||
'casenorm/sensitive_formd_delete': ['FAIL', 7633],
|
||||
'removal/removal_with_zdb': ['SKIP', known_reason],
|
||||
})
|
||||
|
||||
@@ -220,49 +220,49 @@ maybe = {
|
||||
'cli_root/zfs_destroy/zfs_destroy_dev_removal_condense':
|
||||
['FAIL', known_reason],
|
||||
'cli_root/zfs_get/zfs_get_004_pos': ['FAIL', known_reason],
|
||||
'cli_root/zfs_get/zfs_get_009_pos': ['SKIP', '5479'],
|
||||
'cli_root/zfs_get/zfs_get_009_pos': ['SKIP', 5479],
|
||||
'cli_root/zfs_rollback/zfs_rollback_001_pos': ['FAIL', known_reason],
|
||||
'cli_root/zfs_rollback/zfs_rollback_002_pos': ['FAIL', known_reason],
|
||||
'cli_root/zfs_share/setup': ['SKIP', share_reason],
|
||||
'cli_root/zfs_snapshot/zfs_snapshot_002_neg': ['FAIL', known_reason],
|
||||
'cli_root/zfs_unshare/setup': ['SKIP', share_reason],
|
||||
'cli_root/zpool_add/zpool_add_004_pos': ['FAIL', known_reason],
|
||||
'cli_root/zpool_destroy/zpool_destroy_001_pos': ['SKIP', '6145'],
|
||||
'cli_root/zpool_import/zpool_import_missing_003_pos': ['SKIP', '6839'],
|
||||
'cli_root/zpool_destroy/zpool_destroy_001_pos': ['SKIP', 6145],
|
||||
'cli_root/zpool_import/zpool_import_missing_003_pos': ['SKIP', 6839],
|
||||
'cli_root/zpool_initialize/zpool_initialize_import_export':
|
||||
['FAIL', '11948'],
|
||||
['FAIL', 11948],
|
||||
'cli_root/zpool_labelclear/zpool_labelclear_removed':
|
||||
['FAIL', known_reason],
|
||||
'cli_root/zpool_trim/setup': ['SKIP', trim_reason],
|
||||
'cli_root/zpool_upgrade/zpool_upgrade_004_pos': ['FAIL', '6141'],
|
||||
'cli_root/zpool_upgrade/zpool_upgrade_004_pos': ['FAIL', 6141],
|
||||
'delegate/setup': ['SKIP', exec_reason],
|
||||
'fallocate/fallocate_punch-hole': ['SKIP', fspacectl_reason],
|
||||
'history/history_004_pos': ['FAIL', '7026'],
|
||||
'history/history_005_neg': ['FAIL', '6680'],
|
||||
'history/history_006_neg': ['FAIL', '5657'],
|
||||
'history/history_004_pos': ['FAIL', 7026],
|
||||
'history/history_005_neg': ['FAIL', 6680],
|
||||
'history/history_006_neg': ['FAIL', 5657],
|
||||
'history/history_008_pos': ['FAIL', known_reason],
|
||||
'history/history_010_pos': ['SKIP', exec_reason],
|
||||
'io/mmap': ['SKIP', fio_reason],
|
||||
'largest_pool/largest_pool_001_pos': ['FAIL', known_reason],
|
||||
'mmp/mmp_on_uberblocks': ['FAIL', known_reason],
|
||||
'pyzfs/pyzfs_unittest': ['SKIP', python_deps_reason],
|
||||
'pool_checkpoint/checkpoint_discard_busy': ['FAIL', '11946'],
|
||||
'pool_checkpoint/checkpoint_discard_busy': ['FAIL', 11946],
|
||||
'pam/setup': ['SKIP', "pamtester might be not available"],
|
||||
'projectquota/setup': ['SKIP', exec_reason],
|
||||
'removal/removal_condense_export': ['FAIL', known_reason],
|
||||
'reservation/reservation_008_pos': ['FAIL', '7741'],
|
||||
'reservation/reservation_018_pos': ['FAIL', '5642'],
|
||||
'reservation/reservation_008_pos': ['FAIL', 7741],
|
||||
'reservation/reservation_018_pos': ['FAIL', 5642],
|
||||
'snapshot/clone_001_pos': ['FAIL', known_reason],
|
||||
'snapshot/snapshot_009_pos': ['FAIL', '7961'],
|
||||
'snapshot/snapshot_010_pos': ['FAIL', '7961'],
|
||||
'snapused/snapused_004_pos': ['FAIL', '5513'],
|
||||
'snapshot/snapshot_009_pos': ['FAIL', 7961],
|
||||
'snapshot/snapshot_010_pos': ['FAIL', 7961],
|
||||
'snapused/snapused_004_pos': ['FAIL', 5513],
|
||||
'tmpfile/setup': ['SKIP', tmpfile_reason],
|
||||
'trim/setup': ['SKIP', trim_reason],
|
||||
'upgrade/upgrade_projectquota_001_pos': ['SKIP', project_id_reason],
|
||||
'user_namespace/setup': ['SKIP', user_ns_reason],
|
||||
'userquota/setup': ['SKIP', exec_reason],
|
||||
'vdev_zaps/vdev_zaps_004_pos': ['FAIL', known_reason],
|
||||
'zvol/zvol_ENOSPC/zvol_ENOSPC_001_pos': ['FAIL', '5848'],
|
||||
'zvol/zvol_ENOSPC/zvol_ENOSPC_001_pos': ['FAIL', 5848],
|
||||
}
|
||||
|
||||
if sys.platform.startswith('freebsd'):
|
||||
@@ -274,11 +274,11 @@ if sys.platform.startswith('freebsd'):
|
||||
['FAIL', known_reason],
|
||||
'cli_root/zpool_import/zpool_import_012_pos': ['FAIL', known_reason],
|
||||
'delegate/zfs_allow_003_pos': ['FAIL', known_reason],
|
||||
'inheritance/inherit_001_pos': ['FAIL', '11829'],
|
||||
'inheritance/inherit_001_pos': ['FAIL', 11829],
|
||||
'resilver/resilver_restart_001': ['FAIL', known_reason],
|
||||
'pool_checkpoint/checkpoint_big_rewind': ['FAIL', '12622'],
|
||||
'pool_checkpoint/checkpoint_indirect': ['FAIL', '12623'],
|
||||
'snapshot/snapshot_002_pos': ['FAIL', '14831'],
|
||||
'pool_checkpoint/checkpoint_big_rewind': ['FAIL', 12622],
|
||||
'pool_checkpoint/checkpoint_indirect': ['FAIL', 12623],
|
||||
'snapshot/snapshot_002_pos': ['FAIL', 14831],
|
||||
})
|
||||
elif sys.platform.startswith('linux'):
|
||||
maybe.update({
|
||||
@@ -296,7 +296,7 @@ elif sys.platform.startswith('linux'):
|
||||
'mmp/mmp_active_import': ['FAIL', known_reason],
|
||||
'mmp/mmp_exported_import': ['FAIL', known_reason],
|
||||
'mmp/mmp_inactive_import': ['FAIL', known_reason],
|
||||
'zvol/zvol_misc/zvol_misc_snapdev': ['FAIL', '12621'],
|
||||
'zvol/zvol_misc/zvol_misc_snapdev': ['FAIL', 12621],
|
||||
'zvol/zvol_misc/zvol_misc_volmode': ['FAIL', known_reason],
|
||||
})
|
||||
|
||||
@@ -327,7 +327,7 @@ if os.environ.get('CI') == 'true':
|
||||
})
|
||||
|
||||
maybe.update({
|
||||
'events/events_002_pos': ['FAIL', '11546'],
|
||||
'events/events_002_pos': ['FAIL', 11546],
|
||||
})
|
||||
elif sys.platform.startswith('linux'):
|
||||
maybe.update({
|
||||
@@ -451,13 +451,13 @@ if __name__ == "__main__":
|
||||
if test in known:
|
||||
if known[test][1] == na_reason:
|
||||
continue
|
||||
elif known[test][1].isdigit():
|
||||
expect = issue_url + known[test][1]
|
||||
elif isinstance(known[test][1], int):
|
||||
expect = f"{issue_url}{known[test][1]}"
|
||||
else:
|
||||
expect = known[test][1]
|
||||
elif test in maybe:
|
||||
if maybe[test][1].isdigit():
|
||||
expect = issue_url + maybe[test][1]
|
||||
if isinstance(maybe[test][1], int):
|
||||
expect = f"{issue_url}{maybe[test][1]}"
|
||||
else:
|
||||
expect = maybe[test][1]
|
||||
elif setup in known and known[setup][0] == "SKIP" and setup != test:
|
||||
|
||||
@@ -4268,7 +4268,7 @@ function arcstat_quiescence # stat echo
|
||||
|
||||
while $do_once || [ $stat1 -ne $stat2 ] || [ $stat2 -eq 0 ]; do
|
||||
typeset stat1=$(get_arcstat $stat)
|
||||
sleep 2
|
||||
sleep 0.5
|
||||
typeset stat2=$(get_arcstat $stat)
|
||||
do_once=false
|
||||
done
|
||||
|
||||
@@ -27,15 +27,14 @@
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Create pool with a cache device.
|
||||
# 2. Export and re-import pool without writing any data.
|
||||
# 3. Create a random file in that pool and random read for 10 sec.
|
||||
# 4. Export pool.
|
||||
# 5. Read the amount of log blocks written from the header of the
|
||||
# 2. Create a random file in that pool and random read for 10 sec.
|
||||
# 3. Export pool.
|
||||
# 4. Read the amount of log blocks written from the header of the
|
||||
# L2ARC device.
|
||||
# 6. Import pool.
|
||||
# 7. Read the amount of log blocks rebuilt in arcstats and compare to
|
||||
# 5. Import pool.
|
||||
# 6. Read the amount of log blocks rebuilt in arcstats and compare to
|
||||
# (5).
|
||||
# 8. Check if the labels of the L2ARC device are intact.
|
||||
# 7. Check if the labels of the L2ARC device are intact.
|
||||
#
|
||||
# * We can predict the minimum bytes of L2ARC restored if we subtract
|
||||
# from the effective size of the cache device the bytes l2arc_evict()
|
||||
@@ -75,10 +74,8 @@ export FILE_SIZE=$(( floor($fill_mb / $NUMJOBS) ))M
|
||||
|
||||
log_must truncate -s ${cache_sz}M $VDEV_CACHE
|
||||
|
||||
log_must zpool create -f $TESTPOOL $VDEV cache $VDEV_CACHE
|
||||
|
||||
log_must zpool export $TESTPOOL
|
||||
log_must zpool import -d $VDIR $TESTPOOL
|
||||
log_must zpool create -f -o ashift=12 $TESTPOOL $VDEV
|
||||
log_must zpool add $TESTPOOL cache $VDEV_CACHE
|
||||
|
||||
log_must fio $FIO_SCRIPTS/mkfiles.fio
|
||||
log_must fio $FIO_SCRIPTS/random_reads.fio
|
||||
|
||||
@@ -65,7 +65,7 @@ typeset VDEV_MIN_MB=$((MINVDEVSIZE * 0.30 / 1024 / 1024))
|
||||
log_must zpool create -f $TESTPOOL $TRIM_VDEV1 cache $TRIM_VDEV2
|
||||
verify_vdevs "-le" "$VDEV_MIN_MB" $TRIM_VDEV2
|
||||
|
||||
typeset fill_mb=$(( floor(2 * MINVDEVSIZE) ))
|
||||
typeset fill_mb=$(( floor(3 * MINVDEVSIZE) ))
|
||||
export DIRECTORY=/$TESTPOOL
|
||||
export NUMJOBS=1
|
||||
export FILE_SIZE=${fill_mb}
|
||||
|
||||
Reference in New Issue
Block a user