summaryrefslogtreecommitdiff
path: root/tools/lvcreate.c
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2020-04-10 13:17:37 -0500
committerDavid Teigland <teigland@redhat.com>2020-06-16 13:46:51 -0500
commit2aed2a41f7602e9168613a0c37d8dd557e7dba9b (patch)
tree24c6f0ce4eb13a03073c6bf55dc5ef2dafaef519 /tools/lvcreate.c
parent21b37964eb88d404998e37acae5530ec102a2116 (diff)
downloadlvm2-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.c153
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;
+}
+