diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h index 83586063f..26ba5456f 100644 --- a/lib/metadata/metadata-exported.h +++ b/lib/metadata/metadata-exported.h @@ -882,6 +882,8 @@ uint64_t vg_max_pv(const struct volume_group *vg); uint64_t vg_max_lv(const struct volume_group *vg); uint32_t vg_mda_count(const struct volume_group *vg); uint32_t vg_mda_used_count(const struct volume_group *vg); +#define VGMETADATACOPIES_ALL UINT32_MAX +#define VGMETADATACOPIES_UNMANAGED 0 uint32_t vg_mda_copies(const struct volume_group *vg); int vg_set_mda_copies(struct volume_group *vg, uint32_t value); int vg_check_write_mode(struct volume_group *vg); diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c index d17bf742d..45bc72b8e 100644 --- a/lib/metadata/metadata.c +++ b/lib/metadata/metadata.c @@ -1063,7 +1063,7 @@ static int _vg_adjust_ignored_mdas(struct volume_group *vg) int ret = 1; mda_copies = vg_mda_used_count(vg); - if (!vg->mda_copies) + if (vg->mda_copies == VGMETADATACOPIES_UNMANAGED) goto skip_adjust; if (mda_copies > vg->mda_copies) { @@ -1076,6 +1076,15 @@ static int _vg_adjust_ignored_mdas(struct volume_group *vg) count = vg->mda_copies - mda_copies; ret = _vg_unignore_mdas(vg, count); } + /* + * The VGMETADATACOPIES_ALL value will never be written disk. + * It is a special cmdline value that means 2 things: + * 1. clear all ignore bits in all mdas in this vg + * 2. set the "unmanaged" policy going forward for metadata balancing + */ + if (vg->mda_copies == VGMETADATACOPIES_ALL) + vg->mda_copies = VGMETADATACOPIES_UNMANAGED; + if (!ret) return ret; diff --git a/lib/report/report.c b/lib/report/report.c index 57c257d66..9a7633412 100644 --- a/lib/report/report.c +++ b/lib/report/report.c @@ -926,6 +926,11 @@ static int _vgmdacopies_disp(struct dm_report *rh, struct dm_pool *mem, count = vg_mda_copies(vg); + if (count == VGMETADATACOPIES_UNMANAGED) { + dm_report_field_set_value(field, "unmanaged", &_minusone64); + return 1; + } + return _uint32_disp(rh, mem, field, &count, private); } diff --git a/tools/args.h b/tools/args.h index 60d99d15e..ebce2520e 100644 --- a/tools/args.h +++ b/tools/args.h @@ -23,7 +23,7 @@ arg(physicalvolumesize_ARG, '\0', "setphysicalvolumesize", size_mb_arg, 0) arg(ignorelockingfailure_ARG, '\0', "ignorelockingfailure", NULL, 0) arg(nolocking_ARG, '\0', "nolocking", NULL, 0) arg(pvmetadatacopies_ARG, '\0', "pvmetadatacopies", int_arg, 0) -arg(vgmetadatacopies_ARG, '\0', "vgmetadatacopies", int_arg, 0) +arg(vgmetadatacopies_ARG, '\0', "vgmetadatacopies", vgmetadatacopies_arg, 0) arg(metadatacopies_ARG, '\0', "metadatacopies", int_arg, 0) arg(metadatasize_ARG, '\0', "metadatasize", size_mb_arg, 0) arg(metadataignore_ARG, '\0', "metadataignore", yes_no_arg, 0) diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c index 45762b50d..4652888d2 100644 --- a/tools/lvmcmdline.c +++ b/tools/lvmcmdline.c @@ -473,6 +473,34 @@ int readahead_arg(struct cmd_context *cmd __attribute((unused)), struct arg *a) return 1; } +/* + * Non-zero, positive integer, "all", or "unmanaged" + */ +int vgmetadatacopies_arg(struct cmd_context *cmd __attribute((unused)), + struct arg *a) +{ + if (!strcasecmp(a->value, "all")) { + a->ui_value = VGMETADATACOPIES_ALL; + return 1; + } + + if (!strcasecmp(a->value, "unmanaged")) { + a->ui_value = VGMETADATACOPIES_UNMANAGED; + return 1; + } + + if (!_size_arg(cmd, a, 1)) + return 0; + + if (a->sign == SIGN_MINUS) + return 0; + + if (!a->ui_value) + return 0; + + return 1; +} + static void __alloc(int size) { if (!(_cmdline.commands = dm_realloc(_cmdline.commands, sizeof(*_cmdline.commands) * size))) { diff --git a/tools/tools.h b/tools/tools.h index d96b8dc35..a09fa8e8e 100644 --- a/tools/tools.h +++ b/tools/tools.h @@ -152,6 +152,8 @@ int units_arg(struct cmd_context *cmd, struct arg *a); int segtype_arg(struct cmd_context *cmd, struct arg *a); int alloc_arg(struct cmd_context *cmd, struct arg *a); int readahead_arg(struct cmd_context *cmd, struct arg *a); +int vgmetadatacopies_arg(struct cmd_context *cmd __attribute((unused)), + struct arg *a); /* we use the enums to access the switches */ unsigned arg_count(const struct cmd_context *cmd, int a);