1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-09-28 09:44:18 +03:00

Compare commits

..

19 Commits

Author SHA1 Message Date
David Teigland
9d326f4ffb commands: new method for defining commands 2016-09-06 16:30:00 -05:00
David Teigland
8c71fc1cc2 man: lvconvert mention required option 2016-08-17 14:56:01 -05:00
David Teigland
0336b41828 man: lvconvert change location of sentence
The details about each option are explained in the
section for that option.
2016-08-17 14:13:17 -05:00
Heinz Mauelshagen
c0a0eedf2e vgsplit: fix regression processing thin external origins
a579ba2ac2 fixed a regression causing a segfault if no external
origin existed but broke the logic leading to erroneous error
messages and creations of split off exported VGs in case the
external origin and the pool LVs were allocated on different PVs.

- resolves rhbz1367459
2016-08-16 23:57:09 +02:00
Heinz Mauelshagen
73df2aedf9 lvcreate: better error message creating RAID LV on < 4 KiB VG extent size
Creating a RaidLV in VGs with very small extent sizes caused
late failure in the kernel giving a not very informative error
message. Catch the attempt early and display failure message
'Unable to create RAID LV: requires minimum VG extent size 4.00 KiB'.

- resoves rhbz1179970
2016-08-16 13:39:40 +02:00
Alasdair G Kergon
114db6f745 tools: Suppress some unnecessary --stripesize warnings.
https://bugzilla.redhat.com/1366745
2016-08-15 19:38:45 +01:00
Heinz Mauelshagen
d83f2d766d pvmove: fix regression introduced with 8e9d5d12ae
'pvmove -n name pv1 pv2' called with the name of a top-level LV
failed with mentioned commit.

Enhance pvmove-raid-segtypes.sh to test for prohibited RAID SubLV moves.
2016-08-15 19:31:04 +02:00
Heinz Mauelshagen
8e9d5d12ae pvmove: prohibit non-resilient collocation of RAID SubLVs
'pvmove -n name pv1 pv2' allows to collocate multiple RAID SubLVs
on pv2 (e.g. results in collocated raidlv_rimage_0 and raidlv_rimage_1),
thus causing loss of resilence and/or performance of the RaidLV.

Fix this pvmove flaw leading to potential data loss in case of PV failure
by preventing any SubLVs from collocation on any PVs of the RaidLV.
Still allow to collocate any DataLVs of a RaidLV with their sibling MetaLVs
and vice-versa though (e.g. raidlv_rmeta_0 on pv1 may still be moved to pv2
already holding raidlv_rimage_0).

Because access to the top-level RaidLV name is needed,
promote local _top_level_lv_name() from raid_manip.c
to global top_level_lv_name().

- resolves rhbz1202497
2016-08-15 18:22:32 +02:00
Alasdair G Kergon
c7bd33d951 post-release 2016-08-15 13:23:06 +01:00
Alasdair G Kergon
8297276967 pre-release 2016-08-15 13:17:47 +01:00
Peter Rajnoha
2ff893cd85 conf: add comment about cfg_runtime 2016-08-15 10:38:38 +02:00
Heinz Mauelshagen
9c9b9b276a raid_manip: pay attention to PVs listed on command line when allocating MetaLVs
Adding MetaLVs to given DataLVs (e.g. raid0 -> raid0_meta takeover) wasn't
paying attention to any PVs listed on the lvconvert command line.
2016-08-13 00:20:01 +02:00
Heinz Mauelshagen
6d52b17dfc raid_manip: add missing code avoiding MetaLV collocation on the same PV
Adding MetaLVs to given DataLVs (e.g. raid0 -> raid0_meta takeover),
_avoid_pvs_with_other_images_of_lv() was missing code to prohibit
allocation when called with a just allocated MetaLV to prohibit
collaocation of the next allocated MetaLV on the same PV.

- resolves rhbz1366738
2016-08-12 22:46:57 +02:00
Tony Asleson
0973d6e331 notify: Fix hang with lvm shell & --enable-notify-dbus
When lvm is compiled with --enable-notify-dbus and a user uses lvm
shell, after they issue 200+ commands the lvm shell will hang for
~30 seconds trying to notify the lvm dbus service that a change
has occurred.  This appears to be caused by resource exhaustion,
because the sockets used for dbus communication are not be closed.
2016-08-12 14:36:43 -05:00
Heinz Mauelshagen
a185a2bea2 lvcreate/lvconvert: fix validation of maximum mirrors/stripes
Enforce mirror/raid0/1/10/4/5/6 type specific maximum images when
creating LVs or converting them from mirror <-> raid1.

Document those maxima in the lvcreate/lvconvert man pages.

- resolves rhbz1366060
2016-08-12 19:14:28 +02:00
Alasdair G Kergon
93b61c07eb raid: Avoid double suffix on rmeta LV name paired with rimage LV. 2016-08-11 23:31:49 +01:00
Marian Csontos
e30fb19030 spec: Add new files 2016-08-11 14:10:59 +02:00
Peter Rajnoha
2fed8d8515 lvmcmdline: use long int for number returned by strtol 2016-08-10 09:10:37 +02:00
Alasdair G Kergon
480c1c9599 post-release 2016-08-10 03:01:55 +01:00
27 changed files with 3104 additions and 1544 deletions

View File

@@ -1 +1 @@
2.02.163(2)-git (2016-08-10)
2.02.165(2)-git (2016-08-15)

View File

@@ -1 +1 @@
1.02.133-git (2016-08-10)
1.02.134-git (2016-08-15)

View File

@@ -1,3 +1,15 @@
Version 2.02.165 -
===================================
Suppress some unnecessary --stripesize parameter warnings.
Fix 'pvmove -n name ...' to prohibit collocation of RAID SubLVs
Version 2.02.164 - 15th August 2016
===================================
Fix selection of PVs when allocating raid0_meta.
Fix sdbus socket leak leading to hang in lvmnotify.
Specify max stripes for raid LV types: raid0:64; 1:10; 4,5:63; 6:62; 10:32.
Avoid double suffix when naming _rmeta LV paired with _rimage LV.
Version 2.02.163 - 10th August 2016
===================================
Add profile for lvmdbusd which uses lvm shell json report output.

View File

@@ -1,3 +1,6 @@
Version 1.02.134 -
===================================
Version 1.02.133 - 10th August 2016
===================================
Add dm_report_destroy_rows/dm_report_group_output_and_pop_all for lvm shell.

View File

@@ -23,6 +23,11 @@
* - define a configuration array of one or more types:
* cfg_array(id, name, parent, flags, types, default_value, since_version, unconfigured_default_value, deprecated_since_version, deprecation_comment, comment)
*
* - define a configuration setting where the default value is evaluated in runtime
* cfg_runtime(id, name, parent, flags, type, since_version, deprecated_since_version, deprecation_comment, comment)
* (for each cfg_runtime, you need to define 'get_default_<name>(struct cmd_context *cmd, struct profile *profile)' function
* to get the default value in runtime - usually, these functions are placed in config.[ch] file)
*
*
* If default value can't be assigned statically because it depends on some
* run-time checks or if it depends on other settings already defined,

View File

@@ -66,8 +66,13 @@
#define DEFAULT_MIRROR_LOG_FAULT_POLICY "allocate"
#define DEFAULT_MIRROR_IMAGE_FAULT_POLICY "remove"
#define DEFAULT_MIRROR_MAX_IMAGES 8 /* limited by kernel DM_KCOPYD_MAX_REGIONS */
// FIXME Increase this to 64
#define DEFAULT_RAID_MAX_IMAGES 8 /* limited by kernel failed devices bitfield in superblock (raid4/5/6 max 253) */
/* Limited by kernel failed devices bitfield in superblock (raid4/5/6 MD max 253) */
/*
* FIXME: Increase these to 64 and further to the MD maximum
* once the SubLVs split and name shift got enhanced
*/
#define DEFAULT_RAID1_MAX_IMAGES 10
#define DEFAULT_RAID_MAX_IMAGES 64
#define DEFAULT_ALLOCATION_STRIPE_ALL_DEVICES 0 /* Don't stripe across all devices if not -i/--stripes given */
#define DEFAULT_RAID_FAULT_POLICY "warn"

View File

@@ -261,10 +261,17 @@ static void _check_raid_seg(struct lv_segment *seg, int *error_count)
if (seg->extents_copied > seg->area_len)
raid_seg_error_val("extents_copied too large", seg->extents_copied);
/* Default still 8, change! */
if (seg->area_count > DEFAULT_RAID_MAX_IMAGES) {
/* Default < 10, change once raid1 split shift and rename SubLVs works! */
if (seg_is_raid1(seg)) {
if (seg->area_count > DEFAULT_RAID1_MAX_IMAGES) {
log_error("LV %s invalid: maximum supported areas %u (is %u) for %s segment",
seg->lv->name, DEFAULT_RAID1_MAX_IMAGES, seg->area_count, lvseg_name(seg));
if ((*error_count)++ > ERROR_MAX)
return;
}
} else if (seg->area_count > DEFAULT_RAID_MAX_IMAGES) {
log_error("LV %s invalid: maximum supported areas %u (is %u) for %s segment",
seg->lv->name, DEFAULT_RAID_MAX_IMAGES, seg->area_count, lvseg_name(seg));
seg->lv->name, DEFAULT_RAID_MAX_IMAGES, seg->area_count, lvseg_name(seg));
if ((*error_count)++ > ERROR_MAX)
return;
}

View File

@@ -1272,6 +1272,7 @@ uint32_t find_free_lvnum(struct logical_volume *lv);
dm_percent_t copy_percent(const struct logical_volume *lv_mirr);
char *generate_lv_name(struct volume_group *vg, const char *format,
char *buffer, size_t len);
char *top_level_lv_name(struct volume_group *vg, const char *lv_name);
struct generic_logical_volume *get_or_create_glv(struct dm_pool *mem, struct logical_volume *lv, int *glv_created);
struct glv_list *get_or_create_glvl(struct dm_pool *mem, struct logical_volume *lv, int *glv_created);

View File

