diff options
author | Peter Rajnoha <prajnoha@redhat.com> | 2016-03-04 11:36:24 +0100 |
---|---|---|
committer | Peter Rajnoha <prajnoha@redhat.com> | 2016-03-04 11:36:24 +0100 |
commit | 27245d97e57bb42b83aa240979aa6febf9096264 (patch) | |
tree | e20d892a65844b1597af90a3b05b2cddad681085 | |
parent | b114b4d723129998b1578410b0b054bebfef1817 (diff) | |
download | lvm2-27245d97e57bb42b83aa240979aa6febf9096264.tar.gz |
lvrename: support renaming historical logical volumes
-rw-r--r-- | lib/metadata/lv_manip.c | 37 | ||||
-rw-r--r-- | tools/lvrename.c | 92 |
2 files changed, 95 insertions, 34 deletions
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c index 136d232ff..9b51b6d26 100644 --- a/lib/metadata/lv_manip.c +++ b/lib/metadata/lv_manip.c @@ -4196,6 +4196,7 @@ int lv_rename_update(struct cmd_context *cmd, struct logical_volume *lv, { struct volume_group *vg = lv->vg; struct lv_names lv_names = { .old = lv->name }; + int old_lv_is_historical = lv_is_historical(lv); int historical; /* @@ -4210,7 +4211,7 @@ int lv_rename_update(struct cmd_context *cmd, struct logical_volume *lv, if (lv_name_is_used_in_vg(vg, new_name, &historical)) { log_error("%sLogical Volume \"%s\" already exists in " - "volume group \"%s\"", historical ? "historical " : "", + "volume group \"%s\"", historical ? "Historical " : "", new_name, vg->name); return 0; } @@ -4223,23 +4224,31 @@ int lv_rename_update(struct cmd_context *cmd, struct logical_volume *lv, if (update_mda && !archive(vg)) return_0; - if (!(lv_names.new = dm_pool_strdup(cmd->mem, new_name))) { - log_error("Failed to allocate space for new name."); - return 0; - } + if (old_lv_is_historical) { + /* historical LVs don't have sub LVs */ + lv->this_glv->historical->name = lv->name = new_name; + if (update_mda && + (!vg_write(vg) || !vg_commit(vg))) + return_0; + } else { + if (!(lv_names.new = dm_pool_strdup(cmd->mem, new_name))) { + log_error("Failed to allocate space for new name."); + return 0; + } - /* rename sub LVs */ - if (!for_each_sub_lv_except_pools(lv, _rename_cb, (void *) &lv_names)) - return_0; + /* rename sub LVs */ + if (!for_each_sub_lv_except_pools(lv, _rename_cb, (void *) &lv_names)) + return_0; - /* rename main LV */ - lv->name = lv_names.new; + /* rename main LV */ + lv->name = lv_names.new; - if (lv_is_cow(lv)) - lv = origin_from_cow(lv); + if (lv_is_cow(lv)) + lv = origin_from_cow(lv); - if (update_mda && !lv_update_and_reload((struct logical_volume *)lv_lock_holder(lv))) - return_0; + if (update_mda && !lv_update_and_reload((struct logical_volume *)lv_lock_holder(lv))) + return_0; + } return 1; } diff --git a/tools/lvrename.c b/tools/lvrename.c index e37d8aa0f..56c19fdf3 100644 --- a/tools/lvrename.c +++ b/tools/lvrename.c @@ -16,34 +16,64 @@ #include "tools.h" struct lvrename_params { + int historical; const char *lv_name_old; const char *lv_name_new; }; +/* + * Dummy LV to represent historical LV. + */ +static struct logical_volume _historical_lv = { + .name = "", + .major = -1, + .minor = -1, + .snapshot_segs = DM_LIST_HEAD_INIT(_historical_lv.snapshot_segs), + .segments = DM_LIST_HEAD_INIT(_historical_lv.segments), + .tags = DM_LIST_HEAD_INIT(_historical_lv.tags), + .segs_using_this_lv = DM_LIST_HEAD_INIT(_historical_lv.segs_using_this_lv), + .indirect_glvs = DM_LIST_HEAD_INIT(_historical_lv.indirect_glvs), + .hostname = "", +}; + static int _lvrename_single(struct cmd_context *cmd, const char *vg_name, struct volume_group *vg, struct processing_handle *handle) { struct lvrename_params *lp = (struct lvrename_params *) handle->custom_handle; - struct lv_list *lvl; + struct generic_logical_volume *glv; + struct logical_volume *lv; int ret = ECMD_FAILED; - if (!(lvl = find_lv_in_vg(vg, lp->lv_name_old))) { - log_error("Existing logical volume \"%s\" not found in " - "volume group \"%s\"", lp->lv_name_old, vg_name); - goto bad; - } + if (!lp->historical) { + if (!(lv = find_lv(vg, lp->lv_name_old))) { + log_error("Existing logical volume \"%s\" not found in " + "volume group \"%s\"", lp->lv_name_old, vg_name); + goto bad; + } - if (lv_is_raid_image(lvl->lv) || lv_is_raid_metadata(lvl->lv)) { - log_error("Cannot rename a RAID %s directly", - lv_is_raid_image(lvl->lv) ? "image" : - "metadata area"); - goto bad; - } + if (lv_is_raid_image(lv) || lv_is_raid_metadata(lv)) { + log_error("Cannot rename a RAID %s directly", + lv_is_raid_image(lv) ? "image" : + "metadata area"); + goto bad; + } + + if (lv_is_raid_with_tracking(lv)) { + log_error("Cannot rename %s while it is tracking a split image", + lv->name); + goto bad; + } + } else { + if (!(glv = find_historical_glv(vg, lp->lv_name_old, 0, NULL))) { + log_error("Existing historical logical volume \"%s\" not found in " + "volume group \"%s\"", lp->lv_name_old, vg_name); + goto bad; + } - if (lv_is_raid_with_tracking(lvl->lv)) { - log_error("Cannot rename %s while it is tracking a split image", - lvl->lv->name); - goto bad; + _historical_lv.vg = vg; + _historical_lv.name = lp->lv_name_old; + _historical_lv.this_glv = glv; + lv = &_historical_lv; } /* @@ -55,14 +85,16 @@ static int _lvrename_single(struct cmd_context *cmd, const char *vg_name, * lock request acquires the LV lock (or fails). The transient lock * is automatically released when the command exits. */ - if (!lockd_lv(cmd, lvl->lv, "ex", 0)) + if (!lockd_lv(cmd, lv, "ex", 0)) goto_bad; - if (!lv_rename(cmd, lvl->lv, lp->lv_name_new)) + if (!lv_rename(cmd, lv, lp->lv_name_new)) goto_bad; - log_print_unless_silent("Renamed \"%s\" to \"%s\" in volume group \"%s\"", - lp->lv_name_old, lp->lv_name_new, vg_name); + log_print_unless_silent("Renamed \"%s%s\" to \"%s%s\" in volume group \"%s\"", + lp->historical ? HISTORICAL_LV_PREFIX : "", lp->lv_name_old, + lp->historical ? HISTORICAL_LV_PREFIX : "", lp->lv_name_new, + vg_name); ret = ECMD_PROCESSED; bad: @@ -80,9 +112,12 @@ int lvrename(struct cmd_context *cmd, int argc, char **argv) size_t maxlen; char *lv_name_old, *lv_name_new; const char *vg_name, *vg_name_new, *vg_name_old; + int historical = 0; char *st; int ret; + cmd->include_historical_lvs = 1; + if (argc == 3) { vg_name = skip_dev_dir(cmd, argv[0], NULL); lv_name_old = argv[1]; @@ -123,6 +158,21 @@ int lvrename(struct cmd_context *cmd, int argc, char **argv) if ((st = strrchr(lv_name_new, '/'))) lv_name_new = st + 1; + if (!strncmp(lv_name_old, HISTORICAL_LV_PREFIX, strlen(HISTORICAL_LV_PREFIX))) { + lv_name_old = lv_name_old + strlen(HISTORICAL_LV_PREFIX); + historical = 1; + } + + if (!strncmp(lv_name_new, HISTORICAL_LV_PREFIX, strlen(HISTORICAL_LV_PREFIX))) { + if (historical) + lv_name_new = lv_name_old + strlen(HISTORICAL_LV_PREFIX); + else { + log_error("Old name references live LV while " + "new name is for historical LV."); + return EINVALID_CMD_LINE; + } + } + /* Check sanity of new name */ maxlen = NAME_LEN - strlen(vg_name) - 3; if (strlen(lv_name_new) > maxlen) { @@ -152,6 +202,8 @@ int lvrename(struct cmd_context *cmd, int argc, char **argv) return EINVALID_CMD_LINE; } + lp.historical = historical; + if (!(lp.lv_name_old = dm_pool_strdup(cmd->mem, lv_name_old))) return ECMD_FAILED; |