aboutsummaryrefslogtreecommitdiff
path: root/sys/contrib/openzfs/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'sys/contrib/openzfs/cmd')
-rwxr-xr-xsys/contrib/openzfs/cmd/arc_summary3
-rw-r--r--sys/contrib/openzfs/cmd/zdb/zdb.c103
-rw-r--r--sys/contrib/openzfs/cmd/zdb/zdb_il.c8
-rw-r--r--sys/contrib/openzfs/cmd/zed/agents/zfs_agents.c67
-rw-r--r--sys/contrib/openzfs/cmd/zed/zed_event.c2
-rw-r--r--sys/contrib/openzfs/cmd/zfs/zfs_main.c36
-rw-r--r--sys/contrib/openzfs/cmd/zpool/zpool_iter.c5
-rw-r--r--sys/contrib/openzfs/cmd/zpool/zpool_main.c264
-rw-r--r--sys/contrib/openzfs/cmd/zpool/zpool_vdev.c24
-rw-r--r--sys/contrib/openzfs/cmd/ztest.c51
10 files changed, 356 insertions, 207 deletions
diff --git a/sys/contrib/openzfs/cmd/arc_summary b/sys/contrib/openzfs/cmd/arc_summary
index c1319573220c..e60c6b64e8a1 100755
--- a/sys/contrib/openzfs/cmd/arc_summary
+++ b/sys/contrib/openzfs/cmd/arc_summary
@@ -559,6 +559,7 @@ def section_arc(kstats_dict):
print()
compressed_size = arc_stats['compressed_size']
+ uncompressed_size = arc_stats['uncompressed_size']
overhead_size = arc_stats['overhead_size']
bonus_size = arc_stats['bonus_size']
dnode_size = arc_stats['dnode_size']
@@ -671,6 +672,8 @@ def section_arc(kstats_dict):
print()
print('ARC misc:')
+ prt_i2('Uncompressed size:', f_perc(uncompressed_size, compressed_size),
+ f_bytes(uncompressed_size))
prt_i1('Memory throttles:', arc_stats['memory_throttle_count'])
prt_i1('Memory direct reclaims:', arc_stats['memory_direct_count'])
prt_i1('Memory indirect reclaims:', arc_stats['memory_indirect_count'])
diff --git a/sys/contrib/openzfs/cmd/zdb/zdb.c b/sys/contrib/openzfs/cmd/zdb/zdb.c
index 45eb9c783659..bf44d9c322b4 100644
--- a/sys/contrib/openzfs/cmd/zdb/zdb.c
+++ b/sys/contrib/openzfs/cmd/zdb/zdb.c
@@ -208,7 +208,7 @@ sublivelist_verify_blkptr(void *arg, const blkptr_t *bp, boolean_t free,
sublivelist_verify_block_t svb = {
.svb_dva = bp->blk_dva[i],
.svb_allocated_txg =
- BP_GET_LOGICAL_BIRTH(bp)
+ BP_GET_BIRTH(bp)
};
if (zfs_btree_find(&sv->sv_leftover, &svb,
@@ -619,8 +619,9 @@ livelist_metaslab_validate(spa_t *spa)
metaslab_calculate_range_tree_type(vd, m,
&start, &shift);
metaslab_verify_t mv;
- mv.mv_allocated = zfs_range_tree_create(NULL,
- type, NULL, start, shift);
+ mv.mv_allocated = zfs_range_tree_create_flags(
+ NULL, type, NULL, start, shift,
+ 0, "livelist_metaslab_validate:mv_allocated");
mv.mv_vdid = vd->vdev_id;
mv.mv_msid = m->ms_id;
mv.mv_start = m->ms_start;
@@ -797,8 +798,8 @@ usage(void)
"[default is 200]\n");
(void) fprintf(stderr, " -K --key=KEY "
"decryption key for encrypted dataset\n");
- (void) fprintf(stderr, " -o --option=\"OPTION=INTEGER\" "
- "set global variable to an unsigned 32-bit integer\n");
+ (void) fprintf(stderr, " -o --option=\"NAME=VALUE\" "
+ "set the named tunable to the given value\n");
(void) fprintf(stderr, " -p --path==PATH "
"use one or more with -e to specify path to vdev dir\n");
(void) fprintf(stderr, " -P --parseable "
@@ -1991,7 +1992,7 @@ dump_ddt_log(ddt_t *ddt)
c += strlcpy(&flagstr[c], " UNKNOWN",
sizeof (flagstr) - c);
flagstr[1] = '[';
- flagstr[c++] = ']';
+ flagstr[c] = ']';
}
uint64_t count = avl_numnodes(&ddl->ddl_tree);
@@ -2568,7 +2569,7 @@ snprintf_blkptr_compact(char *blkbuf, size_t buflen, const blkptr_t *bp,
(u_longlong_t)BP_GET_PSIZE(bp),
(u_longlong_t)BP_GET_FILL(bp),
(u_longlong_t)BP_GET_LOGICAL_BIRTH(bp),
- (u_longlong_t)BP_GET_BIRTH(bp));
+ (u_longlong_t)BP_GET_PHYSICAL_BIRTH(bp));
if (bp_freed)
(void) snprintf(blkbuf + strlen(blkbuf),
buflen - strlen(blkbuf), " %s", "FREE");
@@ -2618,7 +2619,7 @@ visit_indirect(spa_t *spa, const dnode_phys_t *dnp,
{
int err = 0;
- if (BP_GET_LOGICAL_BIRTH(bp) == 0)
+ if (BP_GET_BIRTH(bp) == 0)
return (0);
print_indirect(spa, bp, zb, dnp);
@@ -2806,7 +2807,7 @@ dump_bptree_cb(void *arg, const blkptr_t *bp, dmu_tx_t *tx)
(void) arg, (void) tx;
char blkbuf[BP_SPRINTF_LEN];
- if (BP_GET_LOGICAL_BIRTH(bp) != 0) {
+ if (BP_GET_BIRTH(bp) != 0) {
snprintf_blkptr(blkbuf, sizeof (blkbuf), bp);
(void) printf("\t%s\n", blkbuf);
}
@@ -2847,7 +2848,7 @@ dump_bpobj_cb(void *arg, const blkptr_t *bp, boolean_t bp_freed, dmu_tx_t *tx)
(void) arg, (void) tx;
char blkbuf[BP_SPRINTF_LEN];
- ASSERT(BP_GET_LOGICAL_BIRTH(bp) != 0);
+ ASSERT(BP_GET_BIRTH(bp) != 0);
snprintf_blkptr_compact(blkbuf, sizeof (blkbuf), bp, bp_freed);
(void) printf("\t%s\n", blkbuf);
return (0);
@@ -5921,11 +5922,11 @@ zdb_count_block(zdb_cb_t *zcb, zilog_t *zilog, const blkptr_t *bp,
* entry back to the block pointer before we claim it.
*/
if (v == DDT_PHYS_FLAT) {
- ASSERT3U(BP_GET_BIRTH(bp), ==,
+ ASSERT3U(BP_GET_PHYSICAL_BIRTH(bp), ==,
ddt_phys_birth(dde->dde_phys, v));
tempbp = *bp;
ddt_bp_fill(dde->dde_phys, v, &tempbp,
- BP_GET_BIRTH(bp));
+ BP_GET_PHYSICAL_BIRTH(bp));
bp = &tempbp;
}
@@ -6151,7 +6152,7 @@ zdb_blkptr_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
if (zb->zb_level == ZB_DNODE_LEVEL)
return (0);
- if (dump_opt['b'] >= 5 && BP_GET_LOGICAL_BIRTH(bp) > 0) {
+ if (dump_opt['b'] >= 5 && BP_GET_BIRTH(bp) > 0) {
char blkbuf[BP_SPRINTF_LEN];
snprintf_blkptr(blkbuf, sizeof (blkbuf), bp);
(void) printf("objset %llu object %llu "
@@ -6322,8 +6323,9 @@ zdb_claim_removing(spa_t *spa, zdb_cb_t *zcb)
ASSERT0(zfs_range_tree_space(svr->svr_allocd_segs));
- zfs_range_tree_t *allocs = zfs_range_tree_create(NULL, ZFS_RANGE_SEG64,
- NULL, 0, 0);
+ zfs_range_tree_t *allocs = zfs_range_tree_create_flags(
+ NULL, ZFS_RANGE_SEG64, NULL, 0, 0,
+ 0, "zdb_claim_removing:allocs");
for (uint64_t msi = 0; msi < vd->vdev_ms_count; msi++) {
metaslab_t *msp = vd->vdev_ms[msi];
@@ -6750,6 +6752,7 @@ zdb_leak_init(spa_t *spa, zdb_cb_t *zcb)
spa->spa_normal_class->mc_ops = &zdb_metaslab_ops;
spa->spa_log_class->mc_ops = &zdb_metaslab_ops;
spa->spa_embedded_log_class->mc_ops = &zdb_metaslab_ops;
+ spa->spa_special_embedded_log_class->mc_ops = &zdb_metaslab_ops;
zcb->zcb_vd_obsolete_counts =
umem_zalloc(rvd->vdev_children * sizeof (uint32_t *),
@@ -6887,7 +6890,9 @@ zdb_leak_fini(spa_t *spa, zdb_cb_t *zcb)
for (uint64_t m = 0; m < vd->vdev_ms_count; m++) {
metaslab_t *msp = vd->vdev_ms[m];
ASSERT3P(msp->ms_group, ==, (msp->ms_group->mg_class ==
- spa_embedded_log_class(spa)) ?
+ spa_embedded_log_class(spa) ||
+ msp->ms_group->mg_class ==
+ spa_special_embedded_log_class(spa)) ?
vd->vdev_log_mg : vd->vdev_mg);
/*
@@ -7121,6 +7126,8 @@ dump_block_stats(spa_t *spa)
zcb->zcb_totalasize += metaslab_class_get_alloc(spa_dedup_class(spa));
zcb->zcb_totalasize +=
metaslab_class_get_alloc(spa_embedded_log_class(spa));
+ zcb->zcb_totalasize +=
+ metaslab_class_get_alloc(spa_special_embedded_log_class(spa));
zcb->zcb_start = zcb->zcb_lastprint = gethrtime();
err = traverse_pool(spa, 0, flags, zdb_blkptr_cb, zcb);
@@ -7169,6 +7176,7 @@ dump_block_stats(spa_t *spa)
total_alloc = norm_alloc +
metaslab_class_get_alloc(spa_log_class(spa)) +
metaslab_class_get_alloc(spa_embedded_log_class(spa)) +
+ metaslab_class_get_alloc(spa_special_embedded_log_class(spa)) +
metaslab_class_get_alloc(spa_special_class(spa)) +
metaslab_class_get_alloc(spa_dedup_class(spa)) +
get_unflushed_alloc_space(spa);
@@ -7252,6 +7260,18 @@ dump_block_stats(spa_t *spa)
100.0 * alloc / space);
}
+ if (spa_special_embedded_log_class(spa)->mc_allocator[0].mca_rotor
+ != NULL) {
+ uint64_t alloc = metaslab_class_get_alloc(
+ spa_special_embedded_log_class(spa));
+ uint64_t space = metaslab_class_get_space(
+ spa_special_embedded_log_class(spa));
+
+ (void) printf("\t%-16s %14llu used: %5.2f%%\n",
+ "Special embedded log", (u_longlong_t)alloc,
+ 100.0 * alloc / space);
+ }
+
for (i = 0; i < NUM_BP_EMBEDDED_TYPES; i++) {
if (zcb->zcb_embedded_blocks[i] == 0)
continue;
@@ -7706,7 +7726,8 @@ zdb_set_skip_mmp(char *target)
* applies to the new_path parameter if allocated.
*/
static char *
-import_checkpointed_state(char *target, nvlist_t *cfg, char **new_path)
+import_checkpointed_state(char *target, nvlist_t *cfg, boolean_t target_is_spa,
+ char **new_path)
{
int error = 0;
char *poolname, *bogus_name = NULL;
@@ -7714,11 +7735,11 @@ import_checkpointed_state(char *target, nvlist_t *cfg, char **new_path)
/* If the target is not a pool, the extract the pool name */
char *path_start = strchr(target, '/');
- if (path_start != NULL) {
+ if (target_is_spa || path_start == NULL) {
+ poolname = target;
+ } else {
size_t poolname_len = path_start - target;
poolname = strndup(target, poolname_len);
- } else {
- poolname = target;
}
if (cfg == NULL) {
@@ -7749,10 +7770,11 @@ import_checkpointed_state(char *target, nvlist_t *cfg, char **new_path)
"with error %d\n", bogus_name, error);
}
- if (new_path != NULL && path_start != NULL) {
- if (asprintf(new_path, "%s%s", bogus_name, path_start) == -1) {
+ if (new_path != NULL && !target_is_spa) {
+ if (asprintf(new_path, "%s%s", bogus_name,
+ path_start != NULL ? path_start : "") == -1) {
free(bogus_name);
- if (path_start != NULL)
+ if (!target_is_spa && path_start != NULL)
free(poolname);
return (NULL);
}
@@ -7981,7 +8003,7 @@ verify_checkpoint_blocks(spa_t *spa)
* name) so we can do verification on it against the current state
* of the pool.
*/
- checkpoint_pool = import_checkpointed_state(spa->spa_name, NULL,
+ checkpoint_pool = import_checkpointed_state(spa->spa_name, NULL, B_TRUE,
NULL);
ASSERT(strcmp(spa->spa_name, checkpoint_pool) != 0);
@@ -8451,8 +8473,9 @@ dump_zpool(spa_t *spa)
if (dump_opt['d'] || dump_opt['i']) {
spa_feature_t f;
- mos_refd_objs = zfs_range_tree_create(NULL, ZFS_RANGE_SEG64,
- NULL, 0, 0);
+ mos_refd_objs = zfs_range_tree_create_flags(
+ NULL, ZFS_RANGE_SEG64, NULL, 0, 0,
+ 0, "dump_zpool:mos_refd_objs");
dump_objset(dp->dp_meta_objset);
if (dump_opt['d'] >= 3) {
@@ -8588,9 +8611,9 @@ zdb_dump_indirect(blkptr_t *bp, int nbps, int flags)
}
static void
-zdb_dump_gbh(void *buf, int flags)
+zdb_dump_gbh(void *buf, uint64_t size, int flags)
{
- zdb_dump_indirect((blkptr_t *)buf, SPA_GBH_NBLKPTRS, flags);
+ zdb_dump_indirect((blkptr_t *)buf, gbh_nblkptrs(size), flags);
}
static void
@@ -8780,7 +8803,6 @@ zdb_decompress_block(abd_t *pabd, void *buf, void *lbuf, uint64_t lsize,
(void) buf;
uint64_t orig_lsize = lsize;
boolean_t tryzle = ((getenv("ZDB_NO_ZLE") == NULL));
- boolean_t found = B_FALSE;
/*
* We don't know how the data was compressed, so just try
* every decompress function at every inflated blocksize.
@@ -8823,20 +8845,19 @@ zdb_decompress_block(abd_t *pabd, void *buf, void *lbuf, uint64_t lsize,
for (cfuncp = cfuncs; *cfuncp; cfuncp++) {
if (try_decompress_block(pabd, lsize, psize, flags,
*cfuncp, lbuf, lbuf2)) {
- found = B_TRUE;
+ tryzle = B_FALSE;
break;
}
}
if (*cfuncp != 0)
break;
}
- if (!found && tryzle) {
+ if (tryzle) {
for (lsize = orig_lsize; lsize <= maxlsize;
lsize += SPA_MINBLOCKSIZE) {
if (try_decompress_block(pabd, lsize, psize, flags,
ZIO_COMPRESS_ZLE, lbuf, lbuf2)) {
*cfuncp = ZIO_COMPRESS_ZLE;
- found = B_TRUE;
break;
}
}
@@ -9073,7 +9094,7 @@ zdb_read_block(char *thing, spa_t *spa)
zdb_dump_indirect((blkptr_t *)buf,
orig_lsize / sizeof (blkptr_t), flags);
else if (flags & ZDB_FLAG_GBH)
- zdb_dump_gbh(buf, flags);
+ zdb_dump_gbh(buf, lsize, flags);
else
zdb_dump_block(thing, buf, lsize, flags);
@@ -9120,7 +9141,7 @@ zdb_read_block(char *thing, spa_t *spa)
ck_zio->io_offset =
DVA_GET_OFFSET(&bp->blk_dva[0]);
ck_zio->io_bp = bp;
- zio_checksum_compute(ck_zio, ck, pabd, lsize);
+ zio_checksum_compute(ck_zio, ck, pabd, psize);
printf(
"%12s\t"
"cksum=%016llx:%016llx:%016llx:%016llx\n",
@@ -9377,9 +9398,11 @@ main(int argc, char **argv)
while (*optarg != '\0') { *optarg++ = '*'; }
break;
case 'o':
- error = set_global_var(optarg);
+ dump_opt[c]++;
+ dump_all = 0;
+ error = handle_tunable_option(optarg, B_FALSE);
if (error != 0)
- usage();
+ zdb_exit(1);
break;
case 'p':
if (searchdirs == NULL) {
@@ -9545,6 +9568,12 @@ main(int argc, char **argv)
error = 0;
goto fini;
}
+ if (dump_opt['o'])
+ /*
+ * Avoid blasting tunable options off the top of the
+ * screen.
+ */
+ zdb_exit(1);
usage();
}
@@ -9697,7 +9726,7 @@ main(int argc, char **argv)
char *checkpoint_target = NULL;
if (dump_opt['k']) {
checkpoint_pool = import_checkpointed_state(target, cfg,
- &checkpoint_target);
+ target_is_spa, &checkpoint_target);
if (checkpoint_target != NULL)
target = checkpoint_target;
diff --git a/sys/contrib/openzfs/cmd/zdb/zdb_il.c b/sys/contrib/openzfs/cmd/zdb/zdb_il.c
index 6b90b08ca1b1..62e290cd122c 100644
--- a/sys/contrib/openzfs/cmd/zdb/zdb_il.c
+++ b/sys/contrib/openzfs/cmd/zdb/zdb_il.c
@@ -176,7 +176,7 @@ zil_prt_rec_write(zilog_t *zilog, int txtype, const void *arg)
if (lr->lr_common.lrc_reclen == sizeof (lr_write_t)) {
(void) printf("%shas blkptr, %s\n", tab_prefix,
- !BP_IS_HOLE(bp) && BP_GET_LOGICAL_BIRTH(bp) >=
+ !BP_IS_HOLE(bp) && BP_GET_BIRTH(bp) >=
spa_min_claim_txg(zilog->zl_spa) ?
"will claim" : "won't claim");
print_log_bp(bp, tab_prefix);
@@ -189,7 +189,7 @@ zil_prt_rec_write(zilog_t *zilog, int txtype, const void *arg)
(void) printf("%s<hole>\n", tab_prefix);
return;
}
- if (BP_GET_LOGICAL_BIRTH(bp) < zilog->zl_header->zh_claim_txg) {
+ if (BP_GET_BIRTH(bp) < zilog->zl_header->zh_claim_txg) {
(void) printf("%s<block already committed>\n",
tab_prefix);
return;
@@ -240,7 +240,7 @@ zil_prt_rec_write_enc(zilog_t *zilog, int txtype, const void *arg)
if (lr->lr_common.lrc_reclen == sizeof (lr_write_t)) {
(void) printf("%shas blkptr, %s\n", tab_prefix,
- !BP_IS_HOLE(bp) && BP_GET_LOGICAL_BIRTH(bp) >=
+ !BP_IS_HOLE(bp) && BP_GET_BIRTH(bp) >=
spa_min_claim_txg(zilog->zl_spa) ?
"will claim" : "won't claim");
print_log_bp(bp, tab_prefix);
@@ -476,7 +476,7 @@ print_log_block(zilog_t *zilog, const blkptr_t *bp, void *arg,
if (claim_txg != 0)
claim = "already claimed";
- else if (BP_GET_LOGICAL_BIRTH(bp) >= spa_min_claim_txg(zilog->zl_spa))
+ else if (BP_GET_BIRTH(bp) >= spa_min_claim_txg(zilog->zl_spa))
claim = "will claim";
else
claim = "won't claim";
diff --git a/sys/contrib/openzfs/cmd/zed/agents/zfs_agents.c b/sys/contrib/openzfs/cmd/zed/agents/zfs_agents.c
index 8718dbde03b6..c0590edc7516 100644
--- a/sys/contrib/openzfs/cmd/zed/agents/zfs_agents.c
+++ b/sys/contrib/openzfs/cmd/zed/agents/zfs_agents.c
@@ -134,11 +134,13 @@ zfs_agent_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *arg)
* of blkid cache and L2ARC VDEV does not contain pool guid in its
* blkid, so this is a special case for L2ARC VDEV.
*/
- else if (gsp->gs_vdev_guid != 0 && gsp->gs_devid == NULL &&
+ else if (gsp->gs_vdev_guid != 0 &&
nvlist_lookup_uint64(nvl, ZPOOL_CONFIG_GUID, &vdev_guid) == 0 &&
gsp->gs_vdev_guid == vdev_guid) {
- (void) nvlist_lookup_string(nvl, ZPOOL_CONFIG_DEVID,
- &gsp->gs_devid);
+ if (gsp->gs_devid == NULL) {
+ (void) nvlist_lookup_string(nvl, ZPOOL_CONFIG_DEVID,
+ &gsp->gs_devid);
+ }
(void) nvlist_lookup_uint64(nvl, ZPOOL_CONFIG_EXPANSION_TIME,
&gsp->gs_vdev_expandtime);
return (B_TRUE);
@@ -156,22 +158,28 @@ zfs_agent_iter_pool(zpool_handle_t *zhp, void *arg)
/*
* For each vdev in this pool, look for a match by devid
*/
- if ((config = zpool_get_config(zhp, NULL)) != NULL) {
- if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
- &nvl) == 0) {
- (void) zfs_agent_iter_vdev(zhp, nvl, gsp);
- }
- }
- /*
- * if a match was found then grab the pool guid
- */
- if (gsp->gs_vdev_guid && gsp->gs_devid) {
- (void) nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
- &gsp->gs_pool_guid);
- }
+ boolean_t found = B_FALSE;
+ uint64_t pool_guid;
+ /* Get pool configuration and extract pool GUID */
+ if ((config = zpool_get_config(zhp, NULL)) == NULL ||
+ nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
+ &pool_guid) != 0)
+ goto out;
+
+ /* Skip this pool if we're looking for a specific pool */
+ if (gsp->gs_pool_guid != 0 && pool_guid != gsp->gs_pool_guid)
+ goto out;
+
+ if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, &nvl) == 0)
+ found = zfs_agent_iter_vdev(zhp, nvl, gsp);
+
+ if (found && gsp->gs_pool_guid == 0)
+ gsp->gs_pool_guid = pool_guid;
+
+out:
zpool_close(zhp);
- return (gsp->gs_devid != NULL && gsp->gs_vdev_guid != 0);
+ return (found);
}
void
@@ -233,20 +241,17 @@ zfs_agent_post_event(const char *class, const char *subclass, nvlist_t *nvl)
* For multipath, spare and l2arc devices ZFS_EV_VDEV_GUID or
* ZFS_EV_POOL_GUID may be missing so find them.
*/
- if (devid == NULL || pool_guid == 0 || vdev_guid == 0) {
- if (devid == NULL)
- search.gs_vdev_guid = vdev_guid;
- else
- search.gs_devid = devid;
- zpool_iter(g_zfs_hdl, zfs_agent_iter_pool, &search);
- if (devid == NULL)
- devid = search.gs_devid;
- if (pool_guid == 0)
- pool_guid = search.gs_pool_guid;
- if (vdev_guid == 0)
- vdev_guid = search.gs_vdev_guid;
- devtype = search.gs_vdev_type;
- }
+ search.gs_devid = devid;
+ search.gs_vdev_guid = vdev_guid;
+ search.gs_pool_guid = pool_guid;
+ zpool_iter(g_zfs_hdl, zfs_agent_iter_pool, &search);
+ if (devid == NULL)
+ devid = search.gs_devid;
+ if (pool_guid == 0)
+ pool_guid = search.gs_pool_guid;
+ if (vdev_guid == 0)
+ vdev_guid = search.gs_vdev_guid;
+ devtype = search.gs_vdev_type;
/*
* We want to avoid reporting "remove" events coming from
diff --git a/sys/contrib/openzfs/cmd/zed/zed_event.c b/sys/contrib/openzfs/cmd/zed/zed_event.c
index 296c222ca382..ba7cba304b1d 100644
--- a/sys/contrib/openzfs/cmd/zed/zed_event.c
+++ b/sys/contrib/openzfs/cmd/zed/zed_event.c
@@ -110,7 +110,7 @@ zed_event_fini(struct zed_conf *zcp)
static void
_bump_event_queue_length(void)
{
- int zzlm = -1, wr;
+ int zzlm, wr;
char qlen_buf[12] = {0}; /* parameter is int => max "-2147483647\n" */
long int qlen, orig_qlen;
diff --git a/sys/contrib/openzfs/cmd/zfs/zfs_main.c b/sys/contrib/openzfs/cmd/zfs/zfs_main.c
index 841c356508a5..363bb6da74ec 100644
--- a/sys/contrib/openzfs/cmd/zfs/zfs_main.c
+++ b/sys/contrib/openzfs/cmd/zfs/zfs_main.c
@@ -440,7 +440,7 @@ get_usage(zfs_help_t idx)
return (gettext("\tredact <snapshot> <bookmark> "
"<redaction_snapshot> ...\n"));
case HELP_REWRITE:
- return (gettext("\trewrite [-rvx] [-o <offset>] [-l <length>] "
+ return (gettext("\trewrite [-Prvx] [-o <offset>] [-l <length>] "
"<directory|file ...>\n"));
case HELP_JAIL:
return (gettext("\tjail <jailid|jailname> <filesystem>\n"));
@@ -1974,9 +1974,8 @@ fill_dataset_info(nvlist_t *list, zfs_handle_t *zhp, boolean_t as_int)
}
if (type == ZFS_TYPE_SNAPSHOT) {
- char *ds, *snap;
- ds = snap = strdup(zfs_get_name(zhp));
- ds = strsep(&snap, "@");
+ char *snap = strdup(zfs_get_name(zhp));
+ char *ds = strsep(&snap, "@");
fnvlist_add_string(list, "dataset", ds);
fnvlist_add_string(list, "snapshot_name", snap);
free(ds);
@@ -2019,8 +2018,7 @@ get_callback(zfs_handle_t *zhp, void *data)
nvlist_t *user_props = zfs_get_user_props(zhp);
zprop_list_t *pl = cbp->cb_proplist;
nvlist_t *propval;
- nvlist_t *item, *d, *props;
- item = d = props = NULL;
+ nvlist_t *item, *d = NULL, *props = NULL;
const char *strval;
const char *sourceval;
boolean_t received = is_recvd_column(cbp);
@@ -5879,7 +5877,7 @@ parse_fs_perm_set(fs_perm_set_t *fspset, nvlist_t *nvl)
static inline const char *
deleg_perm_comment(zfs_deleg_note_t note)
{
- const char *str = "";
+ const char *str;
/* subcommands */
switch (note) {
@@ -7729,6 +7727,7 @@ unshare_unmount_path(int op, char *path, int flags, boolean_t is_manual)
struct extmnttab entry;
const char *cmdname = (op == OP_SHARE) ? "unshare" : "unmount";
ino_t path_inode;
+ char *zfs_mntpnt, *entry_mntpnt;
/*
* Search for the given (major,minor) pair in the mount table.
@@ -7770,6 +7769,24 @@ unshare_unmount_path(int op, char *path, int flags, boolean_t is_manual)
goto out;
}
+ /*
+ * If the filesystem is mounted, check that the mountpoint matches
+ * the one in the mnttab entry w.r.t. provided path. If it doesn't,
+ * then we should not proceed further.
+ */
+ entry_mntpnt = strdup(entry.mnt_mountp);
+ if (zfs_is_mounted(zhp, &zfs_mntpnt)) {
+ if (strcmp(zfs_mntpnt, entry_mntpnt) != 0) {
+ (void) fprintf(stderr, gettext("cannot %s '%s': "
+ "not an original mountpoint\n"), cmdname, path);
+ free(zfs_mntpnt);
+ free(entry_mntpnt);
+ goto out;
+ }
+ free(zfs_mntpnt);
+ }
+ free(entry_mntpnt);
+
if (op == OP_SHARE) {
char nfs_mnt_prop[ZFS_MAXPROPLEN];
char smbshare_prop[ZFS_MAXPROPLEN];
@@ -9160,8 +9177,11 @@ zfs_do_rewrite(int argc, char **argv)
zfs_rewrite_args_t args;
memset(&args, 0, sizeof (args));
- while ((c = getopt(argc, argv, "l:o:rvx")) != -1) {
+ while ((c = getopt(argc, argv, "Pl:o:rvx")) != -1) {
switch (c) {
+ case 'P':
+ args.flags |= ZFS_REWRITE_PHYSICAL;
+ break;
case 'l':
args.len = strtoll(optarg, NULL, 0);
break;
diff --git a/sys/contrib/openzfs/cmd/zpool/zpool_iter.c b/sys/contrib/openzfs/cmd/zpool/zpool_iter.c
index 2ec189b98653..2eec9a95e24c 100644
--- a/sys/contrib/openzfs/cmd/zpool/zpool_iter.c
+++ b/sys/contrib/openzfs/cmd/zpool/zpool_iter.c
@@ -379,8 +379,8 @@ process_unique_cmd_columns(vdev_cmd_data_list_t *vcdl)
static int
vdev_process_cmd_output(vdev_cmd_data_t *data, char *line)
{
- char *col = NULL;
- char *val = line;
+ char *col;
+ char *val;
char *equals;
char **tmp;
@@ -397,6 +397,7 @@ vdev_process_cmd_output(vdev_cmd_data_t *data, char *line)
col = line;
val = equals + 1;
} else {
+ col = NULL;
val = line;
}
diff --git a/sys/contrib/openzfs/cmd/zpool/zpool_main.c b/sys/contrib/openzfs/cmd/zpool/zpool_main.c
index e62441894cd7..d401e087916b 100644
--- a/sys/contrib/openzfs/cmd/zpool/zpool_main.c
+++ b/sys/contrib/openzfs/cmd/zpool/zpool_main.c
@@ -34,7 +34,7 @@
* Copyright (c) 2019, loli10K <ezomori.nozomu@gmail.com>
* Copyright (c) 2021, Colm Buckley <colm@tuatha.org>
* Copyright (c) 2021, 2023, Klara Inc.
- * Copyright [2021] Hewlett Packard Enterprise Development LP
+ * Copyright (c) 2021, 2025 Hewlett Packard Enterprise Development LP.
*/
#include <assert.h>
@@ -510,16 +510,16 @@ get_usage(zpool_help_t idx)
case HELP_REOPEN:
return (gettext("\treopen [-n] <pool>\n"));
case HELP_INITIALIZE:
- return (gettext("\tinitialize [-c | -s | -u] [-w] <pool> "
- "[<device> ...]\n"));
+ return (gettext("\tinitialize [-c | -s | -u] [-w] <-a | <pool> "
+ "[<device> ...]>\n"));
case HELP_SCRUB:
- return (gettext("\tscrub [-e | -s | -p | -C] [-w] "
- "<pool> ...\n"));
+ return (gettext("\tscrub [-e | -s | -p | -C | -E | -S] [-w] "
+ "<-a | <pool> [<pool> ...]>\n"));
case HELP_RESILVER:
return (gettext("\tresilver <pool> ...\n"));
case HELP_TRIM:
- return (gettext("\ttrim [-dw] [-r <rate>] [-c | -s] <pool> "
- "[<device> ...]\n"));
+ return (gettext("\ttrim [-dw] [-r <rate>] [-c | -s] "
+ "<-a | <pool> [<device> ...]>\n"));
case HELP_STATUS:
return (gettext("\tstatus [-DdegiLPpstvx] "
"[-c script1[,script2,...]] ...\n"
@@ -560,33 +560,6 @@ get_usage(zpool_help_t idx)
}
}
-static void
-zpool_collect_leaves(zpool_handle_t *zhp, nvlist_t *nvroot, nvlist_t *res)
-{
- uint_t children = 0;
- nvlist_t **child;
- uint_t i;
-
- (void) nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
- &child, &children);
-
- if (children == 0) {
- char *path = zpool_vdev_name(g_zfs, zhp, nvroot,
- VDEV_NAME_PATH);
-
- if (strcmp(path, VDEV_TYPE_INDIRECT) != 0 &&
- strcmp(path, VDEV_TYPE_HOLE) != 0)
- fnvlist_add_boolean(res, path);
-
- free(path);
- return;
- }
-
- for (i = 0; i < children; i++) {
- zpool_collect_leaves(zhp, child[i], res);
- }
-}
-
/*
* Callback routine that will print out a pool property value.
*/
@@ -794,22 +767,26 @@ zpool_do_initialize(int argc, char **argv)
int c;
char *poolname;
zpool_handle_t *zhp;
- nvlist_t *vdevs;
int err = 0;
boolean_t wait = B_FALSE;
+ boolean_t initialize_all = B_FALSE;
struct option long_options[] = {
{"cancel", no_argument, NULL, 'c'},
{"suspend", no_argument, NULL, 's'},
{"uninit", no_argument, NULL, 'u'},
{"wait", no_argument, NULL, 'w'},
+ {"all", no_argument, NULL, 'a'},
{0, 0, 0, 0}
};
pool_initialize_func_t cmd_type = POOL_INITIALIZE_START;
- while ((c = getopt_long(argc, argv, "csuw", long_options,
+ while ((c = getopt_long(argc, argv, "acsuw", long_options,
NULL)) != -1) {
switch (c) {
+ case 'a':
+ initialize_all = B_TRUE;
+ break;
case 'c':
if (cmd_type != POOL_INITIALIZE_START &&
cmd_type != POOL_INITIALIZE_CANCEL) {
@@ -856,7 +833,18 @@ zpool_do_initialize(int argc, char **argv)
argc -= optind;
argv += optind;
- if (argc < 1) {
+ initialize_cbdata_t cbdata = {
+ .wait = wait,
+ .cmd_type = cmd_type
+ };
+
+ if (initialize_all && argc > 0) {
+ (void) fprintf(stderr, gettext("-a cannot be combined with "
+ "individual pools or vdevs\n"));
+ usage(B_FALSE);
+ }
+
+ if (argc < 1 && !initialize_all) {
(void) fprintf(stderr, gettext("missing pool name argument\n"));
usage(B_FALSE);
return (-1);
@@ -868,30 +856,35 @@ zpool_do_initialize(int argc, char **argv)
usage(B_FALSE);
}
- poolname = argv[0];
- zhp = zpool_open(g_zfs, poolname);
- if (zhp == NULL)
- return (-1);
-
- vdevs = fnvlist_alloc();
- if (argc == 1) {
- /* no individual leaf vdevs specified, so add them all */
- nvlist_t *config = zpool_get_config(zhp, NULL);
- nvlist_t *nvroot = fnvlist_lookup_nvlist(config,
- ZPOOL_CONFIG_VDEV_TREE);
- zpool_collect_leaves(zhp, nvroot, vdevs);
+ if (argc == 0 && initialize_all) {
+ /* Initilize each pool recursively */
+ err = for_each_pool(argc, argv, B_TRUE, NULL, ZFS_TYPE_POOL,
+ B_FALSE, zpool_initialize_one, &cbdata);
+ return (err);
+ } else if (argc == 1) {
+ /* no individual leaf vdevs specified, initialize the pool */
+ poolname = argv[0];
+ zhp = zpool_open(g_zfs, poolname);
+ if (zhp == NULL)
+ return (-1);
+ err = zpool_initialize_one(zhp, &cbdata);
} else {
+ /* individual leaf vdevs specified, initialize them */
+ poolname = argv[0];
+ zhp = zpool_open(g_zfs, poolname);
+ if (zhp == NULL)
+ return (-1);
+ nvlist_t *vdevs = fnvlist_alloc();
for (int i = 1; i < argc; i++) {
fnvlist_add_boolean(vdevs, argv[i]);
}
+ if (wait)
+ err = zpool_initialize_wait(zhp, cmd_type, vdevs);
+ else
+ err = zpool_initialize(zhp, cmd_type, vdevs);
+ fnvlist_free(vdevs);
}
- if (wait)
- err = zpool_initialize_wait(zhp, cmd_type, vdevs);
- else
- err = zpool_initialize(zhp, cmd_type, vdevs);
-
- fnvlist_free(vdevs);
zpool_close(zhp);
return (err);
@@ -1788,7 +1781,7 @@ zpool_do_labelclear(int argc, char **argv)
{
char vdev[MAXPATHLEN];
char *name = NULL;
- int c, fd = -1, ret = 0;
+ int c, fd, ret = 0;
nvlist_t *config;
pool_state_t state;
boolean_t inuse = B_FALSE;
@@ -6157,7 +6150,6 @@ static void
get_interval_count_filter_guids(int *argc, char **argv, float *interval,
unsigned long *count, iostat_cbdata_t *cb)
{
- char **tmpargv = argv;
int argc_for_interval = 0;
/* Is the last arg an interval value? Or a guid? */
@@ -6181,7 +6173,7 @@ get_interval_count_filter_guids(int *argc, char **argv, float *interval,
}
/* Point to our list of possible intervals */
- tmpargv = &argv[*argc - argc_for_interval];
+ char **tmpargv = &argv[*argc - argc_for_interval];
*argc = *argc - argc_for_interval;
get_interval_count(&argc_for_interval, tmpargv,
@@ -6377,7 +6369,6 @@ zpool_do_iostat(int argc, char **argv)
int npools;
float interval = 0;
unsigned long count = 0;
- int winheight = 24;
zpool_list_t *list;
boolean_t verbose = B_FALSE;
boolean_t latency = B_FALSE, l_histo = B_FALSE, rq_histo = B_FALSE;
@@ -6673,7 +6664,7 @@ zpool_do_iostat(int argc, char **argv)
* even when terminal window has its height
* changed.
*/
- winheight = terminal_height();
+ int winheight = terminal_height();
/*
* Are we connected to TTY? If not, headers_once
* should be true, to avoid breaking scripts.
@@ -8368,6 +8359,8 @@ zpool_do_reopen(int argc, char **argv)
typedef struct scrub_cbdata {
int cb_type;
pool_scrub_cmd_t cb_scrub_cmd;
+ time_t cb_date_start;
+ time_t cb_date_end;
} scrub_cbdata_t;
static boolean_t
@@ -8411,8 +8404,8 @@ scrub_callback(zpool_handle_t *zhp, void *data)
return (1);
}
- err = zpool_scan(zhp, cb->cb_type, cb->cb_scrub_cmd);
-
+ err = zpool_scan_range(zhp, cb->cb_type, cb->cb_scrub_cmd,
+ cb->cb_date_start, cb->cb_date_end);
if (err == 0 && zpool_has_checkpoint(zhp) &&
cb->cb_type == POOL_SCAN_SCRUB) {
(void) printf(gettext("warning: will not scrub state that "
@@ -8430,10 +8423,34 @@ wait_callback(zpool_handle_t *zhp, void *data)
return (zpool_wait(zhp, *act));
}
+static time_t
+date_string_to_sec(const char *timestr, boolean_t rounding)
+{
+ struct tm tm = {0};
+ int adjustment = rounding ? 1 : 0;
+
+ /* Allow mktime to determine timezone. */
+ tm.tm_isdst = -1;
+
+ if (strptime(timestr, "%Y-%m-%d %H:%M", &tm) == NULL) {
+ if (strptime(timestr, "%Y-%m-%d", &tm) == NULL) {
+ fprintf(stderr, gettext("Failed to parse the date.\n"));
+ usage(B_FALSE);
+ }
+ adjustment *= 24 * 60 * 60;
+ } else {
+ adjustment *= 60;
+ }
+
+ return (mktime(&tm) + adjustment);
+}
+
/*
- * zpool scrub [-e | -s | -p | -C] [-w] <pool> ...
+ * zpool scrub [-e | -s | -p | -C | -E | -S] [-w] <pool> ...
*
* -e Only scrub blocks in the error log.
+ * -E End date of scrub.
+ * -S Start date of scrub.
* -s Stop. Stops any in-progress scrub.
* -p Pause. Pause in-progress scrub.
* -w Wait. Blocks until scrub has completed.
@@ -8449,21 +8466,36 @@ zpool_do_scrub(int argc, char **argv)
cb.cb_type = POOL_SCAN_SCRUB;
cb.cb_scrub_cmd = POOL_SCRUB_NORMAL;
+ cb.cb_date_start = cb.cb_date_end = 0;
boolean_t is_error_scrub = B_FALSE;
boolean_t is_pause = B_FALSE;
boolean_t is_stop = B_FALSE;
boolean_t is_txg_continue = B_FALSE;
+ boolean_t scrub_all = B_FALSE;
/* check options */
- while ((c = getopt(argc, argv, "spweC")) != -1) {
+ while ((c = getopt(argc, argv, "aspweCE:S:")) != -1) {
switch (c) {
+ case 'a':
+ scrub_all = B_TRUE;
+ break;
case 'e':
is_error_scrub = B_TRUE;
break;
+ case 'E':
+ /*
+ * Round the date. It's better to scrub more data than
+ * less. This also makes the date inclusive.
+ */
+ cb.cb_date_end = date_string_to_sec(optarg, B_TRUE);
+ break;
case 's':
is_stop = B_TRUE;
break;
+ case 'S':
+ cb.cb_date_start = date_string_to_sec(optarg, B_FALSE);
+ break;
case 'p':
is_pause = B_TRUE;
break;
@@ -8511,6 +8543,19 @@ zpool_do_scrub(int argc, char **argv)
}
}
+ if ((cb.cb_date_start != 0 || cb.cb_date_end != 0) &&
+ cb.cb_scrub_cmd != POOL_SCRUB_NORMAL) {
+ (void) fprintf(stderr, gettext("invalid option combination: "
+ "start/end date is available only with normal scrub\n"));
+ usage(B_FALSE);
+ }
+ if (cb.cb_date_start != 0 && cb.cb_date_end != 0 &&
+ cb.cb_date_start > cb.cb_date_end) {
+ (void) fprintf(stderr, gettext("invalid arguments: "
+ "end date has to be later than start date\n"));
+ usage(B_FALSE);
+ }
+
if (wait && (cb.cb_type == POOL_SCAN_NONE ||
cb.cb_scrub_cmd == POOL_SCRUB_PAUSE)) {
(void) fprintf(stderr, gettext("invalid option combination: "
@@ -8521,7 +8566,7 @@ zpool_do_scrub(int argc, char **argv)
argc -= optind;
argv += optind;
- if (argc < 1) {
+ if (argc < 1 && !scrub_all) {
(void) fprintf(stderr, gettext("missing pool name argument\n"));
usage(B_FALSE);
}
@@ -8551,6 +8596,7 @@ zpool_do_resilver(int argc, char **argv)
cb.cb_type = POOL_SCAN_RESILVER;
cb.cb_scrub_cmd = POOL_SCRUB_NORMAL;
+ cb.cb_date_start = cb.cb_date_end = 0;
/* check options */
while ((c = getopt(argc, argv, "")) != -1) {
@@ -8593,6 +8639,7 @@ zpool_do_trim(int argc, char **argv)
{"rate", required_argument, NULL, 'r'},
{"suspend", no_argument, NULL, 's'},
{"wait", no_argument, NULL, 'w'},
+ {"all", no_argument, NULL, 'a'},
{0, 0, 0, 0}
};
@@ -8600,11 +8647,16 @@ zpool_do_trim(int argc, char **argv)
uint64_t rate = 0;
boolean_t secure = B_FALSE;
boolean_t wait = B_FALSE;
+ boolean_t trimall = B_FALSE;
+ int error;
int c;
- while ((c = getopt_long(argc, argv, "cdr:sw", long_options, NULL))
+ while ((c = getopt_long(argc, argv, "acdr:sw", long_options, NULL))
!= -1) {
switch (c) {
+ case 'a':
+ trimall = B_TRUE;
+ break;
case 'c':
if (cmd_type != POOL_TRIM_START &&
cmd_type != POOL_TRIM_CANCEL) {
@@ -8663,7 +8715,18 @@ zpool_do_trim(int argc, char **argv)
argc -= optind;
argv += optind;
- if (argc < 1) {
+ trimflags_t trim_flags = {
+ .secure = secure,
+ .rate = rate,
+ .wait = wait,
+ };
+
+ trim_cbdata_t cbdata = {
+ .trim_flags = trim_flags,
+ .cmd_type = cmd_type
+ };
+
+ if (argc < 1 && !trimall) {
(void) fprintf(stderr, gettext("missing pool name argument\n"));
usage(B_FALSE);
return (-1);
@@ -8671,41 +8734,46 @@ zpool_do_trim(int argc, char **argv)
if (wait && (cmd_type != POOL_TRIM_START)) {
(void) fprintf(stderr, gettext("-w cannot be used with -c or "
- "-s\n"));
+ "-s options\n"));
usage(B_FALSE);
}
- char *poolname = argv[0];
- zpool_handle_t *zhp = zpool_open(g_zfs, poolname);
- if (zhp == NULL)
- return (-1);
-
- trimflags_t trim_flags = {
- .secure = secure,
- .rate = rate,
- .wait = wait,
- };
+ if (trimall && argc > 0) {
+ (void) fprintf(stderr, gettext("-a cannot be combined with "
+ "individual zpools or vdevs\n"));
+ usage(B_FALSE);
+ }
- nvlist_t *vdevs = fnvlist_alloc();
- if (argc == 1) {
+ if (argc == 0 && trimall) {
+ cbdata.trim_flags.fullpool = B_TRUE;
+ /* Trim each pool recursively */
+ error = for_each_pool(argc, argv, B_TRUE, NULL, ZFS_TYPE_POOL,
+ B_FALSE, zpool_trim_one, &cbdata);
+ } else if (argc == 1) {
+ char *poolname = argv[0];
+ zpool_handle_t *zhp = zpool_open(g_zfs, poolname);
+ if (zhp == NULL)
+ return (-1);
/* no individual leaf vdevs specified, so add them all */
- nvlist_t *config = zpool_get_config(zhp, NULL);
- nvlist_t *nvroot = fnvlist_lookup_nvlist(config,
- ZPOOL_CONFIG_VDEV_TREE);
- zpool_collect_leaves(zhp, nvroot, vdevs);
- trim_flags.fullpool = B_TRUE;
+ error = zpool_trim_one(zhp, &cbdata);
+ zpool_close(zhp);
} else {
- trim_flags.fullpool = B_FALSE;
+ char *poolname = argv[0];
+ zpool_handle_t *zhp = zpool_open(g_zfs, poolname);
+ if (zhp == NULL)
+ return (-1);
+ /* leaf vdevs specified, trim only those */
+ cbdata.trim_flags.fullpool = B_FALSE;
+ nvlist_t *vdevs = fnvlist_alloc();
for (int i = 1; i < argc; i++) {
fnvlist_add_boolean(vdevs, argv[i]);
}
+ error = zpool_trim(zhp, cbdata.cmd_type, vdevs,
+ &cbdata.trim_flags);
+ fnvlist_free(vdevs);
+ zpool_close(zhp);
}
- int error = zpool_trim(zhp, cmd_type, vdevs, &trim_flags);
-
- fnvlist_free(vdevs);
- zpool_close(zhp);
-
return (error);
}
@@ -10706,7 +10774,6 @@ status_callback_json(zpool_handle_t *zhp, void *data)
uint_t c;
vdev_stat_t *vs;
nvlist_t *item, *d, *load_info, *vds;
- item = d = NULL;
/* If dedup stats were requested, also fetch dedupcached. */
if (cbp->cb_dedup_stats > 1)
@@ -11330,7 +11397,8 @@ upgrade_enable_all(zpool_handle_t *zhp, int *countp)
const char *fname = spa_feature_table[i].fi_uname;
const char *fguid = spa_feature_table[i].fi_guid;
- if (!spa_feature_table[i].fi_zfs_mod_supported)
+ if (!spa_feature_table[i].fi_zfs_mod_supported ||
+ (spa_feature_table[i].fi_flags & ZFEATURE_FLAG_NO_UPGRADE))
continue;
if (!nvlist_exists(enabled, fguid) && requested_features[i]) {
@@ -11485,7 +11553,11 @@ upgrade_list_disabled_cb(zpool_handle_t *zhp, void *arg)
"Note that the pool "
"'compatibility' feature can be "
"used to inhibit\nfeature "
- "upgrades.\n\n"));
+ "upgrades.\n\n"
+ "Features marked with (*) are not "
+ "applied automatically on upgrade, "
+ "and\nmust be applied explicitly "
+ "with zpool-set(7).\n\n"));
(void) printf(gettext("POOL "
"FEATURE\n"));
(void) printf(gettext("------"
@@ -11499,7 +11571,9 @@ upgrade_list_disabled_cb(zpool_handle_t *zhp, void *arg)
poolfirst = B_FALSE;
}
- (void) printf(gettext(" %s\n"), fname);
+ (void) printf(gettext(" %s%s\n"), fname,
+ spa_feature_table[i].fi_flags &
+ ZFEATURE_FLAG_NO_UPGRADE ? "(*)" : "");
}
/*
* If they did "zpool upgrade -a", then we could
diff --git a/sys/contrib/openzfs/cmd/zpool/zpool_vdev.c b/sys/contrib/openzfs/cmd/zpool/zpool_vdev.c
index 07868a30d7e7..684b46a2d673 100644
--- a/sys/contrib/openzfs/cmd/zpool/zpool_vdev.c
+++ b/sys/contrib/openzfs/cmd/zpool/zpool_vdev.c
@@ -574,7 +574,6 @@ get_replication(nvlist_t *nvroot, boolean_t fatal)
nvlist_t *cnv = child[c];
const char *path;
struct stat64 statbuf;
- int64_t size = -1LL;
const char *childtype;
int fd, err;
@@ -656,7 +655,7 @@ get_replication(nvlist_t *nvroot, boolean_t fatal)
statbuf.st_size == MAXOFFSET_T)
continue;
- size = statbuf.st_size;
+ int64_t size = statbuf.st_size;
/*
* Also make sure that devices and
@@ -876,6 +875,18 @@ check_replication(nvlist_t *config, nvlist_t *newroot)
(u_longlong_t)mirror->zprl_children);
ret = -1;
}
+ } else if (is_raidz_draid(current, new)) {
+ if (current->zprl_parity != new->zprl_parity) {
+ vdev_error(gettext(
+ "mismatched replication level: pool and "
+ "new vdev with different redundancy, %s "
+ "and %s vdevs, %llu vs. %llu\n"),
+ current->zprl_type,
+ new->zprl_type,
+ (u_longlong_t)current->zprl_parity,
+ (u_longlong_t)new->zprl_parity);
+ ret = -1;
+ }
} else if (strcmp(current->zprl_type, new->zprl_type) != 0) {
vdev_error(gettext(
"mismatched replication level: pool uses %s "
@@ -1353,7 +1364,7 @@ is_grouping(const char *type, int *mindev, int *maxdev)
static int
draid_config_by_type(nvlist_t *nv, const char *type, uint64_t children)
{
- uint64_t nparity = 1;
+ uint64_t nparity;
uint64_t nspares = 0;
uint64_t ndata = UINT64_MAX;
uint64_t ngroups = 1;
@@ -1581,13 +1592,12 @@ construct_spec(nvlist_t *props, int argc, char **argv)
is_dedup = is_spare = B_FALSE;
}
- if (is_log || is_special || is_dedup) {
+ if (is_log) {
if (strcmp(type, VDEV_TYPE_MIRROR) != 0) {
(void) fprintf(stderr,
gettext("invalid vdev "
- "specification: unsupported '%s' "
- "device: %s\n"), is_log ? "log" :
- "special", type);
+ "specification: unsupported 'log' "
+ "device: %s\n"), type);
goto spec_out;
}
nlogs++;
diff --git a/sys/contrib/openzfs/cmd/ztest.c b/sys/contrib/openzfs/cmd/ztest.c
index 89264c97ff10..2e88ae3e7994 100644
--- a/sys/contrib/openzfs/cmd/ztest.c
+++ b/sys/contrib/openzfs/cmd/ztest.c
@@ -809,8 +809,8 @@ static ztest_option_t option_table[] = {
{ 'X', "raidz-expansion", NULL,
"Perform a dedicated raidz expansion test",
NO_DEFAULT, NULL},
- { 'o', "option", "\"OPTION=INTEGER\"",
- "Set global variable to an unsigned 32-bit integer value",
+ { 'o', "option", "\"NAME=VALUE\"",
+ "Set the named tunable to the given value",
NO_DEFAULT, NULL},
{ 'G', "dump-debug-msg", NULL,
"Dump zfs_dbgmsg buffer before exiting due to an error",
@@ -919,7 +919,7 @@ ztest_parse_name_value(const char *input, ztest_shared_opts_t *zo)
{
char name[32];
char *value;
- int state = ZTEST_VDEV_CLASS_RND;
+ int state;
(void) strlcpy(name, input, sizeof (name));
@@ -3882,7 +3882,7 @@ ztest_vdev_attach_detach(ztest_ds_t *zd, uint64_t id)
* If newvd is too small, it should fail with EOVERFLOW.
*
* If newvd is a distributed spare and it's being attached to a
- * dRAID which is not its parent it should fail with EINVAL.
+ * dRAID which is not its parent it should fail with ENOTSUP.
*/
if (pvd->vdev_ops != &vdev_mirror_ops &&
pvd->vdev_ops != &vdev_root_ops && (!replacing ||
@@ -3901,7 +3901,7 @@ ztest_vdev_attach_detach(ztest_ds_t *zd, uint64_t id)
else if (ashift > oldvd->vdev_top->vdev_ashift)
expected_error = EDOM;
else if (newvd_is_dspare && pvd != vdev_draid_spare_get_parent(newvd))
- expected_error = EINVAL;
+ expected_error = ENOTSUP;
else
expected_error = 0;
@@ -7069,7 +7069,7 @@ ztest_set_global_vars(void)
char *kv = ztest_opts.zo_gvars[i];
VERIFY3U(strlen(kv), <=, ZO_GVARS_MAX_ARGLEN);
VERIFY3U(strlen(kv), >, 0);
- int err = set_global_var(kv);
+ int err = handle_tunable_option(kv, B_TRUE);
if (ztest_opts.zo_verbose > 0) {
(void) printf("setting global var %s ... %s\n", kv,
err ? "failed" : "ok");
@@ -7813,6 +7813,9 @@ ztest_dataset_open(int d)
ztest_dataset_name(name, ztest_opts.zo_pool, d);
+ if (ztest_opts.zo_verbose >= 6)
+ (void) printf("Opening %s\n", name);
+
(void) pthread_rwlock_rdlock(&ztest_name_lock);
error = ztest_dataset_create(name);
@@ -8308,41 +8311,44 @@ static void
ztest_generic_run(ztest_shared_t *zs, spa_t *spa)
{
kthread_t **run_threads;
- int t;
+ int i, ndatasets;
run_threads = umem_zalloc(ztest_opts.zo_threads * sizeof (kthread_t *),
UMEM_NOFAIL);
/*
- * Kick off all the tests that run in parallel.
+ * Actual number of datasets to be used.
*/
- for (t = 0; t < ztest_opts.zo_threads; t++) {
- if (t < ztest_opts.zo_datasets && ztest_dataset_open(t) != 0) {
- umem_free(run_threads, ztest_opts.zo_threads *
- sizeof (kthread_t *));
- return;
- }
+ ndatasets = MIN(ztest_opts.zo_datasets, ztest_opts.zo_threads);
- run_threads[t] = thread_create(NULL, 0, ztest_thread,
- (void *)(uintptr_t)t, 0, NULL, TS_RUN | TS_JOINABLE,
+ /*
+ * Prepare the datasets first.
+ */
+ for (i = 0; i < ndatasets; i++)
+ VERIFY0(ztest_dataset_open(i));
+
+ /*
+ * Kick off all the tests that run in parallel.
+ */
+ for (i = 0; i < ztest_opts.zo_threads; i++) {
+ run_threads[i] = thread_create(NULL, 0, ztest_thread,
+ (void *)(uintptr_t)i, 0, NULL, TS_RUN | TS_JOINABLE,
defclsyspri);
}
/*
* Wait for all of the tests to complete.
*/
- for (t = 0; t < ztest_opts.zo_threads; t++)
- VERIFY0(thread_join(run_threads[t]));
+ for (i = 0; i < ztest_opts.zo_threads; i++)
+ VERIFY0(thread_join(run_threads[i]));
/*
* Close all datasets. This must be done after all the threads
* are joined so we can be sure none of the datasets are in-use
* by any of the threads.
*/
- for (t = 0; t < ztest_opts.zo_threads; t++) {
- if (t < ztest_opts.zo_datasets)
- ztest_dataset_close(t);
- }
+ for (i = 0; i < ndatasets; i++)
+ ztest_dataset_close(i);
txg_wait_synced(spa_get_dsl(spa), 0);
@@ -8465,6 +8471,7 @@ ztest_run(ztest_shared_t *zs)
int d = ztest_random(ztest_opts.zo_datasets);
ztest_dataset_destroy(d);
+ txg_wait_synced(spa_get_dsl(spa), 0);
}
zs->zs_enospc_count = 0;