Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
0884f1c
Refactor mirror map into header for use in other code
pcd1193182 May 19, 2025
7dc0b45
Add sync_extra logic for anyraid to use
pcd1193182 May 19, 2025
3fe3991
Add weight biasing to segment based metaslabs
pcd1193182 May 19, 2025
9e2b642
Change vdev ops to support anyraid
pcd1193182 May 19, 2025
caeea96
New spa_misc functions for anyraid
pcd1193182 May 19, 2025
174639f
Anyraid implementation
pcd1193182 May 19, 2025
f133c0c
Implement rebuild support
pcd1193182 May 31, 2025
9841b37
Add support for anyraid in vdev properties
pcd1193182 Jun 2, 2025
6be21be
Add man page entry
pcd1193182 Jun 9, 2025
a69c08b
improve byteswap logic
pcd1193182 Sep 8, 2025
24e2ce7
Use zinject to try to make test fully reliable
pcd1193182 Sep 9, 2025
f56afe8
Final byteswap handling
pcd1193182 Sep 15, 2025
4da87c3
Tony's feedback
pcd1193182 Sep 16, 2025
18e946e
Fix test failures
pcd1193182 Oct 3, 2025
7b517bb
fix printing layout
pcd1193182 Oct 3, 2025
9dab9ea
Tony feedback
pcd1193182 Oct 7, 2025
a32e2b3
Move two of the map copies to the end of the disk
pcd1193182 Oct 29, 2025
4491437
fix zdb arg and checkpoint test
pcd1193182 Oct 29, 2025
42c9e1f
punch holes in loopbacks
pcd1193182 Oct 29, 2025
b2d0ca6
Add assertion to satisfy codeql
pcd1193182 Nov 3, 2025
15226fa
Fix test bugs
pcd1193182 Nov 11, 2025
4d5de16
Don't allow sizes slightly larger than a tile
pcd1193182 Dec 19, 2025
84f50d0
Add better errors for small disks
pcd1193182 Jan 5, 2026
3247fae
fix define
pcd1193182 Jan 5, 2026
1bbc290
abi
pcd1193182 Jan 5, 2026
3858e9d
Allow arbitrary mirror width
pcd1193182 Jan 8, 2026
09622d0
Tony's feedback
pcd1193182 Jan 8, 2026
5434a5b
man page update
pcd1193182 Jan 20, 2026
7d4b57c
clean up test
pcd1193182 Jan 23, 2026
543dd45
Alek's feedback
pcd1193182 Feb 26, 2026
9eccc35
Supporting patches that clean up and prepare for phase 2
pcd1193182 Feb 25, 2026
69935fe
Add support for RAID-z style parity to AnyRAID.
pcd1193182 Sep 23, 2025
4ff4fc3
Add zpool rebalance command and functionality to AnyRAID
pcd1193182 Oct 14, 2025
6bceacd
Add vdev contraction to AnyRAID
pcd1193182 Jan 26, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
594 changes: 587 additions & 7 deletions cmd/zdb/zdb.c

Large diffs are not rendered by default.

211 changes: 209 additions & 2 deletions cmd/zpool/zpool_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,9 @@ static int zpool_do_wait(int, char **);

static int zpool_do_ddt_prune(int, char **);

static int zpool_do_rebalance(int, char **);
static int zpool_do_contract(int, char **);

static int zpool_do_help(int argc, char **argv);

static zpool_compat_status_t zpool_do_load_compat(
Expand Down Expand Up @@ -202,6 +205,8 @@ typedef enum {
HELP_REGUID,
HELP_REOPEN,
HELP_VERSION,
HELP_REBALANCE,
HELP_CONTRACT,
HELP_WAIT
} zpool_help_t;

Expand Down Expand Up @@ -433,6 +438,8 @@ static zpool_command_t command_table[] = {
{ "wait", zpool_do_wait, HELP_WAIT },
{ NULL },
{ "ddtprune", zpool_do_ddt_prune, HELP_DDT_PRUNE },
{ "rebalance", zpool_do_rebalance, HELP_REBALANCE },
{ "contract", zpool_do_contract, HELP_CONTRACT },
};

#define NCOMMAND (ARRAY_SIZE(command_table))
Expand Down Expand Up @@ -554,6 +561,11 @@ get_usage(zpool_help_t idx)
"<pool> [interval]\n"));
case HELP_DDT_PRUNE:
return (gettext("\tddtprune -d|-p <amount> <pool>\n"));
case HELP_REBALANCE:
return (gettext("\trebalance <pool> [vdev]\n"));
case HELP_CONTRACT:
return (gettext("\tcontract <pool> <anyraid vdev> "
"<leaf vdev>\n"));
default:
__builtin_unreachable();
}
Expand Down Expand Up @@ -10340,6 +10352,104 @@ print_raidz_expand_status(zpool_handle_t *zhp, pool_raidz_expand_stat_t *pres)
}
free(vname);
}

