diff options
author | Matt Macy <mmacy@FreeBSD.org> | 2020-10-01 23:09:24 +0000 |
---|---|---|
committer | Matt Macy <mmacy@FreeBSD.org> | 2020-10-01 23:09:24 +0000 |
commit | e2228bd99047bb6a0cef0da931147b1f28f155c2 (patch) | |
tree | 2859f65ec0723fe7424b97206b84c5d760d12b1c /module/os | |
parent | 01ea34f1d8bc20a76845a15e968388679693ee44 (diff) | |
download | src-e2228bd99047bb6a0cef0da931147b1f28f155c2.tar.gz src-e2228bd99047bb6a0cef0da931147b1f28f155c2.zip |
Update OpenZFS to 2.0.0-rc3-gfc5966vendor/openzfs/2.0-rc3-gfc5966
Notes
Notes:
svn path=/vendor-sys/openzfs/dist/; revision=366348
svn path=/vendor-sys/openzfs/2.0-rc3-gfc5966/; revision=366349; tag=vendor/openzfs/2.0-rc3-gfc5966
Diffstat (limited to 'module/os')
-rw-r--r-- | module/os/freebsd/spl/spl_kstat.c | 289 | ||||
-rw-r--r-- | module/os/freebsd/spl/spl_procfs_list.c | 86 | ||||
-rw-r--r-- | module/os/freebsd/spl/spl_taskq.c | 4 | ||||
-rw-r--r-- | module/os/freebsd/zfs/kmod_core.c | 4 | ||||
-rw-r--r-- | module/os/freebsd/zfs/sysctl_os.c | 17 | ||||
-rw-r--r-- | module/os/freebsd/zfs/zfs_ioctl_compat.c | 4 | ||||
-rw-r--r-- | module/os/freebsd/zfs/zfs_vfsops.c | 4 | ||||
-rw-r--r-- | module/os/freebsd/zfs/zio_crypt.c | 221 | ||||
-rw-r--r-- | module/os/linux/spl/spl-procfs-list.c | 22 | ||||
-rw-r--r-- | module/os/linux/zfs/vdev_disk.c | 10 | ||||
-rw-r--r-- | module/os/linux/zfs/zfs_debug.c | 1 |
11 files changed, 389 insertions, 273 deletions
diff --git a/module/os/freebsd/spl/spl_kstat.c b/module/os/freebsd/spl/spl_kstat.c index df2da2d602b6..4cc77e20a4eb 100644 --- a/module/os/freebsd/spl/spl_kstat.c +++ b/module/os/freebsd/spl/spl_kstat.c @@ -55,6 +55,17 @@ __kstat_set_raw_ops(kstat_t *ksp, ksp->ks_raw_ops.addr = addr; } +void +__kstat_set_seq_raw_ops(kstat_t *ksp, + int (*headers)(struct seq_file *f), + int (*data)(char *buf, size_t size, void *data), + void *(*addr)(kstat_t *ksp, loff_t index)) +{ + ksp->ks_raw_ops.seq_headers = headers; + ksp->ks_raw_ops.data = data; + ksp->ks_raw_ops.addr = addr; +} + static int kstat_default_update(kstat_t *ksp, int rw) { @@ -160,7 +171,7 @@ kstat_sysctl_raw(SYSCTL_HANDLER_ARGS) void *data; kstat_t *ksp = arg1; void *(*addr_op)(kstat_t *ksp, loff_t index); - int n, rc = 0; + int n, has_header, rc = 0; sb = sbuf_new_auto(); if (sb == NULL) @@ -180,14 +191,25 @@ kstat_sysctl_raw(SYSCTL_HANDLER_ARGS) ksp->ks_raw_buf = malloc(PAGE_SIZE, M_TEMP, M_WAITOK); n = 0; + has_header = (ksp->ks_raw_ops.headers || + ksp->ks_raw_ops.seq_headers); + restart_headers: if (ksp->ks_raw_ops.headers) { rc = ksp->ks_raw_ops.headers( ksp->ks_raw_buf, ksp->ks_raw_bufsize); + } else if (ksp->ks_raw_ops.seq_headers) { + struct seq_file f; + + f.sf_buf = ksp->ks_raw_buf; + f.sf_size = ksp->ks_raw_bufsize; + rc = ksp->ks_raw_ops.seq_headers(&f); + } + if (has_header) { if (rc == ENOMEM && !kstat_resize_raw(ksp)) goto restart_headers; if (rc == 0) - sbuf_printf(sb, "%s", ksp->ks_raw_buf); + sbuf_printf(sb, "\n%s", ksp->ks_raw_buf); } while ((data = addr_op(ksp, n)) != NULL) { @@ -220,16 +242,21 @@ kstat_t * __kstat_create(const char *module, int instance, const char *name, const char *class, uchar_t ks_type, uint_t ks_ndata, uchar_t flags) { + char buf[KSTAT_STRLEN]; struct sysctl_oid *root; kstat_t *ksp; + char *pool; KASSERT(instance == 0, ("instance=%d", instance)); if ((ks_type == KSTAT_TYPE_INTR) || (ks_type == KSTAT_TYPE_IO)) ASSERT(ks_ndata == 1); + if (class == NULL) + class = "misc"; + /* - * Allocate the main structure. We don't need to copy module/class/name - * stuff in here, because it is only used for sysctl node creation + * Allocate the main structure. We don't need to keep a copy of + * module in here, because it is only used for sysctl node creation * done in this function. */ ksp = malloc(sizeof (*ksp), M_KSTAT, M_WAITOK|M_ZERO); @@ -237,8 +264,8 @@ __kstat_create(const char *module, int instance, const char *name, ksp->ks_crtime = gethrtime(); ksp->ks_snaptime = ksp->ks_crtime; ksp->ks_instance = instance; - strncpy(ksp->ks_name, name, KSTAT_STRLEN); - strncpy(ksp->ks_class, class, KSTAT_STRLEN); + (void) strlcpy(ksp->ks_name, name, KSTAT_STRLEN); + (void) strlcpy(ksp->ks_class, class, KSTAT_STRLEN); ksp->ks_type = ks_type; ksp->ks_flags = flags; ksp->ks_update = kstat_default_update; @@ -247,28 +274,28 @@ __kstat_create(const char *module, int instance, const char *name, ksp->ks_lock = &ksp->ks_private_lock; switch (ksp->ks_type) { - case KSTAT_TYPE_RAW: - ksp->ks_ndata = 1; - ksp->ks_data_size = ks_ndata; - break; - case KSTAT_TYPE_NAMED: - ksp->ks_ndata = ks_ndata; - ksp->ks_data_size = ks_ndata * sizeof (kstat_named_t); - break; - case KSTAT_TYPE_INTR: - ksp->ks_ndata = ks_ndata; - ksp->ks_data_size = ks_ndata * sizeof (kstat_intr_t); - break; - case KSTAT_TYPE_IO: - ksp->ks_ndata = ks_ndata; - ksp->ks_data_size = ks_ndata * sizeof (kstat_io_t); - break; - case KSTAT_TYPE_TIMER: - ksp->ks_ndata = ks_ndata; - ksp->ks_data_size = ks_ndata * sizeof (kstat_timer_t); - break; - default: - panic("Undefined kstat type %d\n", ksp->ks_type); + case KSTAT_TYPE_RAW: + ksp->ks_ndata = 1; + ksp->ks_data_size = ks_ndata; + break; + case KSTAT_TYPE_NAMED: + ksp->ks_ndata = ks_ndata; + ksp->ks_data_size = ks_ndata * sizeof (kstat_named_t); + break; + case KSTAT_TYPE_INTR: + ksp->ks_ndata = ks_ndata; + ksp->ks_data_size = ks_ndata * sizeof (kstat_intr_t); + break; + case KSTAT_TYPE_IO: + ksp->ks_ndata = ks_ndata; + ksp->ks_data_size = ks_ndata * sizeof (kstat_io_t); + break; + case KSTAT_TYPE_TIMER: + ksp->ks_ndata = ks_ndata; + ksp->ks_data_size = ks_ndata * sizeof (kstat_timer_t); + break; + default: + panic("Undefined kstat type %d\n", ksp->ks_type); } if (ksp->ks_flags & KSTAT_FLAG_VIRTUAL) { @@ -280,10 +307,22 @@ __kstat_create(const char *module, int instance, const char *name, ksp = NULL; } } + + /* + * Some kstats use a module name like "zfs/poolname" to distinguish a + * set of kstats belonging to a specific pool. Split on '/' to add an + * extra node for the pool name if needed. + */ + (void) strlcpy(buf, module, KSTAT_STRLEN); + module = buf; + pool = strchr(module, '/'); + if (pool != NULL) + *pool++ = '\0'; + /* * Create sysctl tree for those statistics: * - * kstat.<module>.<class>.<name>. + * kstat.<module>[.<pool>].<class>.<name> */ sysctl_ctx_init(&ksp->ks_sysctl_ctx); root = SYSCTL_ADD_NODE(&ksp->ks_sysctl_ctx, @@ -295,11 +334,26 @@ __kstat_create(const char *module, int instance, const char *name, free(ksp, M_KSTAT); return (NULL); } + if (pool != NULL) { + root = SYSCTL_ADD_NODE(&ksp->ks_sysctl_ctx, + SYSCTL_CHILDREN(root), OID_AUTO, pool, CTLFLAG_RW, 0, ""); + if (root == NULL) { + printf("%s: Cannot create kstat.%s.%s tree!\n", + __func__, module, pool); + sysctl_ctx_free(&ksp->ks_sysctl_ctx); + free(ksp, M_KSTAT); + return (NULL); + } + } root = SYSCTL_ADD_NODE(&ksp->ks_sysctl_ctx, SYSCTL_CHILDREN(root), OID_AUTO, class, CTLFLAG_RW, 0, ""); if (root == NULL) { - printf("%s: Cannot create kstat.%s.%s tree!\n", __func__, - module, class); + if (pool != NULL) + printf("%s: Cannot create kstat.%s.%s.%s tree!\n", + __func__, module, pool, class); + else + printf("%s: Cannot create kstat.%s.%s tree!\n", + __func__, module, class); sysctl_ctx_free(&ksp->ks_sysctl_ctx); free(ksp, M_KSTAT); return (NULL); @@ -309,8 +363,13 @@ __kstat_create(const char *module, int instance, const char *name, SYSCTL_CHILDREN(root), OID_AUTO, name, CTLFLAG_RW, 0, ""); if (root == NULL) { - printf("%s: Cannot create kstat.%s.%s.%s tree!\n", - __func__, module, class, name); + if (pool != NULL) + printf("%s: Cannot create kstat.%s.%s.%s.%s " + "tree!\n", __func__, module, pool, class, + name); + else + printf("%s: Cannot create kstat.%s.%s.%s " + "tree!\n", __func__, module, class, name); sysctl_ctx_free(&ksp->ks_sysctl_ctx); free(ksp, M_KSTAT); return (NULL); @@ -342,64 +401,62 @@ kstat_install_named(kstat_t *ksp) namelast = ksent->name; } switch (typelast) { - case KSTAT_DATA_CHAR: - /* Not Implemented */ - break; - case KSTAT_DATA_INT32: - SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx, - SYSCTL_CHILDREN(ksp->ks_sysctl_root), - OID_AUTO, namelast, - CTLTYPE_S32 | CTLFLAG_RD, ksp, i, - kstat_sysctl, "I", namelast); - break; - case KSTAT_DATA_UINT32: - SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx, - SYSCTL_CHILDREN(ksp->ks_sysctl_root), - OID_AUTO, namelast, - CTLTYPE_U32 | CTLFLAG_RD, ksp, i, - kstat_sysctl, "IU", namelast); - break; - case KSTAT_DATA_INT64: - SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx, - SYSCTL_CHILDREN(ksp->ks_sysctl_root), - OID_AUTO, namelast, - CTLTYPE_S64 | CTLFLAG_RD, ksp, i, - kstat_sysctl, "Q", namelast); - break; - case KSTAT_DATA_UINT64: - SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx, - SYSCTL_CHILDREN(ksp->ks_sysctl_root), - OID_AUTO, namelast, - CTLTYPE_U64 | CTLFLAG_RD, ksp, i, - kstat_sysctl, "QU", namelast); - break; - case KSTAT_DATA_LONG: - SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx, - SYSCTL_CHILDREN(ksp->ks_sysctl_root), - OID_AUTO, namelast, - CTLTYPE_LONG | CTLFLAG_RD, ksp, i, - kstat_sysctl, "L", namelast); - break; - case KSTAT_DATA_ULONG: - SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx, - SYSCTL_CHILDREN(ksp->ks_sysctl_root), - OID_AUTO, namelast, - CTLTYPE_ULONG | CTLFLAG_RD, ksp, i, - kstat_sysctl, "LU", namelast); - break; - case KSTAT_DATA_STRING: - SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx, - SYSCTL_CHILDREN(ksp->ks_sysctl_root), - OID_AUTO, namelast, - CTLTYPE_STRING | CTLFLAG_RD, ksp, i, - kstat_sysctl_string, "A", namelast); - break; - default: - panic("unsupported type: %d", typelast); + case KSTAT_DATA_CHAR: + /* Not Implemented */ + break; + case KSTAT_DATA_INT32: + SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx, + SYSCTL_CHILDREN(ksp->ks_sysctl_root), + OID_AUTO, namelast, + CTLTYPE_S32 | CTLFLAG_RD | CTLFLAG_MPSAFE, + ksp, i, kstat_sysctl, "I", namelast); + break; + case KSTAT_DATA_UINT32: + SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx, + SYSCTL_CHILDREN(ksp->ks_sysctl_root), + OID_AUTO, namelast, + CTLTYPE_U32 | CTLFLAG_RD | CTLFLAG_MPSAFE, + ksp, i, kstat_sysctl, "IU", namelast); + break; + case KSTAT_DATA_INT64: + SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx, + SYSCTL_CHILDREN(ksp->ks_sysctl_root), + OID_AUTO, namelast, + CTLTYPE_S64 | CTLFLAG_RD | CTLFLAG_MPSAFE, + ksp, i, kstat_sysctl, "Q", namelast); + break; + case KSTAT_DATA_UINT64: + SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx, + SYSCTL_CHILDREN(ksp->ks_sysctl_root), + OID_AUTO, namelast, + CTLTYPE_U64 | CTLFLAG_RD | CTLFLAG_MPSAFE, + ksp, i, kstat_sysctl, "QU", namelast); + break; + case KSTAT_DATA_LONG: + SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx, + SYSCTL_CHILDREN(ksp->ks_sysctl_root), + OID_AUTO, namelast, + CTLTYPE_LONG | CTLFLAG_RD | CTLFLAG_MPSAFE, + ksp, i, kstat_sysctl, "L", namelast); + break; + case KSTAT_DATA_ULONG: + SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx, + SYSCTL_CHILDREN(ksp->ks_sysctl_root), + OID_AUTO, namelast, + CTLTYPE_ULONG | CTLFLAG_RD | CTLFLAG_MPSAFE, + ksp, i, kstat_sysctl, "LU", namelast); + break; + case KSTAT_DATA_STRING: + SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx, + SYSCTL_CHILDREN(ksp->ks_sysctl_root), + OID_AUTO, namelast, + CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, + ksp, i, kstat_sysctl_string, "A", namelast); + break; + default: + panic("unsupported type: %d", typelast); } - } - } void @@ -411,39 +468,37 @@ kstat_install(kstat_t *ksp) VERIFY(ksp->ks_type == KSTAT_TYPE_RAW); switch (ksp->ks_type) { - case KSTAT_TYPE_NAMED: - return (kstat_install_named(ksp)); - break; - case KSTAT_TYPE_RAW: - if (ksp->ks_raw_ops.data) { - root = SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx, - SYSCTL_CHILDREN(ksp->ks_sysctl_root), - OID_AUTO, ksp->ks_name, - CTLTYPE_STRING | CTLFLAG_RD, ksp, 0, - kstat_sysctl_raw, "A", ksp->ks_name); - } else { - root = SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx, - SYSCTL_CHILDREN(ksp->ks_sysctl_root), - OID_AUTO, ksp->ks_name, - CTLTYPE_OPAQUE | CTLFLAG_RD, ksp, 0, - kstat_sysctl_raw, "", ksp->ks_name); - } - VERIFY(root != NULL); - break; - case KSTAT_TYPE_IO: + case KSTAT_TYPE_NAMED: + return (kstat_install_named(ksp)); + case KSTAT_TYPE_RAW: + if (ksp->ks_raw_ops.data) { root = SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx, SYSCTL_CHILDREN(ksp->ks_sysctl_root), OID_AUTO, ksp->ks_name, - CTLTYPE_STRING | CTLFLAG_RD, ksp, 0, - kstat_sysctl_io, "A", ksp->ks_name); - break; - case KSTAT_TYPE_TIMER: - case KSTAT_TYPE_INTR: - default: - panic("unsupported kstat type %d\n", ksp->ks_type); + CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, + ksp, 0, kstat_sysctl_raw, "A", ksp->ks_name); + } else { + root = SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx, + SYSCTL_CHILDREN(ksp->ks_sysctl_root), + OID_AUTO, ksp->ks_name, + CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE, + ksp, 0, kstat_sysctl_raw, "", ksp->ks_name); + } + break; + case KSTAT_TYPE_IO: + root = SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx, + SYSCTL_CHILDREN(ksp->ks_sysctl_root), + OID_AUTO, ksp->ks_name, + CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, + ksp, 0, kstat_sysctl_io, "A", ksp->ks_name); + break; + case KSTAT_TYPE_TIMER: + case KSTAT_TYPE_INTR: + default: + panic("unsupported kstat type %d\n", ksp->ks_type); } + VERIFY(root != NULL); ksp->ks_sysctl_root = root; - } void diff --git a/module/os/freebsd/spl/spl_procfs_list.c b/module/os/freebsd/spl/spl_procfs_list.c index 7b4ae9d0e357..e8448ce00686 100644 --- a/module/os/freebsd/spl/spl_procfs_list.c +++ b/module/os/freebsd/spl/spl_procfs_list.c @@ -32,12 +32,74 @@ __FBSDID("$FreeBSD$"); #include <sys/mutex.h> #include <sys/procfs_list.h> +typedef struct procfs_list_iter { + procfs_list_t *pli_pl; + void *pli_elt; +} pli_t; + void -seq_printf(struct seq_file *m, const char *fmt, ...) -{} +seq_printf(struct seq_file *f, const char *fmt, ...) +{ + va_list adx; + + va_start(adx, fmt); + (void) vsnprintf(f->sf_buf, f->sf_size, fmt, adx); + va_end(adx); +} + +static int +procfs_list_update(kstat_t *ksp, int rw) +{ + procfs_list_t *pl = ksp->ks_private; + + if (rw == KSTAT_WRITE) + pl->pl_clear(pl); + + return (0); +} + +static int +procfs_list_data(char *buf, size_t size, void *data) +{ + pli_t *p; + void *elt; + procfs_list_t *pl; + struct seq_file f; + + p = data; + pl = p->pli_pl; + elt = p->pli_elt; + free(p, M_TEMP); + f.sf_buf = buf; + f.sf_size = size; + return (pl->pl_show(&f, elt)); +} + +static void * +procfs_list_addr(kstat_t *ksp, loff_t n) +{ + procfs_list_t *pl = ksp->ks_private; + void *elt = ksp->ks_private1; + pli_t *p = NULL; + + + if (n == 0) + ksp->ks_private1 = list_head(&pl->pl_list); + else if (elt) + ksp->ks_private1 = list_next(&pl->pl_list, elt); + + if (ksp->ks_private1) { + p = malloc(sizeof (*p), M_TEMP, M_WAITOK); + p->pli_pl = pl; + p->pli_elt = ksp->ks_private1; + } + + return (p); +} void procfs_list_install(const char *module, + const char *submodule, const char *name, mode_t mode, procfs_list_t *procfs_list, @@ -46,12 +108,31 @@ procfs_list_install(const char *module, int (*clear)(procfs_list_t *procfs_list), size_t procfs_list_node_off) { + kstat_t *procfs_kstat; + mutex_init(&procfs_list->pl_lock, NULL, MUTEX_DEFAULT, NULL); list_create(&procfs_list->pl_list, procfs_list_node_off + sizeof (procfs_list_node_t), procfs_list_node_off + offsetof(procfs_list_node_t, pln_link)); + procfs_list->pl_show = show; + procfs_list->pl_show_header = show_header; + procfs_list->pl_clear = clear; procfs_list->pl_next_id = 1; procfs_list->pl_node_offset = procfs_list_node_off; + + procfs_kstat = kstat_create(module, 0, name, submodule, + KSTAT_TYPE_RAW, 0, KSTAT_FLAG_VIRTUAL); + + if (procfs_kstat) { + procfs_kstat->ks_lock = &procfs_list->pl_lock; + procfs_kstat->ks_ndata = UINT32_MAX; + procfs_kstat->ks_private = procfs_list; + procfs_kstat->ks_update = procfs_list_update; + kstat_set_seq_raw_ops(procfs_kstat, show_header, + procfs_list_data, procfs_list_addr); + kstat_install(procfs_kstat); + procfs_list->pl_private = procfs_kstat; + } } void @@ -62,6 +143,7 @@ void procfs_list_destroy(procfs_list_t *procfs_list) { ASSERT(list_is_empty(&procfs_list->pl_list)); + kstat_delete(procfs_list->pl_private); list_destroy(&procfs_list->pl_list); mutex_destroy(&procfs_list->pl_lock); } diff --git a/module/os/freebsd/spl/spl_taskq.c b/module/os/freebsd/spl/spl_taskq.c index 049e889cf304..cc025de959e3 100644 --- a/module/os/freebsd/spl/spl_taskq.c +++ b/module/os/freebsd/spl/spl_taskq.c @@ -169,6 +169,10 @@ taskq_tsd_set(void *context) { taskq_t *tq = context; +#if defined(__amd64__) || defined(__i386__) || defined(__aarch64__) + if (context != NULL && tsd_get(taskq_tsd) == NULL) + fpu_kern_thread(FPU_KERN_NORMAL); +#endif tsd_set(taskq_tsd, tq); } diff --git a/module/os/freebsd/zfs/kmod_core.c b/module/os/freebsd/zfs/kmod_core.c index 4c696129857a..3a13271aac6f 100644 --- a/module/os/freebsd/zfs/kmod_core.c +++ b/module/os/freebsd/zfs/kmod_core.c @@ -86,6 +86,7 @@ __FBSDID("$FreeBSD$"); #include <sys/zio_checksum.h> #include <sys/vdev_removal.h> #include <sys/dsl_crypt.h> +#include <sys/zfs_context.h> #include <sys/zfs_ioctl_compat.h> #include <sys/zfs_ioctl_impl.h> @@ -98,7 +99,7 @@ __FBSDID("$FreeBSD$"); SYSCTL_DECL(_vfs_zfs); SYSCTL_DECL(_vfs_zfs_vdev); - +extern uint_t rrw_tsd_key; static int zfs_version_ioctl = ZFS_IOCVER_OZFS; SYSCTL_DECL(_vfs_zfs_version); SYSCTL_INT(_vfs_zfs_version, OID_AUTO, ioctl, CTLFLAG_RD, &zfs_version_ioctl, @@ -180,6 +181,7 @@ out: if (zcl) kmem_free(zcl, sizeof (zfs_cmd_legacy_t)); kmem_free(zc, sizeof (zfs_cmd_t)); + MPASS(tsd_get(rrw_tsd_key) == NULL); return (error); } diff --git a/module/os/freebsd/zfs/sysctl_os.c b/module/os/freebsd/zfs/sysctl_os.c index b3cb7e7e4374..c9b350a540ea 100644 --- a/module/os/freebsd/zfs/sysctl_os.c +++ b/module/os/freebsd/zfs/sysctl_os.c @@ -243,8 +243,9 @@ sysctl_vfs_zfs_arc_no_grow_shift(SYSCTL_HANDLER_ARGS) return (0); } -SYSCTL_PROC(_vfs_zfs, OID_AUTO, arc_no_grow_shift, CTLTYPE_U32 | CTLFLAG_RWTUN, - 0, sizeof (uint32_t), sysctl_vfs_zfs_arc_no_grow_shift, "U", +SYSCTL_PROC(_vfs_zfs, OID_AUTO, arc_no_grow_shift, + CTLTYPE_U32 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 0, sizeof (uint32_t), + sysctl_vfs_zfs_arc_no_grow_shift, "U", "log2(fraction of ARC which must be free to allow growing)"); int @@ -275,10 +276,12 @@ param_set_arc_int(SYSCTL_HANDLER_ARGS) return (0); } -SYSCTL_PROC(_vfs_zfs, OID_AUTO, arc_min, CTLTYPE_ULONG | CTLFLAG_RWTUN, +SYSCTL_PROC(_vfs_zfs, OID_AUTO, arc_min, + CTLTYPE_ULONG | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, &zfs_arc_min, sizeof (zfs_arc_min), param_set_arc_long, "LU", "min arc size (LEGACY)"); -SYSCTL_PROC(_vfs_zfs, OID_AUTO, arc_max, CTLTYPE_ULONG | CTLFLAG_RWTUN, +SYSCTL_PROC(_vfs_zfs, OID_AUTO, arc_max, + CTLTYPE_ULONG | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, &zfs_arc_max, sizeof (zfs_arc_max), param_set_arc_long, "LU", "max arc size (LEGACY)"); @@ -558,11 +561,13 @@ param_set_max_auto_ashift(SYSCTL_HANDLER_ARGS) return (0); } -SYSCTL_PROC(_vfs_zfs, OID_AUTO, min_auto_ashift, CTLTYPE_U64 | CTLFLAG_RWTUN, +SYSCTL_PROC(_vfs_zfs, OID_AUTO, min_auto_ashift, + CTLTYPE_U64 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, &zfs_vdev_min_auto_ashift, sizeof (zfs_vdev_min_auto_ashift), param_set_min_auto_ashift, "QU", "Min ashift used when creating new top-level vdev. (LEGACY)"); -SYSCTL_PROC(_vfs_zfs, OID_AUTO, max_auto_ashift, CTLTYPE_U64 | CTLFLAG_RWTUN, +SYSCTL_PROC(_vfs_zfs, OID_AUTO, max_auto_ashift, + CTLTYPE_U64 | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, &zfs_vdev_max_auto_ashift, sizeof (zfs_vdev_max_auto_ashift), param_set_max_auto_ashift, "QU", "Max ashift used when optimizing for logical -> physical sector size on " diff --git a/module/os/freebsd/zfs/zfs_ioctl_compat.c b/module/os/freebsd/zfs/zfs_ioctl_compat.c index 8dec8644c06e..81967bed73f9 100644 --- a/module/os/freebsd/zfs/zfs_ioctl_compat.c +++ b/module/os/freebsd/zfs/zfs_ioctl_compat.c @@ -322,8 +322,10 @@ zfs_ioctl_ozfs_to_legacy(int request) if (request > ZFS_IOC_LAST) return (-1); - if (request > ZFS_IOC_PLATFORM) + if (request > ZFS_IOC_PLATFORM) { + request -= ZFS_IOC_PLATFORM + 1; return (zfs_ioctl_ozfs_to_legacy_platform_[request]); + } if (request >= sizeof (zfs_ioctl_ozfs_to_legacy_common_)/sizeof (long)) return (-1); return (zfs_ioctl_ozfs_to_legacy_common_[request]); diff --git a/module/os/freebsd/zfs/zfs_vfsops.c b/module/os/freebsd/zfs/zfs_vfsops.c index 77812ca8d400..ec8303283414 100644 --- a/module/os/freebsd/zfs/zfs_vfsops.c +++ b/module/os/freebsd/zfs/zfs_vfsops.c @@ -1532,8 +1532,12 @@ zfsvfs_teardown(zfsvfs_t *zfsvfs, boolean_t unmounting) * 'z_parent' is self referential for non-snapshots. */ #ifdef FREEBSD_NAMECACHE +#if __FreeBSD_version >= 1300117 + cache_purgevfs(zfsvfs->z_parent->z_vfs); +#else cache_purgevfs(zfsvfs->z_parent->z_vfs, true); #endif +#endif } /* diff --git a/module/os/freebsd/zfs/zio_crypt.c b/module/os/freebsd/zfs/zio_crypt.c index d89ef80edd66..fb88bc325d3c 100644 --- a/module/os/freebsd/zfs/zio_crypt.c +++ b/module/os/freebsd/zfs/zio_crypt.c @@ -1234,8 +1234,7 @@ zio_crypt_do_indirect_mac_checksum_abd(boolean_t generate, abd_t *abd, * accommodate some of the drivers, the authbuf needs to be logically before * the data. This means that we need to copy the source to the destination, * and set up an extra iovec_t at the beginning to handle the authbuf. - * It also means we'll only return one uio_t, which we do via the clumsy - * ifdef in the function declaration. + * It also means we'll only return one uio_t. */ /* ARGSUSED */ @@ -1245,52 +1244,46 @@ zio_crypt_init_uios_zil(boolean_t encrypt, uint8_t *plainbuf, uio_t *out_uio, uint_t *enc_len, uint8_t **authbuf, uint_t *auth_len, boolean_t *no_crypt) { - int ret; - uint64_t txtype, lr_len; - uint_t nr_src, nr_dst, crypt_len; - uint_t aad_len = 0, nr_iovecs = 0, total_len = 0; - iovec_t *src_iovecs = NULL, *dst_iovecs = NULL; + uint8_t *aadbuf = zio_buf_alloc(datalen); uint8_t *src, *dst, *slrp, *dlrp, *blkend, *aadp; + iovec_t *dst_iovecs; zil_chain_t *zilc; lr_t *lr; - uint8_t *aadbuf = zio_buf_alloc(datalen); + uint64_t txtype, lr_len; + uint_t crypt_len, nr_iovecs, vec; + uint_t aad_len = 0, total_len = 0; - /* cipherbuf always needs an extra iovec for the MAC */ if (encrypt) { src = plainbuf; dst = cipherbuf; - nr_src = 0; - nr_dst = 1; } else { src = cipherbuf; dst = plainbuf; - nr_src = 1; - nr_dst = 0; } - - /* - * We need at least two iovecs -- one for the AAD, - * one for the MAC. - */ bcopy(src, dst, datalen); - nr_dst = 2; - /* find the start and end record of the log block */ + /* Find the start and end record of the log block. */ zilc = (zil_chain_t *)src; slrp = src + sizeof (zil_chain_t); aadp = aadbuf; blkend = src + ((byteswap) ? BSWAP_64(zilc->zc_nused) : zilc->zc_nused); - /* calculate the number of encrypted iovecs we will need */ + /* + * Calculate the number of encrypted iovecs we will need. + */ + + /* We need at least two iovecs -- one for the AAD, one for the MAC. */ + nr_iovecs = 2; + for (; slrp < blkend; slrp += lr_len) { lr = (lr_t *)slrp; - if (!byteswap) { - txtype = lr->lrc_txtype; - lr_len = lr->lrc_reclen; - } else { + if (byteswap) { txtype = BSWAP_64(lr->lrc_txtype); lr_len = BSWAP_64(lr->lrc_reclen); + } else { + txtype = lr->lrc_txtype; + lr_len = lr->lrc_reclen; } nr_iovecs++; @@ -1298,27 +1291,7 @@ zio_crypt_init_uios_zil(boolean_t encrypt, uint8_t *plainbuf, nr_iovecs++; } - nr_src = 0; - nr_dst += nr_iovecs; - - /* allocate the iovec arrays */ - if (nr_src != 0) { - src_iovecs = kmem_alloc(nr_src * sizeof (iovec_t), KM_SLEEP); - if (src_iovecs == NULL) { - ret = SET_ERROR(ENOMEM); - goto error; - } - bzero(src_iovecs, nr_src * sizeof (iovec_t)); - } - - if (nr_dst != 0) { - dst_iovecs = kmem_alloc(nr_dst * sizeof (iovec_t), KM_SLEEP); - if (dst_iovecs == NULL) { - ret = SET_ERROR(ENOMEM); - goto error; - } - bzero(dst_iovecs, nr_dst * sizeof (iovec_t)); - } + dst_iovecs = kmem_alloc(nr_iovecs * sizeof (iovec_t), KM_SLEEP); /* * Copy the plain zil header over and authenticate everything except @@ -1326,18 +1299,20 @@ zio_crypt_init_uios_zil(boolean_t encrypt, uint8_t *plainbuf, * the embedded checksum will not have been calculated yet, so we don't * authenticate that. */ - bcopy(src, dst, sizeof (zil_chain_t)); bcopy(src, aadp, sizeof (zil_chain_t) - sizeof (zio_eck_t)); aadp += sizeof (zil_chain_t) - sizeof (zio_eck_t); aad_len += sizeof (zil_chain_t) - sizeof (zio_eck_t); - /* loop over records again, filling in iovecs */ - /* The first one will contain the authbuf */ - nr_iovecs = 1; - slrp = src + sizeof (zil_chain_t); dlrp = dst + sizeof (zil_chain_t); + /* + * Loop over records again, filling in iovecs. + */ + + /* The first iovec will contain the authbuf. */ + vec = 1; + for (; slrp < blkend; slrp += lr_len, dlrp += lr_len) { lr = (lr_t *)slrp; @@ -1355,8 +1330,6 @@ zio_crypt_init_uios_zil(boolean_t encrypt, uint8_t *plainbuf, aadp += sizeof (lr_t); aad_len += sizeof (lr_t); - ASSERT3P(dst_iovecs, !=, NULL); - /* * If this is a TX_WRITE record we want to encrypt everything * except the bp if exists. If the bp does exist we want to @@ -1365,9 +1338,9 @@ zio_crypt_init_uios_zil(boolean_t encrypt, uint8_t *plainbuf, if (txtype == TX_WRITE) { crypt_len = sizeof (lr_write_t) - sizeof (lr_t) - sizeof (blkptr_t); - dst_iovecs[nr_iovecs].iov_base = (char *)dlrp + + dst_iovecs[vec].iov_base = (char *)dlrp + sizeof (lr_t); - dst_iovecs[nr_iovecs].iov_len = crypt_len; + dst_iovecs[vec].iov_len = crypt_len; /* copy the bp now since it will not be encrypted */ bcopy(slrp + sizeof (lr_write_t) - sizeof (blkptr_t), @@ -1377,56 +1350,45 @@ zio_crypt_init_uios_zil(boolean_t encrypt, uint8_t *plainbuf, aadp, sizeof (blkptr_t)); aadp += sizeof (blkptr_t); aad_len += sizeof (blkptr_t); - nr_iovecs++; + vec++; total_len += crypt_len; if (lr_len != sizeof (lr_write_t)) { crypt_len = lr_len - sizeof (lr_write_t); - dst_iovecs[nr_iovecs].iov_base = (char *) + dst_iovecs[vec].iov_base = (char *) dlrp + sizeof (lr_write_t); - dst_iovecs[nr_iovecs].iov_len = crypt_len; - nr_iovecs++; + dst_iovecs[vec].iov_len = crypt_len; + vec++; total_len += crypt_len; } } else { crypt_len = lr_len - sizeof (lr_t); - dst_iovecs[nr_iovecs].iov_base = (char *)dlrp + + dst_iovecs[vec].iov_base = (char *)dlrp + sizeof (lr_t); - dst_iovecs[nr_iovecs].iov_len = crypt_len; - nr_iovecs++; + dst_iovecs[vec].iov_len = crypt_len; + vec++; total_len += crypt_len; } } - *no_crypt = (nr_iovecs == 0); - *enc_len = total_len; - *authbuf = aadbuf; - *auth_len = aad_len; + /* The last iovec will contain the MAC. */ + ASSERT3U(vec, ==, nr_iovecs - 1); + + /* AAD */ dst_iovecs[0].iov_base = aadbuf; dst_iovecs[0].iov_len = aad_len; + /* MAC */ + dst_iovecs[vec].iov_base = 0; + dst_iovecs[vec].iov_len = 0; + *no_crypt = (vec == 1); + *enc_len = total_len; + *authbuf = aadbuf; + *auth_len = aad_len; out_uio->uio_iov = dst_iovecs; - out_uio->uio_iovcnt = nr_dst; + out_uio->uio_iovcnt = nr_iovecs; return (0); - -error: - zio_buf_free(aadbuf, datalen); - if (src_iovecs != NULL) - kmem_free(src_iovecs, nr_src * sizeof (iovec_t)); - if (dst_iovecs != NULL) - kmem_free(dst_iovecs, nr_dst * sizeof (iovec_t)); - - *enc_len = 0; - *authbuf = NULL; - *auth_len = 0; - *no_crypt = B_FALSE; - puio->uio_iov = NULL; - puio->uio_iovcnt = 0; - out_uio->uio_iov = NULL; - out_uio->uio_iovcnt = 0; - - return (ret); } /* @@ -1438,29 +1400,22 @@ zio_crypt_init_uios_dnode(boolean_t encrypt, uint64_t version, uio_t *puio, uio_t *out_uio, uint_t *enc_len, uint8_t **authbuf, uint_t *auth_len, boolean_t *no_crypt) { - int ret; - uint_t nr_src, nr_dst, crypt_len; - uint_t aad_len = 0, nr_iovecs = 0, total_len = 0; - uint_t i, j, max_dnp = datalen >> DNODE_SHIFT; - iovec_t *src_iovecs = NULL, *dst_iovecs = NULL; + uint8_t *aadbuf = zio_buf_alloc(datalen); uint8_t *src, *dst, *aadp; dnode_phys_t *dnp, *adnp, *sdnp, *ddnp; - uint8_t *aadbuf = zio_buf_alloc(datalen); + iovec_t *dst_iovecs; + uint_t nr_iovecs, crypt_len, vec; + uint_t aad_len = 0, total_len = 0; + uint_t i, j, max_dnp = datalen >> DNODE_SHIFT; if (encrypt) { src = plainbuf; dst = cipherbuf; - nr_src = 0; - nr_dst = 1; } else { src = cipherbuf; dst = plainbuf; - nr_src = 1; - nr_dst = 0; } - bcopy(src, dst, datalen); - nr_dst = 2; sdnp = (dnode_phys_t *)src; ddnp = (dnode_phys_t *)dst; @@ -1470,6 +1425,10 @@ zio_crypt_init_uios_dnode(boolean_t encrypt, uint64_t version, * Count the number of iovecs we will need to do the encryption by * counting the number of bonus buffers that need to be encrypted. */ + + /* We need at least two iovecs -- one for the AAD, one for the MAC. */ + nr_iovecs = 2; + for (i = 0; i < max_dnp; i += sdnp[i].dn_extra_slots + 1) { /* * This block may still be byteswapped. However, all of the @@ -1484,34 +1443,17 @@ zio_crypt_init_uios_dnode(boolean_t encrypt, uint64_t version, } } - nr_src = 0; - nr_dst += nr_iovecs; - - if (nr_src != 0) { - src_iovecs = kmem_alloc(nr_src * sizeof (iovec_t), KM_SLEEP); - if (src_iovecs == NULL) { - ret = SET_ERROR(ENOMEM); - goto error; - } - bzero(src_iovecs, nr_src * sizeof (iovec_t)); - } - - if (nr_dst != 0) { - dst_iovecs = kmem_alloc(nr_dst * sizeof (iovec_t), KM_SLEEP); - if (dst_iovecs == NULL) { - ret = SET_ERROR(ENOMEM); - goto error; - } - bzero(dst_iovecs, nr_dst * sizeof (iovec_t)); - } - - nr_iovecs = 1; + dst_iovecs = kmem_alloc(nr_iovecs * sizeof (iovec_t), KM_SLEEP); /* * Iterate through the dnodes again, this time filling in the uios * we allocated earlier. We also concatenate any data we want to * authenticate onto aadbuf. */ + + /* The first iovec will contain the authbuf. */ + vec = 1; + for (i = 0; i < max_dnp; i += sdnp[i].dn_extra_slots + 1) { dnp = &sdnp[i]; @@ -1565,12 +1507,10 @@ zio_crypt_init_uios_dnode(boolean_t encrypt, uint64_t version, if (dnp->dn_type != DMU_OT_NONE && DMU_OT_IS_ENCRYPTED(dnp->dn_bonustype) && dnp->dn_bonuslen != 0) { - ASSERT3U(nr_iovecs, <, nr_dst); - ASSERT3P(dst_iovecs, !=, NULL); - dst_iovecs[nr_iovecs].iov_base = DN_BONUS(&ddnp[i]); - dst_iovecs[nr_iovecs].iov_len = crypt_len; + dst_iovecs[vec].iov_base = DN_BONUS(&ddnp[i]); + dst_iovecs[vec].iov_len = crypt_len; - nr_iovecs++; + vec++; total_len += crypt_len; } else { bcopy(DN_BONUS(dnp), DN_BONUS(&ddnp[i]), crypt_len); @@ -1580,33 +1520,24 @@ zio_crypt_init_uios_dnode(boolean_t encrypt, uint64_t version, } } - *no_crypt = (nr_iovecs == 0); - *enc_len = total_len; - *authbuf = aadbuf; - *auth_len = aad_len; + /* The last iovec will contain the MAC. */ + ASSERT3U(vec, ==, nr_iovecs - 1); + /* AAD */ dst_iovecs[0].iov_base = aadbuf; dst_iovecs[0].iov_len = aad_len; + /* MAC */ + dst_iovecs[vec].iov_base = 0; + dst_iovecs[vec].iov_len = 0; + + *no_crypt = (vec == 1); + *enc_len = total_len; + *authbuf = aadbuf; + *auth_len = aad_len; out_uio->uio_iov = dst_iovecs; - out_uio->uio_iovcnt = nr_dst; + out_uio->uio_iovcnt = nr_iovecs; return (0); - -error: - zio_buf_free(aadbuf, datalen); - if (src_iovecs != NULL) - kmem_free(src_iovecs, nr_src * sizeof (iovec_t)); - if (dst_iovecs != NULL) - kmem_free(dst_iovecs, nr_dst * sizeof (iovec_t)); - - *enc_len = 0; - *authbuf = NULL; - *auth_len = 0; - *no_crypt = B_FALSE; - out_uio->uio_iov = NULL; - out_uio->uio_iovcnt = 0; - - return (ret); } /* ARGSUSED */ diff --git a/module/os/linux/spl/spl-procfs-list.c b/module/os/linux/spl/spl-procfs-list.c index 189d6a7c6082..cae13228c62c 100644 --- a/module/os/linux/spl/spl-procfs-list.c +++ b/module/os/linux/spl/spl-procfs-list.c @@ -89,7 +89,17 @@ procfs_list_next_node(procfs_list_cursor_t *cursor, loff_t *pos) cursor->cached_node = next_node; cursor->cached_pos = NODE_ID(procfs_list, cursor->cached_node); *pos = cursor->cached_pos; + } else { + /* + * seq_read() expects ->next() to update the position even + * when there are no more entries. Advance the position to + * prevent a warning from being logged. + */ + cursor->cached_node = NULL; + cursor->cached_pos++; + *pos = cursor->cached_pos; } + return (next_node); } @@ -105,6 +115,8 @@ procfs_list_seq_start(struct seq_file *f, loff_t *pos) cursor->cached_node = SEQ_START_TOKEN; cursor->cached_pos = 0; return (SEQ_START_TOKEN); + } else if (cursor->cached_node == NULL) { + return (NULL); } /* @@ -207,6 +219,7 @@ static const kstat_proc_op_t procfs_list_operations = { */ void procfs_list_install(const char *module, + const char *submodule, const char *name, mode_t mode, procfs_list_t *procfs_list, @@ -215,6 +228,12 @@ procfs_list_install(const char *module, int (*clear)(procfs_list_t *procfs_list), size_t procfs_list_node_off) { + char *modulestr; + + if (submodule != NULL) + modulestr = kmem_asprintf("%s/%s", module, submodule); + else + modulestr = kmem_asprintf("%s", module); mutex_init(&procfs_list->pl_lock, NULL, MUTEX_DEFAULT, NULL); list_create(&procfs_list->pl_list, procfs_list_node_off + sizeof (procfs_list_node_t), @@ -225,9 +244,10 @@ procfs_list_install(const char *module, procfs_list->pl_clear = clear; procfs_list->pl_node_offset = procfs_list_node_off; - kstat_proc_entry_init(&procfs_list->pl_kstat_entry, module, name); + kstat_proc_entry_init(&procfs_list->pl_kstat_entry, modulestr, name); kstat_proc_entry_install(&procfs_list->pl_kstat_entry, mode, &procfs_list_operations, procfs_list); + kmem_strfree(modulestr); } EXPORT_SYMBOL(procfs_list_install); diff --git a/module/os/linux/zfs/vdev_disk.c b/module/os/linux/zfs/vdev_disk.c index 85daef43be40..a54961c76870 100644 --- a/module/os/linux/zfs/vdev_disk.c +++ b/module/os/linux/zfs/vdev_disk.c @@ -436,6 +436,16 @@ vdev_submit_bio_impl(struct bio *bio) #endif } +/* + * preempt_schedule_notrace is GPL-only which breaks the ZFS build, so + * replace it with preempt_schedule under the following condition: + */ +#if defined(CONFIG_ARM64) && \ + defined(CONFIG_PREEMPTION) && \ + defined(CONFIG_BLK_CGROUP) +#define preempt_schedule_notrace(x) preempt_schedule(x) +#endif + #ifdef HAVE_BIO_SET_DEV #if defined(CONFIG_BLK_CGROUP) && defined(HAVE_BIO_SET_DEV_GPL_ONLY) /* diff --git a/module/os/linux/zfs/zfs_debug.c b/module/os/linux/zfs/zfs_debug.c index d98463f1b7f7..8d7f04097da8 100644 --- a/module/os/linux/zfs/zfs_debug.c +++ b/module/os/linux/zfs/zfs_debug.c @@ -94,6 +94,7 @@ void zfs_dbgmsg_init(void) { procfs_list_install("zfs", + NULL, "dbgmsg", 0600, &zfs_dbgmsgs, |