mirror of
git://sourceware.org/git/lvm2.git
synced 2025-10-06 11:33:14 +03:00
Compare commits
1 Commits
dev-lvmguy
...
dev-dct-cm
Author | SHA1 | Date | |
---|---|---|---|
|
cd8d65b0b8 |
@@ -1,11 +1,5 @@
|
||||
Version 2.02.165 -
|
||||
===================================
|
||||
Avoid PV tags when checking allocation against parallel PVs.
|
||||
Disallow mirror conversions of raid10 volumes.
|
||||
Fix dmeventd unmonitoring when segment type (and dso) changes.
|
||||
Don't allow lvconvert --repair on raid0 devices or attempt to monitor them.
|
||||
No longer adjust incorrect number of raid stripes supplied to lvcreate.
|
||||
Move lcm and gcd to lib/misc.
|
||||
Suppress some unnecessary --stripesize parameter warnings.
|
||||
Fix 'pvmove -n name ...' to prohibit collocation of RAID SubLVs
|
||||
|
||||
|
@@ -50,7 +50,6 @@
|
||||
@top_srcdir@/lib/misc/lvm-file.h
|
||||
@top_srcdir@/lib/misc/lvm-flock.h
|
||||
@top_srcdir@/lib/misc/lvm-globals.h
|
||||
@top_srcdir@/lib/misc/lvm-maths.h
|
||||
@top_srcdir@/lib/misc/lvm-percent.h
|
||||
@top_srcdir@/lib/misc/lvm-signal.h
|
||||
@top_srcdir@/lib/misc/lvm-string.h
|
||||
|
@@ -112,7 +112,6 @@ SOURCES =\
|
||||
misc/lvm-file.c \
|
||||
misc/lvm-flock.c \
|
||||
misc/lvm-globals.c \
|
||||
misc/lvm-maths.c \
|
||||
misc/lvm-signal.c \
|
||||
misc/lvm-string.c \
|
||||
misc/lvm-wrappers.c \
|
||||
|
@@ -1548,7 +1548,7 @@ static struct dm_event_handler *_create_dm_event_handler(struct cmd_context *cmd
|
||||
if (dm_event_handler_set_dmeventd_path(dmevh, find_config_tree_str(cmd, dmeventd_executable_CFG, NULL)))
|
||||
goto_bad;
|
||||
|
||||
if (dso && dm_event_handler_set_dso(dmevh, dso))
|
||||
if (dm_event_handler_set_dso(dmevh, dso))
|
||||
goto_bad;
|
||||
|
||||
if (dm_event_handler_set_uuid(dmevh, dmuuid))
|
||||
@@ -1592,39 +1592,6 @@ static char *_build_target_uuid(struct cmd_context *cmd, const struct logical_vo
|
||||
return build_dm_uuid(cmd->mem, lv, layer);
|
||||
}
|
||||
|
||||
static int _device_registered_with_dmeventd(struct cmd_context *cmd, const struct logical_volume *lv, int *pending, const char **dso)
|
||||
{
|
||||
char *uuid;
|
||||
enum dm_event_mask evmask = 0;
|
||||
struct dm_event_handler *dmevh;
|
||||
|
||||
*pending = 0;
|
||||
|
||||
if (!(uuid = _build_target_uuid(cmd, lv)))
|
||||
return_0;
|
||||
|
||||
if (!(dmevh = _create_dm_event_handler(cmd, uuid, NULL, 0, DM_EVENT_ALL_ERRORS)))
|
||||
return_0;
|
||||
|
||||
if (dm_event_get_registered_device(dmevh, 0)) {
|
||||
dm_event_handler_destroy(dmevh);
|
||||
return 0;
|
||||
}
|
||||
|
||||
evmask = dm_event_handler_get_event_mask(dmevh);
|
||||
if (evmask & DM_EVENT_REGISTRATION_PENDING) {
|
||||
*pending = 1;
|
||||
evmask &= ~DM_EVENT_REGISTRATION_PENDING;
|
||||
}
|
||||
|
||||
if (dso && (*dso = dm_event_handler_get_dso(dmevh)) && !(*dso = dm_pool_strdup(cmd->mem, *dso)))
|
||||
log_error("Failed to duplicate dso name.");
|
||||
|
||||
dm_event_handler_destroy(dmevh);
|
||||
|
||||
return evmask;
|
||||
}
|
||||
|
||||
int target_registered_with_dmeventd(struct cmd_context *cmd, const char *dso,
|
||||
const struct logical_volume *lv, int *pending)
|
||||
{
|
||||
@@ -1707,8 +1674,6 @@ int monitor_dev_for_events(struct cmd_context *cmd, const struct logical_volume
|
||||
uint32_t s;
|
||||
static const struct lv_activate_opts zlaopts = { 0 };
|
||||
struct lvinfo info;
|
||||
const char *dso;
|
||||
int new_unmonitor;
|
||||
|
||||
if (!laopts)
|
||||
laopts = &zlaopts;
|
||||
@@ -1816,58 +1781,42 @@ int monitor_dev_for_events(struct cmd_context *cmd, const struct logical_volume
|
||||
!seg->segtype->ops->target_monitored) /* doesn't support registration */
|
||||
continue;
|
||||
|
||||
if (!monitor)
|
||||
/* When unmonitoring, obtain existing dso being used. */
|
||||
monitored = _device_registered_with_dmeventd(cmd, seg->lv, &pending, &dso);
|
||||
else
|
||||
monitored = seg->segtype->ops->target_monitored(seg, &pending);
|
||||
monitored = seg->segtype->ops->target_monitored(seg, &pending);
|
||||
|
||||
/* FIXME: We should really try again if pending */
|
||||
monitored = (pending) ? 0 : monitored;
|
||||
|
||||
monitor_fn = NULL;
|
||||
new_unmonitor = 0;
|
||||
|
||||
if (monitor) {
|
||||
if (monitored)
|
||||
log_verbose("%s already monitored.", display_lvname(lv));
|
||||
else if (seg->segtype->ops->target_monitor_events) {
|
||||
log_verbose("Monitoring %s%s", display_lvname(lv), test_mode() ? " [Test mode: skipping this]" : "");
|
||||
else if (seg->segtype->ops->target_monitor_events)
|
||||
monitor_fn = seg->segtype->ops->target_monitor_events;
|
||||
}
|
||||
} else {
|
||||
if (!monitored)
|
||||
log_verbose("%s already not monitored.", display_lvname(lv));
|
||||
else if (*dso) {
|
||||
/*
|
||||
* Divert unmonitor away from code that depends on the new segment
|
||||
* type instead of the existing one if it's changing.
|
||||
*/
|
||||
log_verbose("Not monitoring %s with %s%s", display_lvname(lv), dso, test_mode() ? " [Test mode: skipping this]" : "");
|
||||
new_unmonitor = 1;
|
||||
}
|
||||
else if (seg->segtype->ops->target_unmonitor_events)
|
||||
monitor_fn = seg->segtype->ops->target_unmonitor_events;
|
||||
}
|
||||
|
||||
/* Do [un]monitor */
|
||||
if (!monitor_fn)
|
||||
continue;
|
||||
|
||||
log_verbose("%sonitoring %s%s", monitor ? "M" : "Not m", display_lvname(lv),
|
||||
test_mode() ? " [Test mode: skipping this]" : "");
|
||||
|
||||
/* FIXME Test mode should really continue a bit further. */
|
||||
if (test_mode())
|
||||
continue;
|
||||
|
||||
if (new_unmonitor) {
|
||||
if (!target_register_events(cmd, dso, lv, 0, 0, 10)) {
|
||||
log_error("%s: segment unmonitoring failed.",
|
||||
display_lvname(lv));
|
||||
|
||||
return 0;
|
||||
}
|
||||
} else if (monitor_fn) {
|
||||
/* FIXME specify events */
|
||||
if (!monitor_fn(seg, 0)) {
|
||||
log_error("%s: %s segment monitoring function failed.",
|
||||
display_lvname(lv), seg->segtype->name);
|
||||
return 0;
|
||||
}
|
||||
} else
|
||||
continue;
|
||||
/* FIXME specify events */
|
||||
if (!monitor_fn(seg, 0)) {
|
||||
log_error("%s: %s segment monitoring function failed.",
|
||||
display_lvname(lv), seg->segtype->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check [un]monitor results */
|
||||
/* Try a couple times if pending, but not forever... */
|
||||
|
@@ -90,7 +90,7 @@ struct cmd_context {
|
||||
const char *cmd_line;
|
||||
struct command *command;
|
||||
char **argv;
|
||||
struct arg_values *arg_values;
|
||||
struct arg_values *opt_arg_values;
|
||||
struct dm_list arg_value_groups;
|
||||
|
||||
/*
|
||||
|
@@ -391,7 +391,7 @@ static int _read_segment(struct logical_volume *lv, const struct dm_config_node
|
||||
|
||||
if (!(seg = alloc_lv_segment(segtype, lv, start_extent,
|
||||
extent_count, 0, 0, NULL, area_count,
|
||||
segtype->parity_devs ? (extent_count / (area_count - segtype->parity_devs)) : extent_count, 0, 0, 0, NULL))) {
|
||||
extent_count, 0, 0, 0, NULL))) {
|
||||
log_error("Segment allocation failed");
|
||||
return 0;
|
||||
}
|
||||
|
@@ -38,6 +38,9 @@ typedef enum {
|
||||
NEXT_AREA
|
||||
} area_use_t;
|
||||
|
||||
/* FIXME: remove RAID_METADATA_AREA_LEN macro after defining 'raid_log_extents'*/
|
||||
#define RAID_METADATA_AREA_LEN 1
|
||||
|
||||
/* FIXME These ended up getting used differently from first intended. Refactor. */
|
||||
/* Only one of A_CONTIGUOUS_TO_LVSEG, A_CLING_TO_LVSEG, A_CLING_TO_ALLOCED may be set */
|
||||
#define A_CONTIGUOUS_TO_LVSEG 0x01 /* Must be contiguous to an existing segment */
|
||||
@@ -875,51 +878,22 @@ dm_percent_t copy_percent(const struct logical_volume *lv)
|
||||
return denominator ? dm_make_percent(numerator, denominator) : DM_PERCENT_100;
|
||||
}
|
||||
|
||||
/* Round any tiny extents to multiples of 4K */
|
||||
#define MINIMUM_ALLOCATION_SECTORS 8
|
||||
static uint32_t _round_extents(uint32_t extents, uint32_t extent_size, int extend)
|
||||
{
|
||||
uint64_t size = (uint64_t) extents * extent_size;
|
||||
uint64_t rest = size % MINIMUM_ALLOCATION_SECTORS;
|
||||
|
||||
if (!rest)
|
||||
return extents;
|
||||
|
||||
if (!size)
|
||||
return 0;
|
||||
|
||||
rest = MINIMUM_ALLOCATION_SECTORS - rest;
|
||||
|
||||
return (size + (extend ? rest : -(MINIMUM_ALLOCATION_SECTORS - rest))) / extent_size;
|
||||
}
|
||||
|
||||
/* Round up extents to next stripe boundary for number of stripes and ensure minimum sizes */
|
||||
static uint32_t _round_extents_to_boundary(struct volume_group *vg, uint32_t extents,
|
||||
uint32_t stripes, uint32_t stripe_size, int extend)
|
||||
/* Round up extents to next stripe boundary for number of stripes */
|
||||
static uint32_t _round_to_stripe_boundary(struct volume_group *vg, uint32_t extents,
|
||||
uint32_t stripes, int extend)
|
||||
{
|
||||
uint32_t size_rest, new_extents = extents;
|
||||
|
||||
if (stripes < 2)
|
||||
return _round_extents(extents, vg->extent_size, extend);
|
||||
if (!stripes)
|
||||
return extents;
|
||||
|
||||
redo:
|
||||
/* Round up extents to stripe divisible amount */
|
||||
if ((size_rest = new_extents % stripes))
|
||||
if ((size_rest = extents % stripes)) {
|
||||
new_extents += extend ? stripes - size_rest : -size_rest;
|
||||
|
||||
if (stripes > 1 && stripe_size > 1) {
|
||||
uint32_t tmp = new_extents;
|
||||
|
||||
if ((new_extents = _round_extents(tmp / stripes, vg->extent_size, extend) * stripes) != tmp)
|
||||
goto redo;
|
||||
}
|
||||
|
||||
log_debug("Adjusted allocation request of %" PRIu32 " to %" PRIu32 " logical extents.", extents, new_extents);
|
||||
|
||||
if (new_extents != extents)
|
||||
log_print_unless_silent("Rounding size %s (%d extents) up to boundary size %s (%d extents).",
|
||||
log_print_unless_silent("Rounding size %s (%d extents) up to stripe boundary size %s (%d extents).",
|
||||
display_size(vg->cmd, (uint64_t) extents * vg->extent_size), extents,
|
||||
display_size(vg->cmd, (uint64_t) new_extents * vg->extent_size), new_extents);
|
||||
}
|
||||
|
||||
return new_extents;
|
||||
}
|
||||
@@ -1229,8 +1203,6 @@ static uint32_t _calc_area_multiple(const struct segment_type *segtype,
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME:
|
||||
*
|
||||
* RAID10 - only has 2-way mirror right now.
|
||||
* If we are to move beyond 2-way RAID10, then
|
||||
* the 'stripes' argument will always need to
|
||||
@@ -1258,14 +1230,14 @@ static int _lv_segment_reduce(struct lv_segment *seg, uint32_t reduction)
|
||||
uint32_t area_reduction, s;
|
||||
|
||||
/* Caller must ensure exact divisibility */
|
||||
if (seg_is_striped(seg) || (seg_is_raid(seg) && !seg_is_raid1(seg))) {
|
||||
if (reduction % (seg->area_count - seg->segtype->parity_devs)) {
|
||||
if (seg_is_striped(seg)) {
|
||||
if (reduction % seg->area_count) {
|
||||
log_error("Segment extent reduction %" PRIu32
|
||||
" not divisible by #stripes %" PRIu32,
|
||||
reduction, seg->area_count);
|
||||
return 0;
|
||||
}
|
||||
area_reduction = reduction / (seg->area_count - seg->segtype->parity_devs);
|
||||
area_reduction = (reduction / seg->area_count);
|
||||
} else
|
||||
area_reduction = reduction;
|
||||
|
||||
@@ -1609,13 +1581,11 @@ static uint32_t _mirror_log_extents(uint32_t region_size, uint32_t pe_size, uint
|
||||
|
||||
/* Is there enough total space or should we give up immediately? */
|
||||
static int _sufficient_pes_free(struct alloc_handle *ah, struct dm_list *pvms,
|
||||
uint32_t allocated, uint32_t extents_still_needed,
|
||||
uint32_t extent_size)
|
||||
uint32_t allocated, uint32_t extents_still_needed)
|
||||
{
|
||||
uint32_t area_extents_needed = (extents_still_needed - allocated) * ah->area_count / ah->area_multiple;
|
||||
uint32_t parity_extents_needed = (extents_still_needed - allocated) * ah->parity_count / ah->area_multiple;
|
||||
uint32_t metadata_extents_needed = ah->alloc_and_split_meta ? 0 :
|
||||
ah->metadata_area_count * lv_raid_metadata_area_len(ah->region_size, extent_size);
|
||||
uint32_t metadata_extents_needed = ah->alloc_and_split_meta ? 0 : ah->metadata_area_count * RAID_METADATA_AREA_LEN; /* One each */
|
||||
uint32_t total_extents_needed = area_extents_needed + parity_extents_needed + metadata_extents_needed;
|
||||
uint32_t free_pes = pv_maps_size(pvms);
|
||||
|
||||
@@ -1704,6 +1674,49 @@ static void _init_alloc_parms(struct alloc_handle *ah,
|
||||
alloc_parms->flags |= A_CAN_SPLIT;
|
||||
}
|
||||
|
||||
static int _log_parallel_areas(struct dm_pool *mem, struct dm_list *parallel_areas)
|
||||
{
|
||||
struct seg_pvs *spvs;
|
||||
struct pv_list *pvl;
|
||||
char *pvnames;
|
||||
|
||||
if (!parallel_areas)
|
||||
return 1;
|
||||
|
||||
dm_list_iterate_items(spvs, parallel_areas) {
|
||||
if (!dm_pool_begin_object(mem, 256)) {
|
||||
log_error("dm_pool_begin_object failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
dm_list_iterate_items(pvl, &spvs->pvs) {
|
||||
if (!dm_pool_grow_object(mem, pv_dev_name(pvl->pv), strlen(pv_dev_name(pvl->pv)))) {
|
||||
log_error("dm_pool_grow_object failed");
|
||||
dm_pool_abandon_object(mem);
|
||||
return 0;
|
||||
}
|
||||
if (!dm_pool_grow_object(mem, " ", 1)) {
|
||||
log_error("dm_pool_grow_object failed");
|
||||
dm_pool_abandon_object(mem);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!dm_pool_grow_object(mem, "\0", 1)) {
|
||||
log_error("dm_pool_grow_object failed");
|
||||
dm_pool_abandon_object(mem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pvnames = dm_pool_end_object(mem);
|
||||
log_debug_alloc("Parallel PVs at LE %" PRIu32 " length %" PRIu32 ": %s",
|
||||
spvs->le, spvs->len, pvnames);
|
||||
dm_pool_free(mem, pvnames);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Handles also stacking */
|
||||
static int _setup_lv_size(struct logical_volume *lv, uint32_t extents)
|
||||
{
|
||||
@@ -2017,20 +2030,25 @@ static int _is_same_pv(struct pv_match *pvmatch __attribute((unused)), struct pv
|
||||
/*
|
||||
* Does PV area have a tag listed in allocation/cling_tag_list that
|
||||
* matches EITHER a tag of the PV of the existing segment OR a tag in pv_tags?
|
||||
* If mem is set, then instead we append a list of matching tags for printing to the object there.
|
||||
* If tags_list_str is set, then instead we generate a list of matching tags for printing.
|
||||
*/
|
||||
static int _match_pv_tags(const struct dm_config_node *cling_tag_list_cn,
|
||||
struct physical_volume *pv1, uint32_t pv1_start_pe, uint32_t area_num,
|
||||
struct physical_volume *pv2, struct dm_list *pv_tags, unsigned validate_only,
|
||||
struct dm_pool *mem, unsigned parallel_pv)
|
||||
struct dm_pool *mem, const char **tags_list_str)
|
||||
{
|
||||
const struct dm_config_value *cv;
|
||||
const char *str;
|
||||
const char *tag_matched;
|
||||
struct dm_list *tags_to_match = mem ? NULL : pv_tags ? : &pv2->tags;
|
||||
struct dm_list *tags_to_match = tags_list_str ? NULL : pv_tags ? : &pv2->tags;
|
||||
struct dm_str_list *sl;
|
||||
unsigned first_tag = 1;
|
||||
|
||||
if (tags_list_str && !dm_pool_begin_object(mem, 256)) {
|
||||
log_error("PV tags string allocation failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (cv = cling_tag_list_cn->v; cv; cv = cv->next) {
|
||||
if (cv->type != DM_CFG_STRING) {
|
||||
if (validate_only)
|
||||
@@ -2067,14 +2085,16 @@ static int _match_pv_tags(const struct dm_config_node *cling_tag_list_cn,
|
||||
|
||||
/* Wildcard matches any tag against any tag. */
|
||||
if (!strcmp(str, "*")) {
|
||||
if (mem) {
|
||||
if (tags_list_str) {
|
||||
dm_list_iterate_items(sl, &pv1->tags) {
|
||||
if (!first_tag && !dm_pool_grow_object(mem, ",", 0)) {
|
||||
dm_pool_abandon_object(mem);
|
||||
log_error("PV tags string extension failed.");
|
||||
return 0;
|
||||
}
|
||||
first_tag = 0;
|
||||
if (!dm_pool_grow_object(mem, sl->str, 0)) {
|
||||
dm_pool_abandon_object(mem);
|
||||
log_error("PV tags string extension failed.");
|
||||
return 0;
|
||||
}
|
||||
@@ -2084,14 +2104,10 @@ static int _match_pv_tags(const struct dm_config_node *cling_tag_list_cn,
|
||||
if (!str_list_match_list(&pv1->tags, tags_to_match, &tag_matched))
|
||||
continue;
|
||||
else {
|
||||
if (!pv_tags) {
|
||||
if (parallel_pv)
|
||||
log_debug_alloc("Not using free space on %s: Matched allocation PV tag %s on existing parallel PV %s.",
|
||||
pv_dev_name(pv1), tag_matched, pv2 ? pv_dev_name(pv2) : "-");
|
||||
else
|
||||
log_debug_alloc("Matched allocation PV tag %s on existing %s with free space on %s.",
|
||||
tag_matched, pv_dev_name(pv1), pv2 ? pv_dev_name(pv2) : "-");
|
||||
} else
|
||||
if (!pv_tags)
|
||||
log_debug_alloc("Matched allocation PV tag %s on existing %s with free space on %s.",
|
||||
tag_matched, pv_dev_name(pv1), pv2 ? pv_dev_name(pv2) : "-");
|
||||
else
|
||||
log_debug_alloc("Eliminating allocation area %" PRIu32 " at PV %s start PE %" PRIu32
|
||||
" from consideration: PV tag %s already used.",
|
||||
area_num, pv_dev_name(pv1), pv1_start_pe, tag_matched);
|
||||
@@ -2103,26 +2119,24 @@ static int _match_pv_tags(const struct dm_config_node *cling_tag_list_cn,
|
||||
(tags_to_match && !str_list_match_item(tags_to_match, str)))
|
||||
continue;
|
||||
else {
|
||||
if (mem) {
|
||||
if (tags_list_str) {
|
||||
if (!first_tag && !dm_pool_grow_object(mem, ",", 0)) {
|
||||
dm_pool_abandon_object(mem);
|
||||
log_error("PV tags string extension failed.");
|
||||
return 0;
|
||||
}
|
||||
first_tag = 0;
|
||||
if (!dm_pool_grow_object(mem, str, 0)) {
|
||||
dm_pool_abandon_object(mem);
|
||||
log_error("PV tags string extension failed.");
|
||||
return 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (!pv_tags) {
|
||||
if (parallel_pv)
|
||||
log_debug_alloc("Not using free space on %s: Matched allocation PV tag %s on existing parallel PV %s.",
|
||||
pv2 ? pv_dev_name(pv2) : "-", str, pv_dev_name(pv1));
|
||||
else
|
||||
log_debug_alloc("Matched allocation PV tag %s on existing %s with free space on %s.",
|
||||
str, pv_dev_name(pv1), pv2 ? pv_dev_name(pv2) : "-");
|
||||
} else
|
||||
if (!pv_tags)
|
||||
log_debug_alloc("Matched allocation PV tag %s on existing %s with free space on %s.",
|
||||
str, pv_dev_name(pv1), pv2 ? pv_dev_name(pv2) : "-");
|
||||
else
|
||||
log_debug_alloc("Eliminating allocation area %" PRIu32 " at PV %s start PE %" PRIu32
|
||||
" from consideration: PV tag %s already used.",
|
||||
area_num, pv_dev_name(pv1), pv1_start_pe, str);
|
||||
@@ -2130,25 +2144,32 @@ static int _match_pv_tags(const struct dm_config_node *cling_tag_list_cn,
|
||||
}
|
||||
}
|
||||
|
||||
if (mem)
|
||||
if (tags_list_str) {
|
||||
if (!dm_pool_grow_object(mem, "\0", 1)) {
|
||||
dm_pool_abandon_object(mem);
|
||||
log_error("PV tags string extension failed.");
|
||||
return 0;
|
||||
}
|
||||
*tags_list_str = dm_pool_end_object(mem);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _validate_tag_list(const struct dm_config_node *cling_tag_list_cn)
|
||||
{
|
||||
return _match_pv_tags(cling_tag_list_cn, NULL, 0, 0, NULL, NULL, 1, NULL, 0);
|
||||
return _match_pv_tags(cling_tag_list_cn, NULL, 0, 0, NULL, NULL, 1, NULL, NULL);
|
||||
}
|
||||
|
||||
static int _tags_list_str(struct dm_pool *mem, struct physical_volume *pv1, const struct dm_config_node *cling_tag_list_cn)
|
||||
static const char *_tags_list_str(struct alloc_handle *ah, struct physical_volume *pv1)
|
||||
{
|
||||
if (!_match_pv_tags(cling_tag_list_cn, pv1, 0, 0, NULL, NULL, 0, mem, 0)) {
|
||||
dm_pool_abandon_object(mem);
|
||||
return_0;
|
||||
}
|
||||
const char *tags_list_str;
|
||||
|
||||
return 1;
|
||||
if (!_match_pv_tags(ah->cling_tag_list_cn, pv1, 0, 0, NULL, NULL, 0, ah->mem, &tags_list_str))
|
||||
return_NULL;
|
||||
|
||||
return tags_list_str;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2159,7 +2180,7 @@ static int _pv_has_matching_tag(const struct dm_config_node *cling_tag_list_cn,
|
||||
struct physical_volume *pv1, uint32_t pv1_start_pe, uint32_t area_num,
|
||||
struct dm_list *pv_tags)
|
||||
{
|
||||
return _match_pv_tags(cling_tag_list_cn, pv1, pv1_start_pe, area_num, NULL, pv_tags, 0, NULL, 0);
|
||||
return _match_pv_tags(cling_tag_list_cn, pv1, pv1_start_pe, area_num, NULL, pv_tags, 0, NULL, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2167,82 +2188,14 @@ static int _pv_has_matching_tag(const struct dm_config_node *cling_tag_list_cn,
|
||||
* matches a tag of the PV of the existing segment?
|
||||
*/
|
||||
static int _pvs_have_matching_tag(const struct dm_config_node *cling_tag_list_cn,
|
||||
struct physical_volume *pv1, struct physical_volume *pv2,
|
||||
unsigned parallel_pv)
|
||||
struct physical_volume *pv1, struct physical_volume *pv2)
|
||||
{
|
||||
return _match_pv_tags(cling_tag_list_cn, pv1, 0, 0, pv2, NULL, 0, NULL, parallel_pv);
|
||||
return _match_pv_tags(cling_tag_list_cn, pv1, 0, 0, pv2, NULL, 0, NULL, NULL);
|
||||
}
|
||||
|
||||
static int _has_matching_pv_tag(struct pv_match *pvmatch, struct pv_segment *pvseg, struct pv_area *pva)
|
||||
{
|
||||
return _pvs_have_matching_tag(pvmatch->cling_tag_list_cn, pvseg->pv, pva->map->pv, 0);
|
||||
}
|
||||
|
||||
static int _log_parallel_areas(struct dm_pool *mem, struct dm_list *parallel_areas,
|
||||
const struct dm_config_node *cling_tag_list_cn)
|
||||
{
|
||||
struct seg_pvs *spvs;
|
||||
struct pv_list *pvl;
|
||||
char *pvnames;
|
||||
unsigned first;
|
||||
|
||||
if (!parallel_areas)
|
||||
return 1;
|
||||
|
||||
dm_list_iterate_items(spvs, parallel_areas) {
|
||||
first = 1;
|
||||
|
||||
if (!dm_pool_begin_object(mem, 256)) {
|
||||
log_error("dm_pool_begin_object failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
dm_list_iterate_items(pvl, &spvs->pvs) {
|
||||
if (!first && !dm_pool_grow_object(mem, " ", 1)) {
|
||||
log_error("dm_pool_grow_object failed");
|
||||
dm_pool_abandon_object(mem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dm_pool_grow_object(mem, pv_dev_name(pvl->pv), strlen(pv_dev_name(pvl->pv)))) {
|
||||
log_error("dm_pool_grow_object failed");
|
||||
dm_pool_abandon_object(mem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (cling_tag_list_cn) {
|
||||
if (!dm_pool_grow_object(mem, "(", 1)) {
|
||||
log_error("dm_pool_grow_object failed");
|
||||
dm_pool_abandon_object(mem);
|
||||
return 0;
|
||||
}
|
||||
if (!_tags_list_str(mem, pvl->pv, cling_tag_list_cn)) {
|
||||
dm_pool_abandon_object(mem);
|
||||
return_0;
|
||||
}
|
||||
if (!dm_pool_grow_object(mem, ")", 1)) {
|
||||
log_error("dm_pool_grow_object failed");
|
||||
dm_pool_abandon_object(mem);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
first = 0;
|
||||
}
|
||||
|
||||
if (!dm_pool_grow_object(mem, "\0", 1)) {
|
||||
log_error("dm_pool_grow_object failed");
|
||||
dm_pool_abandon_object(mem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pvnames = dm_pool_end_object(mem);
|
||||
log_debug_alloc("Parallel PVs at LE %" PRIu32 " length %" PRIu32 ": %s",
|
||||
spvs->le, spvs->len, pvnames);
|
||||
dm_pool_free(mem, pvnames);
|
||||
}
|
||||
|
||||
return 1;
|
||||
return _pvs_have_matching_tag(pvmatch->cling_tag_list_cn, pvseg->pv, pva->map->pv);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2265,17 +2218,8 @@ static void _reserve_area(struct alloc_handle *ah, struct alloc_state *alloc_sta
|
||||
struct pv_area_used *area_used = &alloc_state->areas[ix_pva];
|
||||
const char *pv_tag_list = NULL;
|
||||
|
||||
if (ah->cling_tag_list_cn) {
|
||||
if (!dm_pool_begin_object(ah->mem, 256))
|
||||
log_error("PV tags string allocation failed");
|
||||
else if (!_tags_list_str(ah->mem, pva->map->pv, ah->cling_tag_list_cn))
|
||||
dm_pool_abandon_object(ah->mem);
|
||||
else if (!dm_pool_grow_object(ah->mem, "\0", 1)) {
|
||||
dm_pool_abandon_object(ah->mem);
|
||||
log_error("PV tags string extension failed.");
|
||||
} else
|
||||
pv_tag_list = dm_pool_end_object(ah->mem);
|
||||
}
|
||||
if (ah->cling_tag_list_cn)
|
||||
pv_tag_list = _tags_list_str(ah, pva->map->pv);
|
||||
|
||||
log_debug_alloc("%s allocation area %" PRIu32 " %s %s start PE %" PRIu32
|
||||
" length %" PRIu32 " leaving %" PRIu32 "%s%s.",
|
||||
@@ -2434,7 +2378,7 @@ static int _check_cling_to_alloced(struct alloc_handle *ah, const struct dm_conf
|
||||
continue; /* Area already assigned */
|
||||
dm_list_iterate_items(aa, &ah->alloced_areas[s]) {
|
||||
if ((!cling_tag_list_cn && (pva->map->pv == aa[0].pv)) ||
|
||||
(cling_tag_list_cn && _pvs_have_matching_tag(cling_tag_list_cn, pva->map->pv, aa[0].pv, 0))) {
|
||||
(cling_tag_list_cn && _pvs_have_matching_tag(cling_tag_list_cn, pva->map->pv, aa[0].pv))) {
|
||||
if (positional)
|
||||
_reserve_required_area(ah, alloc_state, pva, pva->count, s, 0);
|
||||
return 1;
|
||||
@@ -2445,20 +2389,13 @@ static int _check_cling_to_alloced(struct alloc_handle *ah, const struct dm_conf
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _pv_is_parallel(struct physical_volume *pv, struct dm_list *parallel_pvs, const struct dm_config_node *cling_tag_list_cn)
|
||||
static int _pv_is_parallel(struct physical_volume *pv, struct dm_list *parallel_pvs)
|
||||
{
|
||||
struct pv_list *pvl;
|
||||
|
||||
dm_list_iterate_items(pvl, parallel_pvs) {
|
||||
if (pv == pvl->pv) {
|
||||
log_debug_alloc("Not using free space on existing parallel PV %s.",
|
||||
pv_dev_name(pvl->pv));
|
||||
dm_list_iterate_items(pvl, parallel_pvs)
|
||||
if (pv == pvl->pv)
|
||||
return 1;
|
||||
}
|
||||
if (cling_tag_list_cn && _pvs_have_matching_tag(cling_tag_list_cn, pvl->pv, pv, 1))
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -2746,7 +2683,7 @@ static int _find_some_parallel_space(struct alloc_handle *ah,
|
||||
/* FIXME Split into log and non-log parallel_pvs and only check the log ones if log_iteration? */
|
||||
/* (I've temporatily disabled the check.) */
|
||||
/* Avoid PVs used by existing parallel areas */
|
||||
if (!log_iteration_count && parallel_pvs && _pv_is_parallel(pvm->pv, parallel_pvs, ah->cling_tag_list_cn))
|
||||
if (!log_iteration_count && parallel_pvs && _pv_is_parallel(pvm->pv, parallel_pvs))
|
||||
goto next_pv;
|
||||
|
||||
/*
|
||||
@@ -3064,7 +3001,7 @@ static int _allocate(struct alloc_handle *ah,
|
||||
if (!(pvms = create_pv_maps(ah->mem, vg, allocatable_pvs)))
|
||||
return_0;
|
||||
|
||||
if (!_log_parallel_areas(ah->mem, ah->parallel_areas, ah->cling_tag_list_cn))
|
||||
if (!_log_parallel_areas(ah->mem, ah->parallel_areas))
|
||||
stack;
|
||||
|
||||
alloc_state.areas_size = dm_list_size(pvms);
|
||||
@@ -3105,7 +3042,7 @@ static int _allocate(struct alloc_handle *ah,
|
||||
old_allocated = alloc_state.allocated;
|
||||
log_debug_alloc("Trying allocation using %s policy.", get_alloc_string(alloc));
|
||||
|
||||
if (!ah->approx_alloc && !_sufficient_pes_free(ah, pvms, alloc_state.allocated, ah->new_extents, vg->extent_size))
|
||||
if (!ah->approx_alloc && !_sufficient_pes_free(ah, pvms, alloc_state.allocated, ah->new_extents))
|
||||
goto_out;
|
||||
|
||||
_init_alloc_parms(ah, &alloc_parms, alloc, prev_lvseg,
|
||||
@@ -3298,7 +3235,7 @@ static struct alloc_handle *_alloc_init(struct cmd_context *cmd,
|
||||
ah->metadata_area_count = area_count;
|
||||
ah->alloc_and_split_meta = 1;
|
||||
|
||||
ah->log_len = lv_raid_metadata_area_len(ah->region_size, extent_size);
|
||||
ah->log_len = RAID_METADATA_AREA_LEN;
|
||||
|
||||
/*
|
||||
* We need 'log_len' extents for each
|
||||
@@ -3877,7 +3814,8 @@ static int _lv_extend_layered_lv(struct alloc_handle *ah,
|
||||
if (seg_is_raid(seg)) {
|
||||
stripes = 1;
|
||||
stripe_size = 0;
|
||||
area_multiple = _calc_area_multiple(seg->segtype, seg->area_count, seg_is_raid1(seg) ? 1 : seg->area_count - seg->segtype->parity_devs);
|
||||
if (seg_is_any_raid0(seg))
|
||||
area_multiple = seg->area_count;
|
||||
}
|
||||
|
||||
for (fa = first_area, s = 0; s < seg->area_count; s++) {
|
||||
@@ -4000,82 +3938,6 @@ static int _lv_extend_layered_lv(struct alloc_handle *ah,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Adjust region and stripe size on very small LVs */
|
||||
void lv_adjust_region_and_stripe_size(struct logical_volume *lv)
|
||||
{
|
||||
uint32_t size;
|
||||
uint64_t area_size;
|
||||
struct lv_segment *seg = first_seg(lv);
|
||||
|
||||
if (!seg)
|
||||
return;
|
||||
|
||||
area_size = (uint64_t) seg->area_len * lv->vg->extent_size;
|
||||
|
||||
if (seg->region_size > area_size) {
|
||||
size = _round_down_pow2(seg_lv(seg, 0)->size);
|
||||
log_warn("Region size %s too large for LV %s size %s, rounded down to %s",
|
||||
display_size(lv->vg->cmd, seg->region_size),
|
||||
display_lvname(lv),
|
||||
display_size(lv->vg->cmd, lv->size),
|
||||
display_size(lv->vg->cmd, size));
|
||||
seg->region_size = size;
|
||||
}
|
||||
|
||||
if (seg->stripe_size > area_size) {
|
||||
size = _round_down_pow2(seg_lv(seg, 0)->size);
|
||||
log_warn("Stripe size %s too large for LV %s size %s, rounded down to %s",
|
||||
display_size(lv->vg->cmd, seg->stripe_size),
|
||||
display_lvname(lv),
|
||||
display_size(lv->vg->cmd, lv->size),
|
||||
display_size(lv->vg->cmd, size));
|
||||
seg->stripe_size = size;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check MetaLV size is sufficient fro RaidLV @lv size */
|
||||
#define RAID_SUPERBLOCKS_SIZE (2 * 4096) /* dm-raid superblock and bitmap superblock */
|
||||
static int _raid_rmeta_size_sufficient(struct logical_volume *lv)
|
||||
{
|
||||
uint32_t area_multiple;
|
||||
uint64_t max_rimage_size;
|
||||
uint64_t mlv_bytes; /* dm-raid superblock and bitmap superblock */
|
||||
struct lv_segment *seg = first_seg(lv);
|
||||
struct logical_volume *mlv;
|
||||
|
||||
if (!seg ||
|
||||
!seg_is_raid(seg) ||
|
||||
!seg->region_size ||
|
||||
!seg->meta_areas ||
|
||||
!(mlv = seg_metalv(seg, 0)))
|
||||
return 1;
|
||||
|
||||
mlv_bytes = mlv->size << SECTOR_SHIFT;
|
||||
if (mlv_bytes < RAID_SUPERBLOCKS_SIZE) {
|
||||
log_error("Metadata LV %s too small to even hold the RAID headers",
|
||||
display_lvname(mlv));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Subtract space for 2 headers (superblock and bitmap)
|
||||
* and calculate max image size in sectors
|
||||
*/
|
||||
max_rimage_size = (mlv_bytes - RAID_SUPERBLOCKS_SIZE) * 8 * seg->region_size;
|
||||
|
||||
/* Calculate the maximum possible LV size */
|
||||
/* FIXME: area_multiple needs to change once we support odd number of stripes in raid10 */
|
||||
area_multiple = _calc_area_multiple(seg->segtype, seg->area_count, 0);
|
||||
if (max_rimage_size * area_multiple < lv->size) {
|
||||
log_error("Can't extend LV %s larger than %s because of MetaLV size",
|
||||
display_lvname(lv),
|
||||
display_size(lv->vg->cmd, max_rimage_size * area_multiple));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Entry point for single-step LV allocation + extension.
|
||||
* Extents is the number of logical extents to append to the LV unless
|
||||
@@ -4093,7 +3955,7 @@ int lv_extend(struct logical_volume *lv,
|
||||
struct dm_list *allocatable_pvs, alloc_policy_t alloc,
|
||||
int approx_alloc)
|
||||
{
|
||||
int r = 1, empty = 0;
|
||||
int r = 1;
|
||||
int log_count = 0;
|
||||
struct alloc_handle *ah;
|
||||
uint32_t sub_lv_count;
|
||||
@@ -4106,8 +3968,6 @@ int lv_extend(struct logical_volume *lv,
|
||||
return lv_add_virtual_segment(lv, 0u, extents, segtype);
|
||||
|
||||
if (!lv->le_count) {
|
||||
empty = 1;
|
||||
|
||||
if (segtype_is_pool(segtype))
|
||||
/*
|
||||
* Pool allocations treat the metadata device like a mirror log.
|
||||
@@ -4138,8 +3998,6 @@ int lv_extend(struct logical_volume *lv,
|
||||
if (!(r = lv_add_segment(ah, 0, ah->area_count, lv, segtype,
|
||||
stripe_size, 0u, 0)))
|
||||
stack;
|
||||
if (empty)
|
||||
lv_adjust_region_and_stripe_size(lv);
|
||||
} else {
|
||||
/*
|
||||
* For RAID, all the devices are AREA_LV.
|
||||
@@ -4165,17 +4023,6 @@ int lv_extend(struct logical_volume *lv,
|
||||
stripes, stripe_size)))
|
||||
goto_out;
|
||||
|
||||
if (empty)
|
||||
lv_adjust_region_and_stripe_size(lv);
|
||||
|
||||
if (!(r = _raid_rmeta_size_sufficient(lv))) {
|
||||
if (!old_extents &&
|
||||
(!lv_remove(lv) || !vg_write(lv->vg) || !vg_commit(lv->vg)))
|
||||
return_0;
|
||||
|
||||
goto_out;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we are expanding an existing mirror, we can skip the
|
||||
* resync of the extension if the LV is currently in-sync
|
||||
@@ -4486,7 +4333,6 @@ static int _validate_stripesize(const struct volume_group *vg,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Limit stripe size to extent size for non-RAID */
|
||||
if (lp->stripe_size > vg->extent_size) {
|
||||
log_print_unless_silent("Reducing stripe size %s to maximum, "
|
||||
"physical extent size %s.",
|
||||
@@ -4980,10 +4826,6 @@ static int _lvresize_adjust_extents(struct logical_volume *lv,
|
||||
(lp->sign == SIGN_NONE && (lp->extents < existing_extents)))
|
||||
reducing = 1;
|
||||
|
||||
lp->extents = _round_extents_to_boundary(lv->vg, lp->extents,
|
||||
seg_is_mirrored(seg_last) ? 1 : seg_last->area_count - seg_last->segtype->parity_devs,
|
||||
seg_last->stripe_size, !reducing);
|
||||
|
||||
/* If extending, find properties of last segment */
|
||||
if (!reducing) {
|
||||
seg_mirrors = seg_is_mirrored(seg_last) ? lv_mirror_count(lv) : 0;
|
||||
@@ -7242,17 +7084,6 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
|
||||
}
|
||||
}
|
||||
|
||||
#if 1
|
||||
/* FIXME: minimum 1K extent size??? */
|
||||
if (lp->stripe_size > vg->extent_size &&
|
||||
!seg_is_raid(lp)) {
|
||||
log_print_unless_silent("Reducing requested stripe size %s to maximum, "
|
||||
"physical extent size %s.",
|
||||
display_size(cmd, (uint64_t) lp->stripe_size),
|
||||
display_size(cmd, (uint64_t) vg->extent_size));
|
||||
lp->stripe_size = vg->extent_size;
|
||||
}
|
||||
#else
|
||||
if (lp->stripe_size > vg->extent_size) {
|
||||
if (seg_is_raid(lp) && (vg->extent_size < STRIPE_SIZE_MIN)) {
|
||||
/*
|
||||
@@ -7274,9 +7105,8 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
|
||||
display_size(cmd, (uint64_t) vg->extent_size));
|
||||
lp->stripe_size = vg->extent_size;
|
||||
}
|
||||
#endif
|
||||
|
||||
lp->extents = _round_extents_to_boundary(vg, lp->extents, lp->stripes, lp->stripe_size, 1);
|
||||
lp->extents = _round_to_stripe_boundary(vg, lp->extents, lp->stripes, 1);
|
||||
|
||||
if (!lp->extents && !seg_is_thin_volume(lp)) {
|
||||
log_error(INTERNAL_ERROR "Unable to create new logical volume with no extents.");
|
||||
@@ -7428,7 +7258,6 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
|
||||
status |= LV_NOTSYNCED;
|
||||
}
|
||||
|
||||
if (!seg_is_raid(lp))
|
||||
lp->region_size = adjusted_mirror_region_size(vg->extent_size,
|
||||
lp->extents,
|
||||
lp->region_size, 0,
|
||||
|
@@ -413,8 +413,9 @@ int check_lv_segments(struct logical_volume *lv, int complete_vg)
|
||||
inc_error_count;
|
||||
}
|
||||
|
||||
area_multiplier = (segtype_is_striped(seg->segtype) || (seg_is_raid(seg) && !seg_is_raid1(seg))) ?
|
||||
(seg->area_count - seg->segtype->parity_devs) : 1;
|
||||
area_multiplier = segtype_is_striped(seg->segtype) ?
|
||||
seg->area_count : 1;
|
||||
|
||||
if (seg->area_len * area_multiplier != seg->len) {
|
||||
log_error("LV %s: segment %u has inconsistent "
|
||||
"area_len %u",
|
||||
|
@@ -30,11 +30,10 @@
|
||||
#define MAX_STRIPES 128U
|
||||
#define SECTOR_SHIFT 9L
|
||||
#define SECTOR_SIZE ( 1L << SECTOR_SHIFT )
|
||||
#define STRIPE_SIZE_MIN 8 /* 8 sectors minimum to allow for raid takover of striped */
|
||||
#define STRIPE_SIZE_MIN ( (unsigned) lvm_getpagesize() >> SECTOR_SHIFT) /* PAGESIZE in sectors */
|
||||
#define STRIPE_SIZE_MAX ( 512L * 1024L >> SECTOR_SHIFT) /* 512 KB in sectors */
|
||||
#define STRIPE_SIZE_LIMIT ((UINT_MAX >> 2) + 1)
|
||||
#define MAX_RESTRICTED_LVS 255 /* Used by FMT_RESTRICTED_LVIDS */
|
||||
#define MIN_EXTENT_SIZE 8 /* 8 sectors minimum to allow for raid takover of striped */
|
||||
#define MAX_EXTENT_SIZE ((uint32_t) -1)
|
||||
#define MIN_NON_POWER2_EXTENT_SIZE (128U * 2U) /* 128KB in sectors */
|
||||
|
||||
@@ -826,7 +825,6 @@ int lv_rename_update(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
/* Updates and reloads metadata for given lv */
|
||||
int lv_update_and_reload(struct logical_volume *lv);
|
||||
int lv_update_and_reload_origin(struct logical_volume *lv);
|
||||
void lv_adjust_region_and_stripe_size(struct logical_volume *lv);
|
||||
|
||||
uint32_t extents_from_size(struct cmd_context *cmd, uint64_t size,
|
||||
uint32_t extent_size);
|
||||
@@ -947,9 +945,6 @@ struct lvcreate_params {
|
||||
uint32_t chunk_size; /* snapshot */
|
||||
uint32_t region_size; /* mirror */
|
||||
|
||||
unsigned stripes_supplied; /* striped */
|
||||
unsigned stripe_size_supplied; /* striped */
|
||||
|
||||
uint32_t mirrors; /* mirror */
|
||||
|
||||
uint32_t min_recovery_rate; /* RAID */
|
||||
@@ -1214,7 +1209,6 @@ int lv_raid_replace(struct logical_volume *lv, struct dm_list *remove_pvs,
|
||||
struct dm_list *allocate_pvs);
|
||||
int lv_raid_remove_missing(struct logical_volume *lv);
|
||||
int partial_raid_lv_supports_degraded_activation(const struct logical_volume *lv);
|
||||
uint32_t lv_raid_metadata_area_len(uint32_t region_size, uint32_t extent_size);
|
||||
/* -- metadata/raid_manip.c */
|
||||
|
||||
/* ++ metadata/cache_manip.c */
|
||||
|
@@ -1008,11 +1008,6 @@ int vgcreate_params_validate(struct cmd_context *cmd,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (vp->extent_size < MIN_EXTENT_SIZE) {
|
||||
log_error("Physical extent size < 4 KiB restricts RAID use.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(cmd->fmt->features & FMT_UNLIMITED_VOLS)) {
|
||||
if (!vp->max_lv)
|
||||
vp->max_lv = 255;
|
||||
|
@@ -430,6 +430,28 @@ int validate_pool_chunk_size(struct cmd_context *cmd,
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Greatest common divisor */
|
||||
static unsigned long _gcd(unsigned long n1, unsigned long n2)
|
||||
{
|
||||
unsigned long remainder;
|
||||
|
||||
do {
|
||||
remainder = n1 % n2;
|
||||
n1 = n2;
|
||||
n2 = remainder;
|
||||
} while (n2);
|
||||
|
||||
return n1;
|
||||
}
|
||||
|
||||
/* Least common multiple */
|
||||
static unsigned long _lcm(unsigned long n1, unsigned long n2)
|
||||
{
|
||||
if (!n1 || !n2)
|
||||
return 0;
|
||||
return (n1 * n2) / _gcd(n1, n2);
|
||||
}
|
||||
|
||||
int recalculate_pool_chunk_size_with_dev_hints(struct logical_volume *pool_lv,
|
||||
int passed_args,
|
||||
int chunk_size_calc_policy)
|
||||
@@ -475,7 +497,7 @@ int recalculate_pool_chunk_size_with_dev_hints(struct logical_volume *pool_lv,
|
||||
continue;
|
||||
|
||||
if (previous_hint)
|
||||
hint = lcm(previous_hint, hint);
|
||||
hint = _lcm(previous_hint, hint);
|
||||
previous_hint = hint;
|
||||
break;
|
||||
case AREA_LV:
|
||||
|
@@ -151,26 +151,6 @@ int lv_is_raid_with_tracking(const struct logical_volume *lv)
|
||||
return _lv_is_raid_with_tracking(lv, &tracking);
|
||||
}
|
||||
|
||||
/* FIXME: remove lv_raid_metadata_area_len() after defining 'lv_raid_rmeta_extents'*/
|
||||
uint32_t lv_raid_metadata_area_len(uint32_t region_size, uint32_t extent_size)
|
||||
{
|
||||
uint32_t r;
|
||||
uint64_t max_lv_size;
|
||||
|
||||
if (!region_size)
|
||||
region_size++;
|
||||
|
||||
/* Ensure senseful minimum metadata device size until we get dynamic rmeta resizing... */
|
||||
max_lv_size = UINT32_MAX / 2;
|
||||
max_lv_size *= extent_size;
|
||||
max_lv_size = min(max_lv_size, (uint64_t) 2048 * 1024 * 1024 * 128);
|
||||
r = (max_lv_size / region_size / (8*2048*extent_size) ?: 1);
|
||||
if (r * extent_size < 2 * 12)
|
||||
r = 2 * 12;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
uint32_t lv_raid_image_count(const struct logical_volume *lv)
|
||||
{
|
||||
struct lv_segment *seg = first_seg(lv);
|
||||
@@ -648,9 +628,6 @@ static int _alloc_image_components(struct logical_volume *lv,
|
||||
else
|
||||
region_size = seg->region_size;
|
||||
|
||||
if (!region_size)
|
||||
region_size = get_default_region_size(lv->vg->cmd);
|
||||
|
||||
if (seg_is_raid(seg))
|
||||
segtype = seg->segtype;
|
||||
else if (!(segtype = get_segtype_from_string(lv->vg->cmd, SEG_TYPE_NAME_RAID1)))
|
||||
@@ -732,7 +709,6 @@ static int _alloc_rmeta_for_lv(struct logical_volume *data_lv,
|
||||
struct logical_volume **meta_lv,
|
||||
struct dm_list *allocate_pvs)
|
||||
{
|
||||
uint32_t region_size;
|
||||
struct dm_list allocatable_pvs;
|
||||
struct alloc_handle *ah;
|
||||
struct lv_segment *seg = first_seg(data_lv);
|
||||
@@ -759,10 +735,9 @@ static int _alloc_rmeta_for_lv(struct logical_volume *data_lv,
|
||||
if (!(base_name = top_level_lv_name(data_lv->vg, data_lv->name)))
|
||||
return_0;
|
||||
|
||||
region_size = seg->region_size ?: get_default_region_size(data_lv->vg->cmd);
|
||||
if (!(ah = allocate_extents(data_lv->vg, NULL, seg->segtype, 0, 1, 0,
|
||||
seg->region_size,
|
||||
lv_raid_metadata_area_len(region_size, data_lv->vg->extent_size),
|
||||
1 /*RAID_METADATA_AREA_LEN*/,
|
||||
allocate_pvs, data_lv->alloc, 0, NULL)))
|
||||
return_0;
|
||||
|
||||
@@ -870,9 +845,7 @@ static int _raid_add_images_without_commit(struct logical_volume *lv,
|
||||
lv->status |= RAID;
|
||||
seg = first_seg(lv);
|
||||
seg_lv(seg, 0)->status |= RAID_IMAGE | LVM_READ | LVM_WRITE;
|
||||
if (!seg->region_size)
|
||||
seg->region_size = get_default_region_size(lv->vg->cmd);
|
||||
seg->stripe_size = 0;
|
||||
seg->region_size = get_default_region_size(lv->vg->cmd);
|
||||
|
||||
/* MD's bitmap is limited to tracking 2^21 regions */
|
||||
while (seg->region_size < (lv->size / (1 << 21))) {
|
||||
@@ -2547,7 +2520,7 @@ static struct possible_takeover_reshape_type _possible_takeover_reshape_types[]
|
||||
.current_areas = 1,
|
||||
.options = ALLOW_STRIPE_SIZE },
|
||||
{ .current_types = SEG_STRIPED_TARGET, /* striped, i.e. seg->area_count > 1 */
|
||||
.possible_types = SEG_RAID0|SEG_RAID0_META|SEG_RAID4,
|
||||
.possible_types = SEG_RAID0|SEG_RAID0_META,
|
||||
.current_areas = ~0U,
|
||||
.options = ALLOW_NONE },
|
||||
/* raid0* -> */
|
||||
@@ -2913,7 +2886,7 @@ static int _raid456_to_raid0_or_striped_wrapper(TAKEOVER_FN_ARGS)
|
||||
return_0;
|
||||
|
||||
/* FIXME Hard-coded raid4 to raid0 */
|
||||
seg->area_len = seg->extents_copied = seg->len / (seg->area_count - seg->segtype->parity_devs);
|
||||
seg->area_len = seg->extents_copied = seg->area_len / seg->area_count;
|
||||
|
||||
if (segtype_is_striped_target(new_segtype)) {
|
||||
if (!_convert_raid0_to_striped(lv, 0, &removal_lvs))
|
||||
@@ -2999,13 +2972,10 @@ static int _striped_or_raid0_to_raid45610_wrapper(TAKEOVER_FN_ARGS)
|
||||
|
||||
seg->segtype = new_segtype;
|
||||
seg->region_size = new_region_size;
|
||||
|
||||
/* FIXME Hard-coded raid0 -> raid4 */
|
||||
if (seg_is_any_raid0(seg))
|
||||
seg->area_len = seg->extents_copied = seg->len / (seg->area_count - seg->segtype->parity_devs);
|
||||
/* FIXME Hard-coded raid0 to raid4 */
|
||||
seg->area_len = seg->len;
|
||||
|
||||
_check_and_adjust_region_size(lv);
|
||||
lv_adjust_region_and_stripe_size(lv);
|
||||
|
||||
log_debug_metadata("Updating VG metadata and reloading %s LV %s",
|
||||
lvseg_name(seg), display_lvname(lv));
|
||||
@@ -3095,7 +3065,7 @@ static int _takeover_from_raid0_to_raid10(TAKEOVER_FN_ARGS)
|
||||
|
||||
static int _takeover_from_raid0_to_raid45(TAKEOVER_FN_ARGS)
|
||||
{
|
||||
return _striped_or_raid0_to_raid45610_wrapper(lv, new_segtype, yes, force, first_seg(lv)->area_count + 1, 2 /* data_copies */, 0, 0, new_region_size, allocate_pvs);
|
||||
return _striped_or_raid0_to_raid45610_wrapper(lv, new_segtype, yes, force, first_seg(lv)->area_count + 1, 1 /* data_copies */, 0, 0, new_region_size, allocate_pvs);
|
||||
}
|
||||
|
||||
static int _takeover_from_raid0_to_raid6(TAKEOVER_FN_ARGS)
|
||||
@@ -3141,7 +3111,7 @@ static int _takeover_from_raid0_meta_to_raid10(TAKEOVER_FN_ARGS)
|
||||
|
||||
static int _takeover_from_raid0_meta_to_raid45(TAKEOVER_FN_ARGS)
|
||||
{
|
||||
return _striped_or_raid0_to_raid45610_wrapper(lv, new_segtype, yes, force, first_seg(lv)->area_count + 1, 2 /* data_copies */, 0, 0, new_region_size, allocate_pvs);
|
||||
return _striped_or_raid0_to_raid45610_wrapper(lv, new_segtype, yes, force, first_seg(lv)->area_count + 1, 1 /* data_copies */, 0, 0, new_region_size, allocate_pvs);
|
||||
}
|
||||
|
||||
static int _takeover_from_raid0_meta_to_raid6(TAKEOVER_FN_ARGS)
|
||||
@@ -3414,6 +3384,12 @@ static int _set_convenient_raid456_segtype_to(const struct lv_segment *seg_from,
|
||||
!segtype_is_raid5_n(*segtype)) {
|
||||
log_error("Conversion to raid5_n not yet supported.");
|
||||
return 0;
|
||||
|
||||
/* If this is any raid6 conversion request -> enforce raid6_n_6, because we convert from striped */
|
||||
} else if (segtype_is_any_raid6(*segtype) &&
|
||||
!segtype_is_raid6_n_6(*segtype)) {
|
||||
log_error("Conversion to raid6_n_6 not yet supported.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Got to do check for raid5 -> raid6 ... */
|
||||
|
@@ -145,7 +145,7 @@ struct dev_manager;
|
||||
#define segtype_is_unknown(segtype) ((segtype)->flags & SEG_UNKNOWN ? 1 : 0)
|
||||
|
||||
#define segtype_supports_stripe_size(segtype) \
|
||||
((segtype_is_striped(segtype) || \
|
||||
((segtype_is_striped(segtype) || segtype_is_mirror(segtype) || \
|
||||
segtype_is_cache(segtype) || segtype_is_cache_pool(segtype) || \
|
||||
segtype_is_thin(segtype) || segtype_is_snapshot(segtype) || \
|
||||
(segtype_is_raid(segtype) && !segtype_is_raid1(segtype))) ? 1 : 0)
|
||||
|
@@ -89,7 +89,6 @@
|
||||
# include "lvm-logging.h"
|
||||
# include "lvm-globals.h"
|
||||
# include "lvm-wrappers.h"
|
||||
# include "lvm-maths.h"
|
||||
#endif
|
||||
|
||||
#include <unistd.h>
|
||||
|
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
|
||||
/* Greatest common divisor */
|
||||
unsigned long gcd(unsigned long n1, unsigned long n2)
|
||||
{
|
||||
unsigned long remainder;
|
||||
|
||||
do {
|
||||
remainder = n1 % n2;
|
||||
n1 = n2;
|
||||
n2 = remainder;
|
||||
} while (n2);
|
||||
|
||||
return n1;
|
||||
}
|
||||
|
||||
/* Least common multiple */
|
||||
unsigned long lcm(unsigned long n1, unsigned long n2)
|
||||
{
|
||||
if (!n1 || !n2)
|
||||
return 0;
|
||||
|
||||
return (n1 * n2) / gcd(n1, n2);
|
||||
}
|
@@ -1,24 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_MATH_H
|
||||
#define _LVM_MATH_H
|
||||
|
||||
/* Greatest common divisor */
|
||||
unsigned long gcd(unsigned long n1, unsigned long n2);
|
||||
|
||||
/* Least common multiple */
|
||||
unsigned long lcm(unsigned long n1, unsigned long n2);
|
||||
|
||||
#endif
|
@@ -499,12 +499,7 @@ static struct segment_type *_init_raid_segtype(struct cmd_context *cmd,
|
||||
|
||||
segtype->ops = &_raid_ops;
|
||||
segtype->name = rt->name;
|
||||
segtype->flags = SEG_RAID | SEG_ONLY_EXCLUSIVE | rt->extra_flags;
|
||||
|
||||
/* Never monitor raid0 or raid0_meta LVs */
|
||||
if (!segtype_is_any_raid0(segtype))
|
||||
segtype->flags |= monitored;
|
||||
|
||||
segtype->flags = SEG_RAID | SEG_ONLY_EXCLUSIVE | rt->extra_flags | monitored;
|
||||
segtype->parity_devs = rt->parity;
|
||||
|
||||
log_very_verbose("Initialised segtype: %s", segtype->name);
|
||||
|
@@ -491,7 +491,7 @@ static int handle_connect(daemon_state s)
|
||||
|
||||
client.socket_fd = accept(s.socket_fd, (struct sockaddr *) &sockaddr, &sl);
|
||||
if (client.socket_fd < 0) {
|
||||
ERROR(&s, "Failed to accept connection errno %d.", errno);
|
||||
ERROR(&s, "Failed to accept connection.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -513,7 +513,7 @@ static int handle_connect(daemon_state s)
|
||||
ts->client = client;
|
||||
|
||||
if (pthread_create(&ts->client.thread_id, NULL, _client_thread, ts)) {
|
||||
ERROR(&s, "Failed to create client thread errno %d.", errno);
|
||||
ERROR(&s, "Failed to create client thread.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@@ -216,7 +216,6 @@ int dm_task_set_major_minor(struct dm_task *dmt, int major, int minor, int allow
|
||||
int dm_task_set_uid(struct dm_task *dmt, uid_t uid);
|
||||
int dm_task_set_gid(struct dm_task *dmt, gid_t gid);
|
||||
int dm_task_set_mode(struct dm_task *dmt, mode_t mode);
|
||||
/* See also description for DM_UDEV_DISABLE_LIBRARY_FALLBACK flag! */
|
||||
int dm_task_set_cookie(struct dm_task *dmt, uint32_t *cookie, uint16_t flags);
|
||||
int dm_task_set_event_nr(struct dm_task *dmt, uint32_t event_nr);
|
||||
int dm_task_set_geometry(struct dm_task *dmt, const char *cylinders, const char *heads, const char *sectors, const char *start);
|
||||
@@ -3497,18 +3496,7 @@ struct dm_pool *dm_config_memory(struct dm_config_tree *cft);
|
||||
* DM_UDEV_DISABLE_LIBRARY_FALLBACK is set in case we need to disable
|
||||
* libdevmapper's node management. We will rely on udev completely
|
||||
* and there will be no fallback action provided by libdevmapper if
|
||||
* udev does something improperly. Using the library fallback code has
|
||||
* a consequence that you need to take into account: any device node
|
||||
* or symlink created without udev is not recorded in udev database
|
||||
* which other applications may read to get complete list of devices.
|
||||
* For this reason, use of DM_UDEV_DISABLE_LIBRARY_FALLBACK is
|
||||
* recommended on systems where udev is used. Keep library fallback
|
||||
* enabled just for exceptional cases where you need to debug udev-related
|
||||
* problems. If you hit such problems, please contact us through upstream
|
||||
* LVM2 development mailing list (see also README file). This flag is
|
||||
* currently not set by default in libdevmapper so you need to set it
|
||||
* explicitly if you're sure that udev is behaving correctly on your
|
||||
* setups.
|
||||
* udev does something improperly.
|
||||
*/
|
||||
#define DM_UDEV_DISABLE_LIBRARY_FALLBACK 0x0020
|
||||
/*
|
||||
|
1245
scripts/command-lines.in
Normal file
1245
scripts/command-lines.in
Normal file
File diff suppressed because it is too large
Load Diff
1712
scripts/create-commands.c
Normal file
1712
scripts/create-commands.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,128 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Copyright (C) 2016 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
SKIP_WITH_LVMLOCKD=1
|
||||
SKIP_WITH_LVMPOLLD=1
|
||||
|
||||
. lib/inittest
|
||||
|
||||
aux have_raid 1 3 2 || skip
|
||||
|
||||
aux prepare_vg 8
|
||||
|
||||
# Delay 1st leg so that rebuilding status characters can be read
|
||||
for d in "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" "$dev6" "$dev7" "$dev8"
|
||||
do
|
||||
aux delay_dev $d 0 3
|
||||
done
|
||||
|
||||
# rhbz 1064592
|
||||
|
||||
##############################################
|
||||
# Create an 8-way striped raid10 with 4 mirror
|
||||
# groups and rebuild selected PVs.
|
||||
lvcreate --type raid10 -m 1 -i 4 -l 2 -n $lv1 $vg
|
||||
aux wait_for_sync $vg $lv1
|
||||
|
||||
# Rebuild 1st and 2nd device would rebuild a
|
||||
# whole mirror group and needs to be rejected.
|
||||
not lvchange --yes --rebuild "$dev1" --rebuild "$dev2" $vg/$lv1
|
||||
not aux check_status_chars $vg $lv1 "aAaAAAAA"
|
||||
aux wait_for_sync $vg $lv1
|
||||
|
||||
# Rebuild 1st and 3nd device from different mirror groups is fine.
|
||||
lvchange --yes --rebuild "$dev1" --rebuild "$dev3" $vg/$lv1
|
||||
aux check_status_chars $vg $lv1 "aAaAAAAA"
|
||||
aux wait_for_sync $vg $lv1
|
||||
|
||||
# Rebuild devices 1, 3, 6 from different mirror groups is fine.
|
||||
lvchange --yes --rebuild "$dev1" --rebuild "$dev3" --rebuild "$dev6" $vg/$lv1
|
||||
aux check_status_chars $vg $lv1 "aAaAAaAA"
|
||||
aux wait_for_sync $vg $lv1
|
||||
|
||||
# Rebuild devices 1, 3, 5 and 6 with 5+6 being
|
||||
# being a whole mirror group needs to be rejected.
|
||||
not lvchange --yes --rebuild "$dev1" --rebuild "$dev3" --rebuild "$dev6" --rebuild "$dev5" $vg/$lv1
|
||||
not aux check_status_chars $vg $lv1 "aAaAaaAA"
|
||||
aux wait_for_sync $vg $lv1
|
||||
|
||||
# Rebuild devices 1, 3, 5 and 7 from different mirror groups is fine.
|
||||
lvchange --yes --rebuild "$dev1" --rebuild "$dev3" --rebuild "$dev5" --rebuild "$dev7" $vg/$lv1
|
||||
aux check_status_chars $vg $lv1 "aAaAaAaA"
|
||||
aux wait_for_sync $vg $lv1
|
||||
|
||||
# Rebuild devices 2, 4, 6 and 8 from different mirror groups is fine.
|
||||
lvchange --yes --rebuild "$dev2" --rebuild "$dev4" --rebuild "$dev6" --rebuild "$dev8" $vg/$lv1
|
||||
aux check_status_chars $vg $lv1 "AaAaAaAa"
|
||||
aux wait_for_sync $vg $lv1
|
||||
|
||||
##############################################
|
||||
# Create an 8-legged raid1 and rebuild selected PVs
|
||||
lvremove --yes $vg/$lv1
|
||||
lvcreate --yes --type raid1 -m 7 -l 2 -n $lv1 $vg
|
||||
aux wait_for_sync $vg $lv1
|
||||
|
||||
# Rebuilding all raid1 legs needs to be rejected.
|
||||
not lvchange --yes --rebuild "$dev1" --rebuild "$dev2" --rebuild "$dev3" --rebuild "$dev4" \
|
||||
--rebuild "$dev5" --rebuild "$dev6" --rebuild "$dev7" --rebuild "$dev8" $vg/$lv1
|
||||
not aux check_status_chars $vg $lv1 "aaaaaaaa"
|
||||
aux wait_for_sync $vg $lv1
|
||||
|
||||
# Rebuilding all but the raid1 master leg is fine.
|
||||
lvchange --yes --rebuild "$dev2" --rebuild "$dev3" --rebuild "$dev4" \
|
||||
--rebuild "$dev5" --rebuild "$dev6" --rebuild "$dev7" --rebuild "$dev8" $vg/$lv1
|
||||
aux check_status_chars $vg $lv1 "Aaaaaaaa"
|
||||
aux wait_for_sync $vg $lv1
|
||||
|
||||
# Rebuilding the raid1 master leg is fine.
|
||||
lvchange --yes --rebuild "$dev1" $vg/$lv1
|
||||
aux check_status_chars $vg $lv1 "aAAAAAAA"
|
||||
aux wait_for_sync $vg $lv1
|
||||
|
||||
# Rebuild legs on devices 2, 4, 6 and 8 is fine.
|
||||
lvchange --yes --rebuild "$dev2" --rebuild "$dev4" --rebuild "$dev6" --rebuild "$dev8" $vg/$lv1
|
||||
aux check_status_chars $vg $lv1 "AaAaAaAa"
|
||||
aux wait_for_sync $vg $lv1
|
||||
|
||||
##############################################
|
||||
# Create an 6-legged raid6 and rebuild selected PVs
|
||||
lvremove --yes $vg/$lv1
|
||||
lvcreate --yes --type raid6 -i 4 -l 2 -n $lv1 $vg
|
||||
aux wait_for_sync $vg $lv1
|
||||
|
||||
# Rebuilding all raid6 stripes needs to be rejected.
|
||||
not lvchange --yes --rebuild "$dev1" --rebuild "$dev2" --rebuild "$dev3" \
|
||||
--rebuild "$dev4" --rebuild "$dev5" --rebuild "$dev6" $vg/$lv1
|
||||
not aux check_status_chars $vg $lv1 "aaaaaa"
|
||||
aux wait_for_sync $vg $lv1
|
||||
|
||||
# Rebuilding more than 2 raid6 stripes needs to be rejected.
|
||||
not lvchange --yes --rebuild "$dev2" --rebuild "$dev4" --rebuild "$dev6" $vg/$lv1
|
||||
not aux check_status_chars $vg $lv1 "AaAaAa"
|
||||
aux wait_for_sync $vg $lv1
|
||||
|
||||
# Rebuilding any 1 raid6 stripe is fine.
|
||||
lvchange --yes --rebuild "$dev2" $vg/$lv1
|
||||
aux check_status_chars $vg $lv1 "AaAAAA"
|
||||
aux wait_for_sync $vg $lv1
|
||||
lvchange --yes --rebuild "$dev5" $vg/$lv1
|
||||
aux check_status_chars $vg $lv1 "AAAAaA"
|
||||
aux wait_for_sync $vg $lv1
|
||||
|
||||
# Rebuilding any 2 raid6 stripes is fine.
|
||||
lvchange --yes --rebuild "$dev2" --rebuild "$dev4" $vg/$lv1
|
||||
aux check_status_chars $vg $lv1 "AaAaAA"
|
||||
aux wait_for_sync $vg $lv1
|
||||
lvchange --yes --rebuild "$dev1" --rebuild "$dev5" $vg/$lv1
|
||||
aux check_status_chars $vg $lv1 "aAAAaA"
|
||||
aux wait_for_sync $vg $lv1
|
||||
|
||||
vgremove -ff $vg
|
405
tools/args.h
405
tools/args.h
@@ -17,215 +17,214 @@
|
||||
* Put all long args that don't have a corresponding short option first.
|
||||
*/
|
||||
/* *INDENT-OFF* */
|
||||
arg(abort_ARG, '\0', "abort", NULL, 0, 0)
|
||||
arg(activationmode_ARG, '\0', "activationmode", string_arg, 0, 0)
|
||||
arg(addtag_ARG, '\0', "addtag", tag_arg, ARG_GROUPABLE, 0)
|
||||
arg(aligned_ARG, '\0', "aligned", NULL, 0, 0)
|
||||
arg(alloc_ARG, '\0', "alloc", alloc_arg, 0, 0)
|
||||
arg(atomic_ARG, '\0', "atomic", NULL, 0, 0)
|
||||
arg(atversion_ARG, '\0', "atversion", string_arg, 0, 0)
|
||||
arg(binary_ARG, '\0', "binary", NULL, 0, 0)
|
||||
arg(bootloaderareasize_ARG, '\0', "bootloaderareasize", size_mb_arg, 0, 0)
|
||||
arg(cache_long_ARG, '\0', "cache", NULL, 0, 0)
|
||||
arg(cachemode_ARG, '\0', "cachemode", cachemode_arg, 0, 0)
|
||||
arg(cachepool_ARG, '\0', "cachepool", string_arg, 0, 0)
|
||||
arg(commandprofile_ARG, '\0', "commandprofile", string_arg, 0, 0)
|
||||
arg(config_ARG, '\0', "config", string_arg, 0, 0)
|
||||
arg(configreport_ARG, '\0', "configreport", string_arg, ARG_GROUPABLE, 1)
|
||||
arg(configtype_ARG, '\0', "type", string_arg, 0, 0)
|
||||
arg(corelog_ARG, '\0', "corelog", NULL, 0, 0)
|
||||
arg(dataalignment_ARG, '\0', "dataalignment", size_kb_arg, 0, 0)
|
||||
arg(dataalignmentoffset_ARG, '\0', "dataalignmentoffset", size_kb_arg, 0, 0)
|
||||
arg(deltag_ARG, '\0', "deltag", tag_arg, ARG_GROUPABLE, 0)
|
||||
arg(detachprofile_ARG, '\0', "detachprofile", NULL, 0, 0)
|
||||
arg(discards_ARG, '\0', "discards", discards_arg, 0, 0)
|
||||
arg(driverloaded_ARG, '\0', "driverloaded", yes_no_arg, 0, 0)
|
||||
arg(errorwhenfull_ARG, '\0', "errorwhenfull", yes_no_arg, 0, 0)
|
||||
arg(force_long_ARG, '\0', "force", NULL, ARG_COUNTABLE, 0)
|
||||
arg(foreign_ARG, '\0', "foreign", NULL, 0, 0)
|
||||
arg(handlemissingpvs_ARG, '\0', "handlemissingpvs", NULL, 0, 0)
|
||||
arg(ignoreadvanced_ARG, '\0', "ignoreadvanced", NULL, 0, 0)
|
||||
arg(ignorelocal_ARG, '\0', "ignorelocal", NULL, 0, 0)
|
||||
arg(ignorelockingfailure_ARG, '\0', "ignorelockingfailure", NULL, 0, 0)
|
||||
arg(ignoremonitoring_ARG, '\0', "ignoremonitoring", NULL, 0, 0)
|
||||
arg(ignoreskippedcluster_ARG, '\0', "ignoreskippedcluster", NULL, 0, 0)
|
||||
arg(ignoreunsupported_ARG, '\0', "ignoreunsupported", NULL, 0, 0)
|
||||
arg(labelsector_ARG, '\0', "labelsector", int_arg, 0, 0)
|
||||
arg(lockopt_ARG, '\0', "lockopt", string_arg, 0, 0)
|
||||
arg(lockstart_ARG, '\0', "lockstart", NULL, 0, 0)
|
||||
arg(lockstop_ARG, '\0', "lockstop", NULL, 0, 0)
|
||||
arg(locktype_ARG, '\0', "locktype", locktype_arg, 0, 0)
|
||||
arg(logonly_ARG, '\0', "logonly", NULL, 0, 0)
|
||||
arg(maxrecoveryrate_ARG, '\0', "maxrecoveryrate", size_kb_arg, 0, 0)
|
||||
arg(merge_ARG, '\0', "merge", NULL, 0, 0)
|
||||
arg(mergedconfig_ARG, '\0', "mergedconfig", NULL, 0, 0)
|
||||
arg(metadatacopies_ARG, '\0', "metadatacopies", metadatacopies_arg, 0, 0)
|
||||
arg(metadataignore_ARG, '\0', "metadataignore", yes_no_arg, 0, 0)
|
||||
arg(metadataprofile_ARG, '\0', "metadataprofile", string_arg, 0, 0)
|
||||
arg(metadatasize_ARG, '\0', "metadatasize", size_mb_arg, 0, 0)
|
||||
arg(minor_ARG, '\0', "minor", int_arg, ARG_GROUPABLE, 0)
|
||||
arg(minrecoveryrate_ARG, '\0', "minrecoveryrate", size_kb_arg, 0, 0)
|
||||
arg(mirrorlog_ARG, '\0', "mirrorlog", mirrorlog_arg, 0, 0)
|
||||
arg(mirrorsonly_ARG, '\0', "mirrorsonly", NULL, 0, 0)
|
||||
arg(mknodes_ARG, '\0', "mknodes", NULL, 0, 0)
|
||||
arg(monitor_ARG, '\0', "monitor", yes_no_arg, 0, 0)
|
||||
arg(nameprefixes_ARG, '\0', "nameprefixes", NULL, 0, 0)
|
||||
arg(noheadings_ARG, '\0', "noheadings", NULL, 0, 0)
|
||||
arg(nohistory_ARG, '\0', "nohistory", NULL, 0, 0)
|
||||
arg(nolocking_ARG, '\0', "nolocking", NULL, 0, 0)
|
||||
arg(norestorefile_ARG, '\0', "norestorefile", NULL, 0, 0)
|
||||
arg(nosuffix_ARG, '\0', "nosuffix", NULL, 0, 0)
|
||||
arg(nosync_ARG, '\0', "nosync", NULL, 0, 0)
|
||||
arg(notifydbus_ARG, '\0', "notifydbus", NULL, 0, 0)
|
||||
arg(noudevsync_ARG, '\0', "noudevsync", NULL, 0, 0)
|
||||
arg(originname_ARG, '\0', "originname", string_arg, 0, 0)
|
||||
arg(physicalvolumesize_ARG, '\0', "setphysicalvolumesize", size_mb_arg, 0, 0)
|
||||
arg(poll_ARG, '\0', "poll", yes_no_arg, 0, 0)
|
||||
arg(polloperation_ARG, '\0', "polloperation", string_arg, 0, 0)
|
||||
arg(pooldatasize_ARG, '\0', "pooldatasize", size_mb_arg, 0, 0)
|
||||
arg(poolmetadata_ARG, '\0', "poolmetadata", string_arg, 0, 0)
|
||||
arg(poolmetadatasize_ARG, '\0', "poolmetadatasize", size_mb_arg, 0, 0)
|
||||
arg(poolmetadataspare_ARG, '\0', "poolmetadataspare", yes_no_arg, 0, 0)
|
||||
arg(profile_ARG, '\0', "profile", string_arg, 0, 0)
|
||||
arg(pvmetadatacopies_ARG, '\0', "pvmetadatacopies", int_arg, 0, 0)
|
||||
arg(raidrebuild_ARG, '\0', "raidrebuild", string_arg, ARG_GROUPABLE, 0)
|
||||
arg(raidmaxrecoveryrate_ARG, '\0', "raidmaxrecoveryrate", size_kb_arg, 0, 0)
|
||||
arg(raidminrecoveryrate_ARG, '\0', "raidminrecoveryrate", size_kb_arg, 0, 0)
|
||||
arg(raidsyncaction_ARG, '\0', "raidsyncaction", string_arg, 0, 0)
|
||||
arg(raidwritebehind_ARG, '\0', "raidwritebehind", int_arg, 0, 0)
|
||||
arg(raidwritemostly_ARG, '\0', "raidwritemostly", string_arg, ARG_GROUPABLE, 0)
|
||||
arg(readonly_ARG, '\0', "readonly", NULL, 0, 0)
|
||||
arg(refresh_ARG, '\0', "refresh", NULL, 0, 0)
|
||||
arg(removemissing_ARG, '\0', "removemissing", NULL, 0, 0)
|
||||
arg(rebuild_ARG, '\0', "rebuild", string_arg, ARG_GROUPABLE, 0)
|
||||
arg(repair_ARG, '\0', "repair", NULL, 0, 0)
|
||||
arg(replace_ARG, '\0', "replace", string_arg, ARG_GROUPABLE, 0)
|
||||
arg(reportformat_ARG, '\0', "reportformat", string_arg, 0, 0)
|
||||
arg(restorefile_ARG, '\0', "restorefile", string_arg, 0, 0)
|
||||
arg(restoremissing_ARG, '\0', "restoremissing", NULL, 0, 0)
|
||||
arg(resync_ARG, '\0', "resync", NULL, 0, 0)
|
||||
arg(rows_ARG, '\0', "rows", NULL, 0, 0)
|
||||
arg(segments_ARG, '\0', "segments", NULL, 0, 0)
|
||||
arg(separator_ARG, '\0', "separator", string_arg, 0, 0)
|
||||
arg(shared_ARG, '\0', "shared", NULL, 0, 0)
|
||||
arg(sinceversion_ARG, '\0', "sinceversion", string_arg, 0, 0)
|
||||
arg(split_ARG, '\0', "split", NULL, 0, 0)
|
||||
arg(splitcache_ARG, '\0', "splitcache", NULL, 0, 0)
|
||||
arg(splitmirrors_ARG, '\0', "splitmirrors", int_arg, 0, 0)
|
||||
arg(splitsnapshot_ARG, '\0', "splitsnapshot", NULL, 0, 0)
|
||||
arg(showdeprecated_ARG, '\0', "showdeprecated", NULL, 0, 0)
|
||||
arg(showunsupported_ARG, '\0', "showunsupported", NULL, 0, 0)
|
||||
arg(stripes_long_ARG, '\0', "stripes", int_arg, 0, 0)
|
||||
arg(syncaction_ARG, '\0', "syncaction", string_arg, 0, 0) /* FIXME Use custom validation fn */
|
||||
arg(sysinit_ARG, '\0', "sysinit", NULL, 0, 0)
|
||||
arg(systemid_ARG, '\0', "systemid", string_arg, 0, 0)
|
||||
arg(thinpool_ARG, '\0', "thinpool", string_arg, 0, 0)
|
||||
arg(trackchanges_ARG, '\0', "trackchanges", NULL, 0, 0)
|
||||
arg(trustcache_ARG, '\0', "trustcache", NULL, 0, 0)
|
||||
arg(type_ARG, '\0', "type", segtype_arg, 0, 0)
|
||||
arg(unbuffered_ARG, '\0', "unbuffered", NULL, 0, 0)
|
||||
arg(uncache_ARG, '\0', "uncache", NULL, 0, 0)
|
||||
arg(cachepolicy_ARG, '\0', "cachepolicy", string_arg, 0, 0)
|
||||
arg(cachesettings_ARG, '\0', "cachesettings", string_arg, ARG_GROUPABLE, 0)
|
||||
arg(unconfigured_ARG, '\0', "unconfigured", NULL, 0, 0)
|
||||
arg(units_ARG, '\0', "units", string_arg, 0, 0)
|
||||
arg(unquoted_ARG, '\0', "unquoted", NULL, 0, 0)
|
||||
arg(usepolicies_ARG, '\0', "usepolicies", NULL, 0, 0)
|
||||
arg(validate_ARG, '\0', "validate", NULL, 0, 0)
|
||||
arg(version_ARG, '\0', "version", NULL, 0, 0)
|
||||
arg(vgmetadatacopies_ARG, '\0', "vgmetadatacopies", metadatacopies_arg, 0, 0)
|
||||
arg(virtualoriginsize_ARG, '\0', "virtualoriginsize", size_mb_arg, 0, 0)
|
||||
arg(withsummary_ARG, '\0', "withsummary", NULL, 0, 0)
|
||||
arg(withcomments_ARG, '\0', "withcomments", NULL, 0, 0)
|
||||
arg(withspaces_ARG, '\0', "withspaces", NULL, 0, 0)
|
||||
arg(withversions_ARG, '\0', "withversions", NULL, 0, 0)
|
||||
arg(writebehind_ARG, '\0', "writebehind", int_arg, 0, 0)
|
||||
arg(writemostly_ARG, '\0', "writemostly", string_arg, ARG_GROUPABLE, 0)
|
||||
arg(abort_ARG, '\0', "abort", 0, 0, 0)
|
||||
arg(activationmode_ARG, '\0', "activationmode", activationmode_VAL, 0, 0)
|
||||
arg(addtag_ARG, '\0', "addtag", tag_VAL, ARG_GROUPABLE, 0)
|
||||
arg(aligned_ARG, '\0', "aligned", 0, 0, 0)
|
||||
arg(alloc_ARG, '\0', "alloc", alloc_VAL, 0, 0)
|
||||
arg(atomic_ARG, '\0', "atomic", 0, 0, 0)
|
||||
arg(atversion_ARG, '\0', "atversion", string_VAL, 0, 0)
|
||||
arg(binary_ARG, '\0', "binary", 0, 0, 0)
|
||||
arg(bootloaderareasize_ARG, '\0', "bootloaderareasize", sizemb_VAL, 0, 0)
|
||||
arg(cache_long_ARG, '\0', "cache", 0, 0, 0)
|
||||
arg(cachemode_ARG, '\0', "cachemode", cachemode_VAL, 0, 0)
|
||||
arg(cachepool_ARG, '\0', "cachepool", lv_VAL, 0, 0)
|
||||
arg(commandprofile_ARG, '\0', "commandprofile", string_VAL, 0, 0)
|
||||
arg(config_ARG, '\0', "config", string_VAL, 0, 0)
|
||||
arg(configreport_ARG, '\0', "configreport", string_VAL, ARG_GROUPABLE, 1)
|
||||
arg(configtype_ARG, '\0', "typeconfig", string_VAL, 0, 0)
|
||||
arg(corelog_ARG, '\0', "corelog", 0, 0, 0)
|
||||
arg(dataalignment_ARG, '\0', "dataalignment", sizekb_VAL, 0, 0)
|
||||
arg(dataalignmentoffset_ARG, '\0', "dataalignmentoffset", sizekb_VAL, 0, 0)
|
||||
arg(deltag_ARG, '\0', "deltag", tag_VAL, ARG_GROUPABLE, 0)
|
||||
arg(detachprofile_ARG, '\0', "detachprofile", 0, 0, 0)
|
||||
arg(discards_ARG, '\0', "discards", discards_VAL, 0, 0)
|
||||
arg(driverloaded_ARG, '\0', "driverloaded", bool_VAL, 0, 0)
|
||||
arg(errorwhenfull_ARG, '\0', "errorwhenfull", bool_VAL, 0, 0)
|
||||
arg(force_long_ARG, '\0', "force", 0, ARG_COUNTABLE, 0)
|
||||
arg(foreign_ARG, '\0', "foreign", 0, 0, 0)
|
||||
arg(handlemissingpvs_ARG, '\0', "handlemissingpvs", 0, 0, 0)
|
||||
arg(ignoreadvanced_ARG, '\0', "ignoreadvanced", 0, 0, 0)
|
||||
arg(ignorelocal_ARG, '\0', "ignorelocal", 0, 0, 0)
|
||||
arg(ignorelockingfailure_ARG, '\0', "ignorelockingfailure", 0, 0, 0)
|
||||
arg(ignoremonitoring_ARG, '\0', "ignoremonitoring", 0, 0, 0)
|
||||
arg(ignoreskippedcluster_ARG, '\0', "ignoreskippedcluster", 0, 0, 0)
|
||||
arg(ignoreunsupported_ARG, '\0', "ignoreunsupported", 0, 0, 0)
|
||||
arg(labelsector_ARG, '\0', "labelsector", number_VAL, 0, 0)
|
||||
arg(lockopt_ARG, '\0', "lockopt", string_VAL, 0, 0)
|
||||
arg(lockstart_ARG, '\0', "lockstart", 0, 0, 0)
|
||||
arg(lockstop_ARG, '\0', "lockstop", 0, 0, 0)
|
||||
arg(locktype_ARG, '\0', "locktype", locktype_VAL, 0, 0)
|
||||
arg(logonly_ARG, '\0', "logonly", 0, 0, 0)
|
||||
arg(maxrecoveryrate_ARG, '\0', "maxrecoveryrate", sizekb_VAL, 0, 0)
|
||||
arg(merge_ARG, '\0', "merge", 0, 0, 0)
|
||||
arg(mergedconfig_ARG, '\0', "mergedconfig", 0, 0, 0)
|
||||
arg(metadatacopies_ARG, '\0', "metadatacopies", metadatacopies_VAL, 0, 0)
|
||||
arg(metadataignore_ARG, '\0', "metadataignore", bool_VAL, 0, 0)
|
||||
arg(metadataprofile_ARG, '\0', "metadataprofile", string_VAL, 0, 0)
|
||||
arg(metadatasize_ARG, '\0', "metadatasize", sizemb_VAL, 0, 0)
|
||||
arg(minor_ARG, '\0', "minor", number_VAL, ARG_GROUPABLE, 0)
|
||||
arg(minrecoveryrate_ARG, '\0', "minrecoveryrate", sizekb_VAL, 0, 0)
|
||||
arg(mirrorlog_ARG, '\0', "mirrorlog", mirrorlog_VAL, 0, 0)
|
||||
arg(mirrorsonly_ARG, '\0', "mirrorsonly", 0, 0, 0)
|
||||
arg(mknodes_ARG, '\0', "mknodes", 0, 0, 0)
|
||||
arg(monitor_ARG, '\0', "monitor", bool_VAL, 0, 0)
|
||||
arg(nameprefixes_ARG, '\0', "nameprefixes", 0, 0, 0)
|
||||
arg(noheadings_ARG, '\0', "noheadings", 0, 0, 0)
|
||||
arg(nohistory_ARG, '\0', "nohistory", 0, 0, 0)
|
||||
arg(nolocking_ARG, '\0', "nolocking", 0, 0, 0)
|
||||
arg(norestorefile_ARG, '\0', "norestorefile", 0, 0, 0)
|
||||
arg(nosuffix_ARG, '\0', "nosuffix", 0, 0, 0)
|
||||
arg(nosync_ARG, '\0', "nosync", 0, 0, 0)
|
||||
arg(notifydbus_ARG, '\0', "notifydbus", 0, 0, 0)
|
||||
arg(noudevsync_ARG, '\0', "noudevsync", 0, 0, 0)
|
||||
arg(originname_ARG, '\0', "originname", lv_VAL, 0, 0)
|
||||
arg(physicalvolumesize_ARG, '\0', "setphysicalvolumesize", sizemb_VAL, 0, 0)
|
||||
arg(poll_ARG, '\0', "poll", bool_VAL, 0, 0)
|
||||
arg(polloperation_ARG, '\0', "polloperation", string_VAL, 0, 0)
|
||||
arg(pooldatasize_ARG, '\0', "pooldatasize", sizemb_VAL, 0, 0)
|
||||
arg(poolmetadata_ARG, '\0', "poolmetadata", lv_VAL, 0, 0)
|
||||
arg(poolmetadatasize_ARG, '\0', "poolmetadatasize", sizemb_VAL, 0, 0)
|
||||
arg(poolmetadataspare_ARG, '\0', "poolmetadataspare", bool_VAL, 0, 0)
|
||||
arg(profile_ARG, '\0', "profile", string_VAL, 0, 0)
|
||||
arg(pvmetadatacopies_ARG, '\0', "pvmetadatacopies", number_VAL, 0, 0)
|
||||
arg(raidrebuild_ARG, '\0', "raidrebuild", string_VAL, ARG_GROUPABLE, 0)
|
||||
arg(raidmaxrecoveryrate_ARG, '\0', "raidmaxrecoveryrate", sizekb_VAL, 0, 0)
|
||||
arg(raidminrecoveryrate_ARG, '\0', "raidminrecoveryrate", sizekb_VAL, 0, 0)
|
||||
arg(raidsyncaction_ARG, '\0', "raidsyncaction", string_VAL, 0, 0)
|
||||
arg(raidwritebehind_ARG, '\0', "raidwritebehind", number_VAL, 0, 0)
|
||||
arg(raidwritemostly_ARG, '\0', "raidwritemostly", string_VAL, ARG_GROUPABLE, 0)
|
||||
arg(readonly_ARG, '\0', "readonly", 0, 0, 0)
|
||||
arg(refresh_ARG, '\0', "refresh", 0, 0, 0)
|
||||
arg(removemissing_ARG, '\0', "removemissing", 0, 0, 0)
|
||||
arg(rebuild_ARG, '\0', "rebuild", pv_VAL, ARG_GROUPABLE, 0)
|
||||
arg(repair_ARG, '\0', "repair", 0, 0, 0)
|
||||
arg(replace_ARG, '\0', "replace", pv_VAL, ARG_GROUPABLE, 0)
|
||||
arg(reportformat_ARG, '\0', "reportformat", string_VAL, 0, 0)
|
||||
arg(restorefile_ARG, '\0', "restorefile", string_VAL, 0, 0)
|
||||
arg(restoremissing_ARG, '\0', "restoremissing", 0, 0, 0)
|
||||
arg(resync_ARG, '\0', "resync", 0, 0, 0)
|
||||
arg(rows_ARG, '\0', "rows", 0, 0, 0)
|
||||
arg(segments_ARG, '\0', "segments", 0, 0, 0)
|
||||
arg(separator_ARG, '\0', "separator", string_VAL, 0, 0)
|
||||
arg(shared_ARG, '\0', "shared", 0, 0, 0)
|
||||
arg(sinceversion_ARG, '\0', "sinceversion", string_VAL, 0, 0)
|
||||
arg(split_ARG, '\0', "split", 0, 0, 0)
|
||||
arg(splitcache_ARG, '\0', "splitcache", 0, 0, 0)
|
||||
arg(splitmirrors_ARG, '\0', "splitmirrors", number_VAL, 0, 0)
|
||||
arg(splitsnapshot_ARG, '\0', "splitsnapshot", 0, 0, 0)
|
||||
arg(showdeprecated_ARG, '\0', "showdeprecated", 0, 0, 0)
|
||||
arg(showunsupported_ARG, '\0', "showunsupported", 0, 0, 0)
|
||||
arg(stripes_long_ARG, '\0', "stripes", number_VAL, 0, 0)
|
||||
arg(syncaction_ARG, '\0', "syncaction", string_VAL, 0, 0) /* FIXME Use custom VAL */
|
||||
arg(sysinit_ARG, '\0', "sysinit", 0, 0, 0)
|
||||
arg(systemid_ARG, '\0', "systemid", string_VAL, 0, 0)
|
||||
arg(thinpool_ARG, '\0', "thinpool", lv_VAL, 0, 0)
|
||||
arg(trackchanges_ARG, '\0', "trackchanges", 0, 0, 0)
|
||||
arg(trustcache_ARG, '\0', "trustcache", 0, 0, 0)
|
||||
arg(type_ARG, '\0', "type", segtype_VAL, 0, 0)
|
||||
arg(unbuffered_ARG, '\0', "unbuffered", 0, 0, 0)
|
||||
arg(uncache_ARG, '\0', "uncache", 0, 0, 0)
|
||||
arg(cachepolicy_ARG, '\0', "cachepolicy", string_VAL, 0, 0)
|
||||
arg(cachesettings_ARG, '\0', "cachesettings", string_VAL, ARG_GROUPABLE, 0)
|
||||
arg(unconfigured_ARG, '\0', "unconfigured", 0, 0, 0)
|
||||
arg(units_ARG, '\0', "units", units_VAL, 0, 0)
|
||||
arg(unquoted_ARG, '\0', "unquoted", 0, 0, 0)
|
||||
arg(usepolicies_ARG, '\0', "usepolicies", 0, 0, 0)
|
||||
arg(validate_ARG, '\0', "validate", 0, 0, 0)
|
||||
arg(version_ARG, '\0', "version", 0, 0, 0)
|
||||
arg(vgmetadatacopies_ARG, '\0', "vgmetadatacopies", metadatacopies_VAL, 0, 0)
|
||||
arg(virtualoriginsize_ARG, '\0', "virtualoriginsize", sizemb_VAL, 0, 0)
|
||||
arg(withsummary_ARG, '\0', "withsummary", 0, 0, 0)
|
||||
arg(withcomments_ARG, '\0', "withcomments", 0, 0, 0)
|
||||
arg(withspaces_ARG, '\0', "withspaces", 0, 0, 0)
|
||||
arg(withversions_ARG, '\0', "withversions", 0, 0, 0)
|
||||
arg(writebehind_ARG, '\0', "writebehind", number_VAL, 0, 0)
|
||||
arg(writemostly_ARG, '\0', "writemostly", string_VAL, ARG_GROUPABLE, 0)
|
||||
|
||||
/* Allow some variations */
|
||||
arg(allocation_ARG, '\0', "allocation", yes_no_arg, 0, 0)
|
||||
arg(available_ARG, '\0', "available", activation_arg, 0, 0)
|
||||
arg(resizable_ARG, '\0', "resizable", yes_no_arg, 0, 0)
|
||||
arg(allocation_ARG, '\0', "allocation", bool_VAL, 0, 0)
|
||||
arg(available_ARG, '\0', "available", activation_VAL, 0, 0)
|
||||
arg(resizable_ARG, '\0', "resizable", bool_VAL, 0, 0)
|
||||
|
||||
/*
|
||||
* ... and now the short args.
|
||||
*/
|
||||
arg(activate_ARG, 'a', "activate", activation_arg, 0, 0)
|
||||
arg(all_ARG, 'a', "all", NULL, 0, 0)
|
||||
arg(autobackup_ARG, 'A', "autobackup", yes_no_arg, 0, 0)
|
||||
arg(activevolumegroups_ARG, 'A', "activevolumegroups", NULL, 0, 0)
|
||||
arg(background_ARG, 'b', "background", NULL, 0, 0)
|
||||
arg(backgroundfork_ARG, 'b', "background", NULL, 0, 0)
|
||||
arg(basevgname_ARG, 'n', "basevgname", string_arg, 0, 0)
|
||||
arg(blockdevice_ARG, 'b', "blockdevice", NULL, 0, 0)
|
||||
arg(chunksize_ARG, 'c', "chunksize", size_kb_arg, 0, 0)
|
||||
arg(clustered_ARG, 'c', "clustered", yes_no_arg, 0, 0)
|
||||
arg(colon_ARG, 'c', "colon", NULL, 0, 0)
|
||||
arg(columns_ARG, 'C', "columns", NULL, 0, 0)
|
||||
arg(contiguous_ARG, 'C', "contiguous", yes_no_arg, 0, 0)
|
||||
arg(debug_ARG, 'd', "debug", NULL, ARG_COUNTABLE, 0)
|
||||
arg(exported_ARG, 'e', "exported", NULL, 0, 0)
|
||||
arg(physicalextent_ARG, 'E', "physicalextent", NULL, 0, 0)
|
||||
arg(file_ARG, 'f', "file", string_arg, 0, 0)
|
||||
arg(force_ARG, 'f', "force", NULL, ARG_COUNTABLE, 0)
|
||||
arg(full_ARG, 'f', "full", NULL, 0, 0)
|
||||
arg(help_ARG, 'h', "help", NULL, 0, 0)
|
||||
arg(cache_ARG, 'H', "cache", NULL, 0, 0)
|
||||
arg(history_ARG, 'H', "history", NULL, 0, 0)
|
||||
arg(help2_ARG, '?', "", NULL, 0, 0)
|
||||
arg(import_ARG, 'i', "import", NULL, 0, 0)
|
||||
arg(interval_ARG, 'i', "interval", int_arg, 0, 0)
|
||||
arg(iop_version_ARG, 'i', "iop_version", NULL, 0, 0)
|
||||
arg(stripes_ARG, 'i', "stripes", int_arg, 0, 0)
|
||||
arg(stripesize_ARG, 'I', "stripesize", size_kb_arg, 0, 0)
|
||||
arg(logicalvolume_ARG, 'l', "logicalvolume", int_arg, 0, 0)
|
||||
arg(maxlogicalvolumes_ARG, 'l', "maxlogicalvolumes", int_arg, 0, 0)
|
||||
arg(extents_ARG, 'l', "extents", int_arg_with_sign_and_percent, 0, 0)
|
||||
arg(list_ARG, 'l', "list", NULL, 0, 0)
|
||||
arg(lvmpartition_ARG, 'l', "lvmpartition", NULL, 0, 0)
|
||||
arg(logicalextent_ARG, 'L', "logicalextent", int_arg_with_sign, 0, 0)
|
||||
arg(size_ARG, 'L', "size", size_mb_arg, 0, 0)
|
||||
arg(persistent_ARG, 'M', "persistent", yes_no_arg, 0, 0)
|
||||
arg(major_ARG, 'j', "major", int_arg, ARG_GROUPABLE, 0)
|
||||
arg(setactivationskip_ARG, 'k', "setactivationskip", yes_no_arg, 0, 0)
|
||||
arg(ignoreactivationskip_ARG, 'K', "ignoreactivationskip", NULL, 0, 0)
|
||||
arg(maps_ARG, 'm', "maps", NULL, 0, 0)
|
||||
arg(mirrors_ARG, 'm', "mirrors", int_arg_with_sign, 0, 0)
|
||||
arg(metadatatype_ARG, 'M', "metadatatype", metadatatype_arg, 0, 0)
|
||||
arg(name_ARG, 'n', "name", string_arg, 0, 0)
|
||||
arg(nofsck_ARG, 'n', "nofsck", NULL, 0, 0)
|
||||
arg(novolumegroup_ARG, 'n', "novolumegroup", NULL, 0, 0)
|
||||
arg(oldpath_ARG, 'n', "oldpath", NULL, 0, 0)
|
||||
arg(options_ARG, 'o', "options", string_arg, ARG_GROUPABLE, 0)
|
||||
arg(sort_ARG, 'O', "sort", string_arg, ARG_GROUPABLE, 0)
|
||||
arg(maxphysicalvolumes_ARG, 'p', "maxphysicalvolumes", int_arg, 0, 0)
|
||||
arg(permission_ARG, 'p', "permission", permission_arg, 0, 0)
|
||||
arg(partial_ARG, 'P', "partial", NULL, 0, 0)
|
||||
arg(physicalvolume_ARG, 'P', "physicalvolume", NULL, 0, 0)
|
||||
arg(quiet_ARG, 'q', "quiet", NULL, ARG_COUNTABLE, 0)
|
||||
arg(readahead_ARG, 'r', "readahead", readahead_arg, 0, 0)
|
||||
arg(resizefs_ARG, 'r', "resizefs", NULL, 0, 0)
|
||||
arg(reset_ARG, 'R', "reset", NULL, 0, 0)
|
||||
arg(regionsize_ARG, 'R', "regionsize", size_mb_arg, 0, 0)
|
||||
arg(physicalextentsize_ARG, 's', "physicalextentsize", size_mb_arg, 0, 0)
|
||||
arg(snapshot_ARG, 's', "snapshot", NULL, 0, 0)
|
||||
arg(short_ARG, 's', "short", NULL, 0, 0)
|
||||
arg(stdin_ARG, 's', "stdin", NULL, 0, 0)
|
||||
arg(select_ARG, 'S', "select", string_arg, ARG_GROUPABLE, 0)
|
||||
arg(test_ARG, 't', "test", NULL, 0, 0)
|
||||
arg(thin_ARG, 'T', "thin", NULL, 0, 0)
|
||||
arg(uuid_ARG, 'u', "uuid", NULL, 0, 0)
|
||||
arg(uuidstr_ARG, 'u', "uuid", string_arg, 0, 0)
|
||||
arg(uuidlist_ARG, 'U', "uuidlist", NULL, 0, 0)
|
||||
arg(verbose_ARG, 'v', "verbose", NULL, ARG_COUNTABLE, 0)
|
||||
arg(volumegroup_ARG, 'V', "volumegroup", NULL, 0, 0)
|
||||
arg(virtualsize_ARG, 'V', "virtualsize", size_mb_arg, 0, 0)
|
||||
arg(wipesignatures_ARG, 'W', "wipesignatures", yes_no_arg, 0, 0)
|
||||
arg(allocatable_ARG, 'x', "allocatable", yes_no_arg, 0, 0)
|
||||
arg(resizeable_ARG, 'x', "resizeable", yes_no_arg, 0, 0)
|
||||
arg(yes_ARG, 'y', "yes", NULL, 0, 0)
|
||||
arg(zero_ARG, 'Z', "zero", yes_no_arg, 0, 0)
|
||||
arg(activate_ARG, 'a', "activate", activation_VAL, 0, 0)
|
||||
arg(all_ARG, 'a', "all", 0, 0, 0)
|
||||
arg(autobackup_ARG, 'A', "autobackup", bool_VAL, 0, 0)
|
||||
arg(activevolumegroups_ARG, 'A', "activevolumegroups", 0, 0, 0)
|
||||
arg(background_ARG, 'b', "background", 0, 0, 0)
|
||||
arg(backgroundfork_ARG, 'b', "background", 0, 0, 0)
|
||||
arg(basevgname_ARG, 'n', "basevgname", string_VAL, 0, 0)
|
||||
arg(blockdevice_ARG, 'b', "blockdevice", 0, 0, 0)
|
||||
arg(chunksize_ARG, 'c', "chunksize", sizekb_VAL, 0, 0)
|
||||
arg(clustered_ARG, 'c', "clustered", bool_VAL, 0, 0)
|
||||
arg(colon_ARG, 'c', "colon", 0, 0, 0)
|
||||
arg(columns_ARG, 'C', "columns", 0, 0, 0)
|
||||
arg(contiguous_ARG, 'C', "contiguous", bool_VAL, 0, 0)
|
||||
arg(debug_ARG, 'd', "debug", 0, ARG_COUNTABLE, 0)
|
||||
arg(exported_ARG, 'e', "exported", 0, 0, 0)
|
||||
arg(physicalextent_ARG, 'E', "physicalextent", 0, 0, 0)
|
||||
arg(file_ARG, 'f', "file", string_VAL, 0, 0)
|
||||
arg(force_ARG, 'f', "force", 0, ARG_COUNTABLE, 0)
|
||||
arg(full_ARG, 'f', "full", 0, 0, 0)
|
||||
arg(help_ARG, 'h', "help", 0, ARG_COUNTABLE, 0)
|
||||
arg(cache_ARG, 'H', "cache", 0, 0, 0)
|
||||
arg(history_ARG, 'H', "history", 0, 0, 0)
|
||||
arg(help2_ARG, '?', "", 0, 0, 0)
|
||||
arg(import_ARG, 'i', "import", 0, 0, 0)
|
||||
arg(interval_ARG, 'i', "interval", number_VAL, 0, 0)
|
||||
arg(iop_version_ARG, 'i', "iop_version", 0, 0, 0)
|
||||
arg(stripes_ARG, 'i', "stripes", number_VAL, 0, 0)
|
||||
arg(stripesize_ARG, 'I', "stripesize", sizekb_VAL, 0, 0)
|
||||
arg(logicalvolume_ARG, 'l', "logicalvolume", number_VAL, 0, 0)
|
||||
arg(maxlogicalvolumes_ARG, 'l', "maxlogicalvolumes", number_VAL, 0, 0)
|
||||
arg(extents_ARG, 'l', "extents", numsignedper_VAL, 0, 0)
|
||||
arg(list_ARG, 'l', "list", 0, 0, 0)
|
||||
arg(lvmpartition_ARG, 'l', "lvmpartition", 0, 0, 0)
|
||||
arg(size_ARG, 'L', "size", sizemb_VAL, 0, 0)
|
||||
arg(persistent_ARG, 'M', "persistent", bool_VAL, 0, 0)
|
||||
arg(major_ARG, 'j', "major", number_VAL, ARG_GROUPABLE, 0)
|
||||
arg(setactivationskip_ARG, 'k', "setactivationskip", bool_VAL, 0, 0)
|
||||
arg(ignoreactivationskip_ARG, 'K', "ignoreactivationskip", 0, 0, 0)
|
||||
arg(maps_ARG, 'm', "maps", 0, 0, 0)
|
||||
arg(mirrors_ARG, 'm', "mirrors", numsigned_VAL, 0, 0)
|
||||
arg(metadatatype_ARG, 'M', "metadatatype", metadatatype_VAL, 0, 0)
|
||||
arg(name_ARG, 'n', "name", string_VAL, 0, 0)
|
||||
arg(nofsck_ARG, 'n', "nofsck", 0, 0, 0)
|
||||
arg(novolumegroup_ARG, 'n', "novolumegroup", 0, 0, 0)
|
||||
arg(oldpath_ARG, 'n', "oldpath", 0, 0, 0)
|
||||
arg(options_ARG, 'o', "options", string_VAL, ARG_GROUPABLE, 0)
|
||||
arg(sort_ARG, 'O', "sort", string_VAL, ARG_GROUPABLE, 0)
|
||||
arg(maxphysicalvolumes_ARG, 'p', "maxphysicalvolumes", number_VAL, 0, 0)
|
||||
arg(permission_ARG, 'p', "permission", permission_VAL, 0, 0)
|
||||
arg(partial_ARG, 'P', "partial", 0, 0, 0)
|
||||
arg(physicalvolume_ARG, 'P', "physicalvolume", 0, 0, 0)
|
||||
arg(quiet_ARG, 'q', "quiet", 0, ARG_COUNTABLE, 0)
|
||||
arg(readahead_ARG, 'r', "readahead", readahead_VAL, 0, 0)
|
||||
arg(resizefs_ARG, 'r', "resizefs", 0, 0, 0)
|
||||
arg(reset_ARG, 'R', "reset", 0, 0, 0)
|
||||
arg(regionsize_ARG, 'R', "regionsize", sizemb_VAL, 0, 0)
|
||||
arg(physicalextentsize_ARG, 's', "physicalextentsize", sizemb_VAL, 0, 0)
|
||||
arg(snapshot_ARG, 's', "snapshot", 0, 0, 0)
|
||||
arg(short_ARG, 's', "short", 0, 0, 0)
|
||||
arg(stdin_ARG, 's', "stdin", 0, 0, 0)
|
||||
arg(select_ARG, 'S', "select", string_VAL, ARG_GROUPABLE, 0)
|
||||
arg(test_ARG, 't', "test", 0, 0, 0)
|
||||
arg(thin_ARG, 'T', "thin", 0, 0, 0)
|
||||
arg(uuid_ARG, 'u', "uuid", 0, 0, 0)
|
||||
arg(uuidstr_ARG, 'u', "uuid", string_VAL, 0, 0)
|
||||
arg(uuidlist_ARG, 'U', "uuidlist", 0, 0, 0)
|
||||
arg(verbose_ARG, 'v', "verbose", 0, ARG_COUNTABLE, 0)
|
||||
arg(volumegroup_ARG, 'V', "volumegroup", 0, 0, 0)
|
||||
arg(virtualsize_ARG, 'V', "virtualsize", sizemb_VAL, 0, 0)
|
||||
arg(wipesignatures_ARG, 'W', "wipesignatures", bool_VAL, 0, 0)
|
||||
arg(allocatable_ARG, 'x', "allocatable", bool_VAL, 0, 0)
|
||||
arg(resizeable_ARG, 'x', "resizeable", bool_VAL, 0, 0)
|
||||
arg(yes_ARG, 'y', "yes", 0, 0, 0)
|
||||
arg(zero_ARG, 'Z', "zero", bool_VAL, 0, 0)
|
||||
|
||||
/* this should always be last */
|
||||
arg(ARG_COUNT, '-', "", NULL, 0, 0)
|
||||
arg(ARG_COUNT, '-', "", 0, 0, 0)
|
||||
/* *INDENT-ON* */
|
||||
|
3
tools/command-lines-count.h
Normal file
3
tools/command-lines-count.h
Normal file
@@ -0,0 +1,3 @@
|
||||
/* Do not edit. This file is generated by scripts/create-commands */
|
||||
/* using command definitions from scripts/command-lines.in */
|
||||
#define COMMAND_COUNT 146
|
8409
tools/command-lines.h
Normal file
8409
tools/command-lines.h
Normal file
File diff suppressed because it is too large
Load Diff
169
tools/command.h
Normal file
169
tools/command.h
Normal file
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2015 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_COMMAND_H
|
||||
#define _LVM_COMMAND_H
|
||||
|
||||
struct cmd_context;
|
||||
|
||||
/* old per-command-name function */
|
||||
typedef int (*command_fn) (struct cmd_context *cmd, int argc, char **argv);
|
||||
|
||||
/* new per-command-line-id functions */
|
||||
typedef int (*command_line_fn) (struct cmd_context *cmd, int argc, char **argv);
|
||||
|
||||
struct command_function {
|
||||
int command_line_enum;
|
||||
command_line_fn fn;
|
||||
};
|
||||
|
||||
struct command_name {
|
||||
const char *name;
|
||||
const char *desc; /* general command description from commands.h */
|
||||
unsigned int flags;
|
||||
|
||||
/* union of {required,optional}_opt_args for all commands with this name */
|
||||
int valid_args[ARG_COUNT];
|
||||
int num_args;
|
||||
};
|
||||
|
||||
/*
|
||||
* Command defintion
|
||||
*
|
||||
* A command is defined in terms of a command name,
|
||||
* required options (+args), optional options (+args),
|
||||
* required positional args, optional positional args.
|
||||
*
|
||||
* A positional arg always has non-zero pos_arg.def.types.
|
||||
* The first positional arg has pos_arg.pos of 1.
|
||||
*/
|
||||
|
||||
/* arg_def flags */
|
||||
#define ARG_DEF_FLAG_NEW 1 << 0
|
||||
#define ARG_DEF_FLAG_MAY_REPEAT 1 << 1
|
||||
|
||||
/* arg_def lv_types */
|
||||
enum {
|
||||
ARG_DEF_LV_ANY = 0,
|
||||
ARG_DEF_LV_LINEAR = 1 << 0,
|
||||
ARG_DEF_LV_STRIPED = 1 << 1,
|
||||
ARG_DEF_LV_SNAPSHOT = 1 << 2,
|
||||
ARG_DEF_LV_MIRROR = 1 << 3,
|
||||
ARG_DEF_LV_RAID = 1 << 4,
|
||||
ARG_DEF_LV_RAID0 = 1 << 5,
|
||||
ARG_DEF_LV_RAID1 = 1 << 6,
|
||||
ARG_DEF_LV_RAID4 = 1 << 7,
|
||||
ARG_DEF_LV_RAID5 = 1 << 8,
|
||||
ARG_DEF_LV_RAID6 = 1 << 9,
|
||||
ARG_DEF_LV_RAID10 = 1 << 10,
|
||||
ARG_DEF_LV_THIN = 1 << 11,
|
||||
ARG_DEF_LV_THINPOOL = 1 << 12,
|
||||
ARG_DEF_LV_CACHE = 1 << 13,
|
||||
ARG_DEF_LV_CACHEPOOL = 1 << 14,
|
||||
ARG_DEF_LV_LAST = 1 << 15,
|
||||
};
|
||||
|
||||
static inline int val_bit_is_set(uint64_t val_bits, int val_enum)
|
||||
{
|
||||
return (val_bits & (1 << val_enum)) ? 1 : 0;
|
||||
}
|
||||
|
||||
static inline uint64_t val_enum_to_bit(int val_enum)
|
||||
{
|
||||
return 1 << val_enum;
|
||||
}
|
||||
|
||||
/* Description a value that follows an option or exists in a position. */
|
||||
|
||||
struct arg_def {
|
||||
uint64_t val_bits; /* bits of x_VAL, can be multiple for pos_arg */
|
||||
uint64_t num; /* a literal number for conststr_VAL */
|
||||
const char *str; /* a literal string for constnum_VAL */
|
||||
uint32_t lv_types; /* ARG_DEF_LV_, for lv_VAL, can be multiple */
|
||||
uint32_t flags; /* ARG_DEF_FLAG_ */
|
||||
};
|
||||
|
||||
/* Description of an option and the value that follows it. */
|
||||
|
||||
struct opt_arg {
|
||||
int opt; /* option, e.g. foo_ARG */
|
||||
struct arg_def def; /* defines accepted values */
|
||||
};
|
||||
|
||||
/* Description of a position and the value that exists there. */
|
||||
|
||||
struct pos_arg {
|
||||
int pos; /* position, e.g. first is 1 */
|
||||
struct arg_def def; /* defines accepted values */
|
||||
};
|
||||
|
||||
/*
|
||||
* CMD_RO_ARGS needs to accomodate a list of options,
|
||||
* of which one is required after which the rest are
|
||||
* optional.
|
||||
*/
|
||||
#define CMD_RO_ARGS 64 /* required opt args */
|
||||
#define CMD_OO_ARGS 150 /* optional opt args */
|
||||
#define CMD_RP_ARGS 8 /* required positional args */
|
||||
#define CMD_OP_ARGS 8 /* optional positional args */
|
||||
|
||||
/*
|
||||
* one or more from required_opt_args is required,
|
||||
* then the rest are optional.
|
||||
*/
|
||||
#define CMD_FLAG_ONE_REQUIRED_OPT 1
|
||||
|
||||
/* a register of the lvm commands */
|
||||
struct command {
|
||||
const char *name;
|
||||
const char *desc; /* specific command description from command-lines.h */
|
||||
const char *usage; /* excludes common options like --help, --debug */
|
||||
const char *usage_common; /* includes commmon options like --help, --debug */
|
||||
const char *command_line_id;
|
||||
int command_line_enum; /* <command_line_id>_CMD */
|
||||
|
||||
struct command_name *cname;
|
||||
|
||||
command_fn fn; /* old style */
|
||||
struct command_function *functions; /* new style */
|
||||
|
||||
unsigned int flags; /* copied from command_name.flags from commands.h */
|
||||
|
||||
unsigned int cmd_flags; /* CMD_FLAG_ */
|
||||
|
||||
/* definitions of opt/pos args */
|
||||
|
||||
/* required args following an --opt */
|
||||
struct opt_arg required_opt_args[CMD_RO_ARGS];
|
||||
|
||||
/* optional args following an --opt */
|
||||
struct opt_arg optional_opt_args[CMD_OO_ARGS];
|
||||
|
||||
/* required positional args */
|
||||
struct pos_arg required_pos_args[CMD_RP_ARGS];
|
||||
|
||||
/* optional positional args */
|
||||
struct pos_arg optional_pos_args[CMD_OP_ARGS];
|
||||
|
||||
int ro_count;
|
||||
int oo_count;
|
||||
int rp_count;
|
||||
int op_count;
|
||||
|
||||
/* used for processing current position */
|
||||
int pos_count;
|
||||
};
|
||||
|
||||
#endif
|
1428
tools/commands.h
1428
tools/commands.h
File diff suppressed because it is too large
Load Diff
@@ -86,8 +86,7 @@ struct lvconvert_params {
|
||||
sign_t mirrors_sign;
|
||||
uint32_t stripes;
|
||||
uint32_t stripe_size;
|
||||
unsigned stripes_supplied;
|
||||
unsigned stripe_size_supplied;
|
||||
uint32_t stripe_size_supplied;
|
||||
uint32_t read_ahead;
|
||||
cache_mode_t cache_mode; /* cache */
|
||||
const char *policy_name; /* cache */
|
||||
@@ -1849,11 +1848,6 @@ static int _lvconvert_raid(struct logical_volume *lv, struct lvconvert_params *l
|
||||
lvseg_name(seg));
|
||||
return 0;
|
||||
}
|
||||
if (seg_is_raid10(seg)) {
|
||||
log_error("--mirrors/-m cannot be changed with %s.",
|
||||
lvseg_name(seg));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_lvconvert_validate_thin(lv, lp))
|
||||
@@ -1968,13 +1962,7 @@ static int _lvconvert_raid(struct logical_volume *lv, struct lvconvert_params *l
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (seg_is_striped(seg)) {
|
||||
log_error("Cannot repair LV %s of type raid0.",
|
||||
display_lvname(lv));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!lv_raid_percent(lv, &sync_percent)) {
|
||||
if (!seg_is_striped(seg) && !lv_raid_percent(lv, &sync_percent)) {
|
||||
log_error("Unable to determine sync status of %s.",
|
||||
display_lvname(lv));
|
||||
return 0;
|
||||
@@ -3195,7 +3183,7 @@ static int _lvconvert_pool(struct cmd_context *cmd,
|
||||
return_0;
|
||||
|
||||
if (!get_stripe_params(cmd, get_segtype_from_string(cmd, SEG_TYPE_NAME_STRIPED),
|
||||
&lp->stripes, &lp->stripe_size, &lp->stripes_supplied, &lp->stripe_size_supplied))
|
||||
&lp->stripes, &lp->stripe_size))
|
||||
return_0;
|
||||
|
||||
if (!archive(vg))
|
||||
@@ -4485,8 +4473,10 @@ static int _lvconvert(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
if (_mirror_or_raid_type_requested(cmd, lp->type_str) || _raid0_type_requested(lp->type_str) ||
|
||||
_striped_type_requested(lp->type_str) || lp->repair || lp->mirrorlog || lp->corelog) {
|
||||
/* FIXME Handle +/- adjustments too? */
|
||||
if (!get_stripe_params(cmd, lp->segtype, &lp->stripes, &lp->stripe_size, &lp->stripes_supplied, &lp->stripe_size_supplied))
|
||||
if (!get_stripe_params(cmd, lp->segtype, &lp->stripes, &lp->stripe_size))
|
||||
return_0;
|
||||
/* FIXME Move this into the get function */
|
||||
lp->stripe_size_supplied = arg_is_set(cmd, stripesize_ARG);
|
||||
|
||||
if (_raid0_type_requested(lp->type_str) || _striped_type_requested(lp->type_str))
|
||||
/* FIXME Shouldn't need to override get_stripe_params which defaults to 1 stripe (i.e. linear)! */
|
||||
|
@@ -464,13 +464,8 @@ static int _read_raid_params(struct cmd_context *cmd,
|
||||
/*
|
||||
* RAID10 needs at least 4 stripes
|
||||
*/
|
||||
if (lp->stripes_supplied) {
|
||||
log_error("Minimum of 2 stripes required for %s.",
|
||||
lp->segtype->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_verbose("Using 2 stripes for %s.", lp->segtype->name);
|
||||
log_warn("Adjusting stripes to the minimum of 2 for %s.",
|
||||
lp->segtype->name);
|
||||
lp->stripes = 2;
|
||||
}
|
||||
|
||||
@@ -485,28 +480,14 @@ static int _read_raid_params(struct cmd_context *cmd,
|
||||
/*
|
||||
* RAID1 does not take a stripe arg
|
||||
*/
|
||||
log_error("Stripes argument cannot be used with segment type, %s",
|
||||
log_error("Stripe argument cannot be used with segment type, %s",
|
||||
lp->segtype->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
} else if (seg_is_any_raid6(lp) && lp->stripes < 3) {
|
||||
if (lp->stripes_supplied) {
|
||||
log_error("Minimum of 3 stripes required for %s.", lp->segtype->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_verbose("Using 3 stripes for %s.", lp->segtype->name);
|
||||
lp->stripes = 3;
|
||||
} else if (lp->stripes < 2) {
|
||||
if (lp->stripes_supplied) {
|
||||
log_error("Minimum of 2 stripes required for %s.", lp->segtype->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_verbose("Using 2 stripes for %s.", lp->segtype->name);
|
||||
lp->stripes = 2;
|
||||
}
|
||||
} else if (lp->stripes < 2)
|
||||
/* No stripes argument was given */
|
||||
lp->stripes = seg_is_any_raid6(lp) ? 3 : 2;
|
||||
|
||||
if (seg_is_raid1(lp)) {
|
||||
if (lp->stripe_size) {
|
||||
@@ -514,8 +495,6 @@ static int _read_raid_params(struct cmd_context *cmd,
|
||||
lp->segtype->name);
|
||||
return 0;
|
||||
}
|
||||
} else if (!lp->stripe_size) {
|
||||
; // lp->stripe_size = find_config_tree_int(cmd, metadata_stripesize_CFG, NULL) * 2;
|
||||
}
|
||||
|
||||
if (arg_is_set(cmd, mirrors_ARG) && segtype_is_raid(lp->segtype) &&
|
||||
@@ -547,6 +526,7 @@ static int _read_raid_params(struct cmd_context *cmd,
|
||||
static int _read_mirror_and_raid_params(struct cmd_context *cmd,
|
||||
struct lvcreate_params *lp)
|
||||
{
|
||||
int pagesize = lvm_getpagesize();
|
||||
unsigned max_images;
|
||||
|
||||
if (seg_is_raid(lp)) {
|
||||
@@ -623,20 +603,12 @@ static int _read_mirror_and_raid_params(struct cmd_context *cmd,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 1
|
||||
if (lp->region_size && !is_power_of_2(lp->region_size)) {
|
||||
log_error("Region size (%" PRIu32 ") must be power of 2",
|
||||
lp->region_size);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
if (lp->region_size % (pagesize >> SECTOR_SHIFT)) {
|
||||
log_error("Region size (%" PRIu32 ") must be a multiple of "
|
||||
"machine memory page size (%d)",
|
||||
lp->region_size, pagesize >> SECTOR_SHIFT);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (seg_is_mirror(lp) && !_read_mirror_params(cmd, lp))
|
||||
return_0;
|
||||
@@ -1089,7 +1061,7 @@ static int _lvcreate_params(struct cmd_context *cmd,
|
||||
|
||||
if (!_lvcreate_name_params(cmd, &argc, &argv, lp) ||
|
||||
!_read_size_params(cmd, lp, lcp) ||
|
||||
!get_stripe_params(cmd, lp->segtype, &lp->stripes, &lp->stripe_size, &lp->stripes_supplied, &lp->stripe_size_supplied) ||
|
||||
!get_stripe_params(cmd, lp->segtype, &lp->stripes, &lp->stripe_size) ||
|
||||
(lp->create_pool &&
|
||||
!get_pool_params(cmd, lp->segtype, &lp->passed_args,
|
||||
&lp->pool_metadata_size, &lp->pool_metadata_spare,
|
||||
@@ -1283,10 +1255,17 @@ static int _check_raid_parameters(struct volume_group *vg,
|
||||
struct lvcreate_cmdline_params *lcp)
|
||||
{
|
||||
unsigned devs = lcp->pv_count ? : dm_list_size(&vg->pvs);
|
||||
uint64_t page_sectors = lvm_getpagesize() >> SECTOR_SHIFT;
|
||||
struct cmd_context *cmd = vg->cmd;
|
||||
int old_stripes = !arg_is_set(cmd, stripes_ARG) &&
|
||||
find_config_tree_bool(cmd, allocation_raid_stripe_all_devices_CFG, NULL);
|
||||
|
||||
if (vg->extent_size < page_sectors) {
|
||||
log_error("Unable to create RAID LV: requires minimum VG extent size %s",
|
||||
display_size(vg->cmd, page_sectors));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we requested the previous behaviour by setting
|
||||
* "allocation/raid_stripe_all_devices = 1" and the
|
||||
|
32
tools/lvm.c
32
tools/lvm.c
@@ -45,9 +45,9 @@ static char *_list_cmds(const char *text, int state)
|
||||
len = strlen(text);
|
||||
}
|
||||
|
||||
while (i < _cmdline->num_commands)
|
||||
if (!strncmp(text, _cmdline->commands[i++].name, len))
|
||||
return strdup(_cmdline->commands[i - 1].name);
|
||||
while (i < _cmdline->num_command_names)
|
||||
if (!strncmp(text, _cmdline->command_names[i++].name, len))
|
||||
return strdup(_cmdline->command_names[i - 1].name);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -57,7 +57,7 @@ static char *_list_args(const char *text, int state)
|
||||
{
|
||||
static int match_no = 0;
|
||||
static size_t len = 0;
|
||||
static struct command *com;
|
||||
static struct command_name *cname;
|
||||
|
||||
/* Initialise if this is a new completion attempt */
|
||||
if (!state) {
|
||||
@@ -65,40 +65,40 @@ static char *_list_args(const char *text, int state)
|
||||
int j;
|
||||
|
||||
match_no = 0;
|
||||
com = NULL;
|
||||
cname = NULL;
|
||||
len = strlen(text);
|
||||
|
||||
/* Find start of first word in line buffer */
|
||||
while (isspace(*s))
|
||||
s++;
|
||||
|
||||
/* Look for word in list of commands */
|
||||
for (j = 0; j < _cmdline->num_commands; j++) {
|
||||
/* Look for word in list of command names */
|
||||
for (j = 0; j < _cmdline->num_command_names; j++) {
|
||||
const char *p;
|
||||
char *q = s;
|
||||
|
||||
p = _cmdline->commands[j].name;
|
||||
p = _cmdline->command_names[j].name;
|
||||
while (*p == *q) {
|
||||
p++;
|
||||
q++;
|
||||
}
|
||||
if ((!*p) && *q == ' ') {
|
||||
com = _cmdline->commands + j;
|
||||
cname = _cmdline->command_names + j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!com)
|
||||
if (!cname)
|
||||
return NULL;
|
||||
|
||||
/* Short form arguments */
|
||||
if (len < 3) {
|
||||
while (match_no < com->num_args) {
|
||||
while (match_no < cname->num_args) {
|
||||
char s[3];
|
||||
char c;
|
||||
if (!(c = (_cmdline->arg_props +
|
||||
com->valid_args[match_no++])->short_arg))
|
||||
cname->valid_args[match_no++])->short_arg))
|
||||
continue;
|
||||
|
||||
sprintf(s, "-%c", c);
|
||||
@@ -108,13 +108,13 @@ static char *_list_args(const char *text, int state)
|
||||
}
|
||||
|
||||
/* Long form arguments */
|
||||
if (match_no < com->num_args)
|
||||
match_no = com->num_args;
|
||||
if (match_no < cname->num_args)
|
||||
match_no = cname->num_args;
|
||||
|
||||
while (match_no - com->num_args < com->num_args) {
|
||||
while (match_no - cname->num_args < cname->num_args) {
|
||||
const char *l;
|
||||
l = (_cmdline->arg_props +
|
||||
com->valid_args[match_no++ - com->num_args])->long_arg;
|
||||
cname->valid_args[match_no++ - cname->num_args])->long_arg;
|
||||
if (*(l + 2) && !strncmp(text, l, len))
|
||||
return strdup(l);
|
||||
}
|
||||
|
@@ -19,10 +19,11 @@
|
||||
struct cmd_context;
|
||||
|
||||
struct cmdline_context {
|
||||
struct arg_props *arg_props;
|
||||
struct command *commands;
|
||||
int num_commands;
|
||||
int commands_size;
|
||||
struct arg_props *arg_props;
|
||||
struct command *commands;
|
||||
int num_commands;
|
||||
struct command_name *command_names;
|
||||
int num_command_names;
|
||||
};
|
||||
|
||||
int lvm2_main(int argc, char **argv);
|
||||
|
1055
tools/lvmcmdline.c
1055
tools/lvmcmdline.c
File diff suppressed because it is too large
Load Diff
@@ -1278,31 +1278,16 @@ static int _validate_stripe_params(struct cmd_context *cmd, const struct segment
|
||||
{
|
||||
int stripe_size_required = segtype_supports_stripe_size(segtype);
|
||||
|
||||
#if 1
|
||||
if (stripe_size_required) {
|
||||
if (*stripes == 1 && segtype_is_mirror(segtype)) {
|
||||
stripe_size_required = 0;
|
||||
if (*stripe_size) {
|
||||
log_print_unless_silent("Ignoring stripesize argument with single stripe.");
|
||||
*stripe_size = 0;
|
||||
}
|
||||
}
|
||||
} else if (*stripe_size) {
|
||||
log_print_unless_silent("Ignoring stripesize argument for %s devices.", segtype->name);
|
||||
*stripe_size = 0;
|
||||
}
|
||||
#else
|
||||
if (!stripe_size_required && *stripe_size) {
|
||||
log_print_unless_silent("Ignoring stripesize argument for %s devices.", segtype->name);
|
||||
*stripe_size = 0;
|
||||
} else if (*stripes == 1 && (segtype_is_striped_target(segtype) || segtype_is_mirror(segtype))) {
|
||||
} else if (*stripes == 1 && (segtype_is_striped(segtype) || segtype_is_mirror(segtype))) {
|
||||
stripe_size_required = 0;
|
||||
if (*stripe_size) {
|
||||
log_print_unless_silent("Ignoring stripesize argument with single stripe.");
|
||||
*stripe_size = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (stripe_size_required) {
|
||||
if (!*stripe_size) {
|
||||
@@ -1333,17 +1318,13 @@ static int _validate_stripe_params(struct cmd_context *cmd, const struct segment
|
||||
* power of 2, we must divide UINT_MAX by four and add 1 (to round it
|
||||
* up to the power of 2)
|
||||
*/
|
||||
int get_stripe_params(struct cmd_context *cmd, const struct segment_type *segtype,
|
||||
uint32_t *stripes, uint32_t *stripe_size,
|
||||
unsigned *stripes_supplied, unsigned *stripe_size_supplied)
|
||||
int get_stripe_params(struct cmd_context *cmd, const struct segment_type *segtype, uint32_t *stripes, uint32_t *stripe_size)
|
||||
{
|
||||
/* stripes_long_ARG takes precedence (for lvconvert) */
|
||||
/* FIXME Cope with relative +/- changes for lvconvert. */
|
||||
*stripes = arg_uint_value(cmd, arg_is_set(cmd, stripes_long_ARG) ? stripes_long_ARG : stripes_ARG, 1);
|
||||
*stripes_supplied = arg_is_set(cmd, stripes_long_ARG) ? : arg_is_set(cmd, stripes_ARG);
|
||||
|
||||
*stripe_size = arg_uint_value(cmd, stripesize_ARG, 0);
|
||||
*stripe_size_supplied = arg_is_set(cmd, stripesize_ARG);
|
||||
if (*stripe_size) {
|
||||
if (arg_sign_value(cmd, stripesize_ARG, SIGN_NONE) == SIGN_MINUS) {
|
||||
log_error("Negative stripesize is invalid.");
|
||||
@@ -2365,8 +2346,12 @@ int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
|
||||
struct dm_str_list *sl;
|
||||
struct dm_list final_lvs;
|
||||
struct lv_list *final_lvl;
|
||||
struct dm_list found_arg_lvnames;
|
||||
struct glv_list *glvl, *tglvl;
|
||||
int do_report_ret_code = 1;
|
||||
uint32_t lv_types;
|
||||
struct logical_volume *lv;
|
||||
struct lv_segment *seg;
|
||||
|
||||
log_set_report_object_type(LOG_REPORT_OBJECT_TYPE_LV);
|
||||
|
||||
@@ -2375,6 +2360,7 @@ int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
|
||||
stack;
|
||||
|
||||
dm_list_init(&final_lvs);
|
||||
dm_list_init(&found_arg_lvnames);
|
||||
|
||||
if (!vg_check_status(vg, EXPORTED_VG)) {
|
||||
ret_max = ECMD_FAILED;
|
||||
@@ -2468,6 +2454,7 @@ int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
|
||||
if (lvargs_supplied && str_list_match_item(arg_lvnames, lvl->lv->name)) {
|
||||
/* Remove LV from list of unprocessed LV names */
|
||||
str_list_del(arg_lvnames, lvl->lv->name);
|
||||
str_list_add(cmd->mem, &found_arg_lvnames, lvl->lv->name);
|
||||
process_lv = 1;
|
||||
}
|
||||
|
||||
@@ -2515,6 +2502,64 @@ int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
|
||||
if (lv_is_removed(lvl->lv))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* If the command definition specifies one required positional
|
||||
* LV (possibly repeatable), and specifies accepted LV types,
|
||||
* then verify that the LV being processed matches one of those
|
||||
* types.
|
||||
*
|
||||
* process_each_lv() can only be used for commands that have
|
||||
* one positional LV arg (optionally repeating, where each is
|
||||
* processed independently.) It cannot work for commands that
|
||||
* have different required LVs in designated positions, like
|
||||
* 'lvrename LV1 LV2', where each LV is not processed
|
||||
* independently. That means that this LV type check only
|
||||
* needs to check the lv_type of the first positional arg.
|
||||
*
|
||||
* There is one command that violates this rule by stealing
|
||||
* the first positional LV arg before calling process_each_lv:
|
||||
* lvconvert --type snapshot LV_linear_striped_raid LV_snapshot
|
||||
* This code cannot validate that case. process_each_lv() sees
|
||||
* a single LV name arg, but it's in pos 2. Could we work around
|
||||
* this by looking at the final positional arg rather than always
|
||||
* looking at pos 1?
|
||||
*
|
||||
* This only validates types for required LV positional args
|
||||
* (currently there are no command specifications that include
|
||||
* specific LV types in optional positional args.)
|
||||
*/
|
||||
|
||||
if ((cmd->command->rp_count == 1) &&
|
||||
val_bit_is_set(cmd->command->required_pos_args[0].def.val_bits, lv_VAL) &&
|
||||
cmd->command->required_pos_args[0].def.lv_types) {
|
||||
|
||||
lv_types = cmd->command->required_pos_args[0].def.lv_types;
|
||||
lv = lvl->lv;
|
||||
seg = first_seg(lv);
|
||||
|
||||
if ((lv_is_cow(lv) && !(lv_types & ARG_DEF_LV_SNAPSHOT)) ||
|
||||
(lv_is_thin_volume(lv) && !(lv_types & ARG_DEF_LV_THIN)) ||
|
||||
(lv_is_thin_pool(lv) && !(lv_types & ARG_DEF_LV_THINPOOL)) ||
|
||||
(lv_is_cache(lv) && !(lv_types & ARG_DEF_LV_CACHE)) ||
|
||||
(lv_is_cache_pool(lv) && !(lv_types & ARG_DEF_LV_CACHEPOOL)) ||
|
||||
(lv_is_mirror(lv) && !(lv_types & ARG_DEF_LV_MIRROR)) ||
|
||||
(lv_is_raid(lv) && !(lv_types & (ARG_DEF_LV_RAID | ARG_DEF_LV_RAID0 | ARG_DEF_LV_RAID1 | ARG_DEF_LV_RAID4 | ARG_DEF_LV_RAID5 | ARG_DEF_LV_RAID6 | ARG_DEF_LV_RAID10))) ||
|
||||
(segtype_is_striped(seg->segtype) && !(lv_types & ARG_DEF_LV_STRIPED)) ||
|
||||
(segtype_is_linear(seg->segtype) && !(lv_types & ARG_DEF_LV_LINEAR))) {
|
||||
/*
|
||||
* If a named LV arg cannot be processed it's an error, otherwise
|
||||
* the LV is skipped and doesn't cause the command to fail.
|
||||
*/
|
||||
if (str_list_match_item(&found_arg_lvnames, lv->name)) {
|
||||
log_error("Operation not permitted on LV %s with type %s.", display_lvname(lv), seg->segtype->name);
|
||||
ret_max = ECMD_FAILED;
|
||||
} else {
|
||||
log_warn("Operation not permitted on LV %s with type %s.", display_lvname(lv), seg->segtype->name);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
log_very_verbose("Processing LV %s in VG %s.", lvl->lv->name, vg->name);
|
||||
|
||||
ret = process_single_lv(cmd, lvl->lv, handle);
|
||||
|
@@ -197,8 +197,7 @@ int get_pool_params(struct cmd_context *cmd,
|
||||
int *zero);
|
||||
|
||||
int get_stripe_params(struct cmd_context *cmd, const struct segment_type *segtype,
|
||||
uint32_t *stripes, uint32_t *stripe_size,
|
||||
unsigned *stripes_supplied, unsigned *stripe_size_supplied);
|
||||
uint32_t *stripes, uint32_t *stripe_size);
|
||||
|
||||
int get_cache_params(struct cmd_context *cmd,
|
||||
cache_mode_t *cache_mode,
|
||||
|
@@ -50,20 +50,27 @@
|
||||
#define CMD_LEN 256
|
||||
#define MAX_ARGS 64
|
||||
|
||||
/* command functions */
|
||||
typedef int (*command_fn) (struct cmd_context * cmd, int argc, char **argv);
|
||||
/* define the enums for the values accepted by command line --options */
|
||||
enum {
|
||||
#define val(a, b, c, d) a ,
|
||||
#include "vals.h"
|
||||
#undef val
|
||||
};
|
||||
|
||||
#define xx(a, b...) int a(struct cmd_context *cmd, int argc, char **argv);
|
||||
#include "commands.h"
|
||||
#undef xx
|
||||
|
||||
/* define the enums for the command line switches */
|
||||
/* define the enums for the command line --options */
|
||||
enum {
|
||||
#define arg(a, b, c, d, e, f) a ,
|
||||
#include "args.h"
|
||||
#undef arg
|
||||
};
|
||||
|
||||
/* command functions */
|
||||
#define xx(a, b...) int a(struct cmd_context *cmd, int argc, char **argv);
|
||||
#include "commands.h"
|
||||
#undef xx
|
||||
|
||||
#include "command.h"
|
||||
|
||||
#define ARG_COUNTABLE 0x00000001 /* E.g. -vvvv */
|
||||
#define ARG_GROUPABLE 0x00000002 /* E.g. --addtag */
|
||||
|
||||
@@ -79,13 +86,13 @@ struct arg_values {
|
||||
/* void *ptr; // Currently not used. */
|
||||
};
|
||||
|
||||
/* a global table of possible arguments */
|
||||
/* a global table of possible --option's */
|
||||
struct arg_props {
|
||||
int arg_enum; /* foo_ARG from args.h */
|
||||
const char short_arg;
|
||||
char _padding[7];
|
||||
const char *long_arg;
|
||||
|
||||
int (*fn) (struct cmd_context *cmd, struct arg_values *av);
|
||||
int val_enum; /* foo_VAL from vals.h */
|
||||
uint32_t flags;
|
||||
uint32_t prio;
|
||||
};
|
||||
@@ -96,6 +103,14 @@ struct arg_value_group_list {
|
||||
uint32_t prio;
|
||||
};
|
||||
|
||||
/* a global table of possible --option values */
|
||||
struct val_props {
|
||||
int val_enum; /* foo_VAL from vals.h */
|
||||
int (*fn) (struct cmd_context *cmd, struct arg_values *av);
|
||||
const char *name;
|
||||
const char *usage;
|
||||
};
|
||||
|
||||
#define CACHE_VGMETADATA 0x00000001
|
||||
#define PERMITTED_READ_ONLY 0x00000002
|
||||
/* Process all VGs if none specified on the command line. */
|
||||
@@ -118,19 +133,6 @@ struct arg_value_group_list {
|
||||
#define ENABLE_DUPLICATE_DEVS 0x00000400
|
||||
/* Command does not accept tags as args. */
|
||||
#define DISALLOW_TAG_ARGS 0x00000800
|
||||
|
||||
/* a register of the lvm commands */
|
||||
struct command {
|
||||
const char *name;
|
||||
const char *desc;
|
||||
const char *usage;
|
||||
command_fn fn;
|
||||
|
||||
unsigned flags;
|
||||
|
||||
int num_args;
|
||||
int *valid_args;
|
||||
};
|
||||
|
||||
void usage(const char *name);
|
||||
|
||||
|
135
tools/vals.h
Normal file
135
tools/vals.h
Normal file
@@ -0,0 +1,135 @@
|
||||
|
||||
/*
|
||||
* Define value types which describe values accepted
|
||||
* by the --option's in args.h, and can also describe
|
||||
* the values accepted as positional args.
|
||||
*
|
||||
* Previously, accepted values were only "described"
|
||||
* by identifying the parsing function to use.
|
||||
*
|
||||
* Some standard val types are used by many options,
|
||||
* e.g. many options (aa_ARG, bb_ARG, cc_ARG) all
|
||||
* accept a number_VAL.
|
||||
*
|
||||
* Other special val types are used by only one option,
|
||||
* e.g. only mirrorlog_ARG accepts a mirrorlog_VAL.
|
||||
* This typically means that there are some specific
|
||||
* words that are recognized after the option.
|
||||
*
|
||||
* Some options currently take a standard val type,
|
||||
* (esp string_VAL), but they could be given their
|
||||
* own custom val type. The advantage of using a
|
||||
* custom val type is the possibility of validating
|
||||
* the value when parsing it with a custom parsing
|
||||
* function, and the possibility of displaying the
|
||||
* actual accepted values in the command usage.
|
||||
* Without a custom val type, the code must do ad hoc
|
||||
* validation of the string values, and the usage
|
||||
* output for the option will only say "String"
|
||||
* rather than giving the accepted string values.
|
||||
* Even without a custom parsing function, there is
|
||||
* reason to define a custom x_VAL enum so that a
|
||||
* more descriptive usage string can be specified
|
||||
* as opposed to just "String".
|
||||
*
|
||||
* Most of the val types defined here are used after
|
||||
* --option's, and are referenced in foo_ARG entries
|
||||
* in args.h. But, some val types are only used to
|
||||
* represent positional values in command definitions,
|
||||
* e.g. vg_VAL.
|
||||
*
|
||||
* val(a, b, c, d)
|
||||
*
|
||||
* a: foo_VAL enums
|
||||
* b: the function to parse and set the value
|
||||
* c: the name used to reference this value in command defs
|
||||
* d: what to display in usage output for this value
|
||||
*
|
||||
* command defintions will use --option NAME, where NAME
|
||||
* is shown in val() field c. NAME will be translated to
|
||||
* foo_VAL enum in field a, which is used in commands[]
|
||||
* structs.
|
||||
*
|
||||
* option definitions (arg.h) will reference foo_VAL enum
|
||||
* in field a.
|
||||
*
|
||||
* FIXME: for specialized val types, the set of recognized
|
||||
* words is not defined or stored in a consistent way,
|
||||
* but is just whatever the parsing function happens to look
|
||||
* for, so adding a new accepted value for the val type is
|
||||
* often just making the parsing function recognize a new
|
||||
* word. This new word should then also be added to the
|
||||
* usage string for the val type here. It would be nice
|
||||
* if the accepted values could be defined in a more
|
||||
* consistent way, perhaps in struct val_props.
|
||||
*
|
||||
* The usage text for an option is not always the full
|
||||
* set of words accepted for an option, but may be a
|
||||
* subset. i.e. an outdated word that no longer does
|
||||
* anything may not be shown, but may still be recognized
|
||||
* and ignored, or an option that shouldn't be used in
|
||||
* general isn't shown to avoid suggesting it.
|
||||
* e.g. for --activate we show the most common "y|n|ay"
|
||||
* without showing the lvmlockd variations "ey|sy" which
|
||||
* are not applicable in general.
|
||||
*
|
||||
* FIXME: are there some specialized or irrelevant
|
||||
* options included in the usage text below that should
|
||||
* be removed? Should "lvm1" be removed?
|
||||
*
|
||||
* For Number args that take optional units, a full usage
|
||||
* could be "Number[bBsSkKmMgGtTpPeE]" (with implied |),
|
||||
* but repeating this full specification produces cluttered
|
||||
* output, and doesn't indicate which unit is the default.
|
||||
* "Number[units]" would be cleaner, as would a subset of
|
||||
* common units, e.g. "Number[kmg...]", but neither helps
|
||||
* with default. "Number[k|unit]" and "Number[m|unit]" show
|
||||
* the default, and "unit" indicates that other units
|
||||
* are possible without listing them all. This also
|
||||
* suggests using the preferred lower case letters, because
|
||||
* --size and other option args treat upper/lower letters
|
||||
* the same, all as 1024 SI base. For this reason, we
|
||||
* should avoid suggesting the upper case letters.
|
||||
*/
|
||||
|
||||
val(none_VAL, NULL, "None", "") /* unused, for enum value 0 */
|
||||
val(conststr_VAL, NULL, "ConstString", "") /* used only for command defs */
|
||||
val(constnum_VAL, NULL, "ConstNumber", "") /* used only for command defs */
|
||||
val(bool_VAL, yes_no_arg, "Bool", "y|n")
|
||||
val(number_VAL, int_arg, "Number", NULL)
|
||||
val(string_VAL, string_arg, "String", NULL)
|
||||
val(vg_VAL, string_arg, "VG", NULL)
|
||||
val(lv_VAL, string_arg, "LV", NULL)
|
||||
val(pv_VAL, string_arg, "PV", NULL)
|
||||
val(tag_VAL, tag_arg, "Tag", NULL)
|
||||
val(select_VAL, NULL, "Select", NULL) /* used only for command defs */
|
||||
val(activationmode_VAL, string_arg, "ActivationMode", "partial|degraded|complete")
|
||||
val(activation_VAL, activation_arg, "Active", "y|n|ay")
|
||||
val(cachemode_VAL, cachemode_arg, "CacheMode", "writethrough|writeback")
|
||||
val(discards_VAL, discards_arg, "Discards", "passdown|nopassdown|ignore")
|
||||
val(mirrorlog_VAL, mirrorlog_arg, "MirrorLog", "core|disk")
|
||||
val(sizekb_VAL, size_kb_arg, "SizeKB", "Number[k|unit]")
|
||||
val(sizemb_VAL, size_mb_arg, "SizeMB", "Number[m|unit]")
|
||||
val(numsigned_VAL, int_arg_with_sign, "SNumber", "[+|-]Number")
|
||||
val(numsignedper_VAL, int_arg_with_sign_and_percent, "SNumberP", "[+|-]Number[%{VG|PVS|FREE}]")
|
||||
val(permission_VAL, permission_arg, "Permission", "rw|r")
|
||||
val(metadatatype_VAL, metadatatype_arg, "MetadataType", "lvm2|lvm1")
|
||||
val(units_VAL, string_arg, "Units", "hHbBsSkKmMgGtTpPeE")
|
||||
val(segtype_VAL, segtype_arg, "SegType", "linear|striped|snapshot|mirror|raid*|thin|cache|thin-pool|cache-pool")
|
||||
val(alloc_VAL, alloc_arg, "Alloc", "contiguous|cling|cling_by_tags|normal|anywhere|inherit")
|
||||
val(locktype_VAL, locktype_arg, "LockType", "sanlock|dlm|none")
|
||||
val(readahead_VAL, readahead_arg, "Readahead", "auto|none|NumberSectors")
|
||||
val(metadatacopies_VAL, metadatacopies_arg, "MetadataCopies", "all|unmanaged|Number")
|
||||
|
||||
/* this should always be last */
|
||||
val(VAL_COUNT, NULL, NULL, NULL)
|
||||
|
||||
/*
|
||||
* I suspect many of the following are good candidates for a custom VAL enum
|
||||
* for the benefit of custom parsing, or custom usage, or both:
|
||||
*
|
||||
* configreport_ARG, configtype_ARG, polloperation_ARG, raidrebuild_ARG,
|
||||
* raidsyncaction_ARG, raidwritemostly_ARG, reportformat_ARG, syncaction_ARG,
|
||||
* cachepolicy_ARG, cachesettings_ARG, writemostly_ARG
|
||||
*/
|
||||
|
Reference in New Issue
Block a user