Skip to content

Commit b6e8db5

Browse files
authored
zpool/zfs: Add '-a|--all' option to scrub, trim, initialize
Add support for the '-a | --all' option to perform trim, scrub, and initialize operations on all pools. Previously, specifying a pool name was mandatory for these operations. With this enhancement, users can now execute these operations across all pools at once, without needing to manually iterate over each pool from the command line. Reviewed-by: Brian Behlendorf <[email protected]> Reviewed-by: Alexander Motin <[email protected]> Reviewed-by: Tino Reichardt <[email protected]> Signed-off-by: Akash B <[email protected]> Closes #17524
1 parent fc885f3 commit b6e8db5

File tree

15 files changed

+637
-104
lines changed

15 files changed

+637
-104
lines changed

cmd/zpool/zpool_main.c

Lines changed: 102 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
* Copyright (c) 2019, loli10K <[email protected]>
3535
* Copyright (c) 2021, Colm Buckley <[email protected]>
3636
* Copyright (c) 2021, 2023, Klara Inc.
37-
* Copyright [2021] Hewlett Packard Enterprise Development LP
37+
* Copyright (c) 2021, 2025 Hewlett Packard Enterprise Development LP.
3838
*/
3939

4040
#include <assert.h>
@@ -510,16 +510,16 @@ get_usage(zpool_help_t idx)
510510
case HELP_REOPEN:
511511
return (gettext("\treopen [-n] <pool>\n"));
512512
case HELP_INITIALIZE:
513-
return (gettext("\tinitialize [-c | -s | -u] [-w] <pool> "
514-
"[<device> ...]\n"));
513+
return (gettext("\tinitialize [-c | -s | -u] [-w] <-a | <pool> "
514+
"[<device> ...]>\n"));
515515
case HELP_SCRUB:
516-
return (gettext("\tscrub [-e | -s | -p | -C] [-w] "
517-
"<pool> ...\n"));
516+
return (gettext("\tscrub [-e | -s | -p | -C] [-w] <-a | "
517+
"<pool> [<pool> ...]>\n"));
518518
case HELP_RESILVER:
519519
return (gettext("\tresilver <pool> ...\n"));
520520
case HELP_TRIM:
521-
return (gettext("\ttrim [-dw] [-r <rate>] [-c | -s] <pool> "
522-
"[<device> ...]\n"));
521+
return (gettext("\ttrim [-dw] [-r <rate>] [-c | -s] "
522+
"<-a | <pool> [<device> ...]>\n"));
523523
case HELP_STATUS:
524524
return (gettext("\tstatus [-DdegiLPpstvx] "
525525
"[-c script1[,script2,...]] ...\n"
@@ -560,33 +560,6 @@ get_usage(zpool_help_t idx)
560560
}
561561
}
562562

563-
static void
564-
zpool_collect_leaves(zpool_handle_t *zhp, nvlist_t *nvroot, nvlist_t *res)
565-
{
566-
uint_t children = 0;
567-
nvlist_t **child;
568-
uint_t i;
569-
570-
(void) nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
571-
&child, &children);
572-
573-
if (children == 0) {
574-
char *path = zpool_vdev_name(g_zfs, zhp, nvroot,
575-
VDEV_NAME_PATH);
576-
577-
if (strcmp(path, VDEV_TYPE_INDIRECT) != 0 &&
578-
strcmp(path, VDEV_TYPE_HOLE) != 0)
579-
fnvlist_add_boolean(res, path);
580-
581-
free(path);
582-
return;
583-
}
584-
585-
for (i = 0; i < children; i++) {
586-
zpool_collect_leaves(zhp, child[i], res);
587-
}
588-
}
589-
590563
/*
591564
* Callback routine that will print out a pool property value.
592565
*/
@@ -794,22 +767,26 @@ zpool_do_initialize(int argc, char **argv)
794767
int c;
795768
char *poolname;
796769
zpool_handle_t *zhp;
797-
nvlist_t *vdevs;
798770
int err = 0;
799771
boolean_t wait = B_FALSE;
772+
boolean_t initialize_all = B_FALSE;
800773

801774
struct option long_options[] = {
802775
{"cancel", no_argument, NULL, 'c'},
803776
{"suspend", no_argument, NULL, 's'},
804777
{"uninit", no_argument, NULL, 'u'},
805778
{"wait", no_argument, NULL, 'w'},
779+
{"all", no_argument, NULL, 'a'},
806780
{0, 0, 0, 0}
807781
};
808782

