Tizen 2.1 base
[external/device-mapper.git] / tools / vgrename.c
1 /*
2  * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
3  * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
4  *
5  * This file is part of LVM2.
6  *
7  * This copyrighted material is made available to anyone wishing to use,
8  * modify, copy, or redistribute it subject to the terms and conditions
9  * of the GNU Lesser General Public License v.2.1.
10  *
11  * You should have received a copy of the GNU Lesser General Public License
12  * along with this program; if not, write to the Free Software Foundation,
13  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
14  */
15
16 #include "tools.h"
17
18 static struct volume_group *_get_old_vg_for_rename(struct cmd_context *cmd,
19                                                    const char *vg_name_old,
20                                                    const char *vgid)
21 {
22         struct volume_group *vg;
23
24         /* FIXME we used to print an error about EXPORTED, but proceeded
25            nevertheless. */
26         vg = vg_read_for_update(cmd, vg_name_old, vgid, READ_ALLOW_EXPORTED);
27         if (vg_read_error(vg)) {
28                 free_vg(vg);
29                 return_NULL;
30         }
31
32         return vg;
33 }
34
35 static int _lock_new_vg_for_rename(struct cmd_context *cmd,
36                                    const char *vg_name_new)
37 {
38         int rc;
39
40         log_verbose("Checking for new volume group \"%s\"", vg_name_new);
41
42         rc = vg_lock_newname(cmd, vg_name_new);
43
44         if (rc == FAILED_LOCKING) {
45                 log_error("Can't get lock for %s", vg_name_new);
46                 return 0;
47         }
48
49         if (rc == FAILED_EXIST) {
50                 log_error("New volume group \"%s\" already exists",
51                           vg_name_new);
52                 return 0;
53         }
54         return 1;
55 }
56
57 static int vg_rename_path(struct cmd_context *cmd, const char *old_vg_path,
58                           const char *new_vg_path)
59 {
60         char *dev_dir;
61         struct id id;
62         int match = 0;
63         int found_id = 0;
64         struct dm_list *vgids;
65         struct str_list *sl;
66         char *vg_name_new;
67         const char *vgid = NULL, *vg_name, *vg_name_old;
68         char old_path[NAME_LEN], new_path[NAME_LEN];
69         struct volume_group *vg = NULL;
70         int lock_vg_old_first = 1;
71
72         vg_name_old = skip_dev_dir(cmd, old_vg_path, NULL);
73         vg_name_new = skip_dev_dir(cmd, new_vg_path, NULL);
74
75         dev_dir = cmd->dev_dir;
76
77         if (!validate_vg_rename_params(cmd, vg_name_old, vg_name_new))
78                 return_0;
79
80         log_verbose("Checking for existing volume group \"%s\"", vg_name_old);
81
82         /* Avoid duplicates */
83         if (!(vgids = get_vgids(cmd, 0)) || dm_list_empty(vgids)) {
84                 log_error("No complete volume groups found");
85                 return 0;
86         }
87
88         dm_list_iterate_items(sl, vgids) {
89                 vgid = sl->str;
90                 if (!vgid || !(vg_name = vgname_from_vgid(NULL, vgid)))
91                         continue;
92                 if (!strcmp(vg_name, vg_name_old)) {
93                         if (match) {
94                                 log_error("Found more than one VG called %s. "
95                                           "Please supply VG uuid.", vg_name_old);
96                                 return 0;
97                         }
98                         match = 1;
99                 }
100         }
101
102         log_suppress(2);
103         found_id = id_read_format(&id, vg_name_old);
104         log_suppress(0);
105         if (found_id && (vg_name = vgname_from_vgid(cmd->mem, (char *)id.uuid))) {
106                 vg_name_old = vg_name;
107                 vgid = (char *)id.uuid;
108         } else
109                 vgid = NULL;
110
111         if (strcmp(vg_name_new, vg_name_old) < 0)
112                 lock_vg_old_first = 0;
113
114         if (lock_vg_old_first) {
115                 vg = _get_old_vg_for_rename(cmd, vg_name_old, vgid);
116                 if (!vg)
117                         return_0;
118
119                 if (!_lock_new_vg_for_rename(cmd, vg_name_new)) {
120                         unlock_and_free_vg(cmd, vg, vg_name_old);
121                         return_0;
122                 }
123         } else {
124                 if (!_lock_new_vg_for_rename(cmd, vg_name_new))
125                         return_0;
126
127                 vg = _get_old_vg_for_rename(cmd, vg_name_old, vgid);
128                 if (!vg) {
129                         unlock_vg(cmd, vg_name_new);
130                         return_0;
131                 }
132         }
133
134         if (!archive(vg))
135                 goto error;
136
137         /* Remove references based on old name */
138         drop_cached_metadata(vg);
139
140         /* Change the volume group name */
141         vg_rename(cmd, vg, vg_name_new);
142
143         /* store it on disks */
144         log_verbose("Writing out updated volume group");
145         if (!vg_write(vg) || !vg_commit(vg)) {
146                 goto error;
147         }
148
149         sprintf(old_path, "%s%s", dev_dir, vg_name_old);
150         sprintf(new_path, "%s%s", dev_dir, vg_name_new);
151
152         if (activation() && dir_exists(old_path)) {
153                 log_verbose("Renaming \"%s\" to \"%s\"", old_path, new_path);
154
155                 if (test_mode())
156                         log_verbose("Test mode: Skipping rename.");
157
158                 else if (lvs_in_vg_activated(vg)) {
159                         if (!vg_refresh_visible(cmd, vg)) {
160                                 log_error("Renaming \"%s\" to \"%s\" failed", 
161                                         old_path, new_path);
162                                 goto error;
163                         }
164                 }
165         }
166
167         backup(vg);
168         backup_remove(cmd, vg_name_old);
169
170         unlock_vg(cmd, vg_name_new);
171         unlock_and_free_vg(cmd, vg, vg_name_old);
172
173         log_print("Volume group \"%s\" successfully renamed to \"%s\"",
174                   vg_name_old, vg_name_new);
175
176         /* FIXME lvmcache corruption - vginfo duplicated instead of renamed */
177         persistent_filter_wipe(cmd->filter);
178         lvmcache_destroy(cmd, 1);
179
180         return 1;
181
182       error:
183         if (lock_vg_old_first) {
184                 unlock_vg(cmd, vg_name_new);
185                 unlock_and_free_vg(cmd, vg, vg_name_old);
186         } else {
187                 unlock_and_free_vg(cmd, vg, vg_name_old);
188                 unlock_vg(cmd, vg_name_new);
189         }
190         return 0;
191 }
192
193 int vgrename(struct cmd_context *cmd, int argc, char **argv)
194 {
195         if (argc != 2) {
196                 log_error("Old and new volume group names need specifying");
197                 return EINVALID_CMD_LINE;
198         }
199
200         if (!vg_rename_path(cmd, argv[0], argv[1])) {
201                 stack;
202                 return ECMD_FAILED;
203         }
204
205         return ECMD_PROCESSED;
206 }
207