]>
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 | ||
d1d9800e | 7 | #include "lib.h" |
a381c45a | 8 | #include "metadata.h" |
b1713d28 | 9 | #include "activate.h" |
914c9723 | 10 | #include "memlock.h" |
78125be9 | 11 | #include "display.h" |
f7a14956 | 12 | #include "fs.h" |
41b2fd5f | 13 | #include "lvm-string.h" |
413cc918 AK |
14 | #include "pool.h" |
15 | #include "toolcontext.h" | |
de6c9183 | 16 | #include "dev_manager.h" |
12137231 JT |
17 | |
18 | #include <limits.h> | |
5986ec94 | 19 | #include <fcntl.h> |
914c9723 | 20 | #include <unistd.h> |
12137231 | 21 | |
6d52fb46 | 22 | #define _skip(fmt, args...) log_very_verbose("Skipping: " fmt , ## args) |
b1713d28 | 23 | |
199e490e AK |
24 | #ifndef DEVMAPPER_SUPPORT |
25 | void set_activation(int act) | |
26 | { | |
27 | if (act) | |
28 | log_error("Compiled without libdevmapper support. " | |
29 | "Can't enable activation."); | |
30 | } | |
31 | int activation(void) | |
32 | { | |
33 | return 0; | |
34 | } | |
35 | int library_version(char *version, size_t size) | |
36 | { | |
37 | return 0; | |
38 | } | |
39 | int driver_version(char *version, size_t size) | |
40 | { | |
41 | return 0; | |
42 | } | |
43 | int lv_info(const struct logical_volume *lv, struct lvinfo *info) | |
44 | { | |
45 | return 0; | |
46 | } | |
47 | int lv_snapshot_percent(struct logical_volume *lv, float *percent) | |
48 | { | |
49 | return 0; | |
50 | } | |
914c9723 AK |
51 | int lv_mirror_percent(struct logical_volume *lv, int wait, float *percent, |
52 | uint32_t *event_nr) | |
10b29b8d AK |
53 | { |
54 | return 0; | |
55 | } | |
199e490e AK |
56 | int lvs_in_vg_activated(struct volume_group *vg) |
57 | { | |
58 | return 0; | |
59 | } | |
60 | int lvs_in_vg_opened(struct volume_group *vg) | |
61 | { | |
62 | return 0; | |
63 | } | |
64 | int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s) | |
65 | { | |
66 | return 1; | |
67 | } | |
68 | int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s) | |
69 | { | |
70 | return 1; | |
71 | } | |
72 | int lv_deactivate(struct cmd_context *cmd, const char *lvid_s) | |
73 | { | |
74 | return 1; | |
75 | } | |
76 | int lv_activate(struct cmd_context *cmd, const char *lvid_s) | |
77 | { | |
78 | return 1; | |
79 | } | |
914c9723 AK |
80 | void activation_exit(void) |
81 | { | |
82 | return; | |
83 | } | |
199e490e AK |
84 | |
85 | #else /* DEVMAPPER_SUPPORT */ | |
86 | ||
d1d9800e AK |
87 | static int _activation = 1; |
88 | ||
8ef2b021 | 89 | void set_activation(int act) |
d1d9800e | 90 | { |
8ef2b021 | 91 | if (act == _activation) |
d1d9800e AK |
92 | return; |
93 | ||
8ef2b021 | 94 | _activation = act; |
d1d9800e AK |
95 | if (_activation) |
96 | log_verbose("Activation enabled. Device-mapper kernel " | |
97 | "driver will be used."); | |
98 | else | |
99 | log_verbose("Activation disabled. No device-mapper " | |
100 | "interaction will be attempted."); | |
101 | } | |
102 | ||
8ef2b021 | 103 | int activation(void) |
d1d9800e AK |
104 | { |
105 | return _activation; | |
106 | } | |
107 | ||
fae0c576 AK |
108 | int library_version(char *version, size_t size) |
109 | { | |
d1d9800e AK |
110 | if (!activation()) |
111 | return 0; | |
112 | ||
fae0c576 AK |
113 | if (!dm_get_library_version(version, size)) |
114 | return 0; | |
115 | return 1; | |
116 | } | |
117 | ||
fae0c576 AK |
118 | int driver_version(char *version, size_t size) |
119 | { | |
120 | int r = 0; | |
121 | struct dm_task *dmt; | |
122 | ||
d1d9800e AK |
123 | if (!activation()) |
124 | return 0; | |
125 | ||
fae0c576 AK |
126 | log_very_verbose("Getting driver version"); |
127 | if (!(dmt = dm_task_create(DM_DEVICE_VERSION))) { | |
128 | stack; | |
129 | return 0; | |
130 | } | |
131 | ||
132 | if (!dm_task_run(dmt)) | |
133 | log_error("Failed to get driver version"); | |
134 | ||
135 | if (!dm_task_get_driver_version(dmt, version, size)) | |
136 | goto out; | |
137 | ||
138 | r = 1; | |
139 | ||
2ed2a724 | 140 | out: |
fae0c576 AK |
141 | dm_task_destroy(dmt); |
142 | ||
143 | return r; | |
144 | } | |
145 | ||
de6c9183 JT |
146 | /* |
147 | * Returns 1 if info structure populated, else 0 on failure. | |
148 | */ | |
199e490e | 149 | int lv_info(const struct logical_volume *lv, struct lvinfo *info) |
37ed70b9 | 150 | { |
de6c9183 JT |
151 | int r; |
152 | struct dev_manager *dm; | |
199e490e | 153 | struct dm_info dminfo; |
4a624ca0 | 154 | |
d1d9800e AK |
155 | if (!activation()) |
156 | return 0; | |
157 | ||
a9953411 | 158 | if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cf))) { |
12137231 | 159 | stack; |
de6c9183 | 160 | return 0; |
12137231 | 161 | } |
4a624ca0 | 162 | |
199e490e | 163 | if (!(r = dev_manager_info(dm, lv, &dminfo))) |
de6c9183 | 164 | stack; |
4a624ca0 | 165 | |
199e490e AK |
166 | info->exists = dminfo.exists; |
167 | info->suspended = dminfo.suspended; | |
168 | info->open_count = dminfo.open_count; | |
169 | info->major = dminfo.major; | |
170 | info->minor = dminfo.minor; | |
171 | info->read_only = dminfo.read_only; | |
172 | ||
de6c9183 JT |
173 | dev_manager_destroy(dm); |
174 | return r; | |
175 | } | |
a62ee8ad | 176 | |
1951dba9 AL |
177 | /* |
178 | * Returns 1 if percent set, else 0 on failure. | |
179 | */ | |
c826c0d1 | 180 | int lv_snapshot_percent(struct logical_volume *lv, float *percent) |
1951dba9 AL |
181 | { |
182 | int r; | |
183 | struct dev_manager *dm; | |
184 | ||
d1d9800e AK |
185 | if (!activation()) |
186 | return 0; | |
187 | ||
a9953411 | 188 | if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cf))) { |
1951dba9 AL |
189 | stack; |
190 | return 0; | |
191 | } | |
192 | ||
c826c0d1 | 193 | if (!(r = dev_manager_snapshot_percent(dm, lv, percent))) |
1951dba9 | 194 | stack; |
c826c0d1 | 195 | |
1951dba9 AL |
196 | dev_manager_destroy(dm); |
197 | ||
198 | return r; | |
199 | } | |
200 | ||
10b29b8d AK |
201 | /* FIXME Merge with snapshot_percent */ |
202 | int lv_mirror_percent(struct logical_volume *lv, int wait, float *percent, | |
203 | uint32_t *event_nr) | |
204 | { | |
205 | int r; | |
206 | struct dev_manager *dm; | |
207 | ||
208 | if (!activation()) | |
209 | return 0; | |
210 | ||
211 | if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cf))) { | |
212 | stack; | |
213 | return 0; | |
214 | } | |
215 | ||
216 | if (!(r = dev_manager_mirror_percent(dm, lv, wait, percent, event_nr))) | |
217 | stack; | |
218 | ||
219 | dev_manager_destroy(dm); | |
220 | ||
221 | return r; | |
222 | } | |
223 | ||
41967a02 | 224 | static int _lv_active(struct logical_volume *lv) |
2ba80b43 | 225 | { |
199e490e | 226 | struct lvinfo info; |
2ba80b43 | 227 | |
de6c9183 | 228 | if (!lv_info(lv, &info)) { |
2ba80b43 | 229 | stack; |
de6c9183 | 230 | return -1; |
2ba80b43 JT |
231 | } |
232 | ||
de6c9183 | 233 | return info.exists; |
2ba80b43 JT |
234 | } |
235 | ||
41967a02 | 236 | static int _lv_open_count(struct logical_volume *lv) |
5986ec94 | 237 | { |
199e490e | 238 | struct lvinfo info; |
5986ec94 | 239 | |
de6c9183 | 240 | if (!lv_info(lv, &info)) { |
5986ec94 | 241 | stack; |
de6c9183 | 242 | return -1; |
5986ec94 JT |
243 | } |
244 | ||
de6c9183 | 245 | return info.open_count; |
5986ec94 JT |
246 | } |
247 | ||
8c013da4 | 248 | /* FIXME Need to detect and handle an lv rename */ |
be326a2f | 249 | static int _lv_activate(struct logical_volume *lv) |
b1713d28 | 250 | { |
6d52fb46 | 251 | int r; |
de6c9183 | 252 | struct dev_manager *dm; |
b1713d28 | 253 | |
a9953411 | 254 | if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cf))) { |
6d52fb46 JT |
255 | stack; |
256 | return 0; | |
ae2bb665 JT |
257 | } |
258 | ||
0fe3a2c5 | 259 | if (!(r = dev_manager_activate(dm, lv))) |
6d52fb46 | 260 | stack; |
ae2bb665 | 261 | |
de6c9183 | 262 | dev_manager_destroy(dm); |
ae2bb665 | 263 | return r; |
b1713d28 | 264 | } |
a381c45a | 265 | |
be326a2f | 266 | static int _lv_deactivate(struct logical_volume *lv) |
0a5e4a14 | 267 | { |
de6c9183 JT |
268 | int r; |
269 | struct dev_manager *dm; | |
37ed70b9 | 270 | |
a9953411 | 271 | if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cf))) { |
6d52fb46 JT |
272 | stack; |
273 | return 0; | |
274 | } | |
37ed70b9 | 275 | |
de6c9183 | 276 | if (!(r = dev_manager_deactivate(dm, lv))) |
37ed70b9 | 277 | stack; |
37ed70b9 | 278 | |
de6c9183 JT |
279 | dev_manager_destroy(dm); |
280 | return r; | |
37ed70b9 JT |
281 | } |
282 | ||
be326a2f | 283 | static int _lv_suspend(struct logical_volume *lv) |
4a624ca0 | 284 | { |
20c5fcf7 AK |
285 | int r; |
286 | struct dev_manager *dm; | |
c2d72fd4 | 287 | |
a9953411 | 288 | if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cf))) { |
37ed70b9 JT |
289 | stack; |
290 | return 0; | |
291 | } | |
0a5e4a14 | 292 | |
20c5fcf7 | 293 | if (!(r = dev_manager_suspend(dm, lv))) |
37ed70b9 | 294 | stack; |
0a5e4a14 | 295 | |
20c5fcf7 AK |
296 | dev_manager_destroy(dm); |
297 | return r; | |
6d52fb46 | 298 | } |
4a624ca0 | 299 | |
8c013da4 AK |
300 | /* |
301 | * These two functions return the number of LVs in the state, | |
302 | * or -1 on error. | |
303 | */ | |
f047219b AK |
304 | int lvs_in_vg_activated(struct volume_group *vg) |
305 | { | |
37ed70b9 JT |
306 | struct list *lvh; |
307 | struct logical_volume *lv; | |
94b8220f | 308 | int count = 0; |
37ed70b9 | 309 | |
d1d9800e AK |
310 | if (!activation()) |
311 | return 0; | |
312 | ||
37ed70b9 | 313 | list_iterate(lvh, &vg->lvs) { |
f868d635 | 314 | lv = list_item(lvh, struct lv_list)->lv; |
41967a02 | 315 | count += (_lv_active(lv) == 1); |
37ed70b9 JT |
316 | } |
317 | ||
318 | return count; | |
f047219b | 319 | } |
2ba80b43 JT |
320 | |
321 | int lvs_in_vg_opened(struct volume_group *vg) | |
322 | { | |
323 | struct list *lvh; | |
324 | struct logical_volume *lv; | |
94b8220f | 325 | int count = 0; |
2ba80b43 | 326 | |
d1d9800e AK |
327 | if (!activation()) |
328 | return 0; | |
329 | ||
2ba80b43 | 330 | list_iterate(lvh, &vg->lvs) { |
f868d635 | 331 | lv = list_item(lvh, struct lv_list)->lv; |
41967a02 | 332 | count += (_lv_open_count(lv) == 1); |
2ba80b43 JT |
333 | } |
334 | ||
335 | return count; | |
336 | } | |
413cc918 | 337 | |
20c5fcf7 | 338 | /* These return success if the device is not active */ |
15c325f0 | 339 | int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s) |
413cc918 AK |
340 | { |
341 | struct logical_volume *lv; | |
199e490e | 342 | struct lvinfo info; |
413cc918 | 343 | |
d1d9800e AK |
344 | if (!activation()) |
345 | return 1; | |
346 | ||
347 | if (!(lv = lv_from_lvid(cmd, lvid_s))) | |
413cc918 AK |
348 | return 0; |
349 | ||
20c5fcf7 AK |
350 | if (test_mode()) { |
351 | _skip("Suspending '%s'.", lv->name); | |
711f7fc6 | 352 | return 1; |
20c5fcf7 AK |
353 | } |
354 | ||
2ed2a724 AK |
355 | if (!lv_info(lv, &info)) { |
356 | stack; | |
357 | return 0; | |
358 | } | |
41967a02 | 359 | |
914c9723 AK |
360 | if (!info.exists || info.suspended) |
361 | return 1; | |
362 | ||
363 | memlock_inc(); | |
364 | if (!_lv_suspend(lv)) { | |
365 | memlock_dec(); | |
366 | fs_unlock(); | |
367 | return 0; | |
368 | } | |
8c013da4 | 369 | |
413cc918 AK |
370 | return 1; |
371 | } | |
372 | ||
15c325f0 | 373 | int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s) |
413cc918 AK |
374 | { |
375 | struct logical_volume *lv; | |
199e490e | 376 | struct lvinfo info; |
413cc918 | 377 | |
d1d9800e AK |
378 | if (!activation()) |
379 | return 1; | |
380 | ||
381 | if (!(lv = lv_from_lvid(cmd, lvid_s))) | |
413cc918 AK |
382 | return 0; |
383 | ||
20c5fcf7 AK |
384 | if (test_mode()) { |
385 | _skip("Resuming '%s'.", lv->name); | |
711f7fc6 | 386 | return 1; |
20c5fcf7 AK |
387 | } |
388 | ||
2ed2a724 AK |
389 | if (!lv_info(lv, &info)) { |
390 | stack; | |
391 | return 0; | |
392 | } | |
41967a02 | 393 | |
914c9723 AK |
394 | if (!info.exists || !info.suspended) |
395 | return 1; | |
396 | ||
397 | if (!_lv_activate(lv)) | |
398 | return 0; | |
399 | ||
400 | memlock_dec(); | |
401 | fs_unlock(); | |
413cc918 AK |
402 | |
403 | return 1; | |
404 | } | |
405 | ||
be326a2f | 406 | int lv_deactivate(struct cmd_context *cmd, const char *lvid_s) |
f4cbeaf0 AK |
407 | { |
408 | struct logical_volume *lv; | |
199e490e | 409 | struct lvinfo info; |
914c9723 | 410 | int r; |
f4cbeaf0 | 411 | |
d1d9800e AK |
412 | if (!activation()) |
413 | return 1; | |
414 | ||
415 | if (!(lv = lv_from_lvid(cmd, lvid_s))) | |
f4cbeaf0 AK |
416 | return 0; |
417 | ||
20c5fcf7 AK |
418 | if (test_mode()) { |
419 | _skip("Deactivating '%s'.", lv->name); | |
711f7fc6 | 420 | return 1; |
20c5fcf7 AK |
421 | } |
422 | ||
2ed2a724 AK |
423 | if (!lv_info(lv, &info)) { |
424 | stack; | |
425 | return 0; | |
426 | } | |
41967a02 | 427 | |
914c9723 AK |
428 | if (!info.exists) |
429 | return 1; | |
f4cbeaf0 | 430 | |
0cf96f33 AK |
431 | if (info.open_count) { |
432 | log_error("LV %s/%s in use: not removing", lv->vg->name, | |
433 | lv->name); | |
434 | return 0; | |
435 | } | |
436 | ||
914c9723 AK |
437 | memlock_inc(); |
438 | r = _lv_deactivate(lv); | |
439 | memlock_dec(); | |
440 | fs_unlock(); | |
441 | ||
442 | return r; | |
f4cbeaf0 AK |
443 | } |
444 | ||
be326a2f | 445 | int lv_activate(struct cmd_context *cmd, const char *lvid_s) |
f4cbeaf0 AK |
446 | { |
447 | struct logical_volume *lv; | |
199e490e | 448 | struct lvinfo info; |
914c9723 | 449 | int r; |
f4cbeaf0 | 450 | |
d1d9800e AK |
451 | if (!activation()) |
452 | return 1; | |
453 | ||
454 | if (!(lv = lv_from_lvid(cmd, lvid_s))) | |
f4cbeaf0 AK |
455 | return 0; |
456 | ||
20c5fcf7 AK |
457 | if (test_mode()) { |
458 | _skip("Activating '%s'.", lv->name); | |
711f7fc6 | 459 | return 1; |
20c5fcf7 AK |
460 | } |
461 | ||
2ed2a724 AK |
462 | if (!lv_info(lv, &info)) { |
463 | stack; | |
464 | return 0; | |
465 | } | |
8c013da4 | 466 | |
914c9723 AK |
467 | if (info.exists && !info.suspended) |
468 | return 1; | |
f4cbeaf0 | 469 | |
914c9723 AK |
470 | memlock_inc(); |
471 | r = _lv_activate(lv); | |
472 | memlock_dec(); | |
473 | fs_unlock(); | |
474 | ||
475 | return r; | |
f4cbeaf0 | 476 | } |
199e490e | 477 | |
914c9723 AK |
478 | void activation_exit(void) |
479 | { | |
480 | dev_manager_exit(); | |
481 | } | |
199e490e | 482 | #endif |