809783
pool_initialize_func_t cmd_type = POOL_INITIALIZE_START;
810-
while ((c = getopt_long(argc, argv, "csuw", long_options,
784+
while ((c = getopt_long(argc, argv, "acsuw", long_options,
811785
NULL)) != -1) {
812786
switch (c) {
787+
case 'a':
788+
initialize_all = B_TRUE;
789+
break;
813790
case 'c':
814791
if (cmd_type != POOL_INITIALIZE_START &&
815792
cmd_type != POOL_INITIALIZE_CANCEL) {
@@ -856,7 +833,18 @@ zpool_do_initialize(int argc, char **argv)
856833
argc -= optind;
857834
argv += optind;
858835

859-
if (argc < 1) {
836+
initialize_cbdata_t cbdata = {
837+
.wait = wait,
838+
.cmd_type = cmd_type
839+
};
840+
841+
if (initialize_all && argc > 0) {
842+
(void) fprintf(stderr, gettext("-a cannot be combined with "
843+
"individual pools or vdevs\n"));
844+
usage(B_FALSE);
845+
}
846+
847+
if (argc < 1 && !initialize_all) {
860848
(void) fprintf(stderr, gettext("missing pool name argument\n"));
861849
usage(B_FALSE);
862850
return (-1);
@@ -868,30 +856,35 @@ zpool_do_initialize(int argc, char **argv)
868856
usage(B_FALSE);
869857
}
870858

871-
poolname = argv[0];
872-
zhp = zpool_open(g_zfs, poolname);
873-
if (zhp == NULL)
874-
return (-1);
875-
876-
vdevs = fnvlist_alloc();
877-
if (argc == 1) {
878-
/* no individual leaf vdevs specified, so add them all */
879-
nvlist_t *config = zpool_get_config(zhp, NULL);
880-
nvlist_t *nvroot = fnvlist_lookup_nvlist(config,
881-
ZPOOL_CONFIG_VDEV_TREE);
882-
zpool_collect_leaves(zhp, nvroot, vdevs);
859+
if (argc == 0 && initialize_all) {
860+
/* Initilize each pool recursively */
861+
err = for_each_pool(argc, argv, B_TRUE, NULL, ZFS_TYPE_POOL,
862+
B_FALSE, zpool_initialize_one, &cbdata);
863+
return (err);
864+
} else if (argc == 1) {
865+
/* no individual leaf vdevs specified, initialize the pool */
866+
poolname = argv[0];
867+
zhp = zpool_open(g_zfs, poolname);
868+
if (zhp == NULL)
869+
return (-1);
870+
err = zpool_initialize_one(zhp, &cbdata);
883871
} else {
872+
/* individual leaf vdevs specified, initialize them */
873+
poolname = argv[0];
874+
zhp = zpool_open(g_zfs, poolname);
875+
if (zhp == NULL)
876+
return (-1);
877+
nvlist_t *vdevs = fnvlist_alloc();
884878
for (int i = 1; i < argc; i++) {
885879
fnvlist_add_boolean(vdevs, argv[i]);
886880
}
881+
if (wait)
882+
err = zpool_initialize_wait(zhp, cmd_type, vdevs);
883+
else
884+
err = zpool_initialize(zhp, cmd_type, vdevs);
885+
fnvlist_free(vdevs);
887886
}
888887

889-
if (wait)
890-
err = zpool_initialize_wait(zhp, cmd_type, vdevs);
891-
else
892-
err = zpool_initialize(zhp, cmd_type, vdevs);
893-
894-
fnvlist_free(vdevs);
895888
zpool_close(zhp);
896889

897890
return (err);
@@ -8452,10 +8445,14 @@ zpool_do_scrub(int argc, char **argv)
84528445
boolean_t is_pause = B_FALSE;
84538446
boolean_t is_stop = B_FALSE;
84548447
boolean_t is_txg_continue = B_FALSE;
8448+
boolean_t scrub_all = B_FALSE;
84558449

84568450
/* check options */
8457-
while ((c = getopt(argc, argv, "spweC")) != -1) {
8451+
while ((c = getopt(argc, argv, "aspweC")) != -1) {
84588452
switch (c) {
8453+
case 'a':
8454+
scrub_all = B_TRUE;
8455+
break;
84598456
case 'e':
84608457
is_error_scrub = B_TRUE;
84618458
break;
@@ -8519,7 +8516,7 @@ zpool_do_scrub(int argc, char **argv)
85198516
argc -= optind;
85208517
argv += optind;
85218518

8522-
if (argc < 1) {
8519+
if (argc < 1 && !scrub_all) {
85238520
(void) fprintf(stderr, gettext("missing pool name argument\n"));
85248521
usage(B_FALSE);
85258522
}
@@ -8591,18 +8588,24 @@ zpool_do_trim(int argc, char **argv)
85918588
{"rate", required_argument, NULL, 'r'},
85928589
{"suspend", no_argument, NULL, 's'},
85938590
{"wait", no_argument, NULL, 'w'},
8591+
{"all", no_argument, NULL, 'a'},
85948592
{0, 0, 0, 0}
85958593
};
85968594

85978595
pool_trim_func_t cmd_type = POOL_TRIM_START;
85988596
uint64_t rate = 0;
85998597
boolean_t secure = B_FALSE;
86008598
boolean_t wait = B_FALSE;
8599+
boolean_t trimall = B_FALSE;
8600+
int error;
86018601

86028602
int c;
8603-
while ((c = getopt_long(argc, argv, "cdr:sw", long_options, NULL))
8603+
while ((c = getopt_long(argc, argv, "acdr:sw", long_options, NULL))
86048604
!= -1) {
86058605
switch (c) {
8606+
case 'a':
8607+
trimall = B_TRUE;
8608+
break;
86068609
case 'c':
86078610
if (cmd_type != POOL_TRIM_START &&
86088611
cmd_type != POOL_TRIM_CANCEL) {
@@ -8661,49 +8664,65 @@ zpool_do_trim(int argc, char **argv)
86618664
argc -= optind;
86628665
argv += optind;
86638666

8664-
if (argc < 1) {
8667+
trimflags_t trim_flags = {
8668+
.secure = secure,
8669+
.rate = rate,
8670+
.wait = wait,
8671+
};
8672+
8673+
trim_cbdata_t cbdata = {
8674+
.trim_flags = trim_flags,
8675+
.cmd_type = cmd_type
8676+
};
8677+
8678+
if (argc < 1 && !trimall) {
86658679
(void) fprintf(stderr, gettext("missing pool name argument\n"));
86668680
usage(B_FALSE);
86678681
return (-1);
86688682
}
86698683

86708684
if (wait && (cmd_type != POOL_TRIM_START)) {
86718685
(void) fprintf(stderr, gettext("-w cannot be used with -c or "
8672-
"-s\n"));
8686+
"-s options\n"));
86738687
usage(B_FALSE);
86748688
}
86758689

8676-
char *poolname = argv[0];
8677-
zpool_handle_t *zhp = zpool_open(g_zfs, poolname);
8678-
if (zhp == NULL)
8679-
return (-1);
8680-
8681-
trimflags_t trim_flags = {
8682-
.secure = secure,
8683-
.rate = rate,
8684-
.wait = wait,
8685-
};
8690+
if (trimall && argc > 0) {
8691+
(void) fprintf(stderr, gettext("-a cannot be combined with "
8692+
"individual zpools or vdevs\n"));
8693+
usage(B_FALSE);
8694+
}
86868695

8687-
nvlist_t *vdevs = fnvlist_alloc();
8688-
if (argc == 1) {
8696+
if (argc == 0 && trimall) {
8697+
cbdata.trim_flags.fullpool = B_TRUE;
8698+
/* Trim each pool recursively */
8699+
error = for_each_pool(argc, argv, B_TRUE, NULL, ZFS_TYPE_POOL,
8700+
B_FALSE, zpool_trim_one, &cbdata);
8701+
} else if (argc == 1) {
8702+
char *poolname = argv[0];
8703+
zpool_handle_t *zhp = zpool_open(g_zfs, poolname);
8704+
if (zhp == NULL)
8705+
return (-1);
86898706
/* no individual leaf vdevs specified, so add them all */
8690-
nvlist_t *config = zpool_get_config(zhp, NULL);
8691-
nvlist_t *nvroot = fnvlist_lookup_nvlist(config,
8692-
ZPOOL_CONFIG_VDEV_TREE);
8693-
zpool_collect_leaves(zhp, nvroot, vdevs);
8694-
trim_flags.fullpool = B_TRUE;
8707+
error = zpool_trim_one(zhp, &cbdata);
8708+
zpool_close(zhp);
86958709
} else {
8696-
trim_flags.fullpool = B_FALSE;
8710+
char *poolname = argv[0];
8711+
zpool_handle_t *zhp = zpool_open(g_zfs, poolname);
8712+
if (zhp == NULL)
8713+
return (-1);
8714+
/* leaf vdevs specified, trim only those */
8715+
cbdata.trim_flags.fullpool = B_FALSE;
8716+
nvlist_t *vdevs = fnvlist_alloc();
86978717
for (int i = 1; i < argc; i++) {
86988718
fnvlist_add_boolean(vdevs, argv[i]);
86998719
}
8720+
error = zpool_trim(zhp, cbdata.cmd_type, vdevs,
8721+
&cbdata.trim_flags);
8722+
fnvlist_free(vdevs);
8723+
zpool_close(zhp);
87008724
}
87018725

8702-
int error = zpool_trim(zhp, cmd_type, vdevs, &trim_flags);
8703-
8704-
fnvlist_free(vdevs);
8705-
zpool_close(zhp);
8706-
87078726
return (error);
87088727
}
87098728

include/libzfs.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
* Copyright (c) 2017 Open-E, Inc. All Rights Reserved.
3131
* Copyright (c) 2019 Datto Inc.
3232
* Copyright (c) 2021, Colm Buckley <[email protected]>
33+
* Copyright (c) 2025 Hewlett Packard Enterprise Development LP.
3334
*/
3435

3536
#ifndef _LIBZFS_H
@@ -288,10 +289,20 @@ typedef struct trimflags {
288289
uint64_t rate;
289290
} trimflags_t;
290291

292+
typedef struct trim_cbdata {
293+
trimflags_t trim_flags;
294+
pool_trim_func_t cmd_type;
295+
} trim_cbdata_t;
296+
297+
typedef struct initialize_cbdata {
298+
boolean_t wait;
299+
pool_initialize_func_t cmd_type;
300+
} initialize_cbdata_t;
291301
/*
292302
* Functions to manipulate pool and vdev state
293303
*/
294304
_LIBZFS_H int zpool_scan(zpool_handle_t *, pool_scan_func_t, pool_scrub_cmd_t);
305+
_LIBZFS_H int zpool_initialize_one(zpool_handle_t *, void *);
295306
_LIBZFS_H int zpool_initialize(zpool_handle_t *, pool_initialize_func_t,
296307
nvlist_t *);
297308
_LIBZFS_H int zpool_initialize_wait(zpool_handle_t *, pool_initialize_func_t,
@@ -304,7 +315,9 @@ _LIBZFS_H int zpool_reguid(zpool_handle_t *);
304315
_LIBZFS_H int zpool_set_guid(zpool_handle_t *, const uint64_t *);
305316
_LIBZFS_H int zpool_reopen_one(zpool_handle_t *, void *);
306317

318+
_LIBZFS_H void zpool_collect_leaves(zpool_handle_t *, nvlist_t *, nvlist_t *);
307319
_LIBZFS_H int zpool_sync_one(zpool_handle_t *, void *);
320+
_LIBZFS_H int zpool_trim_one(zpool_handle_t *, void *);
308321

309322
_LIBZFS_H int zpool_ddt_prune(zpool_handle_t *, zpool_ddt_prune_unit_t,
310323
uint64_t);

lib/libuutil/libuutil.abi

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1475,6 +1475,11 @@
14751475
<parameter type-id='80f4b756' name='name'/>
14761476
<return type-id='a27af98c'/>
14771477
</function-decl>
1478+
<function-decl name='zfs_tunable_iter' mangled-name='zfs_tunable_iter' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_tunable_iter'>
1479+
<parameter type-id='d8d5f4ab' name='cb'/>
1480+
<parameter type-id='eaa32e2f' name='arg'/>
1481+
<return type-id='48b5725f'/>
1482+
</function-decl>
14781483
<function-decl name='zfs_tunable_set' mangled-name='zfs_tunable_set' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_tunable_set'>
14791484
<parameter type-id='a27af98c' name='zt'/>
14801485
<parameter type-id='80f4b756' name='val'/>
@@ -1486,11 +1491,6 @@
14861491
<parameter type-id='b59d7dce' name='valsz'/>
14871492
<return type-id='95e97e5e'/>
14881493
</function-decl>
1489-
<function-decl name='zfs_tunable_iter' mangled-name='zfs_tunable_iter' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_tunable_iter'>
1490-
<parameter type-id='d8d5f4ab' name='cb'/>
1491-
<parameter type-id='eaa32e2f' name='arg'/>
1492-
<return type-id='48b5725f'/>
1493-
</function-decl>
14941494
<function-type size-in-bits='64' id='92f86508'>
14951495
<parameter type-id='a27af98c'/>
14961496
<parameter type-id='eaa32e2f'/>

0 commit comments

Comments
 (0)