]> sourceware.org Git - lvm2.git/blame - lib/activate/activate.c
Keep same sign for 's' counter
[lvm2.git] / lib / activate / activate.c
CommitLineData
b1713d28 1/*
67cdbd7e 2 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
a18dcfb5 3 * Copyright (C) 2004-2012 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
be684599 9 * of the GNU Lesser General Public License v.2.1.
6606c3ae 10 *
be684599 11 * You should have received a copy of the GNU Lesser General Public License
6606c3ae
AK
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"
d1e8046f 31#include "sharedlib.h"
12137231
JT
32
33#include <limits.h>
5986ec94 34#include <fcntl.h>
914c9723 35#include <unistd.h>
12137231 36
6d52fb46 37#define _skip(fmt, args...) log_very_verbose("Skipping: " fmt , ## args)
b1713d28 38
7d1552c9
AK
39int lvm1_present(struct cmd_context *cmd)
40{
900f5f81 41 static char path[PATH_MAX];
7d1552c9 42
0550c1b6 43 if (dm_snprintf(path, sizeof(path), "%s/lvm/global", cmd->proc_dir)
7d1552c9
AK
44 < 0) {
45 log_error("LVM1 proc global snprintf failed");
46 return 0;
47 }
48
49 if (path_exists(path))
50 return 1;
51 else
52 return 0;
53}
54
6c81ed26 55int list_segment_modules(struct dm_pool *mem, const struct lv_segment *seg,
2c44337b 56 struct dm_list *modules)
6c81ed26
AK
57{
58 unsigned int s;
59 struct lv_segment *seg2, *snap_seg;
2c44337b 60 struct dm_list *snh;
6c81ed26
AK
61
62 if (seg->segtype->ops->modules_needed &&
63 !seg->segtype->ops->modules_needed(mem, seg, modules)) {
64 log_error("module string allocation failed");
65 return 0;
66 }
67
68 if (lv_is_origin(seg->lv))
2c44337b 69 dm_list_iterate(snh, &seg->lv->snapshot_segs)
6c81ed26 70 if (!list_lv_modules(mem,
2c44337b 71 dm_list_struct_base(snh,
6c81ed26
AK
72 struct lv_segment,
73 origin_list)->cow,
74 modules))
75 return_0;
76
77 if (lv_is_cow(seg->lv)) {
78 snap_seg = find_cow(seg->lv);
79 if (snap_seg->segtype->ops->modules_needed &&
80 !snap_seg->segtype->ops->modules_needed(mem, snap_seg,
81 modules)) {
82 log_error("snap_seg module string allocation failed");
83 return 0;
84 }
85 }
86
87 for (s = 0; s < seg->area_count; s++) {
88 switch (seg_type(seg, s)) {
89 case AREA_LV:
90 seg2 = find_seg_by_le(seg_lv(seg, s), seg_le(seg, s));
91 if (seg2 && !list_segment_modules(mem, seg2, modules))
92 return_0;
93 break;
94 case AREA_PV:
95 case AREA_UNASSIGNED:
96 ;
97 }
98 }
99
100 return 1;
101}
102
103int list_lv_modules(struct dm_pool *mem, const struct logical_volume *lv,
2c44337b 104 struct dm_list *modules)
6c81ed26
AK
105{
106 struct lv_segment *seg;
107
2c44337b 108 dm_list_iterate_items(seg, &lv->segments)
6c81ed26
AK
109 if (!list_segment_modules(mem, seg, modules))
110 return_0;
111
112 return 1;
113}
114
199e490e
AK
115#ifndef DEVMAPPER_SUPPORT
116void set_activation(int act)
117{
f2046e0a
AK
118 static int warned = 0;
119
120 if (warned || !act)
121 return;
122
123 log_error("Compiled without libdevmapper support. "
124 "Can't enable activation.");
125
126 warned = 1;
199e490e
AK
127}
128int activation(void)
129{
130 return 0;
131}
132int library_version(char *version, size_t size)
133{
134 return 0;
135}
136int driver_version(char *version, size_t size)
137{
138 return 0;
139}
bbf83db1
AK
140int target_version(const char *target_name, uint32_t *maj,
141 uint32_t *min, uint32_t *patchlevel)
142{
143 return 0;
144}
ed82bfd2
AK
145int target_present(struct cmd_context *cmd, const char *target_name,
146 int use_modprobe)
d1f4953a
AK
147{
148 return 0;
149}
b1859936 150int lvm_dm_prefix_check(int major, int minor, const char *prefix)
07113bee
MB
151{
152 return 0;
153}
e8905d98 154int lv_info(struct cmd_context *cmd, const struct logical_volume *lv, int use_layer,
2d6fcbf6 155 struct lvinfo *info, int with_open_count, int with_read_ahead)
199e490e
AK
156{
157 return 0;
158}
e8905d98 159int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s, int use_layer,
a6b22cf3 160 struct lvinfo *info, int with_open_count, int with_read_ahead)
4bd9480d
AK
161{
162 return 0;
163}
b1859936
ZK
164int lv_check_not_in_use(struct cmd_context *cmd __attribute__((unused)),
165 struct logical_volume *lv, struct lvinfo *info)
166{
167 return 0;
168}
8191fe4f 169int lv_snapshot_percent(const struct logical_volume *lv, percent_t *percent)
199e490e
AK
170{
171 return 0;
172}
aec21154 173int lv_mirror_percent(struct cmd_context *cmd, const struct logical_volume *lv,
8191fe4f 174 int wait, percent_t *percent, uint32_t *event_nr)
10b29b8d
AK
175{
176 return 0;
177}
b1859936
ZK
178int lv_raid_percent(const struct logical_volume *lv, percent_t *percent)
179{
180 return 0;
181}
182int lv_thin_pool_percent(const struct logical_volume *lv, int metadata,
183 percent_t *percent)
184{
185 return 0;
186}
187int lv_thin_percent(const struct logical_volume *lv, int mapped,
188 percent_t *percent)
189{
190 return 0;
191}
192int lv_thin_pool_transaction_id(const struct logical_volume *lv,
193 uint64_t *transaction_id)
194{
195 return 0;
196}
199e490e
AK
197int lvs_in_vg_activated(struct volume_group *vg)
198{
199 return 0;
200}
ab8b85fb 201int lvs_in_vg_opened(const struct volume_group *vg)
199e490e
AK
202{
203 return 0;
204}
2d6fcbf6 205/******
658b5812
AK
206int lv_suspend(struct cmd_context *cmd, const char *lvid_s)
207{
208 return 1;
209}
2d6fcbf6 210*******/
b1859936 211int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s, unsigned origin_only, unsigned exclusive)
199e490e
AK
212{
213 return 1;
214}
ab8b85fb 215int lv_resume(struct cmd_context *cmd, const char *lvid_s, unsigned origin_only)
658b5812
AK
216{
217 return 1;
218}
ab8b85fb 219int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s,
10d0d9c7 220 unsigned origin_only, unsigned exclusive, unsigned revert)
199e490e
AK
221{
222 return 1;
223}
224int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)
225{
226 return 1;
227}
658b5812
AK
228int lv_activation_filter(struct cmd_context *cmd, const char *lvid_s,
229 int *activate_lv)
230{
231 return 1;
232}
07d31831 233int lv_activate(struct cmd_context *cmd, const char *lvid_s, int exclusive)
199e490e
AK
234{
235 return 1;
236}
07d31831 237int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s, int exclusive)
658b5812
AK
238{
239 return 1;
240}
f7dd6d84
AK
241int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv)
242{
243 return 1;
244}
a00cb3a6
ZK
245int lv_send_message(const struct logical_volume *lv, const char *message)
246{
247 return 0;
248}
0ce83a83 249int pv_uses_vg(struct physical_volume *pv,
3e3d5d85 250 struct volume_group *vg)
352a99b9
AK
251{
252 return 0;
253}
2293567c
AK
254void activation_release(void)
255{
2293567c 256}
914c9723
AK
257void activation_exit(void)
258{
914c9723 259}
b19f0121 260
ab8b85fb
ZK
261int lv_is_active(struct logical_volume *lv)
262{
263 return 0;
264}
b19f0121
JEB
265int lv_is_active_but_not_locally(struct logical_volume *lv)
266{
267 return 0;
268}
269int lv_is_active_exclusive(struct logical_volume *lv)
270{
271 return 0;
272}
ab8b85fb
ZK
273int lv_is_active_exclusive_locally(struct logical_volume *lv)
274{
275 return 0;
276}
277int lv_is_active_exclusive_remotely(struct logical_volume *lv)
278{
279 return 0;
280}
b19f0121 281
ab8b85fb
ZK
282int lv_check_transient(struct logical_volume *lv)
283{
284 return 1;
285}
286int monitor_dev_for_events(struct cmd_context *cmd, struct logical_volume *lv,
b1859936 287 const struct lv_activate_opts *laopts, int monitor)
ab8b85fb
ZK
288{
289 return 1;
290}
b1859936
ZK
291/* fs.c */
292void fs_unlock(void)
293{
294}
295/* dev_manager.c */
296int add_areas_line(struct dev_manager *dm, struct lv_segment *seg,
297 struct dm_tree_node *node, uint32_t start_area,
298 uint32_t areas)
299{
300 return 0;
301}
302int device_is_usable(struct device *dev)
303{
304 return 0;
305}
306int lv_has_target_type(struct dm_pool *mem, struct logical_volume *lv,
307 const char *layer, const char *target_type)
308{
309 return 0;
310}
199e490e
AK
311#else /* DEVMAPPER_SUPPORT */
312
d1d9800e
AK
313static int _activation = 1;
314
8ef2b021 315void set_activation(int act)
d1d9800e 316{
8ef2b021 317 if (act == _activation)
d1d9800e
AK
318 return;
319
8ef2b021 320 _activation = act;
d1d9800e
AK
321 if (_activation)
322 log_verbose("Activation enabled. Device-mapper kernel "
323 "driver will be used.");
324 else
e7ddf416 325 log_warn("WARNING: Activation disabled. No device-mapper "
bfe2b548 326 "interaction will be attempted.");
d1d9800e
AK
327}
328
8ef2b021 329int activation(void)
d1d9800e
AK
330{
331 return _activation;
332}
333
a18dcfb5
AK
334static int _passes_volumes_filter(struct cmd_context *cmd,
335 struct logical_volume *lv,
336 const struct dm_config_node *cn,
337 const char *config_path)
de17d760 338{
e59e2f7c 339 const struct dm_config_value *cv;
760d1fac 340 const char *str;
900f5f81 341 static char path[PATH_MAX];
de17d760 342
a18dcfb5
AK
343 log_verbose("%s configuration setting defined: "
344 "Checking the list to match %s/%s",
345 config_path, lv->vg->name, lv->name);
fefa4323 346
f7e3a19f 347 for (cv = cn->v; cv; cv = cv->next) {
e59e2f7c 348 if (cv->type != DM_CFG_STRING) {
a18dcfb5
AK
349 log_error("Ignoring invalid string in config file %s",
350 config_path);
de17d760
AK
351 continue;
352 }
353 str = cv->v.str;
354 if (!*str) {
a18dcfb5
AK
355 log_error("Ignoring empty string in config file %s",
356 config_path);
de17d760
AK
357 continue;
358 }
359
f7e3a19f 360
de17d760
AK
361 /* Tag? */
362 if (*str == '@') {
363 str++;
364 if (!*str) {
365 log_error("Ignoring empty tag in config file "
a18dcfb5 366 "%s", config_path);
de17d760
AK
367 continue;
368 }
369 /* If any host tag matches any LV or VG tag, activate */
370 if (!strcmp(str, "*")) {
eb82bd05 371 if (str_list_match_list(&cmd->tags, &lv->tags, NULL)
de17d760 372 || str_list_match_list(&cmd->tags,
eb82bd05 373 &lv->vg->tags, NULL))
de17d760
AK
374 return 1;
375 else
376 continue;
377 }
378 /* If supplied tag matches LV or VG tag, activate */
379 if (str_list_match_item(&lv->tags, str) ||
380 str_list_match_item(&lv->vg->tags, str))
381 return 1;
382 else
383 continue;
384 }
13835b5f 385 if (!strchr(str, '/')) {
de17d760
AK
386 /* vgname supplied */
387 if (!strcmp(str, lv->vg->name))
388 return 1;
389 else
390 continue;
391 }
392 /* vgname/lvname */
0550c1b6 393 if (dm_snprintf(path, sizeof(path), "%s/%s", lv->vg->name,
de17d760 394 lv->name) < 0) {
0550c1b6 395 log_error("dm_snprintf error from %s/%s", lv->vg->name,
de17d760
AK
396 lv->name);
397 continue;
398 }
399 if (!strcmp(path, str))
400 return 1;
401 }
402
a18dcfb5
AK
403 log_verbose("No item supplied in %s configuration setting "
404 "matches %s/%s", config_path, lv->vg->name, lv->name);
fefa4323 405
de17d760
AK
406 return 0;
407}
408
a18dcfb5
AK
409static int _passes_activation_filter(struct cmd_context *cmd,
410 struct logical_volume *lv)
411{
412 const struct dm_config_node *cn;
413
414 if (!(cn = find_config_tree_node(cmd, "activation/volume_list"))) {
415 log_verbose("activation/volume_list configuration setting "
416 "not defined: Checking only host tags for %s/%s",
417 lv->vg->name, lv->name);
418
419 /* If no host tags defined, activate */
420 if (dm_list_empty(&cmd->tags))
421 return 1;
422
423 /* If any host tag matches any LV or VG tag, activate */
424 if (str_list_match_list(&cmd->tags, &lv->tags, NULL) ||
425 str_list_match_list(&cmd->tags, &lv->vg->tags, NULL))
426 return 1;
427
428 log_verbose("No host tag matches %s/%s",
429 lv->vg->name, lv->name);
430
431 /* Don't activate */
432 return 0;
433 }
434
435 return _passes_volumes_filter(cmd, lv, cn, "activation/volume_list");
436}
437
438static int _passes_readonly_filter(struct cmd_context *cmd,
439 struct logical_volume *lv)
440{
5d5c80ac 441 const struct dm_config_node *cn;
a18dcfb5
AK
442
443 if (!(cn = find_config_tree_node(cmd, "activation/read_only_volume_list")))
444 return 0;
445
446 return _passes_volumes_filter(cmd, lv, cn, "activation/read_only_volume_list");
447}
448
fae0c576
AK
449int library_version(char *version, size_t size)
450{
d1d9800e
AK
451 if (!activation())
452 return 0;
453
f894b4b1 454 return dm_get_library_version(version, size);
fae0c576
AK
455}
456
fae0c576
AK
457int driver_version(char *version, size_t size)
458{
d1d9800e
AK
459 if (!activation())
460 return 0;
461
fae0c576 462 log_very_verbose("Getting driver version");
fae0c576 463
f894b4b1 464 return dm_driver_version(version, size);
fae0c576
AK
465}
466
bbf83db1
AK
467int target_version(const char *target_name, uint32_t *maj,
468 uint32_t *min, uint32_t *patchlevel)
d1f4953a
AK
469{
470 int r = 0;
471 struct dm_task *dmt;
472 struct dm_versions *target, *last_target;
473
d1f4953a 474 log_very_verbose("Getting target version for %s", target_name);
5f4b2acf
AK
475 if (!(dmt = dm_task_create(DM_DEVICE_LIST_VERSIONS)))
476 return_0;
d1f4953a 477
2243718f
AK
478 if (activation_checks() && !dm_task_enable_checks(dmt))
479 goto_out;
480
d1f4953a
AK
481 if (!dm_task_run(dmt)) {
482 log_debug("Failed to get %s target version", target_name);
483 /* Assume this was because LIST_VERSIONS isn't supported */
209da6ef
ZK
484 *maj = 0;
485 *min = 0;
486 *patchlevel = 0;
487 r = 1;
488 goto out;
d1f4953a
AK
489 }
490
491 target = dm_task_get_versions(dmt);
492
493 do {
494 last_target = target;
495
496 if (!strcmp(target_name, target->name)) {
497 r = 1;
bbf83db1
AK
498 *maj = target->version[0];
499 *min = target->version[1];
500 *patchlevel = target->version[2];
d1f4953a
AK
501 goto out;
502 }
503
d40d166f 504 target = (struct dm_versions *)((char *) target + target->next);
d1f4953a
AK
505 } while (last_target != target);
506
507 out:
508 dm_task_destroy(dmt);
509
510 return r;
511}
512
a3390bb5 513int lvm_dm_prefix_check(int major, int minor, const char *prefix)
07113bee
MB
514{
515 struct dm_task *dmt;
516 const char *uuid;
517 int r;
518
519 if (!(dmt = dm_task_create(DM_DEVICE_STATUS)))
d1b36fbe 520 return_0;
07113bee
MB
521
522 if (!dm_task_set_minor(dmt, minor) ||
523 !dm_task_set_major(dmt, major) ||
524 !dm_task_run(dmt) ||
525 !(uuid = dm_task_get_uuid(dmt))) {
526 dm_task_destroy(dmt);
527 return 0;
528 }
529
530 r = strncasecmp(uuid, prefix, strlen(prefix));
531 dm_task_destroy(dmt);
532
d1b36fbe 533 return r ? 0 : 1;
07113bee
MB
534}
535
ed82bfd2 536int module_present(struct cmd_context *cmd, const char *target_name)
f894b4b1 537{
5619c629 538 int ret = 0;
03b49fe1 539#ifdef MODPROBE_CMD
f894b4b1 540 char module[128];
c8669f6b 541 const char *argv[3];
5619c629
MB
542
543 if (dm_snprintf(module, sizeof(module), "dm-%s", target_name) < 0) {
544 log_error("module_present module name too long: %s",
545 target_name);
546 return 0;
547 }
548
c8669f6b
ZK
549 argv[0] = MODPROBE_CMD;
550 argv[1] = module;
551 argv[2] = NULL;
552
b1b38215 553 ret = exec_cmd(cmd, argv, NULL, 0);
03b49fe1 554#endif
5619c629
MB
555 return ret;
556}
557
ed82bfd2
AK
558int target_present(struct cmd_context *cmd, const char *target_name,
559 int use_modprobe)
5619c629
MB
560{
561 uint32_t maj, min, patchlevel;
f894b4b1
AK
562
563 if (!activation())
564 return 0;
565
566#ifdef MODPROBE_CMD
5f4b2acf 567 if (use_modprobe) {
bbf83db1 568 if (target_version(target_name, &maj, &min, &patchlevel))
5f4b2acf 569 return 1;
f894b4b1 570
ed82bfd2 571 if (!module_present(cmd, target_name))
5f4b2acf 572 return_0;
f894b4b1
AK
573 }
574#endif
575
bbf83db1 576 return target_version(target_name, &maj, &min, &patchlevel);
f894b4b1
AK
577}
578
de6c9183
JT
579/*
580 * Returns 1 if info structure populated, else 0 on failure.
581 */
e8905d98 582int lv_info(struct cmd_context *cmd, const struct logical_volume *lv, int use_layer,
ab9663f3 583 struct lvinfo *info, int with_open_count, int with_read_ahead)
37ed70b9 584{
199e490e 585 struct dm_info dminfo;
e8905d98 586 const char *layer;
4a624ca0 587
d1d9800e
AK
588 if (!activation())
589 return 0;
56cab8cc
ZK
590 /*
591 * If open_count info is requested and we have to be sure our own udev
592 * transactions are finished
593 * For non-clustered locking type we are only interested for non-delete operation
594 * in progress - as only those could lead to opened files
595 */
596 if (with_open_count) {
597 if (locking_is_clustered())
598 sync_local_dev_names(cmd); /* Wait to have udev in sync */
f5f6dcbc 599 else if (fs_has_non_delete_ops())
56cab8cc
ZK
600 fs_unlock(); /* For non clustered - wait if there are non-delete ops */
601 }
d1d9800e 602
e8905d98
ZK
603 if (use_layer && lv_is_thin_pool(lv))
604 layer = "tpool";
605 else if (use_layer && lv_is_origin(lv))
606 layer = "real";
607 else
608 layer = NULL;
609
610 if (!dev_manager_info(lv->vg->cmd->mem, lv, layer, with_open_count,
ab9663f3 611 with_read_ahead, &dminfo, &info->read_ahead))
5f4b2acf 612 return_0;
4a624ca0 613
199e490e
AK
614 info->exists = dminfo.exists;
615 info->suspended = dminfo.suspended;
616 info->open_count = dminfo.open_count;
617 info->major = dminfo.major;
618 info->minor = dminfo.minor;
619 info->read_only = dminfo.read_only;
5f4b2acf
AK
620 info->live_table = dminfo.live_table;
621 info->inactive_table = dminfo.inactive_table;
199e490e 622
f894b4b1 623 return 1;
de6c9183 624}
a62ee8ad 625
e8905d98 626int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s, int use_layer,
a6b22cf3 627 struct lvinfo *info, int with_open_count, int with_read_ahead)
4bd9480d 628{
0548bcc2 629 int r;
4bd9480d
AK
630 struct logical_volume *lv;
631
7a593325 632 if (!(lv = lv_from_lvid(cmd, lvid_s, 0)))
4bd9480d
AK
633 return 0;
634
e8905d98 635 r = lv_info(cmd, lv, use_layer, info, with_open_count, with_read_ahead);
077a6755 636 release_vg(lv->vg);
0548bcc2
MB
637
638 return r;
4bd9480d
AK
639}
640
125712be
PR
641int lv_check_not_in_use(struct cmd_context *cmd __attribute__((unused)),
642 struct logical_volume *lv, struct lvinfo *info)
643{
644 if (!info->exists)
645 return 1;
646
647 /* If sysfs is not used, use open_count information only. */
c3e5b497
PR
648 if (!*dm_sysfs_dir()) {
649 if (info->open_count) {
650 log_error("Logical volume %s/%s in use.",
651 lv->vg->name, lv->name);
652 return 0;
653 }
654
655 return 1;
656 }
125712be
PR
657
658 if (dm_device_has_holders(info->major, info->minor)) {
659 log_error("Logical volume %s/%s is used by another device.",
660 lv->vg->name, lv->name);
661 return 0;
662 }
663
664 if (dm_device_has_mounted_fs(info->major, info->minor)) {
665 log_error("Logical volume %s/%s contains a filesystem in use.",
666 lv->vg->name, lv->name);
667 return 0;
668 }
669
670 return 1;
671}
672
d345bf2c
PR
673/*
674 * Returns 1 if percent set, else 0 on failure.
675 */
676int lv_check_transient(struct logical_volume *lv)
677{
678 int r;
679 struct dev_manager *dm;
680
681 if (!activation())
682 return 0;
683
7df72b3c
AK
684 log_debug("Checking transient status for LV %s/%s", lv->vg->name, lv->name);
685
df390f17 686 if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
d345bf2c
PR
687 return_0;
688
689 if (!(r = dev_manager_transient(dm, lv)))
690 stack;
691
692 dev_manager_destroy(dm);
693
694 return r;
695}
696
1951dba9
AL
697/*
698 * Returns 1 if percent set, else 0 on failure.
699 */
8191fe4f 700int lv_snapshot_percent(const struct logical_volume *lv, percent_t *percent)
1951dba9
AL
701{
702 int r;
703 struct dev_manager *dm;
704
d1d9800e
AK
705 if (!activation())
706 return 0;
707
7df72b3c
AK
708 log_debug("Checking snapshot percent for LV %s/%s", lv->vg->name, lv->name);
709
df390f17 710 if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
5f4b2acf 711 return_0;
1951dba9 712
8191fe4f 713 if (!(r = dev_manager_snapshot_percent(dm, lv, percent)))
1951dba9 714 stack;
c826c0d1 715
1951dba9
AL
716 dev_manager_destroy(dm);
717
718 return r;
719}
720
10b29b8d 721/* FIXME Merge with snapshot_percent */
aec21154 722int lv_mirror_percent(struct cmd_context *cmd, const struct logical_volume *lv,
8191fe4f 723 int wait, percent_t *percent, uint32_t *event_nr)
10b29b8d
AK
724{
725 int r;
726 struct dev_manager *dm;
b65b777d 727 struct lvinfo info;
10b29b8d 728
876003dc
AK
729 /* If mirrored LV is temporarily shrinked to 1 area (= linear),
730 * it should be considered in-sync. */
2c44337b 731 if (dm_list_size(&lv->segments) == 1 && first_seg(lv)->area_count == 1) {
8191fe4f 732 *percent = PERCENT_100;
876003dc
AK
733 return 1;
734 }
735
10b29b8d
AK
736 if (!activation())
737 return 0;
738
7df72b3c
AK
739 log_debug("Checking mirror percent for LV %s/%s", lv->vg->name, lv->name);
740
2d6fcbf6 741 if (!lv_info(cmd, lv, 0, &info, 0, 0))
5f4b2acf 742 return_0;
b65b777d
AK
743
744 if (!info.exists)
745 return 0;
746
df390f17 747 if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
5f4b2acf 748 return_0;
10b29b8d 749
8191fe4f 750 if (!(r = dev_manager_mirror_percent(dm, lv, wait, percent, event_nr)))
10b29b8d
AK
751 stack;
752
753 dev_manager_destroy(dm);
754
755 return r;
756}
757
4aebd52c
JEB
758int lv_raid_percent(const struct logical_volume *lv, percent_t *percent)
759{
760 return lv_mirror_percent(lv->vg->cmd, lv, 0, percent, NULL);
761}
762
34507894 763/*
63368983 764 * Returns data or metadata percent usage, depends on metadata 0/1.
34507894
ZK
765 * Returns 1 if percent set, else 0 on failure.
766 */
63368983
ZK
767int lv_thin_pool_percent(const struct logical_volume *lv, int metadata,
768 percent_t *percent)
34507894
ZK
769{
770 int r;
771 struct dev_manager *dm;
772
773 if (!activation())
774 return 0;
775
63368983
ZK
776 log_debug("Checking thin %sdata percent for LV %s/%s",
777 (metadata) ? "meta" : "", lv->vg->name, lv->name);
34507894
ZK
778
779 if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
780 return_0;
781
63368983 782 if (!(r = dev_manager_thin_pool_percent(dm, lv, metadata, percent)))
34507894
ZK
783 stack;
784
785 dev_manager_destroy(dm);
786
787 return r;
788}
789
76ee0899
ZK
790/*
791 * Returns 1 if percent set, else 0 on failure.
792 */
793int lv_thin_percent(const struct logical_volume *lv,
794 int mapped, percent_t *percent)
795{
796 int r;
797 struct dev_manager *dm;
798
799 if (!activation())
800 return 0;
801
802 log_debug("Checking thin percent for LV %s/%s",
803 lv->vg->name, lv->name);
804
805 if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
806 return_0;
807
808 if (!(r = dev_manager_thin_percent(dm, lv, mapped, percent)))
809 stack;
810
811 dev_manager_destroy(dm);
812
813 return r;
814}
815
bdba904d
ZK
816/*
817 * Returns 1 if transaction_id set, else 0 on failure.
818 */
819int lv_thin_pool_transaction_id(const struct logical_volume *lv,
820 uint64_t *transaction_id)
821{
822 int r;
823 struct dev_manager *dm;
824 struct dm_status_thin_pool *status;
825
826 if (!activation())
827 return 0;
828
829 log_debug("Checking thin percent for LV %s/%s",
830 lv->vg->name, lv->name);
831
832 if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
833 return_0;
834
835 if (!(r = dev_manager_thin_pool_status(dm, lv, &status)))
836 stack;
837 else
838 *transaction_id = status->transaction_id;
839
840 dev_manager_destroy(dm);
841
842 return r;
843}
844
ab9663f3 845static int _lv_active(struct cmd_context *cmd, struct logical_volume *lv)
2ba80b43 846{
199e490e 847 struct lvinfo info;
2ba80b43 848
2d6fcbf6 849 if (!lv_info(cmd, lv, 0, &info, 0, 0)) {
2ba80b43 850 stack;
de6c9183 851 return -1;
2ba80b43
JT
852 }
853
de6c9183 854 return info.exists;
2ba80b43
JT
855}
856
f894b4b1 857static int _lv_open_count(struct cmd_context *cmd, struct logical_volume *lv)
5986ec94 858{
199e490e 859 struct lvinfo info;
5986ec94 860
2d6fcbf6 861 if (!lv_info(cmd, lv, 0, &info, 1, 0)) {
5986ec94 862 stack;
de6c9183 863 return -1;
5986ec94
JT
864 }
865
de6c9183 866 return info.open_count;
5986ec94
JT
867}
868
81beded3 869static int _lv_activate_lv(struct logical_volume *lv, struct lv_activate_opts *laopts)
b1713d28 870{
6d52fb46 871 int r;
de6c9183 872 struct dev_manager *dm;
b1713d28 873
df390f17 874 if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, (lv->status & PVMOVE) ? 0 : 1)))
5f4b2acf 875 return_0;
ae2bb665 876
81beded3 877 if (!(r = dev_manager_activate(dm, lv, laopts)))
6d52fb46 878 stack;
ae2bb665 879
de6c9183 880 dev_manager_destroy(dm);
ae2bb665 881 return r;
b1713d28 882}
a381c45a 883
81beded3
ZK
884static int _lv_preload(struct logical_volume *lv, struct lv_activate_opts *laopts,
885 int *flush_required)
0a5e4a14 886{
a18dcfb5 887 int r = 0;
de6c9183 888 struct dev_manager *dm;
a18dcfb5
AK
889 int old_readonly = laopts->read_only;
890
891 laopts->read_only = _passes_readonly_filter(lv->vg->cmd, lv);
37ed70b9 892
df390f17 893 if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, (lv->status & PVMOVE) ? 0 : 1)))
a18dcfb5 894 goto_out;
5f4b2acf 895
81beded3 896 if (!(r = dev_manager_preload(dm, lv, laopts, flush_required)))
6d52fb46 897 stack;
5f4b2acf
AK
898
899 dev_manager_destroy(dm);
a18dcfb5
AK
900
901 laopts->read_only = old_readonly;
902out:
5f4b2acf
AK
903 return r;
904}
905
906static int _lv_deactivate(struct logical_volume *lv)
907{
908 int r;
909 struct dev_manager *dm;
910
df390f17 911 if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
5f4b2acf 912 return_0;
37ed70b9 913
de6c9183 914 if (!(r = dev_manager_deactivate(dm, lv)))
37ed70b9 915 stack;
37ed70b9 916
de6c9183
JT
917 dev_manager_destroy(dm);
918 return r;
37ed70b9
JT
919}
920
81beded3
ZK
921static int _lv_suspend_lv(struct logical_volume *lv, struct lv_activate_opts *laopts,
922 int lockfs, int flush_required)
4a624ca0 923{
20c5fcf7
AK
924 int r;
925 struct dev_manager *dm;
c2d72fd4 926
a18dcfb5
AK
927 laopts->read_only = _passes_readonly_filter(lv->vg->cmd, lv);
928
df390f17
AK
929 /*
930 * When we are asked to manipulate (normally suspend/resume) the PVMOVE
931 * device directly, we don't want to touch the devices that use it.
932 */
933 if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, (lv->status & PVMOVE) ? 0 : 1)))
5f4b2acf 934 return_0;
0a5e4a14 935
81beded3 936 if (!(r = dev_manager_suspend(dm, lv, laopts, lockfs, flush_required)))
37ed70b9 937 stack;
0a5e4a14 938
20c5fcf7
AK
939 dev_manager_destroy(dm);
940 return r;
6d52fb46 941}
4a624ca0 942
8c013da4 943/*
f75c11ed 944 * These two functions return the number of visible LVs in the state,
7df72b3c 945 * or -1 on error. FIXME Check this.
8c013da4 946 */
65752052 947int lvs_in_vg_activated(struct volume_group *vg)
f047219b 948{
60f13f01 949 struct lv_list *lvl;
94b8220f 950 int count = 0;
37ed70b9 951
d1d9800e
AK
952 if (!activation())
953 return 0;
954
7df72b3c 955 dm_list_iterate_items(lvl, &vg->lvs)
59d8429c 956 if (lv_is_visible(lvl->lv))
ab9663f3 957 count += (_lv_active(vg->cmd, lvl->lv) == 1);
7df72b3c
AK
958
959 log_debug("Counted %d active LVs in VG %s", count, vg->name);
37ed70b9
JT
960
961 return count;
f047219b 962}
2ba80b43 963
08c9ff43 964int lvs_in_vg_opened(const struct volume_group *vg)
2ba80b43 965{
08c9ff43 966 const struct lv_list *lvl;
94b8220f 967 int count = 0;
2ba80b43 968
d1d9800e
AK
969 if (!activation())
970 return 0;
971
7df72b3c 972 dm_list_iterate_items(lvl, &vg->lvs)
87371d48 973 if (lv_is_visible(lvl->lv))
f894b4b1 974 count += (_lv_open_count(vg->cmd, lvl->lv) > 0);
7df72b3c
AK
975
976 log_debug("Counted %d open LVs in VG %s", count, vg->name);
2ba80b43
JT
977
978 return count;
979}
413cc918 980
5ca6698f 981/*
27ff8813
JEB
982 * _lv_is_active
983 * @lv: logical volume being queried
984 * @locally: set if active locally (when provided)
985 * @exclusive: set if active exclusively (when provided)
986 *
5ca6698f 987 * Determine whether an LV is active locally or in a cluster.
27ff8813
JEB
988 * In addition to the return code which indicates whether or
989 * not the LV is active somewhere, two other values are set
990 * to yield more information about the status of the activation:
991 * return locally exclusively status
992 * ====== ======= =========== ======
993 * 0 0 0 not active
994 * 1 0 0 active remotely
995 * 1 0 1 exclusive remotely
996 * 1 1 0 active locally and possibly remotely
997 * 1 1 1 exclusive locally (or local && !cluster)
998 * The VG lock must be held to call this function.
999 *
1000 * Returns: 0 or 1
5ca6698f 1001 */
27ff8813
JEB
1002static int _lv_is_active(struct logical_volume *lv,
1003 int *locally, int *exclusive)
5ca6698f 1004{
27ff8813
JEB
1005 int r, l, e; /* remote, local, and exclusive */
1006
1007 r = l = e = 0;
6ac30c94 1008
ab9663f3 1009 if (_lv_active(lv->vg->cmd, lv))
27ff8813 1010 l = 1;
5ca6698f 1011
27ff8813 1012 if (!vg_is_clustered(lv->vg)) {
f5bfc8b1
AK
1013 if (l)
1014 e = 1; /* exclusive by definition */
27ff8813
JEB
1015 goto out;
1016 }
1017
1018 /* Active locally, and the caller doesn't care about exclusive */
1019 if (l && !exclusive)
1020 goto out;
5ca6698f 1021
27ff8813
JEB
1022 if ((r = remote_lock_held(lv->lvid.s, &e)) >= 0)
1023 goto out;
6ac30c94
MB
1024
1025 /*
27ff8813
JEB
1026 * If lock query is not supported (due to interfacing with old
1027 * code), then we cannot evaluate exclusivity properly.
1028 *
1029 * Old users of this function will never be affected by this,
1030 * since they are only concerned about active vs. not active.
1031 * New users of this function who specifically ask for 'exclusive'
1032 * will be given an error message.
6ac30c94 1033 */
f5bfc8b1
AK
1034 log_error("Unable to determine exclusivity of %s", lv->name);
1035
1036 e = 0;
1037
1038 /*
1039 * We used to attempt activate_lv_excl_local(lv->vg->cmd, lv) here,
1040 * but it's unreliable.
1041 */
27ff8813 1042
27ff8813
JEB
1043out:
1044 if (locally)
1045 *locally = l;
1046 if (exclusive)
1047 *exclusive = e;
1048
1049 log_very_verbose("%s/%s is %sactive%s%s",
1050 lv->vg->name, lv->name,
1051 (r || l) ? "" : "not ",
1052 (exclusive && e) ? " exclusive" : "",
1053 e ? (l ? " locally" : " remotely") : "");
1054
1055 return r || l;
1056}
1057
1058int lv_is_active(struct logical_volume *lv)
1059{
1060 return _lv_is_active(lv, NULL, NULL);
1061}
1062
9e277b9e 1063int lv_is_active_but_not_locally(struct logical_volume *lv)
27ff8813
JEB
1064{
1065 int l;
9e277b9e 1066 return _lv_is_active(lv, &l, NULL) && !l;
27ff8813 1067}
27ff8813 1068
b19f0121
JEB
1069int lv_is_active_exclusive(struct logical_volume *lv)
1070{
1071 int e;
1072
1073 return _lv_is_active(lv, NULL, &e) && e;
1074}
1075
27ff8813
JEB
1076int lv_is_active_exclusive_locally(struct logical_volume *lv)
1077{
1078 int l, e;
7df72b3c 1079
27ff8813
JEB
1080 return _lv_is_active(lv, &l, &e) && l && e;
1081}
1082
1083int lv_is_active_exclusive_remotely(struct logical_volume *lv)
1084{
1085 int l, e;
7df72b3c 1086
27ff8813 1087 return _lv_is_active(lv, &l, &e) && !l && e;
5ca6698f
DW
1088}
1089
d1e8046f
AK
1090#ifdef DMEVENTD
1091static struct dm_event_handler *_create_dm_event_handler(struct cmd_context *cmd, const char *dmuuid, const char *dso,
1092 const int timeout, enum dm_event_mask mask)
1093{
1094 struct dm_event_handler *dmevh;
1095
1096 if (!(dmevh = dm_event_handler_create()))
1097 return_NULL;
1098
1099 if (dm_event_handler_set_dmeventd_path(dmevh, find_config_tree_str(cmd, "dmeventd/executable", NULL)))
1100 goto_bad;
1101
1102 if (dm_event_handler_set_dso(dmevh, dso))
1103 goto_bad;
1104
1105 if (dm_event_handler_set_uuid(dmevh, dmuuid))
1106 goto_bad;
1107
1108 dm_event_handler_set_timeout(dmevh, timeout);
1109 dm_event_handler_set_event_mask(dmevh, mask);
1110
1111 return dmevh;
1112
1113bad:
1114 dm_event_handler_destroy(dmevh);
1115 return NULL;
1116}
1117
1118char *get_monitor_dso_path(struct cmd_context *cmd, const char *libpath)
1119{
1120 char *path;
1121
1122 if (!(path = dm_pool_alloc(cmd->mem, PATH_MAX))) {
1123 log_error("Failed to allocate dmeventd library path.");
1124 return NULL;
1125 }
1126
1127 get_shared_library_path(cmd, libpath, path, PATH_MAX);
1128
1129 return path;
1130}
1131
2bc1d759
ZK
1132static char *_build_target_uuid(struct cmd_context *cmd, struct logical_volume *lv)
1133{
1134 const char *layer;
1135
1136 if (lv_is_thin_pool(lv))
1137 layer = "tpool"; /* Monitor "tpool" for the "thin pool". */
1138 else if (lv_is_origin(lv))
1139 layer = "real"; /* Monitor "real" for "snapshot-origin". */
1140 else
1141 layer = NULL;
1142
1143 return build_dm_uuid(cmd->mem, lv->lvid.s, layer);
1144}
1145
f92b4f94
AK
1146int target_registered_with_dmeventd(struct cmd_context *cmd, const char *dso,
1147 struct logical_volume *lv, int *pending)
d1e8046f
AK
1148{
1149 char *uuid;
1150 enum dm_event_mask evmask = 0;
1151 struct dm_event_handler *dmevh;
d1e8046f
AK
1152 *pending = 0;
1153
1154 if (!dso)
1155 return_0;
1156
2bc1d759 1157 if (!(uuid = _build_target_uuid(cmd, lv)))
d1e8046f
AK
1158 return_0;
1159
1160 if (!(dmevh = _create_dm_event_handler(cmd, uuid, dso, 0, DM_EVENT_ALL_ERRORS)))
1161 return_0;
1162
1163 if (dm_event_get_registered_device(dmevh, 0)) {
1164 dm_event_handler_destroy(dmevh);
1165 return 0;
1166 }
1167
1168 evmask = dm_event_handler_get_event_mask(dmevh);
1169 if (evmask & DM_EVENT_REGISTRATION_PENDING) {
1170 *pending = 1;
1171 evmask &= ~DM_EVENT_REGISTRATION_PENDING;
1172 }
1173
1174 dm_event_handler_destroy(dmevh);
1175
1176 return evmask;
1177}
1178
f92b4f94 1179int target_register_events(struct cmd_context *cmd, const char *dso, struct logical_volume *lv,
d1e8046f
AK
1180 int evmask __attribute__((unused)), int set, int timeout)
1181{
1182 char *uuid;
1183 struct dm_event_handler *dmevh;
1184 int r;
1185
1186 if (!dso)
1187 return_0;
1188
f92b4f94 1189 /* We always monitor the "real" device, never the "snapshot-origin" itself. */
2bc1d759 1190 if (!(uuid = _build_target_uuid(cmd, lv)))
d1e8046f
AK
1191 return_0;
1192
1193 if (!(dmevh = _create_dm_event_handler(cmd, uuid, dso, timeout,
1194 DM_EVENT_ALL_ERRORS | (timeout ? DM_EVENT_TIMEOUT : 0))))
1195 return_0;
1196
1197 r = set ? dm_event_register_handler(dmevh) : dm_event_unregister_handler(dmevh);
1198
1199 dm_event_handler_destroy(dmevh);
1200
1201 if (!r)
1202 return_0;
1203
1204 log_info("%s %s for events", set ? "Monitored" : "Unmonitored", uuid);
1205
1206 return 1;
1207}
1208
1209#endif
1210
3e3d5d85 1211/*
8a37910d
AK
1212 * Returns 0 if an attempt to (un)monitor the device failed.
1213 * Returns 1 otherwise.
3e3d5d85 1214 */
2d6fcbf6 1215int monitor_dev_for_events(struct cmd_context *cmd, struct logical_volume *lv,
81beded3 1216 const struct lv_activate_opts *laopts, int monitor)
15d91f5a 1217{
ed09d7e3 1218#ifdef DMEVENTD
8a37910d
AK
1219 int i, pending = 0, monitored;
1220 int r = 1;
2c44337b 1221 struct dm_list *tmp, *snh, *snht;
15d91f5a 1222 struct lv_segment *seg;
7a369d37 1223 struct lv_segment *log_seg;
24f4552b 1224 int (*monitor_fn) (struct lv_segment *s, int e);
4e9083db 1225 uint32_t s;
81beded3
ZK
1226 static const struct lv_activate_opts zlaopts = { 0 };
1227
1228 if (!laopts)
1229 laopts = &zlaopts;
15d91f5a 1230
20db8ffc
AK
1231 /* skip dmeventd code altogether */
1232 if (dmeventd_monitor_mode() == DMEVENTD_MONITOR_IGNORE)
1233 return 1;
1234
8a37910d
AK
1235 /*
1236 * Nothing to do if dmeventd configured not to be used.
1237 */
1238 if (monitor && !dmeventd_monitor_mode())
3e3d5d85
AK
1239 return 1;
1240
67961c7c
PR
1241 /*
1242 * In case of a snapshot device, we monitor lv->snapshot->lv,
1243 * not the actual LV itself.
1244 */
c6168a14
ZK
1245 if (lv_is_cow(lv) && (laopts->no_merging || !lv_is_merging_cow(lv)))
1246 return monitor_dev_for_events(cmd, lv->snapshot->lv, NULL, monitor);
67961c7c
PR
1247
1248 /*
1249 * In case this LV is a snapshot origin, we instead monitor
f92b4f94
AK
1250 * each of its respective snapshots. The origin itself may
1251 * also need to be monitored if it is a mirror, for example.
67961c7c 1252 */
81beded3 1253 if (!laopts->origin_only && lv_is_origin(lv))
2c44337b
AK
1254 dm_list_iterate_safe(snh, snht, &lv->snapshot_segs)
1255 if (!monitor_dev_for_events(cmd, dm_list_struct_base(snh,
81beded3 1256 struct lv_segment, origin_list)->cow, NULL, monitor))
0c06de63 1257 r = 0;
67961c7c 1258
7a369d37
JEB
1259 /*
1260 * If the volume is mirrored and its log is also mirrored, monitor
1261 * the log volume as well.
1262 */
1263 if ((seg = first_seg(lv)) != NULL && seg->log_lv != NULL &&
1264 (log_seg = first_seg(seg->log_lv)) != NULL &&
1265 seg_is_mirrored(log_seg))
81beded3 1266 if (!monitor_dev_for_events(cmd, seg->log_lv, NULL, monitor))
7a369d37
JEB
1267 r = 0;
1268
2c44337b
AK
1269 dm_list_iterate(tmp, &lv->segments) {
1270 seg = dm_list_item(tmp, struct lv_segment);
15d91f5a 1271
4e9083db
AK
1272 /* Recurse for AREA_LV */
1273 for (s = 0; s < seg->area_count; s++) {
1274 if (seg_type(seg, s) != AREA_LV)
1275 continue;
81beded3 1276 if (!monitor_dev_for_events(cmd, seg_lv(seg, s), NULL,
4e9083db
AK
1277 monitor)) {
1278 log_error("Failed to %smonitor %s",
1279 monitor ? "" : "un",
1280 seg_lv(seg, s)->name);
1281 r = 0;
1282 }
1283 }
1284
8ef6eb30
AK
1285 if (!seg_monitored(seg) || (seg->status & PVMOVE))
1286 continue;
8a37910d
AK
1287
1288 monitor_fn = NULL;
ed09d7e3 1289
8ef6eb30 1290 /* Check monitoring status */
8a37910d
AK
1291 if (seg->segtype->ops->target_monitored)
1292 monitored = seg->segtype->ops->target_monitored(seg, &pending);
8ef6eb30
AK
1293 else
1294 continue; /* segtype doesn't support registration */
1295
1296 /*
1297 * FIXME: We should really try again if pending
1298 */
8a37910d 1299 monitored = (pending) ? 0 : monitored;
8ef6eb30 1300
8a37910d
AK
1301 if (monitor) {
1302 if (monitored)
8ef6eb30 1303 log_verbose("%s/%s already monitored.", lv->vg->name, lv->name);
8a37910d
AK
1304 else if (seg->segtype->ops->target_monitor_events)
1305 monitor_fn = seg->segtype->ops->target_monitor_events;
8ef6eb30 1306 } else {
8a37910d 1307 if (!monitored)
8ef6eb30 1308 log_verbose("%s/%s already not monitored.", lv->vg->name, lv->name);
8a37910d
AK
1309 else if (seg->segtype->ops->target_unmonitor_events)
1310 monitor_fn = seg->segtype->ops->target_unmonitor_events;
8ef6eb30 1311 }
15d91f5a 1312
8ef6eb30 1313 /* Do [un]monitor */
8a37910d 1314 if (!monitor_fn)
3e3d5d85 1315 continue;
e24e7130 1316
85a80e05
AK
1317 log_verbose("%sonitoring %s/%s%s", monitor ? "M" : "Not m", lv->vg->name, lv->name,
1318 test_mode() ? " [Test mode: skipping this]" : "");
1319
1320 /* FIXME Test mode should really continue a bit further. */
1321 if (test_mode())
1322 continue;
8a37910d 1323
3e3d5d85 1324 /* FIXME specify events */
57fc4cc0 1325 if (!monitor_fn(seg, 0)) {
8a37910d
AK
1326 log_error("%s/%s: %s segment monitoring function failed.",
1327 lv->vg->name, lv->name, seg->segtype->name);
1328 return 0;
e24e7130 1329 }
3e3d5d85 1330
8ef6eb30
AK
1331 /* Check [un]monitor results */
1332 /* Try a couple times if pending, but not forever... */
1333 for (i = 0; i < 10; i++) {
1334 pending = 0;
8a37910d 1335 monitored = seg->segtype->ops->target_monitored(seg, &pending);
8ef6eb30 1336 if (pending ||
8a37910d
AK
1337 (!monitored && monitor) ||
1338 (monitored && !monitor))
1339 log_very_verbose("%s/%s %smonitoring still pending: waiting...",
1340 lv->vg->name, lv->name, monitor ? "" : "un");
8ef6eb30
AK
1341 else
1342 break;
1343 sleep(1);
1344 }
1345
85a80e05
AK
1346 if (r)
1347 r = (monitored && monitor) || (!monitored && !monitor);
15d91f5a 1348 }
e6493477 1349
3e3d5d85
AK
1350 return r;
1351#else
15d91f5a 1352 return 1;
3e3d5d85 1353#endif
15d91f5a 1354}
15d91f5a 1355
0f2a4ca2
AK
1356struct detached_lv_data {
1357 struct logical_volume *lv_pre;
1358 struct lv_activate_opts *laopts;
1359 int *flush_required;
1360};
1361
1362static int _preload_detached_lv(struct cmd_context *cmd, struct logical_volume *lv, void *data)
1363{
1364 struct detached_lv_data *detached = data;
1365 struct lv_list *lvl_pre;
1366
1367 if ((lvl_pre = find_lv_in_vg(detached->lv_pre->vg, lv->name))) {
ee840ff1 1368 if (lv_is_visible(lvl_pre->lv) && lv_is_active(lv) && (!lv_is_cow(lv) || !lv_is_cow(lvl_pre->lv)) &&
0f2a4ca2
AK
1369 !_lv_preload(lvl_pre->lv, detached->laopts, detached->flush_required))
1370 return_0;
1371 }
1372
1373 return 1;
1374}
1375
658b5812 1376static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
81beded3 1377 struct lv_activate_opts *laopts, int error_if_not_suspended)
413cc918 1378{
df390f17
AK
1379 struct logical_volume *lv = NULL, *lv_pre = NULL, *pvmove_lv = NULL;
1380 struct lv_list *lvl_pre;
1381 struct seg_list *sl;
ee840ff1 1382 struct lv_segment *snap_seg;
199e490e 1383 struct lvinfo info;
eb91c4ee 1384 int r = 0, lockfs = 0, flush_required = 0;
0f2a4ca2 1385 struct detached_lv_data detached;
413cc918 1386
d1d9800e
AK
1387 if (!activation())
1388 return 1;
1389
8b888354 1390 if (!(lv = lv_from_lvid(cmd, lvid_s, 0)))
095bbca6 1391 goto_out;
8b888354 1392
7a593325 1393 /* Use precommitted metadata if present */
8b888354 1394 if (!(lv_pre = lv_from_lvid(cmd, lvid_s, 1)))
095bbca6 1395 goto_out;
413cc918 1396
2d6fcbf6 1397 /* Ignore origin_only unless LV is origin in both old and new metadata */
efc8ca10 1398 if (!lv_is_thin_volume(lv) && !(lv_is_origin(lv) && lv_is_origin(lv_pre)))
81beded3 1399 laopts->origin_only = 0;
2d6fcbf6 1400
20c5fcf7 1401 if (test_mode()) {
81beded3 1402 _skip("Suspending %s%s.", lv->name, laopts->origin_only ? " origin without snapshots" : "");
095bbca6
MB
1403 r = 1;
1404 goto out;
20c5fcf7
AK
1405 }
1406
81beded3 1407 if (!lv_info(cmd, lv, laopts->origin_only, &info, 0, 0))
095bbca6 1408 goto_out;
41967a02 1409
095bbca6 1410 if (!info.exists || info.suspended) {
63ae0d14
MB
1411 if (!error_if_not_suspended) {
1412 r = 1;
1413 if (info.suspended)
df390f17 1414 critical_section_inc(cmd, "already suspended");
63ae0d14 1415 }
095bbca6
MB
1416 goto out;
1417 }
914c9723 1418
9249fb12
ZK
1419 if (!lv_read_replicator_vgs(lv))
1420 goto_out;
1421
c1fdeec9
MB
1422 lv_calculate_readahead(lv, NULL);
1423
df390f17 1424 /*
3a8eb387 1425 * Preload devices for the LV.
df390f17
AK
1426 * If the PVMOVE LV is being removed, it's only present in the old
1427 * metadata and not the new, so we must explicitly add the new
1428 * tables for all the changed LVs here, as the relationships
1429 * are not found by walking the new metadata.
1430 */
3a8eb387
AK
1431 if (!(lv_pre->status & LOCKED) &&
1432 (lv->status & LOCKED) &&
1433 (pvmove_lv = find_pvmove_lv_in_lv(lv))) {
1434 /* Preload all the LVs above the PVMOVE LV */
1435 dm_list_iterate_items(sl, &pvmove_lv->segs_using_this_lv) {
1436 if (!(lvl_pre = find_lv_in_vg(lv_pre->vg, sl->seg->lv->name))) {
ee840ff1 1437 log_error(INTERNAL_ERROR "LV %s missing from preload metadata", sl->seg->lv->name);
df390f17
AK
1438 goto out;
1439 }
81beded3 1440 if (!_lv_preload(lvl_pre->lv, laopts, &flush_required))
df390f17 1441 goto_out;
3a8eb387
AK
1442 }
1443 /* Now preload the PVMOVE LV itself */
1444 if (!(lvl_pre = find_lv_in_vg(lv_pre->vg, pvmove_lv->name))) {
ee840ff1 1445 log_error(INTERNAL_ERROR "LV %s missing from preload metadata", pvmove_lv->name);
3a8eb387
AK
1446 goto out;
1447 }
1448 if (!_lv_preload(lvl_pre->lv, laopts, &flush_required))
1449 goto_out;
1450 } else {
1451 if (!_lv_preload(lv_pre, laopts, &flush_required))
1452 /* FIXME Revert preloading */
1453 goto_out;
0f2a4ca2 1454
3a8eb387
AK
1455 /*
1456 * Search for existing LVs that have become detached and preload them.
1457 */
1458 detached.lv_pre = lv_pre;
1459 detached.laopts = laopts;
1460 detached.flush_required = &flush_required;
0f2a4ca2 1461
3a8eb387
AK
1462 if (!for_each_sub_lv(cmd, lv, &_preload_detached_lv, &detached))
1463 goto_out;
ee840ff1
AK
1464
1465 /*
1466 * Preload any snapshots that are being removed.
1467 */
1468 if (!laopts->origin_only && lv_is_origin(lv)) {
1469 dm_list_iterate_items_gen(snap_seg, &lv->snapshot_segs, origin_list) {
a73e9a6c
AK
1470 if (!(lvl_pre = find_lv_in_vg_by_lvid(lv_pre->vg, &snap_seg->cow->lvid))) {
1471 log_error(INTERNAL_ERROR "LV %s (%s) missing from preload metadata",
1472 snap_seg->cow->name, snap_seg->cow->lvid.id[1].uuid);
ee840ff1
AK
1473 goto out;
1474 }
1475 if (!lv_is_cow(lvl_pre->lv) &&
1476 !_lv_preload(lvl_pre->lv, laopts, &flush_required))
1477 goto_out;
1478 }
1479 }
5f4b2acf
AK
1480 }
1481
81beded3 1482 if (!monitor_dev_for_events(cmd, lv, laopts, 0))
e24e7130 1483 /* FIXME Consider aborting here */
ed09d7e3
AK
1484 stack;
1485
df390f17
AK
1486 critical_section_inc(cmd, "suspending");
1487 if (pvmove_lv)
1488 critical_section_inc(cmd, "suspending pvmove LV");
9cd3426d 1489
81beded3 1490 if (!laopts->origin_only &&
2d6fcbf6 1491 (lv_is_origin(lv_pre) || lv_is_cow(lv_pre)))
9cd3426d
AK
1492 lockfs = 1;
1493
df390f17
AK
1494 /*
1495 * Suspending an LV directly above a PVMOVE LV also
1496 * suspends other LVs using that same PVMOVE LV.
1497 * FIXME Remove this and delay the 'clear node' until
1498 * after the code knows whether there's a different
1499 * inactive table to load or not instead so lv_suspend
1500 * can be called separately for each LV safely.
1501 */
1502 if ((lv_pre->vg->status & PRECOMMITTED) &&
1503 (lv_pre->status & LOCKED) && find_pvmove_lv_in_lv(lv_pre)) {
81beded3 1504 if (!_lv_suspend_lv(lv_pre, laopts, lockfs, flush_required)) {
df390f17
AK
1505 critical_section_dec(cmd, "failed precommitted suspend");
1506 if (pvmove_lv)
1507 critical_section_dec(cmd, "failed precommitted suspend (pvmove)");
1508 goto_out;
1509 }
1510 } else {
1511 /* Normal suspend */
81beded3 1512 if (!_lv_suspend_lv(lv, laopts, lockfs, flush_required)) {
df390f17
AK
1513 critical_section_dec(cmd, "failed suspend");
1514 if (pvmove_lv)
1515 critical_section_dec(cmd, "failed suspend (pvmove)");
1516 goto_out;
1517 }
914c9723 1518 }
8c013da4 1519
095bbca6
MB
1520 r = 1;
1521out:
1522 if (lv_pre)
077a6755 1523 release_vg(lv_pre->vg);
9249fb12
ZK
1524 if (lv) {
1525 lv_release_replicator_vgs(lv);
077a6755 1526 release_vg(lv->vg);
9249fb12 1527 }
095bbca6
MB
1528
1529 return r;
413cc918
AK
1530}
1531
fd7d09e3
AK
1532/*
1533 * In a cluster, set exclusive to indicate that only one node is using the
1534 * device. Any preloaded tables may then use non-clustered targets.
1535 *
1536 * Returns success if the device is not active
1537 */
25d14105 1538int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s, unsigned origin_only, unsigned exclusive)
658b5812 1539{
25d14105
JEB
1540 struct lv_activate_opts laopts = {
1541 .origin_only = origin_only,
1542 .exclusive = exclusive
1543 };
81beded3
ZK
1544
1545 return _lv_suspend(cmd, lvid_s, &laopts, 0);
658b5812
AK
1546}
1547
2d6fcbf6
AK
1548/* No longer used */
1549/***********
658b5812
AK
1550int lv_suspend(struct cmd_context *cmd, const char *lvid_s)
1551{
1552 return _lv_suspend(cmd, lvid_s, 1);
1553}
2d6fcbf6 1554***********/
658b5812
AK
1555
1556static int _lv_resume(struct cmd_context *cmd, const char *lvid_s,
81beded3 1557 struct lv_activate_opts *laopts, int error_if_not_active)
413cc918
AK
1558{
1559 struct logical_volume *lv;
199e490e 1560 struct lvinfo info;
095bbca6 1561 int r = 0;
2258242f 1562 int messages_only = 0;
413cc918 1563
d1d9800e
AK
1564 if (!activation())
1565 return 1;
1566
7a593325 1567 if (!(lv = lv_from_lvid(cmd, lvid_s, 0)))
75b37a11 1568 goto_out;
413cc918 1569
2258242f
ZK
1570 if (lv_is_thin_pool(lv) && laopts->origin_only)
1571 messages_only = 1;
1572
2d6fcbf6 1573 if (!lv_is_origin(lv))
81beded3 1574 laopts->origin_only = 0;
2d6fcbf6 1575
20c5fcf7 1576 if (test_mode()) {
10d0d9c7
AK
1577 _skip("Resuming %s%s%s.", lv->name, laopts->origin_only ? " without snapshots" : "",
1578 laopts->revert ? " (reverting)" : "");
095bbca6
MB
1579 r = 1;
1580 goto out;
20c5fcf7
AK
1581 }
1582
10d0d9c7 1583 log_debug("Resuming LV %s/%s%s%s%s.", lv->vg->name, lv->name,
7df72b3c 1584 error_if_not_active ? "" : " if active",
10d0d9c7
AK
1585 laopts->origin_only ? " without snapshots" : "",
1586 laopts->revert ? " (reverting)" : "");
7df72b3c 1587
81beded3 1588 if (!lv_info(cmd, lv, laopts->origin_only, &info, 0, 0))
095bbca6 1589 goto_out;
41967a02 1590
2258242f 1591 if (!info.exists || !(info.suspended || messages_only)) {
4ec2ae86
ZK
1592 if (error_if_not_active)
1593 goto_out;
1594 r = 1;
df390f17
AK
1595 if (!info.suspended)
1596 critical_section_dec(cmd, "already resumed");
4ec2ae86 1597 goto out;
095bbca6 1598 }
914c9723 1599
a18dcfb5
AK
1600 laopts->read_only = _passes_readonly_filter(cmd, lv);
1601
81beded3 1602 if (!_lv_activate_lv(lv, laopts))
75b37a11 1603 goto_out;
914c9723 1604
df390f17 1605 critical_section_dec(cmd, "resumed");
413cc918 1606
81beded3 1607 if (!monitor_dev_for_events(cmd, lv, laopts, 1))
ed09d7e3 1608 stack;
15d91f5a 1609
095bbca6
MB
1610 r = 1;
1611out:
1612 if (lv)
077a6755 1613 release_vg(lv->vg);
095bbca6
MB
1614
1615 return r;
413cc918
AK
1616}
1617
fd7d09e3
AK
1618/*
1619 * In a cluster, set exclusive to indicate that only one node is using the
1620 * device. Any tables loaded may then use non-clustered targets.
1621 *
5c8b1486
ZK
1622 * @origin_only
1623 * @exclusive This parameter only has an affect in cluster-context.
1624 * It forces local target type to be used (instead of
1625 * cluster-aware type).
fd7d09e3
AK
1626 * Returns success if the device is not active
1627 */
c054e7cc 1628int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s,
fd7d09e3
AK
1629 unsigned origin_only, unsigned exclusive,
1630 unsigned revert)
658b5812 1631{
81beded3
ZK
1632 struct lv_activate_opts laopts = {
1633 .origin_only = origin_only,
10d0d9c7
AK
1634 .exclusive = exclusive,
1635 .revert = revert
81beded3
ZK
1636 };
1637
1638 return _lv_resume(cmd, lvid_s, &laopts, 0);
658b5812
AK
1639}
1640
2d6fcbf6 1641int lv_resume(struct cmd_context *cmd, const char *lvid_s, unsigned origin_only)
658b5812 1642{
81beded3
ZK
1643 struct lv_activate_opts laopts = { .origin_only = origin_only, };
1644
1645 return _lv_resume(cmd, lvid_s, &laopts, 1);
658b5812
AK
1646}
1647
64a95010
AK
1648static int _lv_has_open_snapshots(struct logical_volume *lv)
1649{
1650 struct lv_segment *snap_seg;
1651 struct lvinfo info;
1652 int r = 0;
1653
1654 dm_list_iterate_items_gen(snap_seg, &lv->snapshot_segs, origin_list) {
2d6fcbf6 1655 if (!lv_info(lv->vg->cmd, snap_seg->cow, 0, &info, 1, 0)) {
64a95010
AK
1656 r = 1;
1657 continue;
1658 }
1659
1660 if (info.exists && info.open_count) {
1661 log_error("LV %s/%s has open snapshot %s: "
1662 "not deactivating", lv->vg->name, lv->name,
1663 snap_seg->cow->name);
1664 r = 1;
1665 }
1666 }
1667
1668 return r;
1669}
1670
be326a2f 1671int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)
f4cbeaf0
AK
1672{
1673 struct logical_volume *lv;
199e490e 1674 struct lvinfo info;
095bbca6 1675 int r = 0;
f4cbeaf0 1676
d1d9800e
AK
1677 if (!activation())
1678 return 1;
1679
7a593325 1680 if (!(lv = lv_from_lvid(cmd, lvid_s, 0)))
095bbca6 1681 goto out;
f4cbeaf0 1682
20c5fcf7
AK
1683 if (test_mode()) {
1684 _skip("Deactivating '%s'.", lv->name);
095bbca6
MB
1685 r = 1;
1686 goto out;
20c5fcf7
AK
1687 }
1688
7df72b3c
AK
1689 log_debug("Deactivating %s/%s.", lv->vg->name, lv->name);
1690
2d6fcbf6 1691 if (!lv_info(cmd, lv, 0, &info, 1, 0))
095bbca6 1692 goto_out;
41967a02 1693
095bbca6
MB
1694 if (!info.exists) {
1695 r = 1;
1696 goto out;
1697 }
f4cbeaf0 1698
64a95010 1699 if (lv_is_visible(lv)) {
125712be
PR
1700 if (!lv_check_not_in_use(cmd, lv, &info))
1701 goto_out;
1702
64a95010
AK
1703 if (lv_is_origin(lv) && _lv_has_open_snapshots(lv))
1704 goto_out;
0cf96f33
AK
1705 }
1706
9249fb12
ZK
1707 if (!lv_read_replicator_vgs(lv))
1708 goto_out;
1709
c1fdeec9
MB
1710 lv_calculate_readahead(lv, NULL);
1711
81beded3 1712 if (!monitor_dev_for_events(cmd, lv, NULL, 0))
ed09d7e3 1713 stack;
15d91f5a 1714
df390f17 1715 critical_section_inc(cmd, "deactivating");
914c9723 1716 r = _lv_deactivate(lv);
df390f17 1717 critical_section_dec(cmd, "deactivated");
914c9723 1718
401a40d9 1719 if (!lv_info(cmd, lv, 0, &info, 0, 0) || info.exists)
89a6cdfd 1720 r = 0;
095bbca6 1721out:
9249fb12
ZK
1722 if (lv) {
1723 lv_release_replicator_vgs(lv);
077a6755 1724 release_vg(lv->vg);
9249fb12 1725 }
095bbca6 1726
914c9723 1727 return r;
f4cbeaf0
AK
1728}
1729
658b5812
AK
1730/* Test if LV passes filter */
1731int lv_activation_filter(struct cmd_context *cmd, const char *lvid_s,
1732 int *activate_lv)
1733{
1734 struct logical_volume *lv;
095bbca6 1735 int r = 0;
658b5812 1736
095bbca6
MB
1737 if (!activation()) {
1738 *activate_lv = 1;
1739 return 1;
1740 }
658b5812 1741
424dd43e 1742 if (!(lv = lv_from_lvid(cmd, lvid_s, 0)))
095bbca6 1743 goto out;
658b5812
AK
1744
1745 if (!_passes_activation_filter(cmd, lv)) {
f7e3a19f
PR
1746 log_verbose("Not activating %s/%s since it does not pass "
1747 "activation filter.", lv->vg->name, lv->name);
658b5812 1748 *activate_lv = 0;
095bbca6
MB
1749 } else
1750 *activate_lv = 1;
1751 r = 1;
1752out:
1753 if (lv)
077a6755 1754 release_vg(lv->vg);
658b5812 1755
095bbca6 1756 return r;
658b5812
AK
1757}
1758
07d31831 1759static int _lv_activate(struct cmd_context *cmd, const char *lvid_s,
81beded3 1760 struct lv_activate_opts *laopts, int filter)
f4cbeaf0
AK
1761{
1762 struct logical_volume *lv;
199e490e 1763 struct lvinfo info;
095bbca6 1764 int r = 0;
f4cbeaf0 1765
d1d9800e
AK
1766 if (!activation())
1767 return 1;
1768
424dd43e 1769 if (!(lv = lv_from_lvid(cmd, lvid_s, 0)))
095bbca6 1770 goto out;
f4cbeaf0 1771
658b5812 1772 if (filter && !_passes_activation_filter(cmd, lv)) {
f7e3a19f
PR
1773 log_error("Not activating %s/%s since it does not pass "
1774 "activation filter.", lv->vg->name, lv->name);
095bbca6 1775 goto out;
de17d760
AK
1776 }
1777
cda35408 1778 if ((!lv->vg->cmd->partial_activation) && (lv->status & PARTIAL_LV)) {
8c5bcdab
AK
1779 log_error("Refusing activation of partial LV %s. Use --partial to override.",
1780 lv->name);
095bbca6 1781 goto_out;
8c5bcdab
AK
1782 }
1783
b4048242
PR
1784 if (lv_has_unknown_segments(lv)) {
1785 log_error("Refusing activation of LV %s containing "
1786 "an unrecognised segment.", lv->name);
1787 goto_out;
1788 }
1789
20c5fcf7
AK
1790 if (test_mode()) {
1791 _skip("Activating '%s'.", lv->name);
095bbca6
MB
1792 r = 1;
1793 goto out;
20c5fcf7
AK
1794 }
1795
a18dcfb5
AK
1796 if (filter)
1797 laopts->read_only = _passes_readonly_filter(cmd, lv);
1798
1799 log_debug("Activating %s/%s%s%s.", lv->vg->name, lv->name,
1800 laopts->exclusive ? " exclusively" : "",
1801 laopts->read_only ? " read-only" : "");
7df72b3c 1802
2d6fcbf6 1803 if (!lv_info(cmd, lv, 0, &info, 0, 0))
095bbca6 1804 goto_out;
8c013da4 1805
a18dcfb5
AK
1806 /*
1807 * Nothing to do?
1808 */
1809 if (info.exists && !info.suspended && info.live_table &&
1810 (info.read_only == read_only_lv(lv, laopts))) {
095bbca6
MB
1811 r = 1;
1812 goto out;
1813 }
f4cbeaf0 1814
9249fb12
ZK
1815 if (!lv_read_replicator_vgs(lv))
1816 goto_out;
1817
c1fdeec9
MB
1818 lv_calculate_readahead(lv, NULL);
1819
df390f17 1820 critical_section_inc(cmd, "activating");
81beded3 1821 if (!(r = _lv_activate_lv(lv, laopts)))
75b37a11 1822 stack;
df390f17 1823 critical_section_dec(cmd, "activated");
914c9723 1824
81beded3 1825 if (r && !monitor_dev_for_events(cmd, lv, laopts, 1))
ed09d7e3 1826 stack;
15d91f5a 1827
095bbca6 1828out:
9249fb12
ZK
1829 if (lv) {
1830 lv_release_replicator_vgs(lv);
077a6755 1831 release_vg(lv->vg);
9249fb12 1832 }
095bbca6 1833
914c9723 1834 return r;
f4cbeaf0 1835}
199e490e 1836
658b5812 1837/* Activate LV */
07d31831 1838int lv_activate(struct cmd_context *cmd, const char *lvid_s, int exclusive)
658b5812 1839{
81beded3
ZK
1840 struct lv_activate_opts laopts = { .exclusive = exclusive };
1841
1842 if (!_lv_activate(cmd, lvid_s, &laopts, 0))
75b37a11
AK
1843 return_0;
1844
1845 return 1;
658b5812
AK
1846}
1847
1848/* Activate LV only if it passes filter */
07d31831 1849int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s, int exclusive)
658b5812 1850{
81beded3
ZK
1851 struct lv_activate_opts laopts = { .exclusive = exclusive };
1852
1853 if (!_lv_activate(cmd, lvid_s, &laopts, 1))
75b37a11
AK
1854 return_0;
1855
1856 return 1;
658b5812
AK
1857}
1858
f7dd6d84
AK
1859int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv)
1860{
f7dd6d84
AK
1861 int r = 1;
1862
8b076648 1863 if (!lv) {
2262b320 1864 r = dm_mknodes(NULL);
8b076648
AK
1865 fs_unlock();
1866 return r;
1867 }
1868
ab9663f3
MB
1869 if (!activation())
1870 return 1;
f7dd6d84 1871
ab9663f3 1872 r = dev_manager_mknodes(lv);
f7dd6d84
AK
1873
1874 fs_unlock();
1875
1876 return r;
1877}
1878
352a99b9
AK
1879/*
1880 * Does PV use VG somewhere in its construction?
1881 * Returns 1 on failure.
1882 */
898e6f8e 1883int pv_uses_vg(struct physical_volume *pv,
3e3d5d85 1884 struct volume_group *vg)
352a99b9 1885{
dae08226 1886 if (!activation() || !pv->dev)
352a99b9
AK
1887 return 0;
1888
1889 if (!dm_is_dm_major(MAJOR(pv->dev->dev)))
1890 return 0;
1891
898e6f8e 1892 return dev_manager_device_uses_vg(pv->dev, vg);
352a99b9
AK
1893}
1894
2293567c
AK
1895void activation_release(void)
1896{
1897 dev_manager_release();
1898}
1899
914c9723
AK
1900void activation_exit(void)
1901{
1902 dev_manager_exit();
1903}
199e490e 1904#endif
This page took 0.373134 seconds and 5 git commands to generate.