@@ -108,6 +108,23 @@ static void _check_and_adjust_region_size(const struct logical_volume *lv)
return _ensure_min_region_size(lv);
}
/* Strip any raid suffix off LV name */
char *top_level_lv_name(struct volume_group *vg, const char *lv_name)
{
char *new_lv_name, *suffix;
if (!(new_lv_name = dm_pool_strdup(vg->vgmem, lv_name))) {
log_error("Failed to allocate string for new LV name.");
return NULL;
}
if ((suffix = first_substring(new_lv_name, "_rimage_", "_rmeta_",
"_mimage_", "_mlog_", NULL)))
*suffix = '\0';
return new_lv_name;
}
static int _lv_is_raid_with_tracking(const struct logical_volume *lv,
struct logical_volume **tracking)
{
@@ -160,14 +177,22 @@ static int _activate_sublv_preserving_excl(struct logical_volume *top_lv,
return 1;
}
/* HM Helper: prohibit allocation on @pv if @lv already has segments allocated on it */
static int _avoid_pv_of_lv(struct logical_volume *lv, struct physical_volume *pv)
{
if (!lv_is_partial(lv) && lv_is_on_pv(lv, pv))
pv->status |= PV_ALLOCATION_PROHIBITED;
return 1;
}
static int _avoid_pvs_of_lv(struct logical_volume *lv, void *data)
{
struct dm_list *allocate_pvs = (struct dm_list *) data;
struct pv_list *pvl;
dm_list_iterate_items(pvl, allocate_pvs)
if (!lv_is_partial(lv) && lv_is_on_pv(lv, pvl->pv))
pvl->pv->status |= PV_ALLOCATION_PROHIBITED;
_avoid_pv_of_lv(lv, pvl->pv);
return 1;
}
@@ -179,7 +204,15 @@ static int _avoid_pvs_of_lv(struct logical_volume *lv, void *data)
*/
static int _avoid_pvs_with_other_images_of_lv(struct logical_volume *lv, struct dm_list *allocate_pvs)
{
return for_each_sub_lv(lv, _avoid_pvs_of_lv, allocate_pvs);
/* HM FIXME: check fails in case we will ever have mixed AREA_PV/AREA_LV segments */
if ((seg_type(first_seg(lv), 0) == AREA_PV ? _avoid_pvs_of_lv(lv, allocate_pvs):
for_each_sub_lv(lv, _avoid_pvs_of_lv, allocate_pvs)))
return 1;
log_error("Failed to prevent PVs holding image components "
"from LV %s being used for allocation.",
display_lvname(lv));
return 0;
}
static void _clear_allocation_prohibited(struct dm_list *pvs)
@@ -679,7 +712,7 @@ static int _alloc_rmeta_for_lv(struct logical_volume *data_lv,
struct dm_list allocatable_pvs;
struct alloc_handle *ah;
struct lv_segment *seg = first_seg(data_lv);
char *p, base_name[NAME_LEN];
char *base_name;
dm_list_init(&allocatable_pvs);
@@ -699,9 +732,8 @@ static int _alloc_rmeta_for_lv(struct logical_volume *data_lv,
return 0;
}
(void) dm_strncpy(base_name, data_lv->name, sizeof(base_name));
if ((p = strstr(base_name, "_mimage_")))
*p = '\0';
if (!(base_name = top_level_lv_name(data_lv->vg, data_lv->name)))
return_0;
if (!(ah = allocate_extents(data_lv->vg, NULL, seg->segtype, 0, 1, 0,
seg->region_size,
@@ -1573,14 +1605,25 @@ static int _alloc_rmeta_devs_for_rimage_devs(struct logical_volume *lv,
dm_list_iterate_items(lvl, new_data_lvs) {
log_debug_metadata("Allocating new metadata LV for %s", lvl->lv->name);
if (!_alloc_rmeta_for_lv(lvl->lv, &lvl_array[a].lv, allocate_pvs)) {
log_error("Failed to allocate metadata LV for %s in %s",
lvl->lv->name, lv->vg->name);
return 0;
/*
* Try to collocate with DataLV first and
* if that fails allocate on different PV.
*/
if (!_alloc_rmeta_for_lv(lvl->lv, &lvl_array[a].lv,
allocate_pvs != &lv->vg->pvs ? allocate_pvs : NULL)) {
dm_list_iterate_items(lvl1, new_meta_lvs)
if (!_avoid_pvs_with_other_images_of_lv(lvl1->lv, allocate_pvs))
return_0;
if (!_alloc_rmeta_for_lv(lvl->lv, &lvl_array[a].lv, allocate_pvs)) {
log_error("Failed to allocate metadata LV for %s in %s",
lvl->lv->name, lv->vg->name);
return 0;
}
}
dm_list_add(new_meta_lvs, &lvl_array[a++].list);
dm_list_iterate_items(lvl1, new_meta_lvs)
if (!_avoid_pvs_with_other_images_of_lv(lvl1->lv, allocate_pvs))
return_0;

View File

@@ -73,7 +73,7 @@ void lvmnotify_send(struct cmd_context *cmd)
out:
sd_bus_error_free(&error);
sd_bus_message_unref(m);
sd_bus_unref(bus);
sd_bus_flush_close_unref(bus);
}
void set_vg_notify(struct cmd_context *cmd)

View File

@@ -611,6 +611,9 @@ VG/ThinPoolLV
Convert the data portion of ThinPoolLV to type cache.
.br
\[bu]
Requires \-\-cachepool to specify the cache pool to use.
.br
\[bu]
Operates on the data sub LV of the thin pool LV.
.br
\[bu]
@@ -805,6 +808,8 @@ Specifies the number mirror images in addition to the original LV image,
e.g. \fB\-\-mirrors 1\fP means two copies of the data, the original and
one mirror image.
The current maximum is 9 providing 10 raid1 images.
This option is required when converting an LV to a \fBraid1\fP or
\fBmirror\fP LV.

View File

@@ -399,6 +399,9 @@ to configure default mirror segment type.
The options
\fB\-\-mirrorlog\fP and \fB\-\-corelog\fP apply
to the legacy "\fImirror\fP" segment type only.
Note the current maxima for mirrors are 7 for "mirror" providing
8 mirror legs and 9 for "raid1" providing 10 legs.
.
.HP
.BR \-\-mirrorlog
@@ -633,8 +636,12 @@ section of \fBlvm.conf (5)\fP or add
\fB\-\-config allocation/raid_stripe_all_devices=1\fP
.br
to the command.
.br
Note the current limitation of 8 stripes total in any RaidLV including parity devices.
Note the current maxima for stripes depend on the created RAID type.
For raid10, the maximum of stripes is 32,
for raid0, it is 64,
for raid4/5, it is 63
and for raid6 it is 62.
See the \fB\-\-nosync\fP option to optionally avoid initial syncrhonization of RaidLVs.

800
scripts/command-lines.in Normal file
View File

@@ -0,0 +1,800 @@
#
# A new command has a unique combination of:
# command name, required option args and required
# positional args.
#
# To define a new command, begin a single line with a
# command name, followed by required options/args,
# (e.g. --foo, or --foo val), followed by required
# positional args, (e.g. VG)
#
# After the single line of required elements are lines
# of optional elements:
# . optional options/args are on new line that begins OO:
# . optional positional args are on a new line that begins OP:
#
# command_name required_opt_arg ... required_pos_arg ...
# OO: optional_opt_arg, ...
# OP: optional_pos_arg ...
#
# required_opt_arg/optional_opt_arg must begin with the
# long form option name, e.g. --foo. If the option name
# takes a value, then the type of value is specified,
# e.g. --foo String.
#
# Possible option names are listed in args.h
#
# Use --foo_long to specify that only the long form of
# --foo is accepted by the command. (This is uncommon.)
#
# Possible option arg types that can follow --opt are:
# Bool, Number, String, PV, VG, LV, Tag, Select.
#
# Option args outside the list of types are treated as literal
# (non-variable) strings or numbers.
#
# required_pos_arg/optional_pos_arg can be one of the following:
# PV, VG, LV, Tag, Select.
#
# required_pos_arg/optional_pos_arg can be multiple types
# separated by |, e.g. VG|LV|Tag
#
# If the required_pos_arg/optional_pos_arg is repeatable,
# it is followed by ..., e.g. VG|LV|Tag ...
#
# LV can have a suffix indicating the LV type, e.g. LV_linear, LV_thinpool.
# LV_raid represents any raidN.
#
# VG, LV can have the suffix _new, indicating the named VG or LV
# does not yet exist.
#
# If Select is included in pos_arg, it means that the pos_arg
# may be empty if the --select option is used.
#
# To define a common set of options:
# OO_NAME: --foo, --bar String
#
# To use this set of options, include it on the OO: line, e.g.
# OO: --example, OO_NAME
#
# which is expaneded to
# OO: --example, --foo, --bar String
#
# Including OO_NAME after a command name on the required line
# means that any one of the options is required and the rest
# are optional. The usage syntax for this case is printed as:
# command (--foo A, --bar B)
#
#
# OO_ALL is included in every command automatically.
# FIXME: add --force and --test to OO_ALL so that all commands will
# accept them even if they are not used?
#
OO_ALL: --commandprofile String, --config String, --debug,
--driverloaded Bool, --help, --profile String, --quiet,
--verbose, --version, --yes
#
# pvs, lvs, vgs, fullreport
#
OO_REPORT: --aligned, --all, --binary, --configreport String, --foreign,
--ignorelockingfailure, --ignoreskippedcluster, --logonly,
--nameprefixes, --noheadings, --nolocking, --nosuffix,
--options String, --partial, --readonly, --reportformat String, --rows,
--select String, --separator String, --shared, --sort String,
--trustcache, --unbuffered, --units String, --unquoted
#
# config, dumpconfig, lvmconfig
#
OO_CONFIG: --atversion String, --configtype String, --file String, --ignoreadvanced,
--ignoreunsupported, --ignorelocal, --list, --mergedconfig, --metadataprofile String,
--sinceversion String, --showdeprecated, --showunsupported, --validate, --withsummary,
--withcomments, --withspaces, --unconfigured, --withversions
config
OO: OO_CONFIG
OP: String ...
devtypes
OO: --aligned, --binary, --nameprefixes, --noheadings,
--nosuffix, --options String, --reportformat String, --rows,
--select String, --separator String, --sort String, --unbuffered, --unquoted
dumpconfig
OO: OO_CONFIG
OP: String ...
formats
help
fullreport
OO: OO_REPORT
OP: VG ...
lastlog
OO: --reportformat String, --select String
#
# None of these can function as a required option for lvchange.
#
OO_LVCHANGE: --autobackup Bool, --force, --ignorelockingfailure,
--ignoremonitoring, --ignoreskippedcluster, --noudevsync,
--reportformat String, --sysinit, --test, --select String
#
# Any of these can function as a required option for lvchange.
# profile is also part of OO_ALL, but is repeated in OO_LVCHANGE_META
# because it can function as a required opt.
#
OO_LVCHANGE_META: --addtag Tag, --deltag Tag,
--alloc String, --contiguous Bool,
--detachprofile, --metadataprofile String, --profile String,
--permission, --readahead Number|String, --setactivationskip Bool,
--errorwhenfull Bool, --discards String, --zero Bool,
--cachemode String, --cachepolicy String, --cachesettings String,
--minrecoveryrate Number, --maxrecoveryrate Number,
--writebehind Number, --writemostly PV
lvchange OO_LVCHANGE_META VG|LV|Tag|Select ...
OO: OO_LVCHANGE
lvchange --resync VG|LV|Tag|Select ...
OO: OO_LVCHANGE_META, OO_LVCHANGE
lvchange --syncaction String VG|LV|Tag|Select ...
OO: OO_LVCHANGE_META, OO_LVCHANGE
lvchange --rebuild PV VG|LV|Tag|Select ...
OO: OO_LVCHANGE_META, OO_LVCHANGE
lvchange --activate String VG|LV|Tag|Select ...
OO: --activationmode String, --partial, --ignoreactivationskip, OO_LVCHANGE_META, OO_LVCHANGE
lvchange --refresh VG|LV|Tag|Select ...
OO: OO_LVCHANGE_META, OO_LVCHANGE
lvchange --monitor Bool VG|LV|Tag|Select ...
OO: --poll Bool, OO_LVCHANGE_META, OO_LVCHANGE
lvchange --poll Bool VG|LV|Tag|Select ...
OO: --monitor Bool, OO_LVCHANGE_META, OO_LVCHANGE
lvchange --persistent Bool VG|LV|Tag|Select ...
OO: --minor Number, --major Number, OO_LVCHANGE_META, OO_LVCHANGE
OO_LVCONVERT_RAID: --mirrors Number, --stripes_long Number,
--stripesize Number, --regionsize Number
OO_LVCONVERT_POOL: --poolmetadata LV, --poolmetadatasize Number,
--poolmetadataspare Bool, --readahead Number|String, --chunksize Number
OO_LVCONVERT: --alloc String, --background, --force, --noudevsync,
--test, --usepolicies
# FIXME: use different option names for different operations
lvconvert --merge LV_linear|LV_striped|LV_raid|LV_thin|LV_snapshot|VG|Tag ...
OO: --background, --interval Number
DESC: Merge LV that was previously split from a mirror.
DESC: Merge thin LV into its origin LV.
DESC: Merge COW snapshot LV into its origin.
lvconvert --type snapshot LV_linear|LV_striped|LV_raid LV_snapshot
OO: --chunksize Number, --zero Bool, OO_LVCONVERT
DESC: Combine LV with a previously split snapshot LV.
lvconvert --type thin --thinpool LV LV_linear|LV_striped|LV_raid
OO: --originname LV_new, OO_LVCONVERT_POOL, OO_LVCONVERT
DESC: Convert LV to type thin with an external origin.
# alternate form of lvconvert --type thin
lvconvert --thin --thinpool LV LV_linear|LV_striped|LV_raid
OO: --type thin, --originname LV_new, OO_LVCONVERT_POOL, OO_LVCONVERT
DESC: Convert LV to type thin with an external origin (infers --type thin).
lvconvert --type cache --cachepool LV LV_linear|LV_striped|LV_raid|LV_thinpool
OO: --cachepolicy String, --cachesettings String, OO_LVCONVERT_POOL, OO_LVCONVERT
DESC: Convert LV to type cache.
# alternate form of lvconvert --type cache
lvconvert --cache --cachepool LV LV_linear|LV_striped|LV_raid|LV_thinpool
OO: --type cache, --cachepolicy String, --cachesettings String, OO_LVCONVERT_POOL, OO_LVCONVERT
DESC: Convert LV to type cache (infers --type cache).
lvconvert --type thin-pool LV_linear|LV_striped|LV_raid|LV_cache
OO: --discards String, --zero Bool, OO_LVCONVERT_POOL, OO_LVCONVERT
DESC: Convert LV to type thin-pool.
lvconvert --type cache-pool LV_linear|LV_striped|LV_raid
OO: OO_LVCONVERT_POOL, OO_LVCONVERT
DESC: Convert LV to type cache-pool.
lvconvert --type mirror LV_linear|LV_striped|LV_raid
OO: OO_LVCONVERT_RAID, OO_LVCONVERT
OP: PV ...
DESC: Convert LV to type mirror.
lvconvert --type raid LV_linear|LV_striped|LV_mirror|LV_raid
OO: OO_LVCONVERT_RAID, OO_LVCONVERT
OP: PV ...
DESC: Convert LV to type raid.
DESC: Change LV raid type.
lvconvert --mirrors Number LV_raid|LV_mirror
OO: OO_LVCONVERT
OP: PV ...
DESC: Change the number of mirror images in the LV.
lvconvert --mirrors Number LV_linear|LV_striped
OO: OO_LVCONVERT_RAID, OO_LVCONVERT
OP: PV ...
DESC: Alternate form to convert LV to type raid1 or mirror (use --type raid1|mirror).
lvconvert --splitmirrors Number --name LV_new LV_raid|LV_mirror|LV_cache
OO: OO_LVCONVERT
DESC: Split images from a raid1 or mirror LV and use them to create a new LV.
lvconvert --splitmirrors Number --trackchanges LV_raid|LV_cache
OO: OO_LVCONVERT
DESC: Split images from a raid1 LV and use them to create a new LV.
lvconvert --repair LV_raid|LV_mirror|LV_thinpool
OO: OO_LVCONVERT
DESC: Replace failed PVs in a mirror or raid LV.
DESC: Repair a thin pool.
lvconvert --replace PV LV_raid
OO: OO_LVCONVERT
OP: PV ...
DESC: Replace specific PV(s) in a raid* LV with another PV.
lvconvert --type striped LV_raid
OO: OO_LVCONVERT_RAID, OO_LVCONVERT
OP: PV ...
DESC: Convert LV to type striped.
lvconvert --type linear LV_raid|LV_mirror
OO: OO_LVCONVERT
DESC: Convert LV to type linear.
lvconvert --mirrorlog String LV_mirror
OO: OO_LVCONVERT
DESC: Change the type of log used by LV.
lvconvert --splitcache LV_cachepool|LV_cache|LV_thinpool
OO: OO_LVCONVERT
DESC: Separate and preserve a cache pool from a cache LV.
lvconvert --uncache LV_cache|LV_thinpool
OO: OO_LVCONVERT
DESC: Separate and remove a cache pool from a cache LV.
lvconvert --splitsnapshot LV_snapshot
OO: OO_LVCONVERT
DESC: Separate a COW snapshot from its origin LV.
# deprecated because of non-standard syntax
lvconvert --thinpool LV
OO: OO_LVCONVERT_POOL, OO_LVCONVERT
DESC: Alternate form to convert LV to type thin-pool (use --type thin-pool).
# deprecated because of non-standard syntax
lvconvert --cachepool LV
OO: OO_LVCONVERT_POOL, OO_LVCONVERT
DESC: Alternate form to convert LV to type cache-pool (use --type cache-pool).
# FIXME: add a new option defining this operation, e.g. --poll-mirror
# The function of this command is not entirely clear.
lvconvert LV_mirror
DESC: Poll LV to collapse resync layers.
# FIXME: add a new option defining this operation, e.g. --swapmetadata
lvconvert --poolmetadata LV LV_thinpool|LV_cachepool
DESC: Swap metadata LV in a thin pool or cache pool (temporary command).
# --extents or --size are interchangable
OO_LVCREATE: --addtag Tag, --alloc String, --autobackup Bool, --activate String,
--contiguous Bool, --ignoreactivationskip, --ignoremonitoring, --major Number,
--metadataprofile String, --minor Number, --monitor Bool, --name String, --nosync,
--noudevsync, --permission, --persistent Bool, --readahead Number|String,
--reportformat String, --setactivationskip Bool, --test, --wipesignatures Bool,
--zero Bool
OO_LVCREATE_CACHE: --cachemode String, --cachepolicy String, --cachesettings String
OO_LVCREATE_POOL: --poolmetadatasize Number, --poolmetadataspare Bool, --chunksize Number
OO_LVCREATE_THIN: --discards String, --errorwhenfull Bool
OO_LVCREATE_RAID: --mirrors Number, --stripes Number, --stripesize Number,
--regionsize Number, --minrecoveryrate Number, --maxrecoveryrate Number
lvcreate --type error --size Number VG
OO: OO_LVCREATE
DESC: Create an LV that returns errors when used.
lvcreate --type zero --size Number VG
OO: OO_LVCREATE
DESC: Create an LV that returns zeros when read.
lvcreate --type linear --size Number VG
OO: OO_LVCREATE
OP: PV ...
DESC: Create a linear LV.
lvcreate --type striped --size Number VG
OO: --stripes Number, --stripesize Number, OO_LVCREATE
OP: PV ...
DESC: Create a striped LV.
lvcreate --type mirror --size Number VG
OO: --mirrors Number, --mirrorlog String, --corelog, --regionsize Number, OO_LVCREATE
OP: PV ...
DESC: Create a mirror LV.
lvcreate --type raid --size Number VG
OO: OO_LVCREATE_RAID, OO_LVCREATE
OP: PV ...
DESC: Create a raid LV (a specific raid level must be used, e.g. raid1).
lvcreate --type snapshot --size Number LV
OO: OO_LVCREATE
OP: PV ...
DESC: Create a COW snapshot from an origin LV.
lvcreate --type snapshot --size Number --virtualsize Number VG
OO: --virtualoriginsize Number, OO_LVCREATE
OP: PV ...
DESC: Create a sparse COW snapshot LV of a virtual origin LV.
lvcreate --type thin-pool --size Number VG
OO: OO_LVCREATE_POOL, OO_LVCREATE_THIN, OO_LVCREATE
OP: PV ...
DESC: Create a thin pool.
lvcreate --type cache-pool --size Number VG
OO: OO_LVCREATE_POOL, OO_LVCREATE_CACHE, OO_LVCREATE
OP: PV ...
DESC: Create a cache pool.
lvcreate --type thin --virtualsize Number --thinpool LV_thinpool
OO: OO_LVCREATE_POOL, OO_LVCREATE_THIN, OO_LVCREATE
DESC: Create a thin LV in a thin pool.
lvcreate --type thin --snapshot LV_thin
OO: OO_LVCREATE_POOL, OO_LVCREATE_THIN, OO_LVCREATE
DESC: Create a thin LV that is a snapshot of an existing thin LV.
lvcreate --type thin --snapshot --thinpool LV_thinpool LV
OO: OO_LVCREATE_POOL, OO_LVCREATE_THIN, OO_LVCREATE
DESC: Create a thin LV that is a snapshot of an external origin LV named in arg pos 1.
lvcreate --type thin --virtualsize Number --size Number --thinpool LV_new
OO: OO_LVCREATE_POOL, OO_LVCREATE_THIN, OO_LVCREATE
OP: PV ...
DESC: Create a thin LV, first creating a thin pool for it, where the new thin pool is named by the --thinpool arg.
lvcreate --type thin --virtualsize Number --size Number LV_new
OO: OO_LVCREATE_POOL, OO_LVCREATE_THIN, OO_LVCREATE
OP: PV ...
DESC: Create a thin LV, first creating a thin pool for it, where the new thin pool is named in arg pos 1.
lvcreate --type thin --virtualsize Number --size Number VG
OO: OO_LVCREATE_POOL, OO_LVCREATE_THIN, OO_LVCREATE
OP: PV ...
DESC: Create a thin LV, first creating a thin pool for it.
# FIXME: this should be done by lvconvert, and this command deprecated
lvcreate --type cache --size Number LV
OO: OO_LVCREATE_POOL, OO_LVCREATE_CACHE, OO_LVCREATE
OP: PV ...
DESC: Convert the specified LV to type cache after creating a new cache pool LV to use.
lvcreate --type cache --size Number --cachepool LV_cachepool
OO: OO_LVCREATE_POOL, OO_LVCREATE_CACHE, OO_LVCREATE
OP: PV ...
DESC: Create a cache LV, first creating a new origin LV, then combining it with the existing cache pool in arg pos 1.
lvcreate --size Number VG
OO: --type linear, OO_LVCREATE
OP: PV ...
DESC: Create a linear LV. (default --type linear)
lvcreate --stripes Number --size Number VG
OO: --type striped, --stripesize Number, OO_LVCREATE
OP: PV ...
DESC: Create a striped LV. (infers --type striped)
lvcreate --mirrors Number --size Number VG
OO: --type raid1|mirror, --mirrorlog String, --corelog, OO_LVCREATE_RAID, OO_LVCREATE
OP: PV ...
DESC: Create a raid1 or mirror LV. (infers --type raid1|mirror)
lvcreate --snapshot --size Number LV
OO: --type snapshot, OO_LVCREATE
OP: PV ...
DESC: Create a COW snapshot LV of the origin LV in arg pos 1. (infers --type snapshot)
lvcreate --thin --size Number VG
OO: --type thin-pool, OO_LVCREATE_POOL, OO_LVCREATE_THIN, OO_LVCREATE
OP: PV ...
DESC: Create a thin pool. (infers --type thin-pool)
lvcreate --cache --size Number VG
OO: --type cache-pool, OO_LVCREATE_POOL, OO_LVCREATE_CACHE, OO_LVCREATE
OP: PV ...
DESC: Create a cache pool. (infers --type cache-pool)
lvcreate --snapshot LV_thin
OO: --type thin, OO_LVCREATE_THIN, OO_LVCREATE
DESC: Create a thin LV that is a snapshot of an existing thin LV. (infers --type thin)
lvcreate --snapshot --thinpool LV_thinpool LV
OO: --type thin, OO_LVCREATE_THIN, OO_LVCREATE
DESC: Create a thin LV that is a snapshot of an external origin LV. (infers --type thin)
lvcreate --virtualsize Number --thinpool LV_thinpool
OO: --type thin, OO_LVCREATE_THIN, OO_LVCREATE
DESC: Create a thin LV in a thin pool. (infers --type thin)
lvcreate --size Number --cachepool LV_cachepool
OO: --type cache, OO_LVCREATE_CACHE, OO_LVCREATE
OP: PV ...
DESC: Create a new origin LV, combining it with an existing cache pool to create a new cache LV. (infers --type cache)
lvcreate --thin --virtualsize Number --size Number --thinpool LV_new
OO: --type thin, OO_LVCREATE_POOL, OO_LVCREATE_THIN, OO_LVCREATE
OP: PV ...
DESC: Create a thin LV, first creating a thin pool for it, where the new thin pool is named by the --thinpool arg. (infers --type thin)
lvcreate --thin --virtualsize Number --size Number LV_new
OO: --type thin, OO_LVCREATE_POOL, OO_LVCREATE_THIN, OO_LVCREATE
OP: PV ...
DESC: Create a thin LV, first creating a thin pool for it, where the new thin pool is named in arg pos 1. (infers --type thin)
lvcreate --size Number --virtualsize Number VG
OO: --type thin, --type snapshot, --thin, --snapshot,
--virtualoriginsize Number, OO_LVCREATE_POOL, OO_LVCREATE_THIN, OO_LVCREATE
OP: PV ...
DESC: Create a thin LV, first creating a thin pool for it. (infers --type thin)
DESC: Create a sparse snapshot of a virtual origin LV. (infers --type snapshot)
DESC: (infers --type thin or --type snapshot according to sparse_segtype_default)
lvdisplay
OO: --aligned, --all, --binary, --colon, --columns,
--configreport String, --foreign, --history, --ignorelockingfailure,
--ignoreskippedcluster, --logonly, --maps, --noheadings,
--nosuffix, --options String, --sort String, --partial, --readonly,
--reportformat String, --segments, --select String, --separator String,
--shared, --unbuffered, --units String
OP: VG|LV|Tag ...
# --extents or --size are interchangable
lvextend --size Number LV
OO: --alloc String, --autobackup Bool, --force, --mirrors Number,
--nofsck, --nosync, --noudevsync, --reportformat String, --resizefs,
--stripes Number, --stripesize Number, --test, --poolmetadatasize Number
OP: PV ...
lvextend LV PV ...
OO: --alloc String, --autobackup Bool, --force, --mirrors Number,
--nofsck, --nosync, --noudevsync,
--reportformat String, --resizefs, --stripes Number, --stripesize Number,
--test
lvextend --poolmetadatasize Number LV_thinpool
OO: --alloc String, --autobackup Bool, --force, --mirrors Number,
--nofsck, --nosync, --noudevsync,
--reportformat String, --stripes Number, --stripesize Number,
--test
OP: PV ...
lvextend --usepolicies LV_thinpool|LV_snapshot
OO: --alloc String, --autobackup Bool, --force, --mirrors Number,
--nofsck, --nosync, --noudevsync,
--reportformat String, --resizefs,
--test
lvmchange
lvmconfig
OO: OO_CONFIG
lvmdiskscan
OO: --lvmpartition, --readonly
lvmsadc
lvmsar
OO: --full, --stdin
# --extents or --size are interchangable
lvreduce --size Number LV
OO: --autobackup Bool, --force, --nofsck, --noudevsync,
--reportformat String, --resizefs, --test
lvremove VG|LV|Tag|Select ...
OO: --autobackup Bool, --force, --nohistory, --noudevsync,
--reportformat String, --select String, --test
lvrename VG LV LV_new
OO: --autobackup Bool, --noudevsync, --reportformat String, --test
lvrename LV LV_new
OO: --autobackup Bool, --noudevsync, --reportformat String, --test
# --extents or --size are interchangable
lvresize --size Number LV
OO: --alloc String, --autobackup Bool, --force,
--nofsck, --nosync, --noudevsync, --reportformat String, --resizefs,
--stripes Number, --stripesize Number, --test, --poolmetadatasize Number
OP: PV ...
lvresize LV PV ...
OO: --alloc String, --autobackup Bool, --force,
--nofsck, --nosync, --noudevsync,
--reportformat String, --resizefs, --stripes Number, --stripesize Number,
--test
lvresize --poolmetadatasize Number LV_thinpool
OO: --alloc String, --autobackup Bool, --force,
--nofsck, --nosync, --noudevsync,
--reportformat String, --stripes Number, --stripesize Number,
--test
OP: PV ...
lvs
OO: --history, --segments, OO_REPORT
OP: VG|LV|Tag ...
lvscan
OO: --all, --blockdevice, --ignorelockingfailure, --partial,
--readonly, --reportformat String, --cache_long
#
# None of these can function as a required option for pvchange.
#
OO_PVCHANGE: --autobackup Bool, --force, --ignoreskippedcluster,
--reportformat String, --test, --uuid
#
# Any of these can function as a required option for pvchange.
#
OO_PVCHANGE_META: --allocatable Bool, --addtag Tag, --deltag Tag,
--uuid, --metadataignore Bool
pvchange OO_PVCHANGE_META --all
OO: OO_PVCHANGE
pvchange OO_PVCHANGE_META PV|Select ...
OO: --select String, OO_PVCHANGE
pvresize PV ...
OO: --setphysicalvolumesize Number, --reportformat String, --test
pvck PV ...
OO: --labelsector Number
#
# Use --uuidstr here which will be converted to uuidstr_ARG
# which is actually --uuid string on the command line.
#
pvcreate PV ...
OO: --dataalignment Number, --dataalignmentoffset Number, --bootloaderareasize Number,
--force, --test, --labelsector Number, --metadatatype String,
--pvmetadatacopies Number, --metadatasize Number, --metadataignore Bool,
--norestorefile, --setphysicalvolumesize Number,
--reportformat String, --restorefile String, --uuidstr String, --zero Bool
pvdata
pvdisplay
OO: --aligned, --all, --binary, --colon, --columns, --configreport String,
--foreign, --ignorelockingfailure, --ignoreskippedcluster,
--logonly, --maps, --noheadings, --nosuffix, --options String,
--readonly, --reportformat String, --select String, --separator String, --shared,
--short, --sort String, --unbuffered, --units String
OP: PV|Tag ...
pvmove PV
OO: --abort, --alloc String, --atomic, --autobackup Bool, --background,
--interval Number, --name LV, --noudevsync, --reportformat String, --test
OP: PV ...
pvmove
OO: --abort, --background, --test
lvpoll --polloperation String LV ...
OO: --abort, --autobackup Bool, --handlemissingpvs, --interval Number, --test
pvremove PV ...
OO: --force, --reportformat String, --test
pvs
OO: --segments, OO_REPORT
OP: PV|Tag ...
pvscan
OO: --ignorelockingfailure, --reportformat String, --exported, --novolumegroup,
--short, --uuid
pvscan --cache
OO: --ignorelockingfailure, --reportformat String, --background,
--activate String, --major Number, --minor Number,
OP: PV|String ...
segtypes
systemid
tags
vgcfgbackup
OO: --file String, --foreign, --ignorelockingfailure, --partial, --readonly,
--reportformat String
vgcfgrestore VG
OO: --file String, --force_long, --list, --metadatatype String, --test
vgcfgrestore --list --file String
#
# None of these can function as a required option for vgchange.
#
OO_VGCHANGE: --autobackup Bool, --ignoremonitoring, --ignoreskippedcluster,
--noudevsync, --reportformat String, --select String, --test, --force
#
# Any of these can function as a required option for vgchange.
# profile is also part of OO_ALL, but is repeated in OO_VGCHANGE_META
# because it can function as a required opt.
#
OO_VGCHANGE_META: --addtag Tag, --deltag Tag,
--logicalvolume Number, --maxphysicalvolumes Number, --alloc String, --uuid,
--clustered Bool, --metadatacopies Number, --vgmetadatacopies Number|String,
--physicalextentsize Number, --resizeable Bool, --systemid String, --locktype String,
--profile String, --detachprofile, --metadataprofile String,
vgchange OO_VGCHANGE_META
OO: OO_VGCHANGE
OP: VG|Tag ...
vgchange --monitor Bool
OO: --sysinit, --ignorelockingfailure, --poll Bool, OO_VGCHANGE_META, OO_VGCHANGE
OP: VG|Tag ...
vgchange --poll Bool
OO: --ignorelockingfailure, OO_VGCHANGE_META, OO_VGCHANGE
OP: VG|Tag ...
vgchange --activate String
OO: --activationmode String, --ignoreactivationskip, --partial, --sysinit,
--ignorelockingfailure, --monitor Bool, --poll Bool, OO_VGCHANGE_META, OO_VGCHANGE
OP: VG|Tag ...
vgchange --refresh
OO: --sysinit, --ignorelockingfailure, --monitor Bool, --poll Bool, OO_VGCHANGE_META, OO_VGCHANGE
OP: VG|Tag ...
vgchange --lockstart
OO: --lockopt String, OO_VGCHANGE_META, OO_VGCHANGE
OP: VG|Tag ...
vgchange --lockstop
OO: --lockopt String, OO_VGCHANGE_META, OO_VGCHANGE
OP: VG|Tag ...
vgck
OO: --reportformat String
OP: VG|Tag ...
vgconvert VG ...
OO: --force, --test, --labelsector Number, --bootloaderareasize Number,
--metadatatype String, --pvmetadatacopies Number,
--metadatasize Number, --reportformat String
vgcreate VG_new PV ...
OO: --addtag Tag, --alloc String, --autobackup Bool, --clustered Bool, --maxlogicalvolumes Number,
--maxphysicalvolumes Number, --metadataprofile String, --metadatatype String,
--physicalextentsize Number, --test, --force, --zero Bool, --labelsector Number,
--metadatasize Number, --pvmetadatacopies Number, --reportformat String, --metadatacopies Number,
--vgmetadatacopies Number|String, --dataalignment Number, --dataalignmentoffset Number,
--shared, --systemid String, --locktype String, --lockopt String
vgdisplay
OO: --activevolumegroups, --aligned, --binary, --colon, --columns,
--configreport String, --foreign, --ignorelockingfailure,
--ignoreskippedcluster, --logonly, --noheadings, --nosuffix,
--options String, --partial, --readonly, --reportformat String, --select String,
--shared, --short, --separator String, --sort String, --unbuffered, --units String
OP: VG|Tag ...
OO_VGEXPORT: --reportformat String, --test
vgexport VG|Tag|Select ...
OO: --select String, OO_VGEXPORT
vgexport --all
OO: OO_VGEXPORT
vgextend VG PV ...
OO: --autobackup Bool, --test,
--force, --zero Bool, --labelsector Number, --metadatatype String,
--metadatasize Number, --pvmetadatacopies Number,
--metadataignore Bool, --dataalignment Number, --dataalignmentoffset Number,
--reportformat String, --restoremissing
OO_VGIMPORT: --force, --reportformat String, --test
vgimport VG|Tag|Select ...
OO: --select String, OO_VGIMPORT
vgimport --all
OO: OO_VGIMPORT
vgimportclone PV ...
OO: --basevgname VG, --test, --import
vgmerge VG VG
OO: --autobackup Bool, --list, --test
vgmknodes
OO: --ignorelockingfailure, --refresh, --reportformat String
OP: VG|LV|Tag ...
OO_VGREDUCE: --autobackup Bool, --force, --reportformat String, --test
vgreduce VG PV ...
OO: OO_VGREDUCE
vgreduce --all VG
OO: OO_VGREDUCE
vgreduce --removemissing VG
OO: --mirrorsonly, OO_VGREDUCE
vgremove VG|Tag|Select ...
OO: --force, --noudevsync, --reportformat String, --select String, --test
vgrename VG VG_new
OO: --autobackup Bool, --force, --reportformat String, --test
vgrename String VG_new
OO: --autobackup Bool, --force, --reportformat String, --test
vgs
OO: OO_REPORT
OP: VG|Tag ...
vgscan
OO: --cache_long, --ignorelockingfailure, --mknodes, --notifydbus,
--partial, --reportformat String
OO_VGSPLIT: --autobackup Bool, --test
OO_VGSPLIT_NEW: --alloc String, --clustered Bool,
--maxlogicalvolumes Number, --maxphysicalvolumes Number,
--metadatatype String, --vgmetadatacopies Number|String
vgsplit VG VG PV ...
OO: OO_VGSPLIT
vgsplit --name LV VG VG
OO: OO_VGSPLIT
vgsplit VG VG_new PV ...
OO: OO_VGSPLIT, OO_VGSPLIT_NEW
vgsplit --name LV VG VG_new
OO: OO_VGSPLIT, OO_VGSPLIT_NEW
version

1534
scripts/create-commands.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -115,6 +115,7 @@ fi
%{_mandir}/man8/lvmconfig.8.gz
%{_mandir}/man8/lvmdiskscan.8.gz
%{_mandir}/man8/lvmdump.8.gz
%{_mandir}/man8/lvm-fullreport.8.gz
%{_mandir}/man8/lvmsadc.8.gz
%{_mandir}/man8/lvmsar.8.gz
%{_mandir}/man8/lvreduce.8.gz
@@ -179,6 +180,7 @@ fi
%config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/lvm/profile/thin-performance.profile
%config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/lvm/profile/cache-mq.profile
%config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/lvm/profile/cache-smq.profile
%config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/lvm/profile/lvmdbusd.profile
%dir %{_sysconfdir}/lvm/backup
%dir %{_sysconfdir}/lvm/cache
%dir %{_sysconfdir}/lvm/archive

View File

@@ -53,6 +53,15 @@ lvcreate -l 4 --type raid10 -i 2 -m 1 -n $lv1 $vg \
check lv_tree_on $vg ${lv1}_foo "$dev1"
check lv_tree_on $vg $lv1 "$dev1" "$dev2" "$dev3" "$dev4"
aux mkdev_md5sum $vg $lv1
# Check collocation of SubLVs is prohibited
not pvmove $mode -n ${lv1}_rimage_0 "$dev1" "$dev2"
check lv_tree_on $vg $lv1 "$dev1" "$dev2" "$dev3" "$dev4"
not pvmove $mode -n ${lv1}_rimage_1 "$dev2" "$dev1"
check lv_tree_on $vg $lv1 "$dev1" "$dev2" "$dev3" "$dev4"
not pvmove $mode -n ${lv1}_rmeta_0 "$dev1" "$dev3"
check lv_tree_on $vg $lv1 "$dev1" "$dev2" "$dev3" "$dev4"
pvmove $mode "$dev1" "$dev5"
check lv_tree_on $vg ${lv1}_foo "$dev5"
check lv_tree_on $vg $lv1 "$dev2" "$dev3" "$dev4" "$dev5"

View File

@@ -32,7 +32,7 @@ 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(configtype_ARG, '\0', "configtype", 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)

200
tools/command.h Normal file
View File

@@ -0,0 +1,200 @@
/*
* 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;
/* command functions */
typedef int (*command_fn) (struct cmd_context * cmd, int argc, char **argv);
/*
* 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.
*/
/* Number of string constants accepted after an option. */
#define MAX_STR_SET 16
/* arg_def flags */
#define ARG_DEF_FLAG_NEW 1
#define ARG_DEF_FLAG_MAY_REPEAT 2
/* arg_def types, can be multiple */
enum {
ARG_DEF_TYPE_NONE = 0,
ARG_DEF_TYPE_BOOL = 1 << 0,
ARG_DEF_TYPE_NUM_ANY = 1 << 1,
ARG_DEF_TYPE_STR_ANY = 1 << 2,
ARG_DEF_TYPE_NUM_CONST = 1 << 3,
ARG_DEF_TYPE_STR_CONST = 1 << 4,
ARG_DEF_TYPE_STR_SET = 1 << 5, /* a set of specific accepted string values */
ARG_DEF_TYPE_NAME_ANY = 1 << 6,
ARG_DEF_TYPE_NAME_PV = 1 << 7,
ARG_DEF_TYPE_NAME_VG = 1 << 8,
ARG_DEF_TYPE_NAME_LV = 1 << 9,
ARG_DEF_TYPE_TAG = 1 << 10,
ARG_DEF_TYPE_SELECT = 1 << 11,
};
#define ARG_DEF_TYPES 16
struct arg_def_type {
const char *name;
int flag;
};
/* The names used for arg_def types in command-lines.in */
static struct arg_def_type arg_def_types[ARG_DEF_TYPES] = {
{ "None", ARG_DEF_TYPE_NONE},
{ "Bool", ARG_DEF_TYPE_BOOL},
{ "Number", ARG_DEF_TYPE_NUM_ANY},
{ "String", ARG_DEF_TYPE_STR_ANY},
{ "Name", ARG_DEF_TYPE_NAME_ANY},
{ "PV", ARG_DEF_TYPE_NAME_PV},
{ "VG", ARG_DEF_TYPE_NAME_VG},
{ "LV", ARG_DEF_TYPE_NAME_LV},
{ "Tag", ARG_DEF_TYPE_TAG},
{ "Select", ARG_DEF_TYPE_SELECT},
};
/* arg_def lv_types, can be multiple */
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,
};
#define ARG_DEF_LVS 64
struct arg_def_lv {
const char *name;
int flag;
};
/* The names used for arg_def lv_types in command-lines.in */
static struct arg_def_lv arg_def_lvs[ARG_DEF_LVS] = {
{ "LV", ARG_DEF_LV_ANY},
{ "LV_linear", ARG_DEF_LV_LINEAR},
{ "LV_striped", ARG_DEF_LV_STRIPED},
{ "LV_snapshot", ARG_DEF_LV_SNAPSHOT},
{ "LV_mirror", ARG_DEF_LV_MIRROR},
{ "LV_raid", ARG_DEF_LV_RAID},
{ "LV_raid0", ARG_DEF_LV_RAID0},
{ "LV_raid1", ARG_DEF_LV_RAID1},
{ "LV_raid4", ARG_DEF_LV_RAID4},
{ "LV_raid5", ARG_DEF_LV_RAID5},
{ "LV_raid6", ARG_DEF_LV_RAID6},
{ "LV_raid10", ARG_DEF_LV_RAID10},
{ "LV_thin", ARG_DEF_LV_THIN},
{ "LV_thinpool", ARG_DEF_LV_THINPOOL},
{ "LV_cache", ARG_DEF_LV_CACHE},
{ "LV_cachepool", ARG_DEF_LV_CACHEPOOL},
};
/* Description a value that follows an option or exists in a position. */
struct arg_def {
uint32_t types; /* ARG_DEF_TYPE_, can be multiple */
uint32_t lv_types; /* ARG_DEF_LV_, can be multiple */
uint64_t num; /* a literal number for ARG_DEF_TYPE_NUM_CONST */
const char *str; /* a literal string for ARG_DEF_TYPE_STR_CONST */
const char *str_set[MAX_STR_SET]; /* literal strings for ARG_DEF_TYPE_STR_SET */
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 32 /* required opt args */
#define CMD_OO_ARGS ARG_COUNT /* 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;
const char *usage;
command_fn fn;
unsigned int flags;
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

File diff suppressed because it is too large Load Diff

View File

@@ -1910,6 +1910,11 @@ static int _lvconvert_raid(struct logical_volume *lv, struct lvconvert_params *l
if (lp->mirrors_supplied) {
if (!*lp->type_str || !strcmp(lp->type_str, SEG_TYPE_NAME_RAID1) || !strcmp(lp->type_str, SEG_TYPE_NAME_LINEAR) ||
(!strcmp(lp->type_str, SEG_TYPE_NAME_STRIPED) && image_count == 1)) {
if (image_count > DEFAULT_RAID1_MAX_IMAGES) {
log_error("Only up to %u mirrors in %s LV %s supported currently.",
DEFAULT_RAID1_MAX_IMAGES, lp->segtype->name, display_lvname(lv));
return 0;
}
if (!lv_raid_change_image_count(lv, image_count, lp->pvh))
return_0;

View File

@@ -527,8 +527,21 @@ static int _read_mirror_and_raid_params(struct cmd_context *cmd,
struct lvcreate_params *lp)
{
int pagesize = lvm_getpagesize();
unsigned max_images = segtype_is_raid(lp->segtype) ? DEFAULT_RAID_MAX_IMAGES :
DEFAULT_MIRROR_MAX_IMAGES;
unsigned max_images;
if (seg_is_raid(lp)) {
if (seg_is_raid1(lp))
max_images = DEFAULT_RAID1_MAX_IMAGES;
else {
max_images = DEFAULT_RAID_MAX_IMAGES;
if (seg_is_raid4(lp) ||
seg_is_any_raid5(lp))
max_images--;
else if (seg_is_any_raid6(lp))
max_images -= 2;
}
} else
max_images = DEFAULT_MIRROR_MAX_IMAGES;
/* Common mirror and raid params */
if (arg_is_set(cmd, mirrors_ARG)) {
@@ -556,8 +569,19 @@ static int _read_mirror_and_raid_params(struct cmd_context *cmd,
/* Default to 2 mirrored areas if '--type mirror|raid1|raid10' */
lp->mirrors = seg_is_mirrored(lp) ? 2 : 1;
if (max(lp->mirrors, lp->stripes) > max_images) {
log_error("Only up to %u images in %s supported currently.",
/* FIMXE: raid10 check has to change once we support data copies and odd numbers of stripes */
if (seg_is_raid10(lp) && lp->mirrors * lp->stripes > max_images) {
log_error("Only up to %u stripes in %s supported currently.",
max_images, lp->segtype->name);
return 0;
} else if (seg_is_mirrored(lp)) {
if (lp->mirrors > max_images) {
log_error("Only up to %u mirrors in %s supported currently.",
max_images, lp->segtype->name);
return 0;
}
} else if (lp->stripes > max_images) {
log_error("Only up to %u stripes in %s supported currently.",
max_images, lp->segtype->name);
return 0;
}
@@ -1231,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

View File

@@ -57,7 +57,7 @@ int lvm2_run(void *handle, const char *cmdline)
cmd = (struct cmd_context *) handle;
cmd->argv = argv;
cmd->pos_arg_values = argv;
if (!(cmdcopy = dm_strdup(cmdline))) {
log_error("Cmdline copy failed.");

View File

@@ -49,6 +49,11 @@ extern char *optarg;
# define OPTIND_INIT 1
#endif
#if 0
#include "command-lines-count.h" /* #define COMMAND_COUNT, generated from command-lines.in */
#endif
#define COMMAND_COUNT 128
/*
* Table of valid switches
*/
@@ -58,12 +63,32 @@ static struct arg_props _arg_props[ARG_COUNT + 1] = {
#undef arg
};
/*
* Table of valid command names
*/
#define MAX_COMMAND_NAMES 64
struct command_name {
const char *name;
const char *desc;
unsigned int flags;
};
struct command_name command_names[MAX_COMMAND_NAMES] = {
#define xx(a, b, c...) { # a, b, c }
#include "commands.h"
#undef xx
}
/*
* Table of valid command lines
*/
static struct command commands[COMMAND_COUNT];
static struct cmdline_context _cmdline;
/* Command line args */
unsigned arg_count(const struct cmd_context *cmd, int a)
{
return cmd->arg_values ? cmd->arg_values[a].count : 0;
return cmd->opt_arg_values ? cmd->opt_arg_values[a].count : 0;
}
unsigned grouped_arg_count(const struct arg_values *av, int a)
@@ -182,12 +207,12 @@ const char *arg_long_option_name(int a)
const char *arg_value(const struct cmd_context *cmd, int a)
{
return cmd->arg_values ? cmd->arg_values[a].value : NULL;
return cmd->opt_arg_values ? cmd->opt_arg_values[a].value : NULL;
}
const char *arg_str_value(const struct cmd_context *cmd, int a, const char *def)
{
return arg_is_set(cmd, a) ? cmd->arg_values[a].value : def;
return arg_is_set(cmd, a) ? cmd->opt_arg_values[a].value : def;
}
const char *grouped_arg_str_value(const struct arg_values *av, int a, const char *def)
@@ -217,44 +242,44 @@ int32_t first_grouped_arg_int_value(const struct cmd_context *cmd, int a, const
int32_t arg_int_value(const struct cmd_context *cmd, int a, const int32_t def)
{
return (_cmdline.arg_props[a].flags & ARG_GROUPABLE) ?
first_grouped_arg_int_value(cmd, a, def) : (arg_is_set(cmd, a) ? cmd->arg_values[a].i_value : def);
first_grouped_arg_int_value(cmd, a, def) : (arg_is_set(cmd, a) ? cmd->opt_arg_values[a].i_value : def);
}
uint32_t arg_uint_value(const struct cmd_context *cmd, int a, const uint32_t def)
{
return arg_is_set(cmd, a) ? cmd->arg_values[a].ui_value : def;
return arg_is_set(cmd, a) ? cmd->opt_arg_values[a].ui_value : def;
}
int64_t arg_int64_value(const struct cmd_context *cmd, int a, const int64_t def)
{
return arg_is_set(cmd, a) ? cmd->arg_values[a].i64_value : def;
return arg_is_set(cmd, a) ? cmd->opt_arg_values[a].i64_value : def;
}
uint64_t arg_uint64_value(const struct cmd_context *cmd, int a, const uint64_t def)
{
return arg_is_set(cmd, a) ? cmd->arg_values[a].ui64_value : def;
return arg_is_set(cmd, a) ? cmd->opt_arg_values[a].ui64_value : def;
}
/* No longer used.
const void *arg_ptr_value(struct cmd_context *cmd, int a, const void *def)
{
return arg_is_set(cmd, a) ? cmd->arg_values[a].ptr : def;
return arg_is_set(cmd, a) ? cmd->opt_arg_values[a].ptr : def;
}
*/
sign_t arg_sign_value(const struct cmd_context *cmd, int a, const sign_t def)
{
return arg_is_set(cmd, a) ? cmd->arg_values[a].sign : def;
return arg_is_set(cmd, a) ? cmd->opt_arg_values[a].sign : def;
}
percent_type_t arg_percent_value(const struct cmd_context *cmd, int a, const percent_type_t def)
{
return arg_is_set(cmd, a) ? cmd->arg_values[a].percent : def;
return arg_is_set(cmd, a) ? cmd->opt_arg_values[a].percent : def;
}
int arg_count_increment(struct cmd_context *cmd, int a)
{
return cmd->arg_values[a].count++;
return cmd->opt_arg_values[a].count++;
}
int yes_no_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av)
@@ -709,104 +734,227 @@ int metadatacopies_arg(struct cmd_context *cmd, struct arg_values *av)
return int_arg(cmd, av);
}
static void __alloc(int size)
static struct command_name *_find_command_name(char *name)
{
if (!(_cmdline.commands = dm_realloc(_cmdline.commands, sizeof(*_cmdline.commands) * size))) {
log_fatal("Couldn't allocate memory.");
exit(ECMD_FAILED);
int i;
for (i = 0; i < MAX_COMMAND_NAMES; i++) {
if (!command_names[i].name)
break;
if (!strcmp(command_names[i].name, name))
return &command_names[i];
}
_cmdline.commands_size = size;
return NULL;
}
static void _alloc_command(void)
void _define_commands(void)
{
if (!_cmdline.commands_size)
__alloc(32);
if (_cmdline.commands_size <= _cmdline.num_commands)
__alloc(2 * _cmdline.commands_size);
}
static void _create_new_command(const char *name, command_fn command,
unsigned flags,
const char *desc, const char *usagestr,
int nargs, int *args)
{
struct command *nc;
_alloc_command();
nc = _cmdline.commands + _cmdline.num_commands++;
nc->name = name;
nc->desc = desc;
nc->usage = usagestr;
nc->fn = command;
nc->flags = flags;
nc->num_args = nargs;
nc->valid_args = args;
}
static void _register_command(const char *name, command_fn fn, const char *desc,
unsigned flags, const char *usagestr, ...)
{
int nargs = 0, i;
int *args;
va_list ap;
/* count how many arguments we have */
va_start(ap, usagestr);
while (va_arg(ap, int) >= 0)
nargs++;
va_end(ap);
/* allocate space for them */
if (!(args = dm_malloc(sizeof(*args) * nargs))) {
log_fatal("Out of memory.");
exit(ECMD_FAILED);
}
/* fill them in */
va_start(ap, usagestr);
for (i = 0; i < nargs; i++)
args[i] = va_arg(ap, int);
va_end(ap);
/* enter the command in the register */
_create_new_command(name, fn, flags, desc, usagestr, nargs, args);
/* command-lines.h defines command[] structs, generated from command-lines.in */
#include "command-lines.h" /* generated from command-lines.in */
}
void lvm_register_commands(void)
{
#define xx(a, b, c, d...) _register_command(# a, a, b, c, ## d, \
driverloaded_ARG, \
debug_ARG, help_ARG, help2_ARG, \
version_ARG, verbose_ARG, \
yes_ARG, \
quiet_ARG, config_ARG, \
commandprofile_ARG, \
profile_ARG, -1);
#include "commands.h"
#undef xx
struct command_name *cname;
int i;
_define_commands();
_cmdline.commands = &commands;
_cmdline.num_commands = COMMAND_COUNT;
for (i = 0; i < COMMAND_COUNT; i++) {
if (!(cname = _find_command_name(commands[i].name)))
log_error(INTERNAL_ERROR "Failed to find command name %s.", commands[i].name);
commands[i].flags = cname->flags;
}
}
static struct command *_find_command(const char *name)
/*
* Match what the user typed with a one specific command definition/prototype
* from commands[]. If nothing matches, it's not a valid command. The match
* is based on command name, required opt args and required pos args.
*
* Find an entry in the commands array that matches based the arg values.
*
* If the cmd has opt or pos args set that are not accepted by command,
* we can: silently ignore them, warn they are not being used, or fail.
* Default should probably be to warn and continue.
*
* For each command[i], check how many required opt/pos args cmd matches.
* Save the command[i] that matches the most.
*
* commands[i].cmd_flags & CMD_FLAG_ONE_REQUIRED_OPT means
* any one item from commands[i].required_opt_args needs to be
* set to match.
*
* required_pos_args[0].flags & ARG_DEF_TYPE_SELECT means
* cmd->pos_arg_values[0] can be NULL if arg_is_set(select_ARG)
*/
static int _opt_equivalent_is_set(struct cmd_context *cmd, int opt)
{
int i;
const char *base;
if ((opt == mirrorlog_ARG) && arg_is_set(cmd, corelog_ARG, NULL))
return 1;
base = last_path_component(name);
if ((opt == resizeable_ARG) && arg_is_set(cmd, resizable_ARG, NULL))
return 1;
for (i = 0; i < _cmdline.num_commands; i++) {
if (!strcmp(base, _cmdline.commands[i].name))
break;
if ((opt == allocatable_ARG) && arg_is_set(cmd, allocation_ARG, NULL))
return 1;
if ((opt == resizeable_ARG) && arg_is_set(cmd, allocation_ARG, NULL))
return 1;
if ((opt == activate_ARG) && arg_is_set(cmd, available_ARG, NULL))
return 1;
if ((opt == rebuild_ARG) && arg_is_set(cmd, raidrebuild_ARG, NULL))
return 1;
if ((opt == syncaction_ARG) && arg_is_set(cmd, raidsyncaction_ARG, NULL))
return 1;
if ((opt == writemostly_ARG) && arg_is_set(cmd, raidwritemostly_ARG, NULL))
return 1;
if ((opt == minrecoveryrate_ARG) && arg_is_set(cmd, raidminrecoveryrate_ARG, NULL))
return 1;
if ((opt == maxrecoveryrate_ARG) && arg_is_set(cmd, raidmaxrecoveryrate_ARG, NULL))
return 1;
if ((opt == writebehind_ARG) && arg_is_set(cmd, raidwritebehind_ARG, NULL))
return 1;
return 0;
}
static int _command_required_opt_matches(struct cmd_context *cmd, int ci, int ro)
{
if (arg_is_set(cmd, commands[ci].required_opt_args[ro].opt, NULL))
return 1;
/*
* For some commands, --size and --extents are interchanable,
* but command[] definitions use only --size.
*/
if ((commands[ci].required_opt_args[ro].opt == size_ARG) && arg_is_set(cmd, extents_ARG, NULL)) {
if (!strcmp(commands[i].name, "lvcreate") ||
!strcmp(commands[i].name, "lvresize")
!strcmp(commands[i].name, "lvextend")
!strcmp(commands[i].name, "lvreduce"))
return 1;
}
if (i >= _cmdline.num_commands)
return 0;
/* TODO: for lvmconfig, recognize --type in place of --typeconfig? */
return _cmdline.commands + i;
if (_opt_equivalent_is_set(cmd, commands[ci].required_opt_args[ro].opt))
return 1;
}
static int _command_required_pos_matches(struct cmd_context *cmd, int ci, int rp)
{
if (cmd->pos_arg_values[rp]) {
/* FIXME: can we match object type better than just checking something exists? */
/* Some cases could be validated by looking at defs.types and at the value. */
return 1;
}
/*
* If Select is specified as a pos arg, then that pos arg can be
* empty if --select is used.
*/
if ((commands[ci].required_pos_args[rp].def.types & ARG_DEF_TYPE_SELECT) &&
arg_is_set(cmd, select_ARG, NULL))
return 1;
return 0;
}
static struct command *_find_command(struct cmd_context *cmd, const char *path)
{
const char *name;
int ro, rp;
int found = 0;
int i;
name = last_path_component(path);
for (i = 0; i < COMMAND_COUNT; i++) {
if (strcmp(name, commands[i].name))
continue;
match_count = 1; /* for command name matching */
mismatch_count = 0;
/* match required_opt_args */
for (ro = 0; ro < commands[i].ro_count; ro++) {
if (_command_required_opt_matches(cmd, i, ro))
match_count++;
else
mismatch_count++;
}
/*
* One item in required_opt_args must be set for
* a match, and the rest are optional (don't count
* as mismatches).
*/
if (cmd->cmd_flags & CMD_FLAG_ONE_REQUIRED_OPT) {
if (match_count >= 2) {
match_count = 2;
mismatch_count = 0;
}
}
/* match required_pos_args */
for (rp = 0; rp < commands[i].rp_count; rp++) {
if (_command_required_pos_matches(cmd, i, rp))
match_count++;
else
mismatch_count++;
}
if (mismatch_count) {
/* save i/match_count for "closest" command that doesn't match */
if (!closest_count || (match_count > closest_count)) {
closest_i = i;
closest_count = match_count;
}
continue;
}
if (!best_match_count || (match_count > best_match_count)) {
best_match_i = i;
best_match_count = match_count;
}
}
if (!best_match_count) {
/* nothing matches */
/* TODO: report closest matching command and report missing required opt/pos args for that? */
log_error("Failed to find a matching command definition.");
if (closest_count) {
log_warn("Closest command usage is:");
log_warn("%s", commands[closest_i].usage);
}
return NULL;
}
/*
* Check if all arg_is_set values from cmd are accepted as
* optional_opt_args, and warn (or fail per config?) if options are set
* in cmd that are not accepted by the chosen command[i].
*
* Same for pos args.
*/
log_debug("matched command usage: %.80s ...", commands[best_match_i].usage);
return &commands[best_match_i];
}
static void _short_usage(const char *name)
@@ -816,14 +964,16 @@ static void _short_usage(const char *name)
static int _usage(const char *name)
{
struct command *com = _find_command(name);
struct command_name *cname = _find_command_name(name);
if (!com) {
if (!cname) {
log_print("%s: no such command.", name);
return 0;
}
log_print("%s: %s\n\n%s", com->name, com->desc, com->usage);
/* FIXME: print usage strings from matching commands[] entries? */
log_print("%s: %s", cname->name, cname->desc);
return 1;
}
@@ -890,7 +1040,7 @@ static int _process_command_line(struct cmd_context *cmd, int *argc,
struct arg_values *av;
struct arg_value_group_list *current_group = NULL;
if (!(cmd->arg_values = dm_pool_zalloc(cmd->mem, sizeof(*cmd->arg_values) * ARG_COUNT))) {
if (!(cmd->opt_arg_values = dm_pool_zalloc(cmd->mem, sizeof(*cmd->opt_arg_values) * ARG_COUNT))) {
log_fatal("Unable to allocate memory for command line arguments.");
return 0;
}
@@ -917,7 +1067,7 @@ static int _process_command_line(struct cmd_context *cmd, int *argc,
a = _cmdline.arg_props + arg;
av = &cmd->arg_values[arg];
av = &cmd->opt_arg_values[arg];
if (a->flags & ARG_GROUPABLE) {
/*
@@ -930,7 +1080,7 @@ static int _process_command_line(struct cmd_context *cmd, int *argc,
(current_group->arg_values[arg].count && !(a->flags & ARG_COUNTABLE)) ||
(current_group->prio < a->prio)) {
/* FIXME Reduce size including only groupable args */
if (!(current_group = dm_pool_zalloc(cmd->mem, sizeof(struct arg_value_group_list) + sizeof(*cmd->arg_values) * ARG_COUNT))) {
if (!(current_group = dm_pool_zalloc(cmd->mem, sizeof(struct arg_value_group_list) + sizeof(*cmd->opt_arg_values) * ARG_COUNT))) {
log_fatal("Unable to allocate memory for command line arguments.");
return 0;
}
@@ -1002,12 +1152,12 @@ static int _merge_synonym(struct cmd_context *cmd, int oldarg, int newarg)
/* Not groupable? */
if (!(_cmdline.arg_props[oldarg].flags & ARG_GROUPABLE)) {
if (arg_is_set(cmd, oldarg))
_copy_arg_values(cmd->arg_values, oldarg, newarg);
_copy_arg_values(cmd->opt_arg_values, oldarg, newarg);
return 1;
}
if (arg_is_set(cmd, oldarg))
cmd->arg_values[newarg].count = cmd->arg_values[oldarg].count;
cmd->opt_arg_values[newarg].count = cmd->opt_arg_values[oldarg].count;
/* Groupable */
dm_list_iterate_items(current_group, &cmd->arg_value_groups) {
@@ -1431,7 +1581,7 @@ static int _prepare_profiles(struct cmd_context *cmd)
log_debug(_setting_global_profile_msg, _command_profile_source_name, profile->name);
cmd->profile_params->global_command_profile = profile;
if (!cmd->arg_values)
if (!cmd->opt_arg_values)
cmd->profile_params->shell_profile = profile;
}
@@ -1553,14 +1703,14 @@ int lvm_run_command(struct cmd_context *cmd, int argc, char **argv)
log_debug("Parsing: %s", cmd->cmd_line);
if (!(cmd->command = _find_command(argv[0])))
return ENO_SUCH_CMD;
if (!_process_command_line(cmd, &argc, &argv)) {
log_error("Error during parsing of command line.");
return EINVALID_CMD_LINE;
}
if (!(cmd->command = _find_command(cmd, argv[0])))
return ENO_SUCH_CMD;
set_cmd_name(cmd->command->name);
if (arg_is_set(cmd, backgroundfork_ARG)) {
@@ -1853,7 +2003,7 @@ static int _do_get_custom_fd(const char *env_var_name, int *fd)
{
const char *str;
char *endptr;
int tmp_fd;
long int tmp_fd;
*fd = -1;
@@ -2040,23 +2190,8 @@ struct cmd_context *init_lvm(unsigned set_connections, unsigned set_filters)
return cmd;
}
static void _fin_commands(void)
{
int i;
for (i = 0; i < _cmdline.num_commands; i++)
dm_free(_cmdline.commands[i].valid_args);
dm_free(_cmdline.commands);
_cmdline.commands = NULL;
_cmdline.num_commands = 0;
_cmdline.commands_size = 0;
}
void lvm_fin(struct cmd_context *cmd)
{
_fin_commands();
destroy_toolcontext(cmd);
udev_fin_library_context();
}
@@ -2202,7 +2337,8 @@ int lvm2_main(int argc, char **argv)
if (!(cmd = init_lvm(0, 0)))
return -1;
cmd->argv = argv;
cmd->pos_arg_values = argv;
lvm_register_commands();
if (_lvm1_fallback(cmd)) {

View File

@@ -144,6 +144,75 @@ static struct dm_list *_get_allocatable_pvs(struct cmd_context *cmd, int argc,
return allocatable_pvs;
}
/*
* If @lv_name's a RAID SubLV, check for any PVs
* on @trim_list holding it's sibling (rimage/rmeta)
* and remove it from the @trim_list in order to allow
* for pvmove collocation of DataLV/MetaLV pairs.
*/
static int _remove_sibling_pvs_from_trim_list(struct logical_volume *lv,
const char *lv_name,
struct dm_list *trim_list)
{
char *idx, *suffix, *sublv_name;
size_t len;
struct logical_volume *sublv;
struct dm_list untrim_list, *pvh1, *pvh2;
struct pv_list *pvl1, *pvl2;
/* Give up with success unless @lv_name _and_ valid raid segment type */
if (!lv_name || !*lv_name ||
!seg_is_raid(first_seg(lv)) ||
seg_is_raid0(first_seg(lv)) ||
!strcmp(lv->name, lv_name))
return 1;
dm_list_init(&untrim_list);
if (!(suffix = first_substring(lv_name, "_rimage_", "_rmeta_", NULL)))
return 0;
if (!(idx = strstr(suffix + 1, "_")))
return 0;
idx++;
/* + 2 for the longer rimage string */
if (!(sublv_name = dm_pool_alloc(lv->vg->cmd->mem, strlen(lv_name + 2))))
return_0;
/* Create the siblings name (e.g. "raidlv_rmeta_N" -> "raidlv_rimage_N" */
len = suffix - lv_name;
strncpy(sublv_name, lv_name, len);
sprintf(sublv_name + len, strstr(suffix, "_rimage_") ? "_rmeta_%s" : "_rimage_%s", idx);
if (!(sublv = find_lv(lv->vg, sublv_name))) {
log_error("Can't find sub LV %s?", sublv_name);
return_0;
}
if (!get_pv_list_for_lv(lv->vg->cmd->mem, sublv, &untrim_list)) {
log_error("Can't find PVs for sub LV %s?", sublv_name);
return_0;
}
dm_list_iterate(pvh1, &untrim_list) {
pvl1 = dm_list_item(pvh1, struct pv_list);
dm_list_iterate(pvh2, trim_list) {
pvl2 = dm_list_item(pvh2, struct pv_list);
if (pvl1->pv == pvl2->pv) {
log_debug("Removing PV %s from trim list",
pvl2->pv->dev->pvid);
dm_list_del(&pvl2->list);
break;
}
}
}
return 1;
}
/*
* _trim_allocatable_pvs
* @alloc_list
@@ -324,7 +393,7 @@ static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
if (lv == lv_mirr)
continue;
if (lv_name && strcmp(lv->name, lv_name))
if (lv_name && strcmp(lv->name, top_level_lv_name(vg, lv_name)))
continue;
/*
@@ -334,7 +403,7 @@ static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
*
* Allow clustered mirror, but not raid mirror.
*/
if (vg_is_clustered(lv->vg) && !lv_is_mirror_type(lv))
if (vg_is_clustered(vg) && !lv_is_mirror_type(lv))
continue;
if (!lv_is_on_pvs(lv, source_pvl))
@@ -351,8 +420,18 @@ static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
seg_is_mirrored(first_seg(lv))) {
dm_list_init(&trim_list);
if (!get_pv_list_for_lv(lv->vg->cmd->mem,
lv, &trim_list))
if (!get_pv_list_for_lv(vg->cmd->mem, lv, &trim_list))
return_NULL;
/*
* Remove any PVs holding SubLV siblings to allow
* for collocation (e.g. *rmeta_0 -> *rimage_0).
*
* Callee checks for lv_name and valid raid segment type.
*
* FIXME: don't rely on namespace
*/
if (!_remove_sibling_pvs_from_trim_list(lv, lv_name, &trim_list))
return_NULL;
if (!_trim_allocatable_pvs(allocatable_pvs,
@@ -370,6 +449,7 @@ static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
lv = lvl->lv;
if (lv == lv_mirr)
continue;
if (lv_name) {
if (strcmp(lv->name, lv_name) && !sub_lv_of(lv, lv_name))
continue;

View File

@@ -105,7 +105,7 @@ int become_daemon(struct cmd_context *cmd, int skip_lvm)
init_verbose(VERBOSE_BASE_LEVEL);
#endif /* DEBUG_CHILD */
strncpy(*cmd->argv, "(lvm2)", strlen(*cmd->argv));
strncpy(*cmd->pos_arg_values, "(lvm2)", strlen(*cmd->pos_arg_values));
lvmetad_disconnect();
@@ -1281,10 +1281,12 @@ static int _validate_stripe_params(struct cmd_context *cmd, const struct segment
if (!stripe_size_required && *stripe_size) {
log_print_unless_silent("Ignoring stripesize argument for %s devices.", segtype->name);
*stripe_size = 0;
} else if (segtype_is_striped(segtype) && *stripes == 1 && *stripe_size) {
log_print_unless_silent("Ignoring stripesize argument with single stripe.");
} else if (*stripes == 1 && (segtype_is_striped(segtype) || segtype_is_mirror(segtype))) {
stripe_size_required = 0;
*stripe_size = 0;
if (*stripe_size) {
log_print_unless_silent("Ignoring stripesize argument with single stripe.");
*stripe_size = 0;
}
}
if (stripe_size_required) {

View File

@@ -44,6 +44,8 @@
#include "toollib.h"
#include "lvmnotify.h"
#include "command.h"
#include <ctype.h>
#include <sys/types.h>
@@ -51,8 +53,6 @@
#define MAX_ARGS 64
/* command functions */
typedef int (*command_fn) (struct cmd_context * cmd, int argc, char **argv);
#define xx(a, b...) int a(struct cmd_context *cmd, int argc, char **argv);
#include "commands.h"
#undef xx
@@ -118,19 +118,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);

View File

@@ -331,7 +331,7 @@ static int _move_thins(struct volume_group *vg_from,
data_lv = seg_lv(first_seg(seg->pool_lv), 0);
/* Ignore, if no allocations on PVs of @vg_to */
if (!lv_is_on_pvs(data_lv, &vg_to->pvs) ||
if (!lv_is_on_pvs(data_lv, &vg_to->pvs) &&
(seg->external_lv && !lv_is_on_pvs(seg->external_lv, &vg_to->pvs)))
continue;