diff options
author | David Teigland <teigland@redhat.com> | 2020-04-10 13:17:37 -0500 |
---|---|---|
committer | David Teigland <teigland@redhat.com> | 2020-06-16 13:46:51 -0500 |
commit | 2aed2a41f7602e9168613a0c37d8dd557e7dba9b (patch) | |
tree | 24c6f0ce4eb13a03073c6bf55dc5ef2dafaef519 /tools/lvcreate.c | |
parent | 21b37964eb88d404998e37acae5530ec102a2116 (diff) | |
download | lvm2-2aed2a41f7602e9168613a0c37d8dd557e7dba9b.tar.gz |
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
Diffstat (limited to 'tools/lvcreate.c')
-rw-r--r-- | tools/lvcreate.c | 153 |
1 files changed, 152 insertions, 1 deletions
diff --git a/tools/lvcreate.c b/tools/lvcreate.c index 5c978b3cc..3357a08c5 100644 --- a/tools/lvcreate.c +++ b/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; +} + |