/*
* Print out detailed anyraid rebalance status.
*/
static void
print_anyraid_rebalance_status(zpool_handle_t *zhp,
pool_anyraid_relocate_stat_t *pars)
{
char copied_buf[7];

if (pars == NULL || pars->pars_state == ARS_NONE)
return;

/*
* Determine name of vdev.
*/
nvlist_t *config = zpool_get_config(zhp, NULL);
nvlist_t *nvroot = fnvlist_lookup_nvlist(config,
ZPOOL_CONFIG_VDEV_TREE);
nvlist_t **child;
uint_t children;
verify(nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
&child, &children) == 0);
assert(pars->pars_relocating_vdev < children);

printf(" ");
printf_color(ANSI_BOLD, gettext("rebalance:"));
printf(" ");

time_t start = pars->pars_start_time;
time_t end = pars->pars_end_time;
char *vname =
zpool_vdev_name(g_zfs, zhp, child[pars->pars_relocating_vdev], 0);
zfs_nicenum(pars->pars_moved, copied_buf, sizeof (copied_buf));

/*
* Expansion is finished or canceled.
*/
if (pars->pars_state == ARS_FINISHED) {
char time_buf[32];
secs_to_dhms(end - start, time_buf);

(void) printf(gettext("rebalanced %s-%u moved %s in %s, "
"on %s"), vname, (int)pars->pars_relocating_vdev,
copied_buf, time_buf, ctime((time_t *)&end));
} else {
char examined_buf[7], total_buf[7], rate_buf[7];
uint64_t copied, total, elapsed, rate, secs_left;
double fraction_done;

/*
* Expansion is in progress.
*/
(void) printf(gettext(
"rebalance of %s-%u in progress since %s"),
vname, (int)pars->pars_relocating_vdev, ctime(&start));

copied = pars->pars_moved > 0 ? pars->pars_moved : 1;
total = pars->pars_to_move;
fraction_done = (double)copied / total;

/* elapsed time for this pass */
elapsed = time(NULL) - pars->pars_start_time;
elapsed = elapsed > 0 ? elapsed : 1;
rate = copied / elapsed;
rate = rate > 0 ? rate : 1;
secs_left = (total - copied) / rate;

zfs_nicenum(copied, examined_buf, sizeof (examined_buf));
zfs_nicenum(total, total_buf, sizeof (total_buf));
zfs_nicenum(rate, rate_buf, sizeof (rate_buf));

/*
* do not print estimated time if hours_left is more than
* 30 days
*/
(void) printf(gettext("\t%s / %s copied at %s/s, %.2f%% done"),
examined_buf, total_buf, rate_buf, 100 * fraction_done);
if (pars->pars_state == ARS_SCRUBBING) {
(void) printf(gettext(", waiting for scrub to "
"complete\n"));
} else if (pars->pars_state == ARS_CONTRACTING) {
(void) printf(gettext(", removing vdev\n"));
} else if (pars->pars_waiting_for_resilver) {
(void) printf(gettext(", paused for resilver or "
"clear\n"));
} else if (secs_left < (30 * 24 * 3600)) {
char time_buf[32];
secs_to_dhms(secs_left, time_buf);
(void) printf(gettext(", %s to go\n"), time_buf);
} else {
(void) printf(gettext(
", (copy is slow, no estimated time)\n"));
}
}
free(vname);
}

static void
print_checkpoint_status(pool_checkpoint_stat_t *pcs)
{
Expand Down Expand Up @@ -11087,6 +11197,12 @@ status_callback(zpool_handle_t *zhp, void *data)
ZPOOL_CONFIG_RAIDZ_EXPAND_STATS, (uint64_t **)&pres, &c);
print_raidz_expand_status(zhp, pres);

pool_anyraid_relocate_stat_t *pars = NULL;
(void) nvlist_lookup_uint64_array(nvroot,
ZPOOL_CONFIG_ANYRAID_RELOCATE_STATS, (uint64_t **)&pars,
&c);
print_anyraid_rebalance_status(zhp, pars);

