]>
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" |
6d52fb46 | 9 | #include "ll-activate.h" |
78125be9 | 10 | #include "display.h" |
f047219b | 11 | #include "log.h" |
f7a14956 | 12 | #include "fs.h" |
41b2fd5f | 13 | #include "lvm-string.h" |
12137231 JT |
14 | #include "names.h" |
15 | ||
16 | #include <limits.h> | |
fdc7af23 | 17 | #include <linux/kdev_t.h> |
12137231 | 18 | |
6d52fb46 | 19 | #define _skip(fmt, args...) log_very_verbose("Skipping: " fmt , ## args) |
b1713d28 | 20 | |
fae0c576 AK |
21 | int library_version(char *version, size_t size) |
22 | { | |
23 | if (!dm_get_library_version(version, size)) | |
24 | return 0; | |
25 | return 1; | |
26 | } | |
27 | ||
fae0c576 AK |
28 | int driver_version(char *version, size_t size) |
29 | { | |
30 | int r = 0; | |
31 | struct dm_task *dmt; | |
32 | ||
33 | log_very_verbose("Getting driver version"); | |
34 | if (!(dmt = dm_task_create(DM_DEVICE_VERSION))) { | |
35 | stack; | |
36 | return 0; | |
37 | } | |
38 | ||
39 | if (!dm_task_run(dmt)) | |
40 | log_error("Failed to get driver version"); | |
41 | ||
42 | if (!dm_task_get_driver_version(dmt, version, size)) | |
43 | goto out; | |
44 | ||
45 | r = 1; | |
46 | ||
47 | out: | |
48 | dm_task_destroy(dmt); | |
49 | ||
50 | return r; | |
51 | } | |
52 | ||
6d52fb46 | 53 | static int _query(struct logical_volume *lv, int (*fn)(const char *)) |
37ed70b9 | 54 | { |
6d52fb46 | 55 | char buffer[128]; |
4a624ca0 | 56 | |
6d52fb46 | 57 | if (!build_dm_name(buffer, sizeof(buffer), "", |
12137231 JT |
58 | lv->vg->name, lv->name)) { |
59 | stack; | |
6d52fb46 | 60 | return -1; |
12137231 | 61 | } |
4a624ca0 | 62 | |
6d52fb46 | 63 | return fn(buffer); |
4a624ca0 AK |
64 | } |
65 | ||
a62ee8ad AK |
66 | |
67 | /* | |
fdc7af23 | 68 | * These three functions return the number of LVs in the state, |
a62ee8ad AK |
69 | * or -1 on error. |
70 | */ | |
94b8220f | 71 | int lv_active(struct logical_volume *lv) |
2ba80b43 | 72 | { |
6d52fb46 | 73 | return _query(lv, device_active); |
37ed70b9 JT |
74 | } |
75 | ||
2bc25b54 AK |
76 | int lv_suspended(struct logical_volume *lv) |
77 | { | |
6d52fb46 | 78 | return _query(lv, device_suspended); |
2bc25b54 AK |
79 | } |
80 | ||
94b8220f | 81 | int lv_open_count(struct logical_volume *lv) |
2ba80b43 | 82 | { |
6d52fb46 JT |
83 | return _query(lv, device_open_count); |
84 | } | |
85 | ||
a62ee8ad AK |
86 | |
87 | /* | |
88 | * Returns 1 if info structure populated, else 0 on failure. | |
89 | */ | |
6d52fb46 JT |
90 | int lv_info(struct logical_volume *lv, struct dm_info *info) |
91 | { | |
92 | char buffer[128]; | |
2ba80b43 | 93 | |
6d52fb46 JT |
94 | if (!build_dm_name(buffer, sizeof(buffer), "", |
95 | lv->vg->name, lv->name)) { | |
2ba80b43 | 96 | stack; |
a62ee8ad | 97 | return 0; |
2ba80b43 JT |
98 | } |
99 | ||
6d52fb46 | 100 | return device_info(buffer, info); |
2ba80b43 JT |
101 | } |
102 | ||
fdc7af23 JT |
103 | static inline int _read_only_lv(struct logical_volume *lv) |
104 | { | |
105 | return (lv->status & LVM_WRITE) && (lv->vg->status & LVM_WRITE); | |
106 | } | |
6c4ee296 | 107 | |
6d52fb46 JT |
108 | int lv_activate(struct logical_volume *lv) |
109 | { | |
fdc7af23 JT |
110 | int r = 0; |
111 | struct dm_task *dmt; | |
6d52fb46 | 112 | char buffer[128]; |
6c4ee296 | 113 | |
6d52fb46 JT |
114 | if (test_mode()) { |
115 | _skip("Activation of '%s'.", lv->name); | |
116 | return 0; | |
6c4ee296 JT |
117 | } |
118 | ||
fdc7af23 JT |
119 | /* |
120 | * Decide what we're going to call this device. | |
121 | */ | |
6d52fb46 JT |
122 | if (!build_dm_name(buffer, sizeof(buffer), "", |
123 | lv->vg->name, lv->name)) { | |
124 | stack; | |
125 | return 0; | |
80f9662b JT |
126 | } |
127 | ||
fdc7af23 JT |
128 | /* |
129 | * Create a task. | |
130 | */ | |
131 | if (!(dmt = setup_dm_task(buffer, DM_DEVICE_CREATE))) { | |
6d52fb46 JT |
132 | stack; |
133 | return 0; | |
134 | } | |
a299e388 | 135 | |
fdc7af23 JT |
136 | /* |
137 | * Populate it. | |
138 | */ | |
139 | if (!device_populate_lv(dmt, lv)) { | |
80f9662b JT |
140 | stack; |
141 | return 0; | |
142 | } | |
143 | ||
fdc7af23 JT |
144 | /* |
145 | * Do we want a specific minor number ? | |
146 | */ | |
147 | if (lv->minor >= 0) { | |
148 | if (!dm_task_set_minor(dmt, MINOR(lv->minor))) { | |
149 | log_error("Failed to set minor number for %s to %d " | |
150 | "during activation.", lv->name, lv->minor); | |
151 | goto out; | |
152 | } else | |
153 | log_very_verbose("Set minor number for %s to %d.", | |
154 | lv->name, lv->minor); | |
155 | } | |
156 | ||
157 | /* | |
158 | * Read only ? | |
159 | */ | |
160 | if (!_read_only_lv(lv)) { | |
161 | if (!dm_task_set_ro(dmt)) { | |
162 | log_error("Failed to set %s read-only during " | |
163 | "activation.", lv->name); | |
164 | goto out; | |
165 | } else | |
166 | log_very_verbose("Activating %s read-only", lv->name); | |
167 | } | |
168 | ||
169 | /* | |
170 | * Load this into the kernel. | |
171 | */ | |
172 | if (!(r = dm_task_run(dmt))) { | |
173 | log_err("Activation failed."); | |
174 | goto out; | |
175 | } | |
176 | ||
177 | /* | |
178 | * Create device nodes and symbolic links. | |
179 | */ | |
180 | if (!fs_add_lv(lv, lv->minor)) | |
181 | stack; | |
182 | ||
183 | out: | |
184 | dm_task_destroy(dmt); | |
185 | log_verbose("Logical volume %s%s activated", lv->name, | |
186 | r == 1 ? "" : " not"); | |
187 | return r; | |
188 | } | |
189 | ||
190 | static int _reload(const char *name, struct logical_volume *lv) | |
191 | { | |
192 | int r = 0; | |
193 | struct dm_task *dmt; | |
194 | ||
195 | /* | |
196 | * Create a task. | |
197 | */ | |
198 | if (!(dmt = setup_dm_task(name, DM_DEVICE_RELOAD))) { | |
199 | stack; | |
200 | return 0; | |
201 | } | |
202 | ||
203 | /* | |
204 | * Populate it. | |
205 | */ | |
206 | if (!device_populate_lv(dmt, lv)) { | |
207 | stack; | |
208 | return 0; | |
209 | } | |
210 | ||
211 | /* | |
212 | * Load this into the kernel. | |
213 | */ | |
214 | if (!(r = dm_task_run(dmt))) { | |
215 | log_err("Activation failed."); | |
216 | goto out; | |
217 | } | |
218 | ||
219 | /* | |
220 | * Create device nodes and symbolic links. | |
221 | */ | |
222 | if (!fs_add_lv(lv, lv->minor)) | |
223 | stack; | |
224 | ||
225 | out: | |
226 | dm_task_destroy(dmt); | |
227 | log_verbose("Logical volume %s%s re-activated", lv->name, | |
228 | r == 1 ? "" : " not"); | |
229 | return r; | |
80f9662b JT |
230 | } |
231 | ||
6d52fb46 | 232 | int lv_reactivate(struct logical_volume *lv) |
b1713d28 | 233 | { |
6d52fb46 JT |
234 | int r; |
235 | char buffer[128]; | |
e15559aa | 236 | |
6d52fb46 JT |
237 | if (test_mode()) { |
238 | _skip("Reactivation of '%s'.", lv->name); | |
ae2bb665 JT |
239 | return 0; |
240 | } | |
b1713d28 | 241 | |
fdc7af23 JT |
242 | /* |
243 | * Decide what we're going to call this device. | |
244 | */ | |
6d52fb46 JT |
245 | if (!build_dm_name(buffer, sizeof(buffer), "", |
246 | lv->vg->name, lv->name)) { | |
247 | stack; | |
248 | return 0; | |
ae2bb665 JT |
249 | } |
250 | ||
fdc7af23 JT |
251 | /* |
252 | * Suspend the device if it isn't already. | |
253 | */ | |
6d52fb46 JT |
254 | if (!device_suspended(buffer) && !device_suspend(buffer)) { |
255 | stack; | |
256 | return 0; | |
12a6fcd3 | 257 | } |
2bc25b54 | 258 | |
fdc7af23 | 259 | r = _reload(buffer, lv); |
2bc25b54 | 260 | |
6d52fb46 | 261 | if (!device_resume(buffer)) { |
ae2bb665 | 262 | stack; |
6d52fb46 JT |
263 | return 0; |
264 | } | |
ae2bb665 | 265 | |
ae2bb665 | 266 | return r; |
b1713d28 | 267 | } |
a381c45a | 268 | |
6d52fb46 | 269 | int lv_deactivate(struct logical_volume *lv) |
0a5e4a14 | 270 | { |
6d52fb46 | 271 | char buffer[128]; |
c2d72fd4 | 272 | |
6d52fb46 JT |
273 | log_very_verbose("Deactivating %s", lv->name); |
274 | if (test_mode()) { | |
275 | _skip("Deactivating '%s'.", lv->name); | |
276 | return 0; | |
277 | } | |
37ed70b9 | 278 | |
6d52fb46 JT |
279 | if (!build_dm_name(buffer, sizeof(buffer), "", |
280 | lv->vg->name, lv->name)) { | |
281 | stack; | |
282 | return 0; | |
283 | } | |
37ed70b9 | 284 | |
6d52fb46 | 285 | if (!device_deactivate(buffer)) { |
37ed70b9 JT |
286 | stack; |
287 | return 0; | |
288 | } | |
289 | ||
6d52fb46 | 290 | fs_del_lv(lv); |
37ed70b9 | 291 | |
6d52fb46 | 292 | return 1; |
37ed70b9 JT |
293 | } |
294 | ||
4a624ca0 AK |
295 | int lv_suspend(struct logical_volume *lv) |
296 | { | |
6d52fb46 | 297 | char buffer[128]; |
4a624ca0 | 298 | |
6d52fb46 JT |
299 | log_very_verbose("Suspending %s", lv->name); |
300 | if (test_mode()) { | |
301 | _skip("Suspending '%s'.", lv->name); | |
c2d72fd4 | 302 | return 0; |
6d52fb46 | 303 | } |
c2d72fd4 | 304 | |
6d52fb46 JT |
305 | if (!build_dm_name(buffer, sizeof(buffer), "", |
306 | lv->vg->name, lv->name)) { | |
37ed70b9 JT |
307 | stack; |
308 | return 0; | |
309 | } | |
0a5e4a14 | 310 | |
6d52fb46 | 311 | if (!device_suspend(buffer)) { |
37ed70b9 JT |
312 | stack; |
313 | return 0; | |
314 | } | |
0a5e4a14 | 315 | |
6d52fb46 | 316 | fs_del_lv(lv); |
0a5e4a14 | 317 | |
6d52fb46 JT |
318 | return 1; |
319 | } | |
4a624ca0 | 320 | |
6d52fb46 | 321 | int lv_rename(const char *old_name, struct logical_volume *lv) |
ae2bb665 | 322 | { |
6d52fb46 JT |
323 | int r = 0; |
324 | char new_name[PATH_MAX]; | |
ab269099 JT |
325 | struct dm_task *dmt; |
326 | ||
6d52fb46 JT |
327 | if (test_mode()) { |
328 | _skip("Rename '%s' to '%s'.", old_name, lv->name); | |
c2d72fd4 | 329 | return 0; |
6d52fb46 | 330 | } |
c2d72fd4 | 331 | |
6d52fb46 | 332 | if (!(dmt = setup_dm_task(old_name, DM_DEVICE_RENAME))) { |
ae2bb665 JT |
333 | stack; |
334 | return 0; | |
335 | } | |
336 | ||
6d52fb46 JT |
337 | if (!build_dm_name(new_name, sizeof(new_name), "", |
338 | lv->vg->name, lv->name)) { | |
ae2bb665 | 339 | stack; |
6d52fb46 JT |
340 | return 0; |
341 | } | |
ae2bb665 | 342 | |
6d52fb46 JT |
343 | if (!dm_task_set_newname(dmt, new_name)) { |
344 | stack; | |
345 | r = 0; | |
346 | goto end; | |
347 | } | |
f7a14956 | 348 | |
6d52fb46 JT |
349 | if (!dm_task_run(dmt)) { |
350 | stack; | |
351 | r = 0; | |
352 | goto end; | |
353 | } | |
354 | ||
355 | fs_rename_lv(old_name, lv); | |
f7a14956 | 356 | |
6d52fb46 JT |
357 | end: |
358 | dm_task_destroy(dmt); | |
ae2bb665 JT |
359 | return r; |
360 | } | |
361 | ||
6d52fb46 | 362 | |
37ed70b9 JT |
363 | int activate_lvs_in_vg(struct volume_group *vg) |
364 | { | |
365 | struct list *lvh; | |
366 | struct logical_volume *lv; | |
94b8220f | 367 | int count = 0; |
37ed70b9 JT |
368 | |
369 | list_iterate(lvh, &vg->lvs) { | |
f868d635 | 370 | lv = list_item(lvh, struct lv_list)->lv; |
94b8220f | 371 | count += (!lv_active(lv) && lv_activate(lv)); |
37ed70b9 JT |
372 | } |
373 | ||
374 | return count; | |
375 | } | |
376 | ||
ae2bb665 JT |
377 | int lv_update_write_access(struct logical_volume *lv) |
378 | { | |
2bc25b54 AK |
379 | struct dm_info info; |
380 | ||
381 | if (!lv_info(lv, &info)) { | |
382 | stack; | |
383 | return 0; | |
384 | } | |
385 | ||
386 | if (!info.exists || info.suspended) | |
387 | /* Noop */ | |
388 | return 1; | |
389 | ||
390 | return lv_reactivate(lv); | |
ae2bb665 JT |
391 | } |
392 | ||
a381c45a AK |
393 | int deactivate_lvs_in_vg(struct volume_group *vg) |
394 | { | |
0a5e4a14 | 395 | struct list *lvh; |
37ed70b9 | 396 | struct logical_volume *lv; |
94b8220f | 397 | int count = 0; |
37ed70b9 JT |
398 | |
399 | list_iterate(lvh, &vg->lvs) { | |
f868d635 | 400 | lv = list_item(lvh, struct lv_list)->lv; |
94b8220f | 401 | count += ((lv_active(lv) == 1) && lv_deactivate(lv)); |
37ed70b9 | 402 | } |
0a5e4a14 | 403 | |
37ed70b9 | 404 | return count; |
a381c45a | 405 | } |
f047219b AK |
406 | |
407 | int lvs_in_vg_activated(struct volume_group *vg) | |
408 | { | |
37ed70b9 JT |
409 | struct list *lvh; |
410 | struct logical_volume *lv; | |
94b8220f | 411 | int count = 0; |
37ed70b9 JT |
412 | |
413 | list_iterate(lvh, &vg->lvs) { | |
f868d635 | 414 | lv = list_item(lvh, struct lv_list)->lv; |
94b8220f | 415 | count += (lv_active(lv) == 1); |
37ed70b9 JT |
416 | } |
417 | ||
418 | return count; | |
f047219b | 419 | } |
2ba80b43 JT |
420 | |
421 | int lvs_in_vg_opened(struct volume_group *vg) | |
422 | { | |
423 | struct list *lvh; | |
424 | struct logical_volume *lv; | |
94b8220f | 425 | int count = 0; |
2ba80b43 JT |
426 | |
427 | list_iterate(lvh, &vg->lvs) { | |
f868d635 | 428 | lv = list_item(lvh, struct lv_list)->lv; |
94b8220f | 429 | count += (lv_open_count(lv) == 1); |
2ba80b43 JT |
430 | } |
431 | ||
432 | return count; | |
433 | } |