]>
Commit | Line | Data |
---|---|---|
b1713d28 JT |
1 | /* |
2 | * Copyright (C) 2001 Sistina Software (UK) Limited. | |
3 | * | |
1b9fcf48 | 4 | * This file is released under the LGPL. |
b1713d28 JT |
5 | */ |
6 | ||
a381c45a | 7 | #include "metadata.h" |
b1713d28 | 8 | #include "activate.h" |
78125be9 | 9 | #include "display.h" |
f047219b | 10 | #include "log.h" |
f7a14956 | 11 | #include "fs.h" |
41b2fd5f | 12 | #include "lvm-string.h" |
413cc918 AK |
13 | #include "pool.h" |
14 | #include "toolcontext.h" | |
de6c9183 | 15 | #include "dev_manager.h" |
12137231 | 16 | |
15c325f0 AK |
17 | /* FIXME Temporary */ |
18 | #include "vgcache.h" | |
19 | ||
12137231 | 20 | #include <limits.h> |
fdc7af23 | 21 | #include <linux/kdev_t.h> |
5986ec94 | 22 | #include <fcntl.h> |
12137231 | 23 | |
6d52fb46 | 24 | #define _skip(fmt, args...) log_very_verbose("Skipping: " fmt , ## args) |
b1713d28 | 25 | |
fae0c576 AK |
26 | int library_version(char *version, size_t size) |
27 | { | |
28 | if (!dm_get_library_version(version, size)) | |
29 | return 0; | |
30 | return 1; | |
31 | } | |
32 | ||
fae0c576 AK |
33 | int driver_version(char *version, size_t size) |
34 | { | |
35 | int r = 0; | |
36 | struct dm_task *dmt; | |
37 | ||
38 | log_very_verbose("Getting driver version"); | |
39 | if (!(dmt = dm_task_create(DM_DEVICE_VERSION))) { | |
40 | stack; | |
41 | return 0; | |
42 | } | |
43 | ||
44 | if (!dm_task_run(dmt)) | |
45 | log_error("Failed to get driver version"); | |
46 | ||
47 | if (!dm_task_get_driver_version(dmt, version, size)) | |
48 | goto out; | |
49 | ||
50 | r = 1; | |
51 | ||
de6c9183 | 52 | out: |
fae0c576 AK |
53 | dm_task_destroy(dmt); |
54 | ||
55 | return r; | |
56 | } | |
57 | ||
de6c9183 JT |
58 | /* |
59 | * Returns 1 if info structure populated, else 0 on failure. | |
60 | */ | |
61 | int lv_info(struct logical_volume *lv, struct dm_info *info) | |
37ed70b9 | 62 | { |
de6c9183 JT |
63 | int r; |
64 | struct dev_manager *dm; | |
4a624ca0 | 65 | |
de6c9183 | 66 | if (!(dm = dev_manager_create(lv->vg->name))) { |
12137231 | 67 | stack; |
de6c9183 | 68 | return 0; |
12137231 | 69 | } |
4a624ca0 | 70 | |
de6c9183 JT |
71 | if (!(r = dev_manager_info(dm, lv, info))) |
72 | stack; | |
4a624ca0 | 73 | |
de6c9183 JT |
74 | dev_manager_destroy(dm); |
75 | return r; | |
76 | } | |
a62ee8ad | 77 | |
8c013da4 | 78 | /* FIXME Change these into query macros with lv_get_info() to fill struct? */ |
94b8220f | 79 | int lv_active(struct logical_volume *lv) |
2ba80b43 | 80 | { |
de6c9183 | 81 | struct dm_info info; |
2ba80b43 | 82 | |
de6c9183 | 83 | if (!lv_info(lv, &info)) { |
2ba80b43 | 84 | stack; |
de6c9183 | 85 | return -1; |
2ba80b43 JT |
86 | } |
87 | ||
de6c9183 | 88 | return info.exists; |
2ba80b43 JT |
89 | } |
90 | ||
de6c9183 | 91 | int lv_suspended(struct logical_volume *lv) |
6d52fb46 | 92 | { |
de6c9183 | 93 | struct dm_info info; |
6c4ee296 | 94 | |
de6c9183 | 95 | if (!lv_info(lv, &info)) { |
80f9662b | 96 | stack; |
de6c9183 | 97 | return -1; |
fdc7af23 JT |
98 | } |
99 | ||
de6c9183 | 100 | return info.suspended; |
fdc7af23 JT |
101 | } |
102 | ||
de6c9183 | 103 | int lv_open_count(struct logical_volume *lv) |
5986ec94 | 104 | { |
de6c9183 | 105 | struct dm_info info; |
5986ec94 | 106 | |
de6c9183 | 107 | if (!lv_info(lv, &info)) { |
5986ec94 | 108 | stack; |
de6c9183 | 109 | return -1; |
5986ec94 JT |
110 | } |
111 | ||
de6c9183 | 112 | return info.open_count; |
5986ec94 JT |
113 | } |
114 | ||
de6c9183 | 115 | int lv_activate(struct logical_volume *lv) |
fdc7af23 | 116 | { |
de6c9183 JT |
117 | int r; |
118 | struct dev_manager *dm; | |
fdc7af23 | 119 | |
de6c9183 | 120 | if (!(dm = dev_manager_create(lv->vg->name))) { |
fdc7af23 JT |
121 | stack; |
122 | return 0; | |
123 | } | |
124 | ||
de6c9183 | 125 | if (!(r = dev_manager_activate(dm, lv))) |
fdc7af23 JT |
126 | stack; |
127 | ||
de6c9183 | 128 | dev_manager_destroy(dm); |
fdc7af23 | 129 | return r; |
80f9662b JT |
130 | } |
131 | ||
8c013da4 | 132 | /* FIXME Need to detect and handle an lv rename */ |
6d52fb46 | 133 | int lv_reactivate(struct logical_volume *lv) |
b1713d28 | 134 | { |
6d52fb46 | 135 | int r; |
de6c9183 | 136 | struct dev_manager *dm; |
b1713d28 | 137 | |
de6c9183 | 138 | if (!(dm = dev_manager_create(lv->vg->name))) { |
6d52fb46 JT |
139 | stack; |
140 | return 0; | |
ae2bb665 JT |
141 | } |
142 | ||
0fe3a2c5 | 143 | if (!(r = dev_manager_activate(dm, lv))) |
6d52fb46 | 144 | stack; |
ae2bb665 | 145 | |
de6c9183 | 146 | dev_manager_destroy(dm); |
ae2bb665 | 147 | return r; |
b1713d28 | 148 | } |
a381c45a | 149 | |
6d52fb46 | 150 | int lv_deactivate(struct logical_volume *lv) |
0a5e4a14 | 151 | { |
de6c9183 JT |
152 | int r; |
153 | struct dev_manager *dm; | |
37ed70b9 | 154 | |
de6c9183 | 155 | if (!(dm = dev_manager_create(lv->vg->name))) { |
6d52fb46 JT |
156 | stack; |
157 | return 0; | |
158 | } | |
37ed70b9 | 159 | |
de6c9183 | 160 | if (!(r = dev_manager_deactivate(dm, lv))) |
37ed70b9 | 161 | stack; |
37ed70b9 | 162 | |
de6c9183 JT |
163 | dev_manager_destroy(dm); |
164 | return r; | |
37ed70b9 JT |
165 | } |
166 | ||
4a624ca0 AK |
167 | int lv_suspend(struct logical_volume *lv) |
168 | { | |
de6c9183 | 169 | #if 0 |
6d52fb46 | 170 | char buffer[128]; |
4a624ca0 | 171 | |
6d52fb46 JT |
172 | log_very_verbose("Suspending %s", lv->name); |
173 | if (test_mode()) { | |
174 | _skip("Suspending '%s'.", lv->name); | |
c2d72fd4 | 175 | return 0; |
6d52fb46 | 176 | } |
c2d72fd4 | 177 | |
6d52fb46 JT |
178 | if (!build_dm_name(buffer, sizeof(buffer), "", |
179 | lv->vg->name, lv->name)) { | |
37ed70b9 JT |
180 | stack; |
181 | return 0; | |
182 | } | |
0a5e4a14 | 183 | |
6d52fb46 | 184 | if (!device_suspend(buffer)) { |
37ed70b9 JT |
185 | stack; |
186 | return 0; | |
187 | } | |
0a5e4a14 | 188 | |
6d52fb46 | 189 | fs_del_lv(lv); |
0a5e4a14 | 190 | |
6d52fb46 | 191 | return 1; |
de6c9183 JT |
192 | #else |
193 | log_err("lv_suspend not implemented."); | |
194 | return 1; | |
195 | #endif | |
6d52fb46 | 196 | } |
4a624ca0 | 197 | |
6d52fb46 | 198 | int lv_rename(const char *old_name, struct logical_volume *lv) |
ae2bb665 | 199 | { |
de6c9183 | 200 | #if 0 |
6d52fb46 JT |
201 | int r = 0; |
202 | char new_name[PATH_MAX]; | |
ab269099 JT |
203 | struct dm_task *dmt; |
204 | ||
6d52fb46 JT |
205 | if (test_mode()) { |
206 | _skip("Rename '%s' to '%s'.", old_name, lv->name); | |
c2d72fd4 | 207 | return 0; |
6d52fb46 | 208 | } |
c2d72fd4 | 209 | |
6d52fb46 | 210 | if (!(dmt = setup_dm_task(old_name, DM_DEVICE_RENAME))) { |
ae2bb665 JT |
211 | stack; |
212 | return 0; | |
213 | } | |
214 | ||
6d52fb46 JT |
215 | if (!build_dm_name(new_name, sizeof(new_name), "", |
216 | lv->vg->name, lv->name)) { | |
ae2bb665 | 217 | stack; |
6d52fb46 JT |
218 | return 0; |
219 | } | |
ae2bb665 | 220 | |
6d52fb46 JT |
221 | if (!dm_task_set_newname(dmt, new_name)) { |
222 | stack; | |
223 | r = 0; | |
224 | goto end; | |
225 | } | |
f7a14956 | 226 | |
6d52fb46 JT |
227 | if (!dm_task_run(dmt)) { |
228 | stack; | |
229 | r = 0; | |
230 | goto end; | |
231 | } | |
232 | ||
233 | fs_rename_lv(old_name, lv); | |
f7a14956 | 234 | |
6d52fb46 JT |
235 | end: |
236 | dm_task_destroy(dmt); | |
ae2bb665 | 237 | return r; |
de6c9183 JT |
238 | #else |
239 | log_err("lv_rename not implemented yet."); | |
240 | return 1; | |
241 | #endif | |
ae2bb665 JT |
242 | } |
243 | ||
8c013da4 AK |
244 | /* |
245 | * These two functions return the number of LVs in the state, | |
246 | * or -1 on error. | |
247 | */ | |
f047219b AK |
248 | int lvs_in_vg_activated(struct volume_group *vg) |
249 | { | |
37ed70b9 JT |
250 | struct list *lvh; |
251 | struct logical_volume *lv; | |
94b8220f | 252 | int count = 0; |
37ed70b9 JT |
253 | |
254 | list_iterate(lvh, &vg->lvs) { | |
f868d635 | 255 | lv = list_item(lvh, struct lv_list)->lv; |
94b8220f | 256 | count += (lv_active(lv) == 1); |
37ed70b9 JT |
257 | } |
258 | ||
259 | return count; | |
f047219b | 260 | } |
2ba80b43 JT |
261 | |
262 | int lvs_in_vg_opened(struct volume_group *vg) | |
263 | { | |
264 | struct list *lvh; | |
265 | struct logical_volume *lv; | |
94b8220f | 266 | int count = 0; |
2ba80b43 JT |
267 | |
268 | list_iterate(lvh, &vg->lvs) { | |
f868d635 | 269 | lv = list_item(lvh, struct lv_list)->lv; |
94b8220f | 270 | count += (lv_open_count(lv) == 1); |
2ba80b43 JT |
271 | } |
272 | ||
273 | return count; | |
274 | } | |
413cc918 | 275 | |
de6c9183 | 276 | static struct logical_volume *_lv_from_lvid(struct cmd_context *cmd, |
15c325f0 | 277 | const char *lvid_s) |
413cc918 AK |
278 | { |
279 | struct lv_list *lvl; | |
280 | struct volume_group *vg; | |
15c325f0 | 281 | union lvid *lvid; |
413cc918 | 282 | char *vgname; |
413cc918 | 283 | |
15c325f0 AK |
284 | lvid = (union lvid *) lvid_s; |
285 | ||
286 | /* FIXME Change vgread to accept vgid directly - can't rely on cache */ | |
287 | if (!(vgname = vgname_from_vgid(cmd, &lvid->id[0]))) { | |
288 | log_error("Volume group for uuid not found: %s", lvid_s); | |
413cc918 AK |
289 | return NULL; |
290 | } | |
291 | ||
413cc918 AK |
292 | log_verbose("Finding volume group \"%s\"", vgname); |
293 | if (!(vg = cmd->fid->ops->vg_read(cmd->fid, vgname))) { | |
294 | log_error("Volume group \"%s\" doesn't exist", vgname); | |
295 | return NULL; | |
296 | } | |
297 | ||
298 | if (vg->status & EXPORTED_VG) { | |
299 | log_error("Volume group \"%s\" is exported", vgname); | |
300 | return NULL; | |
301 | } | |
302 | ||
15c325f0 AK |
303 | if (!(lvl = find_lv_in_vg_by_lvid(vg, lvid))) { |
304 | log_very_verbose("Can't find logical volume id %s", lvid_s); | |
413cc918 AK |
305 | return NULL; |
306 | } | |
307 | ||
308 | return lvl->lv; | |
309 | } | |
310 | ||
8c013da4 AK |
311 | /* These functions should become the new interface and the _if_active |
312 | * bits then disappear */ | |
15c325f0 | 313 | int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s) |
413cc918 AK |
314 | { |
315 | struct logical_volume *lv; | |
316 | ||
15c325f0 | 317 | if (!(lv = _lv_from_lvid(cmd, lvid_s))) |
413cc918 AK |
318 | return 0; |
319 | ||
f4cbeaf0 | 320 | if (lv_active(lv) > 0) |
413cc918 | 321 | lv_suspend(lv); |
8c013da4 | 322 | |
413cc918 AK |
323 | return 1; |
324 | } | |
325 | ||
8c013da4 | 326 | |
15c325f0 | 327 | int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s) |
413cc918 AK |
328 | { |
329 | struct logical_volume *lv; | |
330 | ||
15c325f0 | 331 | if (!(lv = _lv_from_lvid(cmd, lvid_s))) |
413cc918 AK |
332 | return 0; |
333 | ||
f4cbeaf0 | 334 | if ((lv_active(lv) > 0) && lv_suspended(lv)) |
413cc918 AK |
335 | lv_reactivate(lv); |
336 | ||
337 | return 1; | |
338 | } | |
339 | ||
15c325f0 | 340 | int lv_deactivate_if_active(struct cmd_context *cmd, const char *lvid_s) |
f4cbeaf0 AK |
341 | { |
342 | struct logical_volume *lv; | |
343 | ||
15c325f0 | 344 | if (!(lv = _lv_from_lvid(cmd, lvid_s))) |
f4cbeaf0 AK |
345 | return 0; |
346 | ||
347 | if (lv_active(lv) > 0) | |
348 | lv_deactivate(lv); | |
349 | ||
350 | return 1; | |
351 | } | |
352 | ||
15c325f0 | 353 | int lv_activate_if_inactive(struct cmd_context *cmd, const char *lvid_s) |
f4cbeaf0 AK |
354 | { |
355 | struct logical_volume *lv; | |
8c013da4 | 356 | int active; |
f4cbeaf0 | 357 | |
15c325f0 | 358 | if (!(lv = _lv_from_lvid(cmd, lvid_s))) |
f4cbeaf0 AK |
359 | return 0; |
360 | ||
8c013da4 AK |
361 | active = lv_active(lv); |
362 | ||
363 | if ((active > 0) && lv_suspended(lv)) { | |
364 | lv_reactivate(lv); | |
365 | } else if (!active) | |
f4cbeaf0 AK |
366 | lv_activate(lv); |
367 | ||
368 | return 1; | |
369 | } | |
370 |