mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
lvcreate: new cache or writecache lv with single command
To create a new cache or writecache LV with a single command: lvcreate --type cache|writecache -n Name -L Size --cachedevice PVfast VG [PVslow ...] - A new main linear|striped LV is created as usual, using the specified -n Name and -L Size, and using the optionally specified PVslow devices. - Then, a new cachevol LV is created internally, using PVfast specified by the cachedevice option. - Then, the cachevol is attached to the main LV, converting the main LV to type cache|writecache. Include --cachesize Size to specify the size of cache|writecache to create from the specified --cachedevice PVs, otherwise the entire cachedevice PV is used. The --cachedevice option can be repeated to create the cache from multiple devices, or the cachedevice option can contain a tag name specifying a set of PVs to allocate the cache from. To create a new cache or writecache LV with a single command using an existing cachevol LV: lvcreate --type cache|writecache -n Name -L Size --cachevol LVfast VG [PVslow ...] - A new main linear|striped LV is created as usual, using the specified -n Name and -L Size, and using the optionally specified PVslow devices. - Then, the cachevol LVfast is attached to the main LV, converting the main LV to type cache|writecache. In cases where more advanced types (for the main LV or cachevol LV) are needed, they should be created independently and then combined with lvconvert. Example ------- user creates a new VG with one slow device and one fast device: $ vgcreate vg /dev/slow1 /dev/fast1 user creates a new 8G main LV on /dev/slow1 that uses all of /dev/fast1 as a writecache: $ lvcreate --type writecache --cachedevice /dev/fast1 -n main -L 8G vg /dev/slow1 Example ------- user creates a new VG with two slow devs and two fast devs: $ vgcreate vg /dev/slow1 /dev/slow2 /dev/fast1 /dev/fast2 user creates a new 8G main LV on /dev/slow1 and /dev/slow2 that uses all of /dev/fast1 and /dev/fast2 as a writecache: $ lvcreate --type writecache --cachedevice /dev/fast1 --cachedevice /dev/fast2 -n main -L 8G vg /dev/slow1 /dev/slow2 Example ------- A user has several slow devices and several fast devices in their VG, the slow devs have tag @slow, the fast devs have tag @fast. user creates a new 8G main LV on the slow devs with a 2G writecache on the fast devs: $ lvcreate --type writecache -n main -L 8G --cachedevice @fast --cachesize 2G vg @slow
This commit is contained in:
parent
21b37964eb
commit
2aed2a41f7
@ -954,6 +954,7 @@ struct lvcreate_params {
|
||||
int thin_chunk_size_calc_policy;
|
||||
unsigned suppress_zero_warn : 1;
|
||||
unsigned needs_lockd_init : 1;
|
||||
unsigned ignore_type : 1;
|
||||
|
||||
const char *vg_name; /* only-used when VG is not yet opened (in /tools) */
|
||||
const char *lv_name; /* all */
|
||||
|
@ -126,7 +126,7 @@ arg(cachepool_ARG, '\0', "cachepool", lv_VAL, 0, 0,
|
||||
arg(cachevol_ARG, '\0', "cachevol", lv_VAL, 0, 0,
|
||||
"The name of a cache volume.\n")
|
||||
|
||||
arg(cachedevice_ARG, '\0', "cachedevice", pv_VAL, 0, 0,
|
||||
arg(cachedevice_ARG, '\0', "cachedevice", pv_VAL, ARG_GROUPABLE, 0,
|
||||
"The name of a device to use for a cache.\n")
|
||||
|
||||
arg(cachesize_ARG, '\0', "cachesize", sizemb_VAL, 0, 0,
|
||||
|
@ -1219,87 +1219,107 @@ lvcreate --type cache --size SizeMB --cachepool LV_cachepool VG
|
||||
OO: --cache, OO_LVCREATE_POOL, OO_LVCREATE_CACHE, OO_LVCREATE,
|
||||
--stripes Number, --stripesize SizeKB
|
||||
OP: PV ...
|
||||
ID: lvcreate_cache_vol_with_new_origin
|
||||
DESC: Create a cache LV, first creating a new origin LV,
|
||||
DESC: then combining it with the existing cache pool named
|
||||
DESC: by the --cachepool arg.
|
||||
ID: lvcreate_and_attach_cachepool
|
||||
DESC: Create a new LV, then attach the specified cachepool
|
||||
DESC: which converts the new LV to type cache.
|
||||
|
||||
# alternate form of lvcreate --type cache
|
||||
# (omits the --type cache option which is inferred)
|
||||
lvcreate --size SizeMB --cachepool LV_cachepool VG
|
||||
OO: --type cache, --cache, OO_LVCREATE_CACHE, OO_LVCREATE,
|
||||
--stripes Number, --stripesize SizeKB
|
||||
OP: PV ...
|
||||
ID: lvcreate_cache_vol_with_new_origin
|
||||
DESC: Create a cache LV, first creating a new origin LV,
|
||||
DESC: then combining it with the existing cache pool named
|
||||
DESC: by the --cachepool arg (variant, infers --type cache).
|
||||
ID: lvcreate_and_attach_cachepool_v2
|
||||
DESC: Create a new LV, then attach the specified cachepool
|
||||
DESC: which converts the new LV to type cache
|
||||
DESC: (variant, infers --type cache.)
|
||||
FLAGS: SECONDARY_SYNTAX
|
||||
|
||||
# alternate form of lvcreate --type cache
|
||||
# (moves cachepool from option arg to position arg,
|
||||
# dropping the normal VG position arg)
|
||||
lvcreate --type cache --size SizeMB LV_cachepool
|
||||
OO: --cache, OO_LVCREATE_POOL, OO_LVCREATE_CACHE, OO_LVCREATE,
|
||||
--stripes Number, --stripesize SizeKB
|
||||
OP: PV ...
|
||||
ID: lvcreate_cache_vol_with_new_origin
|
||||
DESC: Create a cache LV, first creating a new origin LV,
|
||||
DESC: then combining it with the existing cache pool named
|
||||
DESC: in the first arg (variant, also use --cachepool).
|
||||
ID: lvcreate_and_attach_cachepool_v3
|
||||
DESC: Create a new LV, then attach the specified cachepool
|
||||
DESC: which converts the new LV to type cache.
|
||||
DESC: (variant, also use --cachepool).
|
||||
FLAGS: SECONDARY_SYNTAX
|
||||
|
||||
# This is a ridiculously crazy command which nobody could
|
||||
# understand. It should be be eliminated. It does two different
|
||||
# things depending on whether LV in pos 1 is a cachepool LV
|
||||
# or not. Both variations are unnecessary.
|
||||
# This command has two different meanings which ought to
|
||||
# have separate command defs, but since the syntax is the
|
||||
# same for both they have to share one command def with
|
||||
# an ambiguous meaning. Which command is performed depends
|
||||
# on whether the LV in the first arg position is a
|
||||
# cachepool or not (we can't have two different command
|
||||
# defs that differ only in the type of LV in the arg position
|
||||
# because when parsing commands we don't know the LV type.)
|
||||
#
|
||||
# 1. If LV is a cachepool, then it's an alternate form of
|
||||
# an already complicated command above.
|
||||
# 1. An alternate form of lvcreate_and_attach_cachepool_v3
|
||||
# this syntax: lvcreate --cache --size SizeMB LV_cachepool
|
||||
# is alternative for: lvcreate --type cache --size SizeMB LV_cachepool
|
||||
#
|
||||
# # alternate form for lvcreate_cache_vol_with_new_origin
|
||||
# lvcreate --cache --size SizeMB LV_cachepool
|
||||
# OO: --type cache, --cache, OO_LVCREATE_CACHE, OO_LVCREATE, --stripes Number, --stripesize SizeKB
|
||||
# OP: PV ...
|
||||
# ID: lvcreate_cache_vol_with_new_origin
|
||||
# DESC: Create a cache LV, first creating a new origin LV,
|
||||
# DESC: then combining it with the existing cache pool named
|
||||
# DESC: in the first arg (variant, infers --type cache,
|
||||
# DESC: also use --cachepool).
|
||||
#
|
||||
# 2. If LV is not a cachepool, then it's a disguised lvconvert.
|
||||
#
|
||||
# # FIXME: this should be done by lvconvert, and this command removed
|
||||
# lvcreate --type cache --size SizeMB LV
|
||||
# OO: OO_LVCREATE_POOL, OO_LVCREATE_CACHE, OO_LVCREATE
|
||||
# OP: PV ...
|
||||
# ID: lvcreate_convert_to_cache_vol_with_cachepool
|
||||
# DESC: Convert the specified LV to type cache after creating a new
|
||||
# DESC: cache pool LV to use (use lvconvert).
|
||||
# 2. An alternative to using lvconvert to convert LV to type cache,
|
||||
# but in this case the cachepool is created internally and
|
||||
# then attached to the LV arg.
|
||||
#
|
||||
# Note that stripes are accepted by the first and not by the
|
||||
# second, but it's not possible to validate this until after
|
||||
# the LV type is known.
|
||||
#
|
||||
# So, to define this syntax we have to combine both of
|
||||
# those variants, each crazy on it's own, into one
|
||||
# ridiculous command.
|
||||
|
||||
# def1: alternate form of lvcreate --type cache, or
|
||||
# def2: it should be done by lvconvert.
|
||||
lvcreate --cache --size SizeMB LV
|
||||
OO: OO_LVCREATE_CACHE, OO_LVCREATE_POOL, OO_LVCREATE,
|
||||
--stripes Number, --stripesize SizeKB
|
||||
OP: PV ...
|
||||
ID: lvcreate_cache_vol_with_new_origin_or_convert_to_cache_vol_with_cachepool
|
||||
DESC: When LV is a cache pool, create a cache LV,
|
||||
DESC: first creating a new origin LV, then combining it with
|
||||
DESC: the existing cache pool named in the first arg
|
||||
DESC: (variant, infers --type cache, also use --cachepool).
|
||||
DESC: When LV is not a cache pool, convert the specified LV
|
||||
DESC: to type cache after creating a new cache pool LV to use
|
||||
DESC: (use lvconvert).
|
||||
ID: lvcreate_new_plus_old_cachepool_or_lvconvert_old_plus_new_cachepool
|
||||
DESC: When the LV arg is a cachepool, then create a new LV and
|
||||
DESC: attach the cachepool arg to it.
|
||||
DESC: (variant, use --type cache and --cachepool.)
|
||||
DESC: When the LV arg is not a cachepool, then create a new cachepool
|
||||
DESC: and attach it to the LV arg (alternative, use lvconvert.)
|
||||
FLAGS: SECONDARY_SYNTAX
|
||||
|
||||
---
|
||||
|
||||
# These all create a new origin LV, then forwards to lvconvert
|
||||
# which combines it with a cachevol (which already exists or
|
||||
# which needs to be created from cachedevice), converting
|
||||
# the new LV to type cache or writecache.
|
||||
|
||||
lvcreate --type cache --size SizeMB --cachevol LV VG
|
||||
OO: OO_LVCREATE, OO_LVCREATE_CACHE, --stripes Number, --stripesize SizeKB
|
||||
OP: PV ...
|
||||
ID: lvcreate_and_attach_cachevol_for_cache
|
||||
DESC: Create a new LV, then attach the specified cachevol
|
||||
DESC: which converts the new LV to type cache.
|
||||
|
||||
lvcreate --type cache --size SizeMB --cachedevice PV VG
|
||||
OO: OO_LVCREATE, OO_LVCREATE_CACHE, --cachesize SizeMB, --stripes Number, --stripesize SizeKB
|
||||
OP: PV ...
|
||||
ID: lvcreate_and_attach_cachedevice_for_cache
|
||||
DESC: Create a new LV, then attach a cachevol created from
|
||||
DESC: the specified cache device, which converts the
|
||||
DESC: new LV to type cache.
|
||||
|
||||
lvcreate --type writecache --size SizeMB --cachevol LV VG
|
||||
OO: OO_LVCREATE, --cachesettings String, --stripes Number, --stripesize SizeKB
|
||||
OP: PV ...
|
||||
ID: lvcreate_and_attach_cachevol_for_writecache
|
||||
DESC: Create a new LV, then attach the specified cachevol
|
||||
DESC: which converts the new LV to type writecache.
|
||||
|
||||
lvcreate --type writecache --size SizeMB --cachedevice PV VG
|
||||
OO: OO_LVCREATE, --cachesize SizeMB, --cachesettings String, --stripes Number, --stripesize SizeKB
|
||||
OP: PV ...
|
||||
ID: lvcreate_and_attach_cachedevice_for_writecache
|
||||
DESC: Create a new LV, then attach a cachevol created from
|
||||
DESC: the specified cache device, which converts the
|
||||
DESC: new LV to type writecache.
|
||||
|
||||
---
|
||||
|
||||
lvdisplay
|
||||
OO: --aligned, --all, --binary, --colon, --columns,
|
||||
--configreport ConfigReport, --foreign, --history, --ignorelockingfailure,
|
||||
|
@ -1420,6 +1420,9 @@ int define_commands(struct cmd_context *cmdtool, const char *run_name)
|
||||
if (line[0] == '\n')
|
||||
break;
|
||||
|
||||
if (!strcmp(line, "---") || !strcmp(line, "--"))
|
||||
continue;
|
||||
|
||||
if ((n = strchr(line, '\n')))
|
||||
*n = '\0';
|
||||
|
||||
|
@ -4248,18 +4248,25 @@ int lvconvert_to_pool_cmd(struct cmd_context *cmd, int argc, char **argv)
|
||||
NULL, NULL, &_lvconvert_to_pool_single);
|
||||
}
|
||||
|
||||
#define MAX_CACHEDEVS 8
|
||||
|
||||
static int _lv_create_cachevol(struct cmd_context *cmd,
|
||||
struct volume_group *vg,
|
||||
struct logical_volume *lv,
|
||||
const char *dev_name,
|
||||
struct logical_volume **cachevol_lv)
|
||||
{
|
||||
char cvname[NAME_LEN];
|
||||
struct device *dev_fast;
|
||||
struct dm_list *use_pvh;
|
||||
uint64_t cache_size_sectors;
|
||||
struct logical_volume *cachevol;
|
||||
struct pv_list *pvl;
|
||||
char *dev_name;
|
||||
struct device *dev_fast;
|
||||
char *dev_argv[MAX_CACHEDEVS];
|
||||
int dev_argc = 0;
|
||||
uint64_t cache_size_sectors = 0;
|
||||
uint64_t full_size_sectors = 0;
|
||||
uint64_t pv_size_sectors;
|
||||
struct logical_volume *cachevol;
|
||||
struct arg_value_group_list *group;
|
||||
struct lvcreate_params lp = {
|
||||
.activate = CHANGE_AN,
|
||||
.alloc = ALLOC_INHERIT,
|
||||
@ -4275,48 +4282,86 @@ static int _lv_create_cachevol(struct cmd_context *cmd,
|
||||
.suppress_zero_warn = 1,
|
||||
};
|
||||
|
||||
if (dm_snprintf(cvname, NAME_LEN, "%s_cache", lv->name) < 0) {
|
||||
log_error("Failed to create cachevol LV name.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(dev_fast = dev_cache_get(cmd, dev_name, cmd->filter))) {
|
||||
log_error("Device %s not found.", dev_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(pvl = find_pv_in_vg(vg, dev_name))) {
|
||||
log_error("PV %s not found in VG.", dev_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If fast_dev is used in the VG, then require a cachesize to allocate
|
||||
* from it. If fast_dev is not used in the VG, then prompt asking if
|
||||
* the entire dev should be used.
|
||||
* If cache size is not set, and all cachedevice's are unused,
|
||||
* then the cache size is the sum of all cachedevice sizes.
|
||||
*/
|
||||
if (!(cache_size_sectors = arg_uint64_value(cmd, cachesize_ARG, 0))) {
|
||||
if (pvl->pv->pe_alloc_count) {
|
||||
cache_size_sectors = arg_uint64_value(cmd, cachesize_ARG, 0);
|
||||
|
||||
dm_list_iterate_items(group, &cmd->arg_value_groups) {
|
||||
if (!grouped_arg_is_set(group->arg_values, cachedevice_ARG))
|
||||
continue;
|
||||
|
||||
if (!(dev_name = (char *)grouped_arg_str_value(group->arg_values, cachedevice_ARG, NULL)))
|
||||
break;
|
||||
|
||||
if (dev_name[0] == '@') {
|
||||
if (!cache_size_sectors) {
|
||||
log_error("With tag as cachedevice, --cachesize is required.");
|
||||
return 0;
|
||||
}
|
||||
goto add_dev_arg;
|
||||
}
|
||||
|
||||
if (!(dev_fast = dev_cache_get(cmd, dev_name, cmd->filter))) {
|
||||
log_error("Device %s not found.", dev_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(pvl = find_pv_in_vg(vg, dev_name))) {
|
||||
log_error("PV %s not found in VG.", dev_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the dev is used in the VG, then require a cachesize to allocate
|
||||
* from it. If it is not used in the VG, then prompt asking if the
|
||||
* entire dev should be used.
|
||||
*/
|
||||
if (!cache_size_sectors && pvl->pv->pe_alloc_count) {
|
||||
log_error("PV %s is in use, --cachesize is required.", dev_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
cache_size_sectors = (pvl->pv->pe_count * vg->extent_size);
|
||||
if (!cache_size_sectors) {
|
||||
pv_size_sectors = (pvl->pv->pe_count * vg->extent_size);
|
||||
|
||||
if (!arg_is_set(cmd, yes_ARG) &&
|
||||
yes_no_prompt("Use all %s from %s for cache? [y/n]: ",
|
||||
display_size(cmd, cache_size_sectors), dev_name) == 'n') {
|
||||
log_print("Use --cachesize SizeMB to use a part of the cachedevice.");
|
||||
log_error("Conversion aborted.");
|
||||
if (!arg_is_set(cmd, yes_ARG) &&
|
||||
yes_no_prompt("Use all %s from %s for cache? [y/n]: ",
|
||||
display_size(cmd, pv_size_sectors), dev_name) == 'n') {
|
||||
log_print("Use --cachesize SizeMB to use a part of the cachedevice.");
|
||||
log_error("Conversion aborted.");
|
||||
return 0;
|
||||
}
|
||||
full_size_sectors += pv_size_sectors;
|
||||
}
|
||||
add_dev_arg:
|
||||
if (dev_argc >= MAX_CACHEDEVS) {
|
||||
log_error("Cannot allocate from more than %u cache devices.", MAX_CACHEDEVS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dev_argv[dev_argc++] = dev_name;
|
||||
}
|
||||
|
||||
if (!(use_pvh = create_pv_list(cmd->mem, vg, 1, (char **)&dev_name, 1))) {
|
||||
if (!cache_size_sectors)
|
||||
cache_size_sectors = full_size_sectors;
|
||||
|
||||
if (!dev_argc) {
|
||||
log_error("No cachedevice specified to create a cachevol.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(use_pvh = create_pv_list(cmd->mem, vg, dev_argc, dev_argv, 1))) {
|
||||
log_error("cachedevice not found in VG %s.", dev_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dm_snprintf(cvname, NAME_LEN, "%s_cache", lv->name) < 0) {
|
||||
log_error("Failed to create cachevol LV name.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
lp.lv_name = cvname;
|
||||
lp.pvh = use_pvh;
|
||||
lp.extents = cache_size_sectors / vg->extent_size;
|
||||
@ -4338,27 +4383,19 @@ static int _lv_create_cachevol(struct cmd_context *cmd,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _lvconvert_cachevol_attach_single(struct cmd_context *cmd,
|
||||
struct logical_volume *lv,
|
||||
struct processing_handle *handle)
|
||||
int lvconvert_cachevol_attach_single(struct cmd_context *cmd,
|
||||
struct logical_volume *lv,
|
||||
struct processing_handle *handle)
|
||||
{
|
||||
struct volume_group *vg = lv->vg;
|
||||
struct logical_volume *lv_fast;
|
||||
const char *fast_name, *dev_name;
|
||||
|
||||
fast_name = arg_str_value(cmd, cachevol_ARG, NULL);
|
||||
dev_name = arg_str_value(cmd, cachedevice_ARG, NULL);
|
||||
|
||||
if (!fast_name && !dev_name)
|
||||
goto_bad;
|
||||
|
||||
if (fast_name && dev_name)
|
||||
goto_bad;
|
||||
const char *fast_name;
|
||||
|
||||
/*
|
||||
* User specifies an existing cachevol to use.
|
||||
* User specifies an existing cachevol to use or a cachedevice
|
||||
* to create a cachevol from.
|
||||
*/
|
||||
if (fast_name) {
|
||||
if ((fast_name = arg_str_value(cmd, cachevol_ARG, NULL))) {
|
||||
if (!validate_lvname_param(cmd, &vg->name, &fast_name))
|
||||
goto_bad;
|
||||
|
||||
@ -4385,13 +4422,8 @@ static int _lvconvert_cachevol_attach_single(struct cmd_context *cmd,
|
||||
|
||||
if (!lockd_lv(cmd, lv_fast, "ex", 0))
|
||||
goto_bad;
|
||||
}
|
||||
|
||||
/*
|
||||
* User specifies a device and lvm creates a cachevol on it.
|
||||
*/
|
||||
if (dev_name) {
|
||||
if (!_lv_create_cachevol(cmd, vg, lv, dev_name, &lv_fast))
|
||||
} else {
|
||||
if (!_lv_create_cachevol(cmd, vg, lv, &lv_fast))
|
||||
goto_bad;
|
||||
}
|
||||
|
||||
@ -5705,7 +5737,7 @@ bad:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _lvconvert_writecache_attach_single(struct cmd_context *cmd,
|
||||
int lvconvert_writecache_attach_single(struct cmd_context *cmd,
|
||||
struct logical_volume *lv,
|
||||
struct processing_handle *handle)
|
||||
{
|
||||
@ -5713,7 +5745,7 @@ static int _lvconvert_writecache_attach_single(struct cmd_context *cmd,
|
||||
struct logical_volume *lv_wcorig;
|
||||
struct logical_volume *lv_fast;
|
||||
struct writecache_settings settings;
|
||||
const char *fast_name, *dev_name;
|
||||
const char *fast_name;
|
||||
uint32_t block_size_sectors = 0;
|
||||
char *lockd_fast_args = NULL;
|
||||
char *lockd_fast_name = NULL;
|
||||
@ -5721,16 +5753,11 @@ static int _lvconvert_writecache_attach_single(struct cmd_context *cmd,
|
||||
char cvol_name[NAME_LEN];
|
||||
int is_active;
|
||||
|
||||
fast_name = arg_str_value(cmd, cachevol_ARG, NULL);
|
||||
dev_name = arg_str_value(cmd, cachedevice_ARG, NULL);
|
||||
|
||||
if (!fast_name && !dev_name)
|
||||
goto_bad;
|
||||
|
||||
/*
|
||||
* User specifies an existing cachevol to use.
|
||||
* User specifies an existing cachevol to use or a cachedevice
|
||||
* to create a cachevol from.
|
||||
*/
|
||||
if (fast_name) {
|
||||
if ((fast_name = arg_str_value(cmd, cachevol_ARG, NULL))) {
|
||||
if (!validate_lvname_param(cmd, &vg->name, &fast_name))
|
||||
goto_bad;
|
||||
|
||||
@ -5765,13 +5792,8 @@ static int _lvconvert_writecache_attach_single(struct cmd_context *cmd,
|
||||
log_error("Conversion aborted.");
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* User specifies a device and lvm creates a cachevol on it.
|
||||
*/
|
||||
if (dev_name) {
|
||||
if (!_lv_create_cachevol(cmd, vg, lv, dev_name, &lv_fast))
|
||||
} else {
|
||||
if (!_lv_create_cachevol(cmd, vg, lv, &lv_fast))
|
||||
goto_bad;
|
||||
}
|
||||
|
||||
@ -5808,7 +5830,7 @@ static int _lvconvert_writecache_attach_single(struct cmd_context *cmd,
|
||||
/* Ensure the LV is not active elsewhere. */
|
||||
if (!lockd_lv(cmd, lv, "ex", 0))
|
||||
goto_bad;
|
||||
if (!dev_name && !lockd_lv(cmd, lv_fast, "ex", 0))
|
||||
if (fast_name && !lockd_lv(cmd, lv_fast, "ex", 0))
|
||||
goto_bad;
|
||||
|
||||
if (!archive(vg))
|
||||
@ -5899,7 +5921,7 @@ int lvconvert_to_writecache_cmd(struct cmd_context *cmd, int argc, char **argv)
|
||||
cmd->cname->flags &= ~GET_VGNAME_FROM_OPTIONS;
|
||||
|
||||
ret = process_each_lv(cmd, cmd->position_argc, cmd->position_argv, NULL, NULL, READ_FOR_UPDATE, handle, NULL,
|
||||
&_lvconvert_writecache_attach_single);
|
||||
&lvconvert_writecache_attach_single);
|
||||
|
||||
destroy_processing_handle(cmd, handle);
|
||||
|
||||
@ -5922,7 +5944,7 @@ int lvconvert_to_cache_with_cachevol_cmd(struct cmd_context *cmd, int argc, char
|
||||
cmd->cname->flags &= ~GET_VGNAME_FROM_OPTIONS;
|
||||
|
||||
ret = process_each_lv(cmd, cmd->position_argc, cmd->position_argv, NULL, NULL, READ_FOR_UPDATE, handle, NULL,
|
||||
&_lvconvert_cachevol_attach_single);
|
||||
&lvconvert_cachevol_attach_single);
|
||||
|
||||
destroy_processing_handle(cmd, handle);
|
||||
|
||||
|
153
tools/lvcreate.c
153
tools/lvcreate.c
@ -766,7 +766,9 @@ static int _lvcreate_params(struct cmd_context *cmd,
|
||||
*
|
||||
* Ordering of following type tests is IMPORTANT
|
||||
*/
|
||||
if ((segtype_str = arg_str_value(cmd, type_ARG, NULL))) {
|
||||
if (lp->ignore_type) {
|
||||
segtype_str = SEG_TYPE_NAME_STRIPED;
|
||||
} else if ((segtype_str = arg_str_value(cmd, type_ARG, NULL))) {
|
||||
lp->type = 1;
|
||||
if (!strcmp(segtype_str, "linear")) {
|
||||
segtype_str = "striped";
|
||||
@ -1799,3 +1801,152 @@ int lvcreate(struct cmd_context *cmd, int argc, char **argv)
|
||||
destroy_processing_handle(cmd, handle);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _lvcreate_and_attach_writecache_single(struct cmd_context *cmd,
|
||||
const char *vg_name, struct volume_group *vg, struct processing_handle *handle)
|
||||
{
|
||||
struct processing_params *pp = (struct processing_params *) handle->custom_handle;
|
||||
struct lvcreate_params *lp = pp->lp;
|
||||
struct logical_volume *lv;
|
||||
int ret;
|
||||
|
||||
ret = _lvcreate_single(cmd, vg_name, vg, handle);
|
||||
|
||||
if (ret == ECMD_FAILED)
|
||||
return ret;
|
||||
|
||||
if (!(lv = find_lv(vg, lp->lv_name))) {
|
||||
log_error("Failed to find LV %s to add writecache.", lp->lv_name);
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
ret = lvconvert_writecache_attach_single(cmd, lv, handle);
|
||||
|
||||
if (ret == ECMD_FAILED) {
|
||||
log_error("Removing new LV after failing to add writecache.");
|
||||
if (!deactivate_lv(cmd, lv))
|
||||
log_error("Failed to deactivate new LV %s.", display_lvname(lv));
|
||||
if (!lv_remove_with_dependencies(cmd, lv, 1, 0))
|
||||
log_error("Failed to remove new LV %s.", display_lvname(lv));
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
return ECMD_PROCESSED;
|
||||
}
|
||||
|
||||
int lvcreate_and_attach_writecache_cmd(struct cmd_context *cmd, int argc, char **argv)
|
||||
{
|
||||
struct processing_handle *handle = NULL;
|
||||
struct processing_params pp;
|
||||
struct lvcreate_params lp = {
|
||||
.major = -1,
|
||||
.minor = -1,
|
||||
};
|
||||
struct lvcreate_cmdline_params lcp = { 0 };
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Tell lvcreate to ignore --type since we are using lvcreate
|
||||
* to create a linear LV and using lvconvert to add cache.
|
||||
* (Would be better if lvcreate code was split up so we could
|
||||
* call a specific function that just created a linear/striped LV.)
|
||||
*/
|
||||
lp.ignore_type = 1;
|
||||
|
||||
if (!_lvcreate_params(cmd, argc, argv, &lp, &lcp)) {
|
||||
stack;
|
||||
return EINVALID_CMD_LINE;
|
||||
}
|
||||
|
||||
pp.lp = &lp;
|
||||
pp.lcp = &lcp;
|
||||
|
||||
if (!(handle = init_processing_handle(cmd, NULL))) {
|
||||
log_error("Failed to initialize processing handle.");
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
handle->custom_handle = &pp;
|
||||
|
||||
ret = process_each_vg(cmd, 0, NULL, lp.vg_name, NULL, READ_FOR_UPDATE, 0, handle,
|
||||
&_lvcreate_and_attach_writecache_single);
|
||||
|
||||
_destroy_lvcreate_params(&lp);
|
||||
destroy_processing_handle(cmd, handle);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _lvcreate_and_attach_cache_single(struct cmd_context *cmd,
|
||||
const char *vg_name, struct volume_group *vg, struct processing_handle *handle)
|
||||
{
|
||||
struct processing_params *pp = (struct processing_params *) handle->custom_handle;
|
||||
struct lvcreate_params *lp = pp->lp;
|
||||
struct logical_volume *lv;
|
||||
int ret;
|
||||
|
||||
ret = _lvcreate_single(cmd, vg_name, vg, handle);
|
||||
|
||||
if (ret == ECMD_FAILED)
|
||||
return ret;
|
||||
|
||||
if (!(lv = find_lv(vg, lp->lv_name))) {
|
||||
log_error("Failed to find LV %s to add cache.", lp->lv_name);
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
ret = lvconvert_cachevol_attach_single(cmd, lv, handle);
|
||||
|
||||
if (ret == ECMD_FAILED) {
|
||||
log_error("Removing new LV after failing to add cache.");
|
||||
if (!deactivate_lv(cmd, lv))
|
||||
log_error("Failed to deactivate new LV %s.", display_lvname(lv));
|
||||
if (!lv_remove_with_dependencies(cmd, lv, 1, 0))
|
||||
log_error("Failed to remove new LV %s.", display_lvname(lv));
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
return ECMD_PROCESSED;
|
||||
}
|
||||
|
||||
int lvcreate_and_attach_cache_cmd(struct cmd_context *cmd, int argc, char **argv)
|
||||
{
|
||||
struct processing_handle *handle = NULL;
|
||||
struct processing_params pp;
|
||||
struct lvcreate_params lp = {
|
||||
.major = -1,
|
||||
.minor = -1,
|
||||
};
|
||||
struct lvcreate_cmdline_params lcp = { 0 };
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Tell lvcreate to ignore --type since we are using lvcreate
|
||||
* to create a linear LV and using lvconvert to add cache.
|
||||
* (Would be better if lvcreate code was split up so we could
|
||||
* call a specific function that just created a linear/striped LV.)
|
||||
*/
|
||||
lp.ignore_type = 1;
|
||||
|
||||
if (!_lvcreate_params(cmd, argc, argv, &lp, &lcp)) {
|
||||
stack;
|
||||
return EINVALID_CMD_LINE;
|
||||
}
|
||||
|
||||
pp.lp = &lp;
|
||||
pp.lcp = &lcp;
|
||||
|
||||
if (!(handle = init_processing_handle(cmd, NULL))) {
|
||||
log_error("Failed to initialize processing handle.");
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
handle->custom_handle = &pp;
|
||||
|
||||
ret = process_each_vg(cmd, 0, NULL, lp.vg_name, NULL, READ_FOR_UPDATE, 0, handle,
|
||||
&_lvcreate_and_attach_cache_single);
|
||||
|
||||
_destroy_lvcreate_params(&lp);
|
||||
destroy_processing_handle(cmd, handle);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -154,6 +154,12 @@ static const struct command_function _command_functions[CMD_COUNT] = {
|
||||
/* lvconvert for integrity */
|
||||
{ lvconvert_integrity_CMD, lvconvert_integrity_cmd },
|
||||
|
||||
/* lvcreate */
|
||||
{ lvcreate_and_attach_cachevol_for_cache_CMD, lvcreate_and_attach_cache_cmd },
|
||||
{ lvcreate_and_attach_cachedevice_for_cache_CMD, lvcreate_and_attach_cache_cmd },
|
||||
{ lvcreate_and_attach_cachevol_for_writecache_CMD, lvcreate_and_attach_writecache_cmd },
|
||||
{ lvcreate_and_attach_cachedevice_for_writecache_CMD, lvcreate_and_attach_writecache_cmd },
|
||||
|
||||
{ pvscan_display_CMD, pvscan_display_cmd },
|
||||
{ pvscan_cache_CMD, pvscan_cache_cmd },
|
||||
};
|
||||
|
@ -278,7 +278,18 @@ int lvconvert_to_vdopool_param_cmd(struct cmd_context *cmd, int argc, char **arg
|
||||
|
||||
int lvconvert_integrity_cmd(struct cmd_context *cmd, int argc, char **argv);
|
||||
|
||||
int lvcreate_and_attach_writecache_cmd(struct cmd_context *cmd, int argc, char **argv);
|
||||
int lvcreate_and_attach_cache_cmd(struct cmd_context *cmd, int argc, char **argv);
|
||||
|
||||
int pvscan_display_cmd(struct cmd_context *cmd, int argc, char **argv);
|
||||
int pvscan_cache_cmd(struct cmd_context *cmd, int argc, char **argv);
|
||||
|
||||
|
||||
int lvconvert_writecache_attach_single(struct cmd_context *cmd,
|
||||
struct logical_volume *lv,
|
||||
struct processing_handle *handle);
|
||||
int lvconvert_cachevol_attach_single(struct cmd_context *cmd,
|
||||
struct logical_volume *lv,
|
||||
struct processing_handle *handle);
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user