cbp->cb_namewidth = max_width(zhp, nvroot, 0, 0,
cbp->cb_name_flags | VDEV_NAME_TYPE_ID);
if (cbp->cb_namewidth < 10)
Expand Down Expand Up @@ -13313,8 +13429,10 @@ print_wait_status_row(wait_data_t *wd, zpool_handle_t *zhp, int row)
pool_scan_stat_t *pss = NULL;
pool_removal_stat_t *prs = NULL;
pool_raidz_expand_stat_t *pres = NULL;
pool_anyraid_relocate_stat_t *pars = NULL;
const char *const headers[] = {"DISCARD", "FREE", "INITIALIZE",
"REPLACE", "REMOVE", "RESILVER", "SCRUB", "TRIM", "RAIDZ_EXPAND"};
"REPLACE", "REMOVE", "RESILVER", "SCRUB", "TRIM", "RAIDZ_EXPAND",
"ANYRAID_REBALANCE"};
int col_widths[ZPOOL_WAIT_NUM_ACTIVITIES];

/* Calculate the width of each column */
Expand Down Expand Up @@ -13383,6 +13501,13 @@ print_wait_status_row(wait_data_t *wd, zpool_handle_t *zhp, int row)
bytes_rem[ZPOOL_WAIT_RAIDZ_EXPAND] = rem;
}

(void) nvlist_lookup_uint64_array(nvroot,
ZPOOL_CONFIG_ANYRAID_RELOCATE_STATS, (uint64_t **)&pars, &c);
if (pars != NULL && pars->pars_state == ARS_SCANNING) {
int64_t rem = pars->pars_to_move - pars->pars_moved;
bytes_rem[ZPOOL_WAIT_ANYRAID_RELOCATE] = rem;
}

bytes_rem[ZPOOL_WAIT_INITIALIZE] =
vdev_activity_remaining(nvroot, ZPOOL_WAIT_INITIALIZE);
bytes_rem[ZPOOL_WAIT_TRIM] =
Expand Down Expand Up @@ -13521,7 +13646,7 @@ zpool_do_wait(int argc, char **argv)
static const char *const col_opts[] = {
"discard", "free", "initialize", "replace",
"remove", "resilver", "scrub", "trim",
"raidz_expand" };
"raidz_expand", "anyraid_relocate"};

for (i = 0; i < ARRAY_SIZE(col_opts); ++i)
if (strcmp(tok, col_opts[i]) == 0) {
Expand Down Expand Up @@ -13713,6 +13838,88 @@ zpool_do_ddt_prune(int argc, char **argv)
return (error);
}

/*
* zpool rebalance <pool> [vdev]
*
* Rebalance anyraid tiles on the specific vdev, or all anyraid vdevs.
*/
int
zpool_do_rebalance(int argc, char **argv)
{
zpool_handle_t *zhp;
int c;

while ((c = getopt(argc, argv, "")) != -1) {
switch (c) {
case '?':
(void) fprintf(stderr, gettext("invalid option '%c'\n"),
optopt);
usage(B_FALSE);
}
}
argc -= optind;
argv += optind;

if (argc == 0) {
(void) fprintf(stderr, gettext("no pool provided\n"));
usage(B_FALSE);
}
char *poolname = argv[0];
argc--;
argv++;

zhp = zpool_open(g_zfs, poolname);
if (zhp == NULL)
return (-1);

int error = zpool_rebalance(zhp, argv, argc);

zpool_close(zhp);

return (error);
}

/*
* zpool contract <pool> <anyraid vdev> <leaf vdev>
*
* Contract anyraid vdev by removing a specific leaf vdev.
*/
int
zpool_do_contract(int argc, char **argv)
{
zpool_handle_t *zhp;
int c;

while ((c = getopt(argc, argv, "")) != -1) {
switch (c) {
case '?':
(void) fprintf(stderr, gettext("invalid option '%c'\n"),
optopt);
usage(B_FALSE);
}
}
argc -= optind;
argv += optind;

if (argc != 3) {
(void) fprintf(stderr, gettext("incorrect arguments\n"));
usage(B_FALSE);
}
char *poolname = argv[0];
char *anyraid_vdev = argv[1];
char *leaf_vdev = argv[2];

zhp = zpool_open(g_zfs, poolname);
if (zhp == NULL)
return (-1);

int error = zpool_contract(zhp, anyraid_vdev, leaf_vdev);

zpool_close(zhp);

return (error);
}

static int
find_command_idx(const char *command, int *idx)
{
Expand Down
Loading