| /* |
| * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. |
| * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved. |
| * |
| * This file is part of LVM2. |
| * |
| * This copyrighted material is made available to anyone wishing to use, |
| * modify, copy, or redistribute it subject to the terms and conditions |
| * of the GNU Lesser General Public License v.2.1. |
| * |
| * You should have received a copy of the GNU Lesser General Public License |
| * along with this program; if not, write to the Free Software Foundation, |
| * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| */ |
| |
| #include "tools.h" |
| |
| static struct volume_group *_get_old_vg_for_rename(struct cmd_context *cmd, |
| const char *vg_name_old, |
| const char *vgid, |
| uint32_t lockd_state) |
| { |
| struct volume_group *vg; |
| |
| /* FIXME we used to print an error about EXPORTED, but proceeded |
| nevertheless. */ |
| vg = vg_read_for_update(cmd, vg_name_old, vgid, READ_ALLOW_EXPORTED, lockd_state); |
| if (vg_read_error(vg)) { |
| release_vg(vg); |
| return_NULL; |
| } |
| |
| return vg; |
| } |
| |
| static int _lock_new_vg_for_rename(struct cmd_context *cmd, |
| const char *vg_name_new) |
| { |
| int rc; |
| |
| log_verbose("Checking for new volume group \"%s\"", vg_name_new); |
| |
| rc = vg_lock_newname(cmd, vg_name_new); |
| |
| if (rc == FAILED_LOCKING) { |
| log_error("Can't get lock for %s", vg_name_new); |
| return 0; |
| } |
| |
| if (rc == FAILED_EXIST) { |
| log_error("New volume group \"%s\" already exists", |
| vg_name_new); |
| return 0; |
| } |
| return 1; |
| } |
| |
| static int vg_rename_path(struct cmd_context *cmd, const char *old_vg_path, |
| const char *new_vg_path) |
| { |
| char *dev_dir; |
| struct id id; |
| int match = 0; |
| int found_id = 0; |
| struct dm_list *vgids; |
| struct dm_str_list *sl; |
| const char *vg_name_new; |
| const char *vgid = NULL, *vg_name, *vg_name_old; |
| char old_path[NAME_LEN], new_path[NAME_LEN]; |
| struct volume_group *vg = NULL; |
| uint32_t lockd_state = 0; |
| int lock_vg_old_first = 1; |
| |
| vg_name_old = skip_dev_dir(cmd, old_vg_path, NULL); |
| vg_name_new = skip_dev_dir(cmd, new_vg_path, NULL); |
| |
| dev_dir = cmd->dev_dir; |
| |
| if (!validate_vg_rename_params(cmd, vg_name_old, vg_name_new)) |
| return_0; |
| |
| log_verbose("Checking for existing volume group \"%s\"", vg_name_old); |
| |
| /* populate lvmcache */ |
| if (!lvmetad_vg_list_to_lvmcache(cmd)) |
| stack; |
| |
| lvmcache_label_scan(cmd, 2); |
| |
| /* Avoid duplicates */ |
| if (!(vgids = get_vgids(cmd, 0)) || dm_list_empty(vgids)) { |
| log_error("No complete volume groups found"); |
| return 0; |
| } |
| |
| dm_list_iterate_items(sl, vgids) { |
| vgid = sl->str; |
| if (!vgid || !(vg_name = lvmcache_vgname_from_vgid(NULL, vgid))) |
| continue; |
| if (!strcmp(vg_name, vg_name_old)) { |
| if (match) { |
| log_error("Found more than one VG called %s. " |
| "Please supply VG uuid.", vg_name_old); |
| return 0; |
| } |
| match = 1; |
| } |
| } |
| |
| log_suppress(2); |
| found_id = id_read_format(&id, vg_name_old); |
| log_suppress(0); |
| if (found_id && (vg_name = lvmcache_vgname_from_vgid(cmd->mem, (char *)id.uuid))) { |
| vg_name_old = vg_name; |
| vgid = (char *)id.uuid; |
| } else |
| vgid = NULL; |
| |
| if (!lockd_vg(cmd, vg_name_old, "ex", 0, &lockd_state)) |
| return_0; |
| |
| if (strcmp(vg_name_new, vg_name_old) < 0) |
| lock_vg_old_first = 0; |
| |
| if (lock_vg_old_first) { |
| vg = _get_old_vg_for_rename(cmd, vg_name_old, vgid, lockd_state); |
| if (!vg) |
| return_0; |
| |
| if (!_lock_new_vg_for_rename(cmd, vg_name_new)) { |
| unlock_and_release_vg(cmd, vg, vg_name_old); |
| return_0; |
| } |
| } else { |
| if (!_lock_new_vg_for_rename(cmd, vg_name_new)) |
| return_0; |
| |
| vg = _get_old_vg_for_rename(cmd, vg_name_old, vgid, lockd_state); |
| if (!vg) { |
| unlock_vg(cmd, vg_name_new); |
| return_0; |
| } |
| } |
| |
| if (!archive(vg)) |
| goto error; |
| |
| /* Remove references based on old name */ |
| if (!drop_cached_metadata(vg)) |
| stack; |
| |
| if (!lockd_rename_vg_before(cmd, vg)) { |
| stack; |
| goto error; |
| } |
| |
| /* Change the volume group name */ |
| vg_rename(cmd, vg, vg_name_new); |
| |
| /* store it on disks */ |
| log_verbose("Writing out updated volume group"); |
| if (!vg_write(vg) || !vg_commit(vg)) { |
| goto error; |
| } |
| |
| sprintf(old_path, "%s%s", dev_dir, vg_name_old); |
| sprintf(new_path, "%s%s", dev_dir, vg_name_new); |
| |
| if (activation() && dir_exists(old_path)) { |
| log_verbose("Renaming \"%s\" to \"%s\"", old_path, new_path); |
| |
| if (test_mode()) |
| log_verbose("Test mode: Skipping rename."); |
| |
| else if (lvs_in_vg_activated(vg)) { |
| if (!vg_refresh_visible(cmd, vg)) { |
| log_error("Renaming \"%s\" to \"%s\" failed", |
| old_path, new_path); |
| goto error; |
| } |
| } |
| } |
| |
| lockd_rename_vg_final(cmd, vg, 1); |
| |
| if (!backup(vg)) |
| stack; |
| if (!backup_remove(cmd, vg_name_old)) |
| stack; |
| |
| unlock_vg(cmd, vg_name_new); |
| unlock_and_release_vg(cmd, vg, vg_name_old); |
| |
| log_print_unless_silent("Volume group \"%s\" successfully renamed to \"%s\"", |
| vg_name_old, vg_name_new); |
| |
| /* FIXME lvmcache corruption - vginfo duplicated instead of renamed */ |
| if (cmd->filter->wipe) |
| cmd->filter->wipe(cmd->filter); |
| lvmcache_destroy(cmd, 1, 0); |
| |
| return 1; |
| |
| error: |
| lockd_rename_vg_final(cmd, vg, 0); |
| |
| if (lock_vg_old_first) { |
| unlock_vg(cmd, vg_name_new); |
| unlock_and_release_vg(cmd, vg, vg_name_old); |
| } else { |
| unlock_and_release_vg(cmd, vg, vg_name_old); |
| unlock_vg(cmd, vg_name_new); |
| } |
| return 0; |
| } |
| |
| int vgrename(struct cmd_context *cmd, int argc, char **argv) |
| { |
| if (argc != 2) { |
| log_error("Old and new volume group names need specifying"); |
| return EINVALID_CMD_LINE; |
| } |
| |
| /* Needed change the global VG namespace. */ |
| if (!lockd_gl(cmd, "ex", LDGL_UPDATE_NAMES)) |
| return_ECMD_FAILED; |
| |
| if (!vg_rename_path(cmd, argv[0], argv[1])) |
| return_ECMD_FAILED; |
| |
| return ECMD_PROCESSED; |
| } |
| |