1
0
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:
David Teigland 2020-04-10 13:17:37 -05:00
parent 21b37964eb
commit 2aed2a41f7
8 changed files with 340 additions and 126 deletions

View File

@ -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 */

View File

@ -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,

View File

@ -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,

View File

@ -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';

View File

@ -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);

View File

@ -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;
}

View File

@ -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 },
};

View File

@ -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