Skip to content

Commit 0d23aff

Browse files
committed
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. Signed-off-by: Akash B <[email protected]>
1 parent 4c2a7f8 commit 0d23aff

File tree

13 files changed

+732
-98
lines changed

13 files changed

+732
-98
lines changed

cmd/zpool/zpool_main.c

Lines changed: 104 additions & 85 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> "
513+
return (gettext("\tinitialize [-c | -s | -u] [-w] <-a | pool> "
514514
"[<device> ...]\n"));
515515
case HELP_SCRUB:
516-
return (gettext("\tscrub [-e | -s | -p | -C] [-w] "
516+
return (gettext("\tscrub [-e | -s | -p | -C] [-w] <-a | pool> "
517517
"<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,34 +767,38 @@ 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':
814-
if (cmd_type != POOL_INITIALIZE_START &&
815-
cmd_type != POOL_INITIALIZE_CANCEL) {
791+
if ((cmd_type != POOL_INITIALIZE_START &&
792+
cmd_type != POOL_INITIALIZE_CANCEL)) {
816793
(void) fprintf(stderr, gettext("-c cannot be "
817794
"combined with other options\n"));
818795
usage(B_FALSE);
819796
}
820797
cmd_type = POOL_INITIALIZE_CANCEL;
821798
break;
822799
case 's':
823-
if (cmd_type != POOL_INITIALIZE_START &&
824-
cmd_type != POOL_INITIALIZE_SUSPEND) {
800+
if ((cmd_type != POOL_INITIALIZE_START &&
801+
cmd_type != POOL_INITIALIZE_SUSPEND)) {
825802
(void) fprintf(stderr, gettext("-s cannot be "
826803
"combined with other options\n"));
827804
usage(B_FALSE);
@@ -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 zpools 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);
@@ -8454,10 +8447,14 @@ zpool_do_scrub(int argc, char **argv)
84548447
boolean_t is_pause = B_FALSE;
84558448
boolean_t is_stop = B_FALSE;
84568449
boolean_t is_txg_continue = B_FALSE;
8450+
boolean_t scrub_all = B_FALSE;
84578451

84588452
/* check options */
8459-
while ((c = getopt(argc, argv, "spweC")) != -1) {
8453+
while ((c = getopt(argc, argv, "aspweC")) != -1) {
84608454
switch (c) {
8455+
case 'a':
8456+
scrub_all = B_TRUE;
8457+
break;
84618458
case 'e':
84628459
is_error_scrub = B_TRUE;
84638460
break;
@@ -8521,7 +8518,7 @@ zpool_do_scrub(int argc, char **argv)
85218518
argc -= optind;
85228519
argv += optind;
85238520

8524-
if (argc < 1) {
8521+
if (argc < 1 && !scrub_all) {
85258522
(void) fprintf(stderr, gettext("missing pool name argument\n"));
85268523
usage(B_FALSE);
85278524
}
@@ -8593,18 +8590,24 @@ zpool_do_trim(int argc, char **argv)
85938590
{"rate", required_argument, NULL, 'r'},
85948591
{"suspend", no_argument, NULL, 's'},
85958592
{"wait", no_argument, NULL, 'w'},
8593+
{"all", no_argument, NULL, 'a'},
85968594
{0, 0, 0, 0}
85978595
};
85988596

85998597
pool_trim_func_t cmd_type = POOL_TRIM_START;
86008598
uint64_t rate = 0;
86018599
boolean_t secure = B_FALSE;
86028600
boolean_t wait = B_FALSE;
8601+
boolean_t trimall = B_FALSE;
8602+
int error;
86038603

86048604
int c;
8605-
while ((c = getopt_long(argc, argv, "cdr:sw", long_options, NULL))
8605+
while ((c = getopt_long(argc, argv, "acdr:sw", long_options, NULL))
86068606
!= -1) {
86078607
switch (c) {
8608+
case 'a':
8609+
trimall = B_TRUE;
8610+
break;
86088611
case 'c':
86098612
if (cmd_type != POOL_TRIM_START &&
86108613
cmd_type != POOL_TRIM_CANCEL) {
@@ -8663,49 +8666,65 @@ zpool_do_trim(int argc, char **argv)
86638666
argc -= optind;
86648667
argv += optind;
86658668

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

86728686
if (wait && (cmd_type != POOL_TRIM_START)) {
86738687
(void) fprintf(stderr, gettext("-w cannot be used with -c or "
8674-
"-s\n"));
8688+
"-s options\n"));
86758689
usage(B_FALSE);
86768690
}
86778691

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

8689-
nvlist_t *vdevs = fnvlist_alloc();
8690-
if (argc == 1) {
8698+
if (argc == 0 && trimall) {
8699+
cbdata.trim_flags.fullpool = B_TRUE;
8700+
/* Trim each pool recursively */
8701+
error = for_each_pool(argc, argv, B_TRUE, NULL, ZFS_TYPE_POOL,
8702+
B_FALSE, zpool_trim_one, &cbdata);
8703+
} else if (argc == 1) {
8704+
char *poolname = argv[0];
8705+
zpool_handle_t *zhp = zpool_open(g_zfs, poolname);
8706+
if (zhp == NULL)
8707+
return (-1);
86918708
/* no individual leaf vdevs specified, so add them all */
8692-
nvlist_t *config = zpool_get_config(zhp, NULL);
8693-
nvlist_t *nvroot = fnvlist_lookup_nvlist(config,
8694-
ZPOOL_CONFIG_VDEV_TREE);
8695-
zpool_collect_leaves(zhp, nvroot, vdevs);
8696-
trim_flags.fullpool = B_TRUE;
8709+
error = zpool_trim_one(zhp, &cbdata);
8710+
zpool_close(zhp);
86978711
} else {
8698-
trim_flags.fullpool = B_FALSE;
8712+
char *poolname = argv[0];
8713+
zpool_handle_t *zhp = zpool_open(g_zfs, poolname);
8714+
if (zhp == NULL)
8715+
return (-1);
8716+
/* leaf vdevs specified, trim only those */
8717+
cbdata.trim_flags.fullpool = B_FALSE;
8718+
nvlist_t *vdevs = fnvlist_alloc();
86998719
for (int i = 1; i < argc; i++) {
87008720
fnvlist_add_boolean(vdevs, argv[i]);
87018721
}
8722+
error = zpool_trim(zhp, cbdata.cmd_type, vdevs,
8723+
&cbdata.trim_flags);
8724+
fnvlist_free(vdevs);
8725+
zpool_close(zhp);
87028726
}
87038727

8704-
int error = zpool_trim(zhp, cmd_type, vdevs, &trim_flags);
8705-
8706-
fnvlist_free(vdevs);
8707-
zpool_close(zhp);
8708-
87098728
return (error);
87108729
}
87118730

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);

0 commit comments

Comments
 (0)