]>
Commit | Line | Data |
---|---|---|
b1713d28 | 1 | /* |
6606c3ae | 2 | * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. |
5f4b2acf | 3 | * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved. |
b1713d28 | 4 | * |
6606c3ae AK |
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 General Public License v.2. | |
10 | * | |
11 | * You should have received a copy of the GNU 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 | |
b1713d28 JT |
14 | */ |
15 | ||
d1d9800e | 16 | #include "lib.h" |
a381c45a | 17 | #include "metadata.h" |
b1713d28 | 18 | #include "activate.h" |
914c9723 | 19 | #include "memlock.h" |
78125be9 | 20 | #include "display.h" |
f7a14956 | 21 | #include "fs.h" |
f894b4b1 | 22 | #include "lvm-exec.h" |
7d1552c9 | 23 | #include "lvm-file.h" |
41b2fd5f | 24 | #include "lvm-string.h" |
413cc918 | 25 | #include "toolcontext.h" |
de6c9183 | 26 | #include "dev_manager.h" |
de17d760 | 27 | #include "str_list.h" |
4922197a | 28 | #include "config.h" |
352a99b9 | 29 | #include "filter.h" |
15d91f5a | 30 | #include "segtype.h" |
12137231 JT |
31 | |
32 | #include <limits.h> | |
5986ec94 | 33 | #include <fcntl.h> |
914c9723 | 34 | #include <unistd.h> |
12137231 | 35 | |
6d52fb46 | 36 | #define _skip(fmt, args...) log_very_verbose("Skipping: " fmt , ## args) |
b1713d28 | 37 | |
7d1552c9 AK |
38 | int lvm1_present(struct cmd_context *cmd) |
39 | { | |
40 | char path[PATH_MAX]; | |
41 | ||
42 | if (lvm_snprintf(path, sizeof(path), "%s/lvm/global", cmd->proc_dir) | |
43 | < 0) { | |
44 | log_error("LVM1 proc global snprintf failed"); | |
45 | return 0; | |
46 | } | |
47 | ||
48 | if (path_exists(path)) | |
49 | return 1; | |
50 | else | |
51 | return 0; | |
52 | } | |
53 | ||
199e490e AK |
54 | #ifndef DEVMAPPER_SUPPORT |
55 | void set_activation(int act) | |
56 | { | |
f2046e0a AK |
57 | static int warned = 0; |
58 | ||
59 | if (warned || !act) | |
60 | return; | |
61 | ||
62 | log_error("Compiled without libdevmapper support. " | |
63 | "Can't enable activation."); | |
64 | ||
65 | warned = 1; | |
199e490e AK |
66 | } |
67 | int activation(void) | |
68 | { | |
69 | return 0; | |
70 | } | |
71 | int library_version(char *version, size_t size) | |
72 | { | |
73 | return 0; | |
74 | } | |
75 | int driver_version(char *version, size_t size) | |
76 | { | |
77 | return 0; | |
78 | } | |
bbf83db1 AK |
79 | int target_version(const char *target_name, uint32_t *maj, |
80 | uint32_t *min, uint32_t *patchlevel) | |
81 | { | |
82 | return 0; | |
83 | } | |
d1f4953a AK |
84 | int target_present(const char *target_name) |
85 | { | |
86 | return 0; | |
87 | } | |
f894b4b1 | 88 | int lv_info(struct cmd_context *cmd, const struct logical_volume *lv, struct lvinfo *info, |
e9c761b8 | 89 | int with_open_count) |
199e490e AK |
90 | { |
91 | return 0; | |
92 | } | |
4bd9480d | 93 | int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s, |
e9c761b8 | 94 | struct lvinfo *info, int with_open_count) |
4bd9480d AK |
95 | { |
96 | return 0; | |
97 | } | |
472ac5bd | 98 | int lv_snapshot_percent(const struct logical_volume *lv, float *percent) |
199e490e AK |
99 | { |
100 | return 0; | |
101 | } | |
472ac5bd AK |
102 | int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv, |
103 | int wait, float *percent, uint32_t *event_nr) | |
10b29b8d AK |
104 | { |
105 | return 0; | |
106 | } | |
199e490e AK |
107 | int lvs_in_vg_activated(struct volume_group *vg) |
108 | { | |
109 | return 0; | |
110 | } | |
111 | int lvs_in_vg_opened(struct volume_group *vg) | |
112 | { | |
113 | return 0; | |
114 | } | |
658b5812 AK |
115 | int lv_suspend(struct cmd_context *cmd, const char *lvid_s) |
116 | { | |
117 | return 1; | |
118 | } | |
199e490e AK |
119 | int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s) |
120 | { | |
121 | return 1; | |
122 | } | |
658b5812 AK |
123 | int lv_resume(struct cmd_context *cmd, const char *lvid_s) |
124 | { | |
125 | return 1; | |
126 | } | |
199e490e AK |
127 | int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s) |
128 | { | |
129 | return 1; | |
130 | } | |
131 | int lv_deactivate(struct cmd_context *cmd, const char *lvid_s) | |
132 | { | |
133 | return 1; | |
134 | } | |
658b5812 AK |
135 | int lv_activation_filter(struct cmd_context *cmd, const char *lvid_s, |
136 | int *activate_lv) | |
137 | { | |
138 | return 1; | |
139 | } | |
07d31831 | 140 | int lv_activate(struct cmd_context *cmd, const char *lvid_s, int exclusive) |
199e490e AK |
141 | { |
142 | return 1; | |
143 | } | |
07d31831 | 144 | int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s, int exclusive) |
658b5812 AK |
145 | { |
146 | return 1; | |
147 | } | |
f7dd6d84 AK |
148 | |
149 | int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv) | |
150 | { | |
151 | return 1; | |
152 | } | |
153 | ||
352a99b9 AK |
154 | int pv_uses_vg(struct cmd_context *cmd, struct physical_volume *pv, |
155 | struct volume_group *vg) | |
156 | { | |
157 | return 0; | |
158 | } | |
159 | ||
914c9723 AK |
160 | void activation_exit(void) |
161 | { | |
162 | return; | |
163 | } | |
199e490e AK |
164 | |
165 | #else /* DEVMAPPER_SUPPORT */ | |
166 | ||
d1d9800e AK |
167 | static int _activation = 1; |
168 | ||
8ef2b021 | 169 | void set_activation(int act) |
d1d9800e | 170 | { |
8ef2b021 | 171 | if (act == _activation) |
d1d9800e AK |
172 | return; |
173 | ||
8ef2b021 | 174 | _activation = act; |
d1d9800e AK |
175 | if (_activation) |
176 | log_verbose("Activation enabled. Device-mapper kernel " | |
177 | "driver will be used."); | |
178 | else | |
bfe2b548 AK |
179 | log_print("WARNING: Activation disabled. No device-mapper " |
180 | "interaction will be attempted."); | |
d1d9800e AK |
181 | } |
182 | ||
8ef2b021 | 183 | int activation(void) |
d1d9800e AK |
184 | { |
185 | return _activation; | |
186 | } | |
187 | ||
de17d760 AK |
188 | static int _passes_activation_filter(struct cmd_context *cmd, |
189 | struct logical_volume *lv) | |
190 | { | |
25579907 | 191 | const struct config_node *cn; |
de17d760 AK |
192 | struct config_value *cv; |
193 | char *str; | |
194 | char path[PATH_MAX]; | |
195 | ||
814643d8 | 196 | if (!(cn = find_config_node(cmd->cft->root, "activation/volume_list"))) { |
25579907 | 197 | /* If no host tags defined, activate */ |
de17d760 AK |
198 | if (list_empty(&cmd->tags)) |
199 | return 1; | |
200 | ||
201 | /* If any host tag matches any LV or VG tag, activate */ | |
202 | if (str_list_match_list(&cmd->tags, &lv->tags) || | |
203 | str_list_match_list(&cmd->tags, &lv->vg->tags)) | |
204 | return 1; | |
205 | ||
206 | /* Don't activate */ | |
207 | return 0; | |
208 | } | |
209 | ||
210 | for (cv = cn->v; cv; cv = cv->next) { | |
211 | if (cv->type != CFG_STRING) { | |
212 | log_error("Ignoring invalid string in config file " | |
213 | "activation/volume_list"); | |
214 | continue; | |
215 | } | |
216 | str = cv->v.str; | |
217 | if (!*str) { | |
218 | log_error("Ignoring empty string in config file " | |
219 | "activation/volume_list"); | |
220 | continue; | |
221 | } | |
222 | ||
223 | /* Tag? */ | |
224 | if (*str == '@') { | |
225 | str++; | |
226 | if (!*str) { | |
227 | log_error("Ignoring empty tag in config file " | |
228 | "activation/volume_list"); | |
229 | continue; | |
230 | } | |
231 | /* If any host tag matches any LV or VG tag, activate */ | |
232 | if (!strcmp(str, "*")) { | |
233 | if (str_list_match_list(&cmd->tags, &lv->tags) | |
234 | || str_list_match_list(&cmd->tags, | |
235 | &lv->vg->tags)) | |
236 | return 1; | |
237 | else | |
238 | continue; | |
239 | } | |
240 | /* If supplied tag matches LV or VG tag, activate */ | |
241 | if (str_list_match_item(&lv->tags, str) || | |
242 | str_list_match_item(&lv->vg->tags, str)) | |
243 | return 1; | |
244 | else | |
245 | continue; | |
246 | } | |
247 | if (!index(str, '/')) { | |
248 | /* vgname supplied */ | |
249 | if (!strcmp(str, lv->vg->name)) | |
250 | return 1; | |
251 | else | |
252 | continue; | |
253 | } | |
254 | /* vgname/lvname */ | |
255 | if (lvm_snprintf(path, sizeof(path), "%s/%s", lv->vg->name, | |
256 | lv->name) < 0) { | |
257 | log_error("lvm_snprintf error from %s/%s", lv->vg->name, | |
258 | lv->name); | |
259 | continue; | |
260 | } | |
261 | if (!strcmp(path, str)) | |
262 | return 1; | |
263 | } | |
264 | ||
265 | return 0; | |
266 | } | |
267 | ||
fae0c576 AK |
268 | int library_version(char *version, size_t size) |
269 | { | |
d1d9800e AK |
270 | if (!activation()) |
271 | return 0; | |
272 | ||
f894b4b1 | 273 | return dm_get_library_version(version, size); |
fae0c576 AK |
274 | } |
275 | ||
fae0c576 AK |
276 | int driver_version(char *version, size_t size) |
277 | { | |
d1d9800e AK |
278 | if (!activation()) |
279 | return 0; | |
280 | ||
fae0c576 | 281 | log_very_verbose("Getting driver version"); |
fae0c576 | 282 | |
f894b4b1 | 283 | return dm_driver_version(version, size); |
fae0c576 AK |
284 | } |
285 | ||
bbf83db1 AK |
286 | int target_version(const char *target_name, uint32_t *maj, |
287 | uint32_t *min, uint32_t *patchlevel) | |
d1f4953a AK |
288 | { |
289 | int r = 0; | |
290 | struct dm_task *dmt; | |
291 | struct dm_versions *target, *last_target; | |
292 | ||
d1f4953a | 293 | log_very_verbose("Getting target version for %s", target_name); |
5f4b2acf AK |
294 | if (!(dmt = dm_task_create(DM_DEVICE_LIST_VERSIONS))) |
295 | return_0; | |
d1f4953a AK |
296 | |
297 | if (!dm_task_run(dmt)) { | |
298 | log_debug("Failed to get %s target version", target_name); | |
299 | /* Assume this was because LIST_VERSIONS isn't supported */ | |
300 | return 1; | |
301 | } | |
302 | ||
303 | target = dm_task_get_versions(dmt); | |
304 | ||
305 | do { | |
306 | last_target = target; | |
307 | ||
308 | if (!strcmp(target_name, target->name)) { | |
309 | r = 1; | |
bbf83db1 AK |
310 | *maj = target->version[0]; |
311 | *min = target->version[1]; | |
312 | *patchlevel = target->version[2]; | |
d1f4953a AK |
313 | goto out; |
314 | } | |
315 | ||
316 | target = (void *) target + target->next; | |
317 | } while (last_target != target); | |
318 | ||
319 | out: | |
320 | dm_task_destroy(dmt); | |
321 | ||
322 | return r; | |
323 | } | |
324 | ||
5f4b2acf | 325 | int target_present(const char *target_name, int use_modprobe) |
f894b4b1 | 326 | { |
bbf83db1 | 327 | uint32_t maj, min, patchlevel; |
03b49fe1 | 328 | #ifdef MODPROBE_CMD |
f894b4b1 | 329 | char module[128]; |
03b49fe1 | 330 | #endif |
f894b4b1 AK |
331 | |
332 | if (!activation()) | |
333 | return 0; | |
334 | ||
335 | #ifdef MODPROBE_CMD | |
5f4b2acf | 336 | if (use_modprobe) { |
bbf83db1 | 337 | if (target_version(target_name, &maj, &min, &patchlevel)) |
5f4b2acf | 338 | return 1; |
f894b4b1 | 339 | |
5f4b2acf AK |
340 | if (lvm_snprintf(module, sizeof(module), "dm-%s", target_name) |
341 | < 0) { | |
342 | log_error("target_present module name too long: %s", | |
343 | target_name); | |
344 | return 0; | |
345 | } | |
f894b4b1 | 346 | |
5f4b2acf AK |
347 | if (!exec_cmd(MODPROBE_CMD, module, "", "")) |
348 | return_0; | |
f894b4b1 AK |
349 | } |
350 | #endif | |
351 | ||
bbf83db1 | 352 | return target_version(target_name, &maj, &min, &patchlevel); |
f894b4b1 AK |
353 | } |
354 | ||
de6c9183 JT |
355 | /* |
356 | * Returns 1 if info structure populated, else 0 on failure. | |
357 | */ | |
f894b4b1 | 358 | static int _lv_info(struct cmd_context *cmd, const struct logical_volume *lv, int with_mknodes, |
e9c761b8 | 359 | struct lvinfo *info, int with_open_count) |
37ed70b9 | 360 | { |
199e490e | 361 | struct dm_info dminfo; |
f894b4b1 | 362 | char *name; |
4a624ca0 | 363 | |
d1d9800e AK |
364 | if (!activation()) |
365 | return 0; | |
366 | ||
5f4b2acf AK |
367 | if (!(name = build_dm_name(cmd->mem, lv->vg->name, lv->name, NULL))) |
368 | return_0; | |
4a624ca0 | 369 | |
f894b4b1 | 370 | log_debug("Getting device info for %s", name); |
03b49fe1 AK |
371 | if (!dev_manager_info(lv->vg->cmd->mem, name, lv, with_mknodes, |
372 | with_open_count, &dminfo)) { | |
f894b4b1 | 373 | dm_pool_free(cmd->mem, name); |
5f4b2acf | 374 | return_0; |
f894b4b1 | 375 | } |
4a624ca0 | 376 | |
199e490e AK |
377 | info->exists = dminfo.exists; |
378 | info->suspended = dminfo.suspended; | |
379 | info->open_count = dminfo.open_count; | |
380 | info->major = dminfo.major; | |
381 | info->minor = dminfo.minor; | |
382 | info->read_only = dminfo.read_only; | |
5f4b2acf AK |
383 | info->live_table = dminfo.live_table; |
384 | info->inactive_table = dminfo.inactive_table; | |
199e490e | 385 | |
f894b4b1 AK |
386 | dm_pool_free(cmd->mem, name); |
387 | return 1; | |
de6c9183 | 388 | } |
a62ee8ad | 389 | |
f894b4b1 | 390 | int lv_info(struct cmd_context *cmd, const struct logical_volume *lv, struct lvinfo *info, |
e9c761b8 | 391 | int with_open_count) |
8c0388e4 | 392 | { |
f894b4b1 | 393 | return _lv_info(cmd, lv, 0, info, with_open_count); |
8c0388e4 AK |
394 | } |
395 | ||
4bd9480d | 396 | int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s, |
e9c761b8 | 397 | struct lvinfo *info, int with_open_count) |
4bd9480d AK |
398 | { |
399 | struct logical_volume *lv; | |
400 | ||
7a593325 | 401 | if (!(lv = lv_from_lvid(cmd, lvid_s, 0))) |
4bd9480d AK |
402 | return 0; |
403 | ||
f894b4b1 | 404 | return _lv_info(cmd, lv, 0, info, with_open_count); |
4bd9480d AK |
405 | } |
406 | ||
1951dba9 AL |
407 | /* |
408 | * Returns 1 if percent set, else 0 on failure. | |
409 | */ | |
472ac5bd | 410 | int lv_snapshot_percent(const struct logical_volume *lv, float *percent) |
1951dba9 AL |
411 | { |
412 | int r; | |
413 | struct dev_manager *dm; | |
414 | ||
d1d9800e AK |
415 | if (!activation()) |
416 | return 0; | |
417 | ||
5f4b2acf AK |
418 | if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) |
419 | return_0; | |
1951dba9 | 420 | |
c826c0d1 | 421 | if (!(r = dev_manager_snapshot_percent(dm, lv, percent))) |
1951dba9 | 422 | stack; |
c826c0d1 | 423 | |
1951dba9 AL |
424 | dev_manager_destroy(dm); |
425 | ||
426 | return r; | |
427 | } | |
428 | ||
10b29b8d | 429 | /* FIXME Merge with snapshot_percent */ |
472ac5bd AK |
430 | int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv, |
431 | int wait, float *percent, uint32_t *event_nr) | |
10b29b8d AK |
432 | { |
433 | int r; | |
434 | struct dev_manager *dm; | |
b65b777d | 435 | struct lvinfo info; |
10b29b8d AK |
436 | |
437 | if (!activation()) | |
438 | return 0; | |
439 | ||
5f4b2acf AK |
440 | if (!lv_info(cmd, lv, &info, 0)) |
441 | return_0; | |
b65b777d AK |
442 | |
443 | if (!info.exists) | |
444 | return 0; | |
445 | ||
5f4b2acf AK |
446 | if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) |
447 | return_0; | |
10b29b8d AK |
448 | |
449 | if (!(r = dev_manager_mirror_percent(dm, lv, wait, percent, event_nr))) | |
450 | stack; | |
451 | ||
452 | dev_manager_destroy(dm); | |
453 | ||
454 | return r; | |
455 | } | |
456 | ||
f894b4b1 | 457 | static int _lv_active(struct cmd_context *cmd, struct logical_volume *lv) |
2ba80b43 | 458 | { |
199e490e | 459 | struct lvinfo info; |
2ba80b43 | 460 | |
f894b4b1 | 461 | if (!lv_info(cmd, lv, &info, 0)) { |
2ba80b43 | 462 | stack; |
de6c9183 | 463 | return -1; |
2ba80b43 JT |
464 | } |
465 | ||
de6c9183 | 466 | return info.exists; |
2ba80b43 JT |
467 | } |
468 | ||
f894b4b1 | 469 | static int _lv_open_count(struct cmd_context *cmd, struct logical_volume *lv) |
5986ec94 | 470 | { |
199e490e | 471 | struct lvinfo info; |
5986ec94 | 472 | |
f894b4b1 | 473 | if (!lv_info(cmd, lv, &info, 1)) { |
5986ec94 | 474 | stack; |
de6c9183 | 475 | return -1; |
5986ec94 JT |
476 | } |
477 | ||
de6c9183 | 478 | return info.open_count; |
5986ec94 JT |
479 | } |
480 | ||
658b5812 | 481 | static int _lv_activate_lv(struct logical_volume *lv) |
b1713d28 | 482 | { |
6d52fb46 | 483 | int r; |
de6c9183 | 484 | struct dev_manager *dm; |
b1713d28 | 485 | |
5f4b2acf AK |
486 | if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) |
487 | return_0; | |
ae2bb665 | 488 | |
0fe3a2c5 | 489 | if (!(r = dev_manager_activate(dm, lv))) |
6d52fb46 | 490 | stack; |
ae2bb665 | 491 | |
de6c9183 | 492 | dev_manager_destroy(dm); |
ae2bb665 | 493 | return r; |
b1713d28 | 494 | } |
a381c45a | 495 | |
5f4b2acf | 496 | static int _lv_preload(struct logical_volume *lv) |
0a5e4a14 | 497 | { |
de6c9183 JT |
498 | int r; |
499 | struct dev_manager *dm; | |
37ed70b9 | 500 | |
5f4b2acf AK |
501 | if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) |
502 | return_0; | |
503 | ||
504 | if (!(r = dev_manager_preload(dm, lv))) | |
6d52fb46 | 505 | stack; |
5f4b2acf AK |
506 | |
507 | dev_manager_destroy(dm); | |
508 | return r; | |
509 | } | |
510 | ||
511 | static int _lv_deactivate(struct logical_volume *lv) | |
512 | { | |
513 | int r; | |
514 | struct dev_manager *dm; | |
515 | ||
516 | if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) | |
517 | return_0; | |
37ed70b9 | 518 | |
de6c9183 | 519 | if (!(r = dev_manager_deactivate(dm, lv))) |
37ed70b9 | 520 | stack; |
37ed70b9 | 521 | |
de6c9183 JT |
522 | dev_manager_destroy(dm); |
523 | return r; | |
37ed70b9 JT |
524 | } |
525 | ||
658b5812 | 526 | static int _lv_suspend_lv(struct logical_volume *lv) |
4a624ca0 | 527 | { |
20c5fcf7 AK |
528 | int r; |
529 | struct dev_manager *dm; | |
c2d72fd4 | 530 | |
5f4b2acf AK |
531 | if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) |
532 | return_0; | |
0a5e4a14 | 533 | |
20c5fcf7 | 534 | if (!(r = dev_manager_suspend(dm, lv))) |
37ed70b9 | 535 | stack; |
0a5e4a14 | 536 | |
20c5fcf7 AK |
537 | dev_manager_destroy(dm); |
538 | return r; | |
6d52fb46 | 539 | } |
4a624ca0 | 540 | |
8c013da4 | 541 | /* |
f75c11ed | 542 | * These two functions return the number of visible LVs in the state, |
8c013da4 AK |
543 | * or -1 on error. |
544 | */ | |
f047219b AK |
545 | int lvs_in_vg_activated(struct volume_group *vg) |
546 | { | |
60f13f01 | 547 | struct lv_list *lvl; |
94b8220f | 548 | int count = 0; |
37ed70b9 | 549 | |
d1d9800e AK |
550 | if (!activation()) |
551 | return 0; | |
552 | ||
60f13f01 AK |
553 | list_iterate_items(lvl, &vg->lvs) { |
554 | if (lvl->lv->status & VISIBLE_LV) | |
f894b4b1 | 555 | count += (_lv_active(vg->cmd, lvl->lv) == 1); |
37ed70b9 JT |
556 | } |
557 | ||
558 | return count; | |
f047219b | 559 | } |
2ba80b43 JT |
560 | |
561 | int lvs_in_vg_opened(struct volume_group *vg) | |
562 | { | |
60f13f01 | 563 | struct lv_list *lvl; |
94b8220f | 564 | int count = 0; |
2ba80b43 | 565 | |
d1d9800e AK |
566 | if (!activation()) |
567 | return 0; | |
568 | ||
60f13f01 AK |
569 | list_iterate_items(lvl, &vg->lvs) { |
570 | if (lvl->lv->status & VISIBLE_LV) | |
f894b4b1 | 571 | count += (_lv_open_count(vg->cmd, lvl->lv) > 0); |
2ba80b43 JT |
572 | } |
573 | ||
574 | return count; | |
575 | } | |
413cc918 | 576 | |
ed09d7e3 AK |
577 | static int _register_dev_for_events(struct cmd_context *cmd, |
578 | struct logical_volume *lv, int do_reg) | |
15d91f5a | 579 | { |
ed09d7e3 | 580 | #ifdef DMEVENTD |
15d91f5a AK |
581 | struct list *tmp; |
582 | struct lv_segment *seg; | |
583 | int (*reg) (struct dm_pool *mem, struct lv_segment *, | |
584 | struct config_tree *cft, int events); | |
585 | ||
586 | list_iterate(tmp, &lv->segments) { | |
587 | seg = list_item(tmp, struct lv_segment); | |
588 | ||
ed09d7e3 AK |
589 | reg = NULL; |
590 | ||
e6493477 AK |
591 | if (do_reg) { |
592 | if (seg->segtype->ops->target_register_events) | |
593 | reg = seg->segtype->ops->target_register_events; | |
bbf83db1 | 594 | } else if (seg->segtype->ops->target_unregister_events) |
e6493477 | 595 | reg = seg->segtype->ops->target_unregister_events; |
15d91f5a | 596 | |
e24e7130 AK |
597 | if (!reg) |
598 | return_0; | |
599 | ||
15d91f5a | 600 | /* FIXME specify events */ |
e24e7130 AK |
601 | if (!reg(cmd->mem, seg, cmd->cft, 0)) { |
602 | stack; | |
603 | return 0; | |
604 | } | |
15d91f5a | 605 | } |
e6493477 | 606 | |
ed09d7e3 | 607 | #endif |
15d91f5a AK |
608 | return 1; |
609 | } | |
15d91f5a | 610 | |
658b5812 AK |
611 | static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s, |
612 | int error_if_not_suspended) | |
413cc918 | 613 | { |
8b888354 | 614 | struct logical_volume *lv, *lv_pre; |
199e490e | 615 | struct lvinfo info; |
413cc918 | 616 | |
d1d9800e AK |
617 | if (!activation()) |
618 | return 1; | |
619 | ||
8b888354 | 620 | if (!(lv = lv_from_lvid(cmd, lvid_s, 0))) |
e408d62e | 621 | return_0; |
8b888354 | 622 | |
7a593325 | 623 | /* Use precommitted metadata if present */ |
8b888354 | 624 | if (!(lv_pre = lv_from_lvid(cmd, lvid_s, 1))) |
e408d62e | 625 | return_0; |
413cc918 | 626 | |
20c5fcf7 AK |
627 | if (test_mode()) { |
628 | _skip("Suspending '%s'.", lv->name); | |
711f7fc6 | 629 | return 1; |
20c5fcf7 AK |
630 | } |
631 | ||
5f4b2acf AK |
632 | if (!lv_info(cmd, lv, &info, 0)) |
633 | return_0; | |
41967a02 | 634 | |
914c9723 | 635 | if (!info.exists || info.suspended) |
658b5812 | 636 | return error_if_not_suspended ? 0 : 1; |
914c9723 | 637 | |
5f4b2acf | 638 | /* If VG was precommitted, preload devices for the LV */ |
8b888354 AK |
639 | if ((lv_pre->vg->status & PRECOMMITTED)) { |
640 | if (!_lv_preload(lv_pre)) { | |
5f4b2acf AK |
641 | /* FIXME Revert preloading */ |
642 | return_0; | |
643 | } | |
644 | } | |
645 | ||
ed09d7e3 | 646 | if (!_register_dev_for_events(cmd, lv, 0)) |
e24e7130 | 647 | /* FIXME Consider aborting here */ |
ed09d7e3 AK |
648 | stack; |
649 | ||
914c9723 | 650 | memlock_inc(); |
e408d62e | 651 | if (!_lv_suspend_lv(lv)) { |
914c9723 AK |
652 | memlock_dec(); |
653 | fs_unlock(); | |
654 | return 0; | |
655 | } | |
8c013da4 | 656 | |
413cc918 AK |
657 | return 1; |
658 | } | |
659 | ||
658b5812 AK |
660 | /* Returns success if the device is not active */ |
661 | int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s) | |
662 | { | |
663 | return _lv_suspend(cmd, lvid_s, 0); | |
664 | } | |
665 | ||
666 | int lv_suspend(struct cmd_context *cmd, const char *lvid_s) | |
667 | { | |
668 | return _lv_suspend(cmd, lvid_s, 1); | |
669 | } | |
670 | ||
671 | static int _lv_resume(struct cmd_context *cmd, const char *lvid_s, | |
672 | int error_if_not_active) | |
413cc918 AK |
673 | { |
674 | struct logical_volume *lv; | |
199e490e | 675 | struct lvinfo info; |
413cc918 | 676 | |
d1d9800e AK |
677 | if (!activation()) |
678 | return 1; | |
679 | ||
7a593325 | 680 | if (!(lv = lv_from_lvid(cmd, lvid_s, 0))) |
413cc918 AK |
681 | return 0; |
682 | ||
20c5fcf7 AK |
683 | if (test_mode()) { |
684 | _skip("Resuming '%s'.", lv->name); | |
711f7fc6 | 685 | return 1; |
20c5fcf7 AK |
686 | } |
687 | ||
5f4b2acf AK |
688 | if (!lv_info(cmd, lv, &info, 0)) |
689 | return_0; | |
41967a02 | 690 | |
914c9723 | 691 | if (!info.exists || !info.suspended) |
658b5812 | 692 | return error_if_not_active ? 0 : 1; |
914c9723 | 693 | |
658b5812 | 694 | if (!_lv_activate_lv(lv)) |
914c9723 AK |
695 | return 0; |
696 | ||
697 | memlock_dec(); | |
698 | fs_unlock(); | |
413cc918 | 699 | |
ed09d7e3 AK |
700 | if (!_register_dev_for_events(cmd, lv, 1)) |
701 | stack; | |
15d91f5a | 702 | |
413cc918 AK |
703 | return 1; |
704 | } | |
705 | ||
658b5812 AK |
706 | /* Returns success if the device is not active */ |
707 | int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s) | |
708 | { | |
709 | return _lv_resume(cmd, lvid_s, 0); | |
710 | } | |
711 | ||
712 | int lv_resume(struct cmd_context *cmd, const char *lvid_s) | |
713 | { | |
714 | return _lv_resume(cmd, lvid_s, 1); | |
715 | } | |
716 | ||
be326a2f | 717 | int lv_deactivate(struct cmd_context *cmd, const char *lvid_s) |
f4cbeaf0 AK |
718 | { |
719 | struct logical_volume *lv; | |
199e490e | 720 | struct lvinfo info; |
914c9723 | 721 | int r; |
f4cbeaf0 | 722 | |
d1d9800e AK |
723 | if (!activation()) |
724 | return 1; | |
725 | ||
7a593325 | 726 | if (!(lv = lv_from_lvid(cmd, lvid_s, 0))) |
f4cbeaf0 AK |
727 | return 0; |
728 | ||
20c5fcf7 AK |
729 | if (test_mode()) { |
730 | _skip("Deactivating '%s'.", lv->name); | |
711f7fc6 | 731 | return 1; |
20c5fcf7 AK |
732 | } |
733 | ||
5f4b2acf AK |
734 | if (!lv_info(cmd, lv, &info, 1)) |
735 | return_0; | |
41967a02 | 736 | |
914c9723 AK |
737 | if (!info.exists) |
738 | return 1; | |
f4cbeaf0 | 739 | |
c1f50521 | 740 | if (info.open_count && (lv->status & VISIBLE_LV)) { |
5f4b2acf | 741 | log_error("LV %s/%s in use: not deactivating", lv->vg->name, |
0cf96f33 AK |
742 | lv->name); |
743 | return 0; | |
744 | } | |
745 | ||
ed09d7e3 AK |
746 | if (!_register_dev_for_events(cmd, lv, 0)) |
747 | stack; | |
15d91f5a | 748 | |
914c9723 AK |
749 | memlock_inc(); |
750 | r = _lv_deactivate(lv); | |
751 | memlock_dec(); | |
752 | fs_unlock(); | |
753 | ||
754 | return r; | |
f4cbeaf0 AK |
755 | } |
756 | ||
658b5812 AK |
757 | /* Test if LV passes filter */ |
758 | int lv_activation_filter(struct cmd_context *cmd, const char *lvid_s, | |
759 | int *activate_lv) | |
760 | { | |
761 | struct logical_volume *lv; | |
762 | ||
763 | if (!activation()) | |
764 | goto activate; | |
765 | ||
7a593325 | 766 | if (!(lv = lv_from_lvid(cmd, lvid_s, 0))) |
658b5812 AK |
767 | return 0; |
768 | ||
769 | if (!_passes_activation_filter(cmd, lv)) { | |
770 | log_verbose("Not activating %s/%s due to config file settings", | |
771 | lv->vg->name, lv->name); | |
772 | *activate_lv = 0; | |
773 | return 1; | |
774 | } | |
775 | ||
776 | activate: | |
777 | *activate_lv = 1; | |
778 | return 1; | |
779 | } | |
780 | ||
07d31831 AK |
781 | static int _lv_activate(struct cmd_context *cmd, const char *lvid_s, |
782 | int exclusive, int filter) | |
f4cbeaf0 AK |
783 | { |
784 | struct logical_volume *lv; | |
199e490e | 785 | struct lvinfo info; |
914c9723 | 786 | int r; |
f4cbeaf0 | 787 | |
d1d9800e AK |
788 | if (!activation()) |
789 | return 1; | |
790 | ||
7a593325 | 791 | if (!(lv = lv_from_lvid(cmd, lvid_s, 0))) |
f4cbeaf0 AK |
792 | return 0; |
793 | ||
658b5812 | 794 | if (filter && !_passes_activation_filter(cmd, lv)) { |
de17d760 AK |
795 | log_verbose("Not activating %s/%s due to config file settings", |
796 | lv->vg->name, lv->name); | |
797 | return 0; | |
798 | } | |
799 | ||
20c5fcf7 AK |
800 | if (test_mode()) { |
801 | _skip("Activating '%s'.", lv->name); | |
711f7fc6 | 802 | return 1; |
20c5fcf7 AK |
803 | } |
804 | ||
5f4b2acf AK |
805 | if (!lv_info(cmd, lv, &info, 0)) |
806 | return_0; | |
8c013da4 | 807 | |
5f4b2acf | 808 | if (info.exists && !info.suspended && info.live_table) |
914c9723 | 809 | return 1; |
f4cbeaf0 | 810 | |
07d31831 AK |
811 | if (exclusive) |
812 | lv->status |= ACTIVATE_EXCL; | |
813 | ||
914c9723 | 814 | memlock_inc(); |
658b5812 | 815 | r = _lv_activate_lv(lv); |
914c9723 AK |
816 | memlock_dec(); |
817 | fs_unlock(); | |
818 | ||
ed09d7e3 AK |
819 | if (!_register_dev_for_events(cmd, lv, 1)) |
820 | stack; | |
15d91f5a | 821 | |
914c9723 | 822 | return r; |
f4cbeaf0 | 823 | } |
199e490e | 824 | |
658b5812 | 825 | /* Activate LV */ |
07d31831 | 826 | int lv_activate(struct cmd_context *cmd, const char *lvid_s, int exclusive) |
658b5812 | 827 | { |
07d31831 | 828 | return _lv_activate(cmd, lvid_s, exclusive, 0); |
658b5812 AK |
829 | } |
830 | ||
831 | /* Activate LV only if it passes filter */ | |
07d31831 | 832 | int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s, int exclusive) |
658b5812 | 833 | { |
07d31831 | 834 | return _lv_activate(cmd, lvid_s, exclusive, 1); |
658b5812 AK |
835 | } |
836 | ||
f7dd6d84 AK |
837 | int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv) |
838 | { | |
839 | struct lvinfo info; | |
840 | int r = 1; | |
841 | ||
8b076648 | 842 | if (!lv) { |
2262b320 | 843 | r = dm_mknodes(NULL); |
8b076648 AK |
844 | fs_unlock(); |
845 | return r; | |
846 | } | |
847 | ||
5f4b2acf AK |
848 | if (!_lv_info(cmd, lv, 1, &info, 0)) |
849 | return_0; | |
f7dd6d84 AK |
850 | |
851 | if (info.exists) | |
f09fe0ad | 852 | r = dev_manager_lv_mknodes(lv); |
f7dd6d84 | 853 | else |
f09fe0ad | 854 | r = dev_manager_lv_rmnodes(lv); |
f7dd6d84 AK |
855 | |
856 | fs_unlock(); | |
857 | ||
858 | return r; | |
859 | } | |
860 | ||
352a99b9 AK |
861 | /* |
862 | * Does PV use VG somewhere in its construction? | |
863 | * Returns 1 on failure. | |
864 | */ | |
865 | int pv_uses_vg(struct cmd_context *cmd, struct physical_volume *pv, | |
866 | struct volume_group *vg) | |
867 | { | |
868 | struct dev_manager *dm; | |
869 | int r; | |
870 | ||
871 | if (!activation()) | |
872 | return 0; | |
873 | ||
874 | if (!dm_is_dm_major(MAJOR(pv->dev->dev))) | |
875 | return 0; | |
876 | ||
877 | if (!(dm = dev_manager_create(cmd, vg->name))) { | |
878 | stack; | |
879 | return 1; | |
880 | } | |
881 | ||
882 | r = dev_manager_device_uses_vg(dm, pv->dev, vg); | |
883 | ||
884 | dev_manager_destroy(dm); | |
885 | ||
886 | return r; | |
887 | } | |
888 | ||
914c9723 AK |
889 | void activation_exit(void) |
890 | { | |
891 | dev_manager_exit(); | |
892 | } | |
199e490e | 893 | #endif |