2 * Copyright (C) 2005-2010 Red Hat, Inc. All rights reserved.
4 * This file is part of the device-mapper userspace tools.
6 * This copyrighted material is made available to anyone wishing to use,
7 * modify, copy, or redistribute it subject to the terms and conditions
8 * of the GNU Lesser General Public License v.2.1.
10 * You should have received a copy of the GNU Lesser General Public License
11 * along with this program; if not, write to the Free Software Foundation,
12 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 #include "libdm-targets.h"
17 #include "libdm-common.h"
22 #include <sys/param.h>
23 #include <sys/utsname.h>
25 #define MAX_TARGET_PARAMSIZE 500000
27 /* FIXME Fix interface so this is used only by LVM */
28 #define UUID_PREFIX "LVM-"
30 #define REPLICATOR_LOCAL_SITE 0
32 /* Supported segment types */
47 /* FIXME Add crypt and multipath support */
53 { SEG_CRYPT, "crypt" },
54 { SEG_ERROR, "error" },
55 { SEG_LINEAR, "linear" },
56 { SEG_MIRRORED, "mirror" },
57 { SEG_REPLICATOR, "replicator" },
58 { SEG_REPLICATOR_DEV, "replicator-dev" },
59 { SEG_SNAPSHOT, "snapshot" },
60 { SEG_SNAPSHOT_ORIGIN, "snapshot-origin" },
61 { SEG_SNAPSHOT_MERGE, "snapshot-merge" },
62 { SEG_STRIPED, "striped" },
66 /* Some segment types have a list of areas of other devices attached */
70 struct dm_tree_node *dev_node;
74 unsigned rsite_index; /* Replicator site index */
75 struct dm_tree_node *slog; /* Replicator sync log node */
76 uint64_t region_size; /* Replicator sync log size */
77 uint32_t flags; /* Replicator sync log flags */
80 /* Replicator-log has a list of sites */
81 /* FIXME: maybe move to seg_area too? */
82 struct replicator_site {
86 dm_replicator_mode_t mode;
87 uint32_t async_timeout;
88 uint32_t fall_behind_ios;
89 uint64_t fall_behind_data;
92 /* Per-segment properties */
100 unsigned area_count; /* Linear + Striped + Mirrored + Crypt + Replicator */
101 struct dm_list areas; /* Linear + Striped + Mirrored + Crypt + Replicator */
103 uint32_t stripe_size; /* Striped */
105 int persistent; /* Snapshot */
106 uint32_t chunk_size; /* Snapshot */
107 struct dm_tree_node *cow; /* Snapshot */
108 struct dm_tree_node *origin; /* Snapshot + Snapshot origin */
109 struct dm_tree_node *merge; /* Snapshot */
111 struct dm_tree_node *log; /* Mirror + Replicator */
112 uint32_t region_size; /* Mirror */
113 unsigned clustered; /* Mirror */
114 unsigned mirror_area_count; /* Mirror */
115 uint32_t flags; /* Mirror log */
116 char *uuid; /* Clustered mirror log */
118 const char *cipher; /* Crypt */
119 const char *chainmode; /* Crypt */
120 const char *iv; /* Crypt */
121 uint64_t iv_offset; /* Crypt */
122 const char *key; /* Crypt */
124 const char *rlog_type; /* Replicator */
125 struct dm_list rsites; /* Replicator */
126 unsigned rsite_count; /* Replicator */
127 unsigned rdevice_count; /* Replicator */
128 struct dm_tree_node *replicator;/* Replicator-dev */
129 uint64_t rdevice_index; /* Replicator-dev */
132 /* Per-device properties */
133 struct load_properties {
139 uint32_t read_ahead_flags;
141 unsigned segment_count;
142 unsigned size_changed;
145 const char *new_name;
147 /* If immediate_dev_node is set to 1, try to create the dev node
148 * as soon as possible (e.g. in preload stage even during traversal
149 * and processing of dm tree). This will also flush all stacked dev
150 * node operations, synchronizing with udev.
152 int immediate_dev_node;
155 /* Two of these used to join two nodes with uses and used_by. */
156 struct dm_tree_link {
158 struct dm_tree_node *node;
161 struct dm_tree_node {
162 struct dm_tree *dtree;
168 struct dm_list uses; /* Nodes this node uses */
169 struct dm_list used_by; /* Nodes that use this node */
171 int activation_priority; /* 0 gets activated first */
173 uint16_t udev_flags; /* Udev control flags */
175 void *context; /* External supplied context */
177 struct load_properties props; /* For creation/table (re)load */
180 * If presuspend of child node is needed
181 * Note: only direct child is allowed
183 struct dm_tree_node *presuspend_node;
188 struct dm_hash_table *devs;
189 struct dm_hash_table *uuids;
190 struct dm_tree_node root;
191 int skip_lockfs; /* 1 skips lockfs (for non-snapshots) */
192 int no_flush; /* 1 sets noflush (mirrors/multipath) */
196 struct dm_tree *dm_tree_create(void)
198 struct dm_tree *dtree;
200 if (!(dtree = dm_zalloc(sizeof(*dtree)))) {
201 log_error("dm_tree_create malloc failed");
205 dtree->root.dtree = dtree;
206 dm_list_init(&dtree->root.uses);
207 dm_list_init(&dtree->root.used_by);
208 dtree->skip_lockfs = 0;
211 if (!(dtree->mem = dm_pool_create("dtree", 1024))) {
212 log_error("dtree pool creation failed");
217 if (!(dtree->devs = dm_hash_create(8))) {
218 log_error("dtree hash creation failed");
219 dm_pool_destroy(dtree->mem);
224 if (!(dtree->uuids = dm_hash_create(32))) {
225 log_error("dtree uuid hash creation failed");
226 dm_hash_destroy(dtree->devs);
227 dm_pool_destroy(dtree->mem);
235 void dm_tree_free(struct dm_tree *dtree)
240 dm_hash_destroy(dtree->uuids);
241 dm_hash_destroy(dtree->devs);
242 dm_pool_destroy(dtree->mem);
246 static int _nodes_are_linked(const struct dm_tree_node *parent,
247 const struct dm_tree_node *child)
249 struct dm_tree_link *dlink;
251 dm_list_iterate_items(dlink, &parent->uses)
252 if (dlink->node == child)
258 static int _link(struct dm_list *list, struct dm_tree_node *node)
260 struct dm_tree_link *dlink;
262 if (!(dlink = dm_pool_alloc(node->dtree->mem, sizeof(*dlink)))) {
263 log_error("dtree link allocation failed");
268 dm_list_add(list, &dlink->list);
273 static int _link_nodes(struct dm_tree_node *parent,
274 struct dm_tree_node *child)
276 if (_nodes_are_linked(parent, child))
279 if (!_link(&parent->uses, child))
282 if (!_link(&child->used_by, parent))
288 static void _unlink(struct dm_list *list, struct dm_tree_node *node)
290 struct dm_tree_link *dlink;
292 dm_list_iterate_items(dlink, list)
293 if (dlink->node == node) {
294 dm_list_del(&dlink->list);
299 static void _unlink_nodes(struct dm_tree_node *parent,
300 struct dm_tree_node *child)
302 if (!_nodes_are_linked(parent, child))
305 _unlink(&parent->uses, child);
306 _unlink(&child->used_by, parent);
309 static int _add_to_toplevel(struct dm_tree_node *node)
311 return _link_nodes(&node->dtree->root, node);
314 static void _remove_from_toplevel(struct dm_tree_node *node)
316 _unlink_nodes(&node->dtree->root, node);
319 static int _add_to_bottomlevel(struct dm_tree_node *node)
321 return _link_nodes(node, &node->dtree->root);
324 static void _remove_from_bottomlevel(struct dm_tree_node *node)
326 _unlink_nodes(node, &node->dtree->root);
329 static int _link_tree_nodes(struct dm_tree_node *parent, struct dm_tree_node *child)
331 /* Don't link to root node if child already has a parent */
332 if ((parent == &parent->dtree->root)) {
333 if (dm_tree_node_num_children(child, 1))
336 _remove_from_toplevel(child);
338 if ((child == &child->dtree->root)) {
339 if (dm_tree_node_num_children(parent, 0))
342 _remove_from_bottomlevel(parent);
344 return _link_nodes(parent, child);
347 static struct dm_tree_node *_create_dm_tree_node(struct dm_tree *dtree,
350 struct dm_info *info,
354 struct dm_tree_node *node;
357 if (!(node = dm_pool_zalloc(dtree->mem, sizeof(*node)))) {
358 log_error("_create_dm_tree_node alloc failed");
367 node->context = context;
368 node->udev_flags = udev_flags;
369 node->activation_priority = 0;
371 dm_list_init(&node->uses);
372 dm_list_init(&node->used_by);
373 dm_list_init(&node->props.segs);
375 dev = MKDEV(info->major, info->minor);
377 if (!dm_hash_insert_binary(dtree->devs, (const char *) &dev,
378 sizeof(dev), node)) {
379 log_error("dtree node hash insertion failed");
380 dm_pool_free(dtree->mem, node);
385 !dm_hash_insert(dtree->uuids, uuid, node)) {
386 log_error("dtree uuid hash insertion failed");
387 dm_hash_remove_binary(dtree->devs, (const char *) &dev,
389 dm_pool_free(dtree->mem, node);
396 static struct dm_tree_node *_find_dm_tree_node(struct dm_tree *dtree,
397 uint32_t major, uint32_t minor)
399 uint64_t dev = MKDEV(major, minor);
401 return dm_hash_lookup_binary(dtree->devs, (const char *) &dev,
405 static struct dm_tree_node *_find_dm_tree_node_by_uuid(struct dm_tree *dtree,
408 struct dm_tree_node *node;
410 if ((node = dm_hash_lookup(dtree->uuids, uuid)))
413 if (strncmp(uuid, UUID_PREFIX, sizeof(UUID_PREFIX) - 1))
416 return dm_hash_lookup(dtree->uuids, uuid + sizeof(UUID_PREFIX) - 1);
419 static int _deps(struct dm_task **dmt, struct dm_pool *mem, uint32_t major, uint32_t minor,
420 const char **name, const char **uuid,
421 struct dm_info *info, struct dm_deps **deps)
423 memset(info, 0, sizeof(*info));
425 if (!dm_is_dm_major(major)) {
432 info->live_table = 0;
433 info->inactive_table = 0;
438 if (!(*dmt = dm_task_create(DM_DEVICE_DEPS))) {
439 log_error("deps dm_task creation failed");
443 if (!dm_task_set_major(*dmt, major)) {
444 log_error("_deps: failed to set major for (%" PRIu32 ":%" PRIu32 ")",
449 if (!dm_task_set_minor(*dmt, minor)) {
450 log_error("_deps: failed to set minor for (%" PRIu32 ":%" PRIu32 ")",
455 if (!dm_task_run(*dmt)) {
456 log_error("_deps: task run failed for (%" PRIu32 ":%" PRIu32 ")",
461 if (!dm_task_get_info(*dmt, info)) {
462 log_error("_deps: failed to get info for (%" PRIu32 ":%" PRIu32 ")",
472 if (info->major != major) {
473 log_error("Inconsistent dtree major number: %u != %u",
477 if (info->minor != minor) {
478 log_error("Inconsistent dtree minor number: %u != %u",
482 if (!(*name = dm_pool_strdup(mem, dm_task_get_name(*dmt)))) {
483 log_error("name pool_strdup failed");
486 if (!(*uuid = dm_pool_strdup(mem, dm_task_get_uuid(*dmt)))) {
487 log_error("uuid pool_strdup failed");
490 *deps = dm_task_get_deps(*dmt);
496 dm_task_destroy(*dmt);
500 static struct dm_tree_node *_add_dev(struct dm_tree *dtree,
501 struct dm_tree_node *parent,
502 uint32_t major, uint32_t minor,
505 struct dm_task *dmt = NULL;
507 struct dm_deps *deps = NULL;
508 const char *name = NULL;
509 const char *uuid = NULL;
510 struct dm_tree_node *node = NULL;
514 /* Already in tree? */
515 if (!(node = _find_dm_tree_node(dtree, major, minor))) {
516 if (!_deps(&dmt, dtree->mem, major, minor, &name, &uuid, &info, &deps))
519 if (!(node = _create_dm_tree_node(dtree, name, uuid, &info,
525 if (!_link_tree_nodes(parent, node)) {
530 /* If node was already in tree, no need to recurse. */
534 /* Can't recurse if not a mapped device or there are no dependencies */
535 if (!node->info.exists || !deps->count) {
536 if (!_add_to_bottomlevel(node)) {
543 /* Add dependencies to tree */
544 for (i = 0; i < deps->count; i++)
545 if (!_add_dev(dtree, node, MAJOR(deps->device[i]),
546 MINOR(deps->device[i]), udev_flags)) {
553 dm_task_destroy(dmt);
558 static int _node_clear_table(struct dm_tree_node *dnode)
561 struct dm_info *info;
565 if (!(info = &dnode->info)) {
566 log_error("_node_clear_table failed: missing info");
570 if (!(name = dm_tree_node_get_name(dnode))) {
571 log_error("_node_clear_table failed: missing name");
575 /* Is there a table? */
576 if (!info->exists || !info->inactive_table)
579 log_verbose("Clearing inactive table %s (%" PRIu32 ":%" PRIu32 ")",
580 name, info->major, info->minor);
582 if (!(dmt = dm_task_create(DM_DEVICE_CLEAR))) {
583 log_error("Table clear dm_task creation failed for %s", name);
587 if (!dm_task_set_major(dmt, info->major) ||
588 !dm_task_set_minor(dmt, info->minor)) {
589 log_error("Failed to set device number for %s table clear", name);
590 dm_task_destroy(dmt);
594 r = dm_task_run(dmt);
596 if (!dm_task_get_info(dmt, info)) {
597 log_error("_node_clear_table failed: info missing after running task for %s", name);
601 dm_task_destroy(dmt);
606 struct dm_tree_node *dm_tree_add_new_dev(struct dm_tree *dtree,
609 uint32_t major, uint32_t minor,
614 struct dm_tree_node *dnode;
619 /* Do we need to add node to tree? */
620 if (!(dnode = dm_tree_find_node_by_uuid(dtree, uuid))) {
621 if (!(name2 = dm_pool_strdup(dtree->mem, name))) {
622 log_error("name pool_strdup failed");
625 if (!(uuid2 = dm_pool_strdup(dtree->mem, uuid))) {
626 log_error("uuid pool_strdup failed");
634 info.inactive_table = 0;
637 if (!(dnode = _create_dm_tree_node(dtree, name2, uuid2, &info,
641 /* Attach to root node until a table is supplied */
642 if (!_add_to_toplevel(dnode) || !_add_to_bottomlevel(dnode))
645 dnode->props.major = major;
646 dnode->props.minor = minor;
647 dnode->props.new_name = NULL;
648 dnode->props.size_changed = 0;
649 } else if (strcmp(name, dnode->name)) {
650 /* Do we need to rename node? */
651 if (!(dnode->props.new_name = dm_pool_strdup(dtree->mem, name))) {
652 log_error("name pool_strdup failed");
657 dnode->props.read_only = read_only ? 1 : 0;
658 dnode->props.read_ahead = DM_READ_AHEAD_AUTO;
659 dnode->props.read_ahead_flags = 0;
661 if (clear_inactive && !_node_clear_table(dnode))
664 dnode->context = context;
665 dnode->udev_flags = 0;
670 struct dm_tree_node *dm_tree_add_new_dev_with_udev_flags(struct dm_tree *dtree,
680 struct dm_tree_node *node;
682 if ((node = dm_tree_add_new_dev(dtree, name, uuid, major, minor, read_only,
683 clear_inactive, context)))
684 node->udev_flags = udev_flags;
690 void dm_tree_node_set_read_ahead(struct dm_tree_node *dnode,
692 uint32_t read_ahead_flags)
694 dnode->props.read_ahead = read_ahead;
695 dnode->props.read_ahead_flags = read_ahead_flags;
698 void dm_tree_node_set_presuspend_node(struct dm_tree_node *node,
699 struct dm_tree_node *presuspend_node)
701 node->presuspend_node = presuspend_node;
704 int dm_tree_add_dev(struct dm_tree *dtree, uint32_t major, uint32_t minor)
706 return _add_dev(dtree, &dtree->root, major, minor, 0) ? 1 : 0;
709 int dm_tree_add_dev_with_udev_flags(struct dm_tree *dtree, uint32_t major,
710 uint32_t minor, uint16_t udev_flags)
712 return _add_dev(dtree, &dtree->root, major, minor, udev_flags) ? 1 : 0;
715 const char *dm_tree_node_get_name(const struct dm_tree_node *node)
717 return node->info.exists ? node->name : "";
720 const char *dm_tree_node_get_uuid(const struct dm_tree_node *node)
722 return node->info.exists ? node->uuid : "";
725 const struct dm_info *dm_tree_node_get_info(const struct dm_tree_node *node)
730 void *dm_tree_node_get_context(const struct dm_tree_node *node)
732 return node->context;
735 int dm_tree_node_size_changed(const struct dm_tree_node *dnode)
737 return dnode->props.size_changed;
740 int dm_tree_node_num_children(const struct dm_tree_node *node, uint32_t inverted)
743 if (_nodes_are_linked(&node->dtree->root, node))
745 return dm_list_size(&node->used_by);
748 if (_nodes_are_linked(node, &node->dtree->root))
751 return dm_list_size(&node->uses);
755 * Returns 1 if no prefix supplied
757 static int _uuid_prefix_matches(const char *uuid, const char *uuid_prefix, size_t uuid_prefix_len)
762 if (!strncmp(uuid, uuid_prefix, uuid_prefix_len))
765 /* Handle transition: active device uuids might be missing the prefix */
766 if (uuid_prefix_len <= 4)
769 if (!strncmp(uuid, UUID_PREFIX, sizeof(UUID_PREFIX) - 1))
772 if (strncmp(uuid_prefix, UUID_PREFIX, sizeof(UUID_PREFIX) - 1))
775 if (!strncmp(uuid, uuid_prefix + sizeof(UUID_PREFIX) - 1, uuid_prefix_len - (sizeof(UUID_PREFIX) - 1)))
782 * Returns 1 if no children.
784 static int _children_suspended(struct dm_tree_node *node,
786 const char *uuid_prefix,
787 size_t uuid_prefix_len)
789 struct dm_list *list;
790 struct dm_tree_link *dlink;
791 const struct dm_info *dinfo;
795 if (_nodes_are_linked(&node->dtree->root, node))
797 list = &node->used_by;
799 if (_nodes_are_linked(node, &node->dtree->root))
804 dm_list_iterate_items(dlink, list) {
805 if (!(uuid = dm_tree_node_get_uuid(dlink->node))) {
810 /* Ignore if it doesn't belong to this VG */
811 if (!_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))
814 /* Ignore if parent node wants to presuspend this node */
815 if (dlink->node->presuspend_node == node)
818 if (!(dinfo = dm_tree_node_get_info(dlink->node))) {
819 stack; /* FIXME Is this normal? */
823 if (!dinfo->suspended)
831 * Set major and minor to zero for root of tree.
833 struct dm_tree_node *dm_tree_find_node(struct dm_tree *dtree,
837 if (!major && !minor)
840 return _find_dm_tree_node(dtree, major, minor);
844 * Set uuid to NULL for root of tree.
846 struct dm_tree_node *dm_tree_find_node_by_uuid(struct dm_tree *dtree,
852 return _find_dm_tree_node_by_uuid(dtree, uuid);
856 * First time set *handle to NULL.
857 * Set inverted to invert the tree.
859 struct dm_tree_node *dm_tree_next_child(void **handle,
860 const struct dm_tree_node *parent,
863 struct dm_list **dlink = (struct dm_list **) handle;
864 const struct dm_list *use_list;
867 use_list = &parent->used_by;
869 use_list = &parent->uses;
872 *dlink = dm_list_first(use_list);
874 *dlink = dm_list_next(use_list, *dlink);
876 return (*dlink) ? dm_list_item(*dlink, struct dm_tree_link)->node : NULL;
880 * Deactivate a device with its dependencies if the uuid prefix matches.
882 static int _info_by_dev(uint32_t major, uint32_t minor, int with_open_count,
883 struct dm_info *info)
888 if (!(dmt = dm_task_create(DM_DEVICE_INFO))) {
889 log_error("_info_by_dev: dm_task creation failed");
893 if (!dm_task_set_major(dmt, major) || !dm_task_set_minor(dmt, minor)) {
894 log_error("_info_by_dev: Failed to set device number");
895 dm_task_destroy(dmt);
899 if (!with_open_count && !dm_task_no_open_count(dmt))
900 log_error("Failed to disable open_count");
902 if ((r = dm_task_run(dmt)))
903 r = dm_task_get_info(dmt, info);
905 dm_task_destroy(dmt);
910 /* Check if all parent nodes of given node have open_count == 0 */
911 static int _node_has_closed_parents(struct dm_tree_node *node,
912 const char *uuid_prefix,
913 size_t uuid_prefix_len)
915 struct dm_tree_link *dlink;
916 const struct dm_info *dinfo;
920 /* Iterate through parents of this node */
921 dm_list_iterate_items(dlink, &node->used_by) {
922 if (!(uuid = dm_tree_node_get_uuid(dlink->node))) {
927 /* Ignore if it doesn't belong to this VG */
928 if (!_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))
931 if (!(dinfo = dm_tree_node_get_info(dlink->node))) {
932 stack; /* FIXME Is this normal? */
936 /* Refresh open_count */
937 if (!_info_by_dev(dinfo->major, dinfo->minor, 1, &info) ||
948 static int _deactivate_node(const char *name, uint32_t major, uint32_t minor,
949 uint32_t *cookie, uint16_t udev_flags)
954 log_verbose("Removing %s (%" PRIu32 ":%" PRIu32 ")", name, major, minor);
956 if (!(dmt = dm_task_create(DM_DEVICE_REMOVE))) {
957 log_error("Deactivation dm_task creation failed for %s", name);
961 if (!dm_task_set_major(dmt, major) || !dm_task_set_minor(dmt, minor)) {
962 log_error("Failed to set device number for %s deactivation", name);
966 if (!dm_task_no_open_count(dmt))
967 log_error("Failed to disable open_count");
969 if (!dm_task_set_cookie(dmt, cookie, udev_flags))
972 r = dm_task_run(dmt);
974 /* FIXME Until kernel returns actual name so dm-ioctl.c can handle it */
975 rm_dev_node(name, dmt->cookie_set &&
976 !(udev_flags & DM_UDEV_DISABLE_DM_RULES_FLAG));
978 /* FIXME Remove node from tree or mark invalid? */
981 dm_task_destroy(dmt);
986 static int _rename_node(const char *old_name, const char *new_name, uint32_t major,
987 uint32_t minor, uint32_t *cookie, uint16_t udev_flags)
992 log_verbose("Renaming %s (%" PRIu32 ":%" PRIu32 ") to %s", old_name, major, minor, new_name);
994 if (!(dmt = dm_task_create(DM_DEVICE_RENAME))) {
995 log_error("Rename dm_task creation failed for %s", old_name);
999 if (!dm_task_set_name(dmt, old_name)) {
1000 log_error("Failed to set name for %s rename.", old_name);
1004 if (!dm_task_set_newname(dmt, new_name))
1007 if (!dm_task_no_open_count(dmt))
1008 log_error("Failed to disable open_count");
1010 if (!dm_task_set_cookie(dmt, cookie, udev_flags))
1013 r = dm_task_run(dmt);
1016 dm_task_destroy(dmt);
1021 /* FIXME Merge with _suspend_node? */
1022 static int _resume_node(const char *name, uint32_t major, uint32_t minor,
1023 uint32_t read_ahead, uint32_t read_ahead_flags,
1024 struct dm_info *newinfo, uint32_t *cookie,
1025 uint16_t udev_flags)
1027 struct dm_task *dmt;
1030 log_verbose("Resuming %s (%" PRIu32 ":%" PRIu32 ")", name, major, minor);
1032 if (!(dmt = dm_task_create(DM_DEVICE_RESUME))) {
1033 log_error("Suspend dm_task creation failed for %s", name);
1037 /* FIXME Kernel should fill in name on return instead */
1038 if (!dm_task_set_name(dmt, name)) {
1039 log_error("Failed to set readahead device name for %s", name);
1043 if (!dm_task_set_major(dmt, major) || !dm_task_set_minor(dmt, minor)) {
1044 log_error("Failed to set device number for %s resumption.", name);
1048 if (!dm_task_no_open_count(dmt))
1049 log_error("Failed to disable open_count");
1051 if (!dm_task_set_read_ahead(dmt, read_ahead, read_ahead_flags))
1052 log_error("Failed to set read ahead");
1054 if (!dm_task_set_cookie(dmt, cookie, udev_flags))
1057 if ((r = dm_task_run(dmt)))
1058 r = dm_task_get_info(dmt, newinfo);
1061 dm_task_destroy(dmt);
1066 static int _suspend_node(const char *name, uint32_t major, uint32_t minor,
1067 int skip_lockfs, int no_flush, struct dm_info *newinfo)
1069 struct dm_task *dmt;
1072 log_verbose("Suspending %s (%" PRIu32 ":%" PRIu32 ")%s%s",
1074 skip_lockfs ? "" : " with filesystem sync",
1075 no_flush ? "" : " with device flush");
1077 if (!(dmt = dm_task_create(DM_DEVICE_SUSPEND))) {
1078 log_error("Suspend dm_task creation failed for %s", name);
1082 if (!dm_task_set_major(dmt, major) || !dm_task_set_minor(dmt, minor)) {
1083 log_error("Failed to set device number for %s suspension.", name);
1084 dm_task_destroy(dmt);
1088 if (!dm_task_no_open_count(dmt))
1089 log_error("Failed to disable open_count");
1091 if (skip_lockfs && !dm_task_skip_lockfs(dmt))
1092 log_error("Failed to set skip_lockfs flag.");
1094 if (no_flush && !dm_task_no_flush(dmt))
1095 log_error("Failed to set no_flush flag.");
1097 if ((r = dm_task_run(dmt)))
1098 r = dm_task_get_info(dmt, newinfo);
1100 dm_task_destroy(dmt);
1106 * FIXME Don't attempt to deactivate known internal dependencies.
1108 static int _dm_tree_deactivate_children(struct dm_tree_node *dnode,
1109 const char *uuid_prefix,
1110 size_t uuid_prefix_len,
1114 void *handle = NULL;
1115 struct dm_tree_node *child = dnode;
1116 struct dm_info info;
1117 const struct dm_info *dinfo;
1121 while ((child = dm_tree_next_child(&handle, dnode, 0))) {
1122 if (!(dinfo = dm_tree_node_get_info(child))) {
1127 if (!(name = dm_tree_node_get_name(child))) {
1132 if (!(uuid = dm_tree_node_get_uuid(child))) {
1137 /* Ignore if it doesn't belong to this VG */
1138 if (!_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))
1141 /* Refresh open_count */
1142 if (!_info_by_dev(dinfo->major, dinfo->minor, 1, &info) ||
1146 /* Also checking open_count in parent nodes of presuspend_node */
1147 if (info.open_count ||
1148 (child->presuspend_node &&
1149 !_node_has_closed_parents(child->presuspend_node,
1150 uuid_prefix, uuid_prefix_len))) {
1151 /* Only report error from (likely non-internal) dependency at top level */
1153 log_error("Unable to deactivate open %s (%" PRIu32
1154 ":%" PRIu32 ")", name, info.major,
1161 /* Suspend child node first if requested */
1162 if (child->presuspend_node &&
1163 !dm_tree_suspend_children(child, uuid_prefix, uuid_prefix_len))
1166 if (!_deactivate_node(name, info.major, info.minor,
1167 &child->dtree->cookie, child->udev_flags)) {
1168 log_error("Unable to deactivate %s (%" PRIu32
1169 ":%" PRIu32 ")", name, info.major,
1175 if (dm_tree_node_num_children(child, 0)) {
1176 if (!_dm_tree_deactivate_children(child, uuid_prefix, uuid_prefix_len, level + 1))
1184 int dm_tree_deactivate_children(struct dm_tree_node *dnode,
1185 const char *uuid_prefix,
1186 size_t uuid_prefix_len)
1188 return _dm_tree_deactivate_children(dnode, uuid_prefix, uuid_prefix_len, 0);
1191 void dm_tree_skip_lockfs(struct dm_tree_node *dnode)
1193 dnode->dtree->skip_lockfs = 1;
1196 void dm_tree_use_no_flush_suspend(struct dm_tree_node *dnode)
1198 dnode->dtree->no_flush = 1;
1201 int dm_tree_suspend_children(struct dm_tree_node *dnode,
1202 const char *uuid_prefix,
1203 size_t uuid_prefix_len)
1206 void *handle = NULL;
1207 struct dm_tree_node *child = dnode;
1208 struct dm_info info, newinfo;
1209 const struct dm_info *dinfo;
1213 /* Suspend nodes at this level of the tree */
1214 while ((child = dm_tree_next_child(&handle, dnode, 0))) {
1215 if (!(dinfo = dm_tree_node_get_info(child))) {
1220 if (!(name = dm_tree_node_get_name(child))) {
1225 if (!(uuid = dm_tree_node_get_uuid(child))) {
1230 /* Ignore if it doesn't belong to this VG */
1231 if (!_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))
1234 /* Ensure immediate parents are already suspended */
1235 if (!_children_suspended(child, 1, uuid_prefix, uuid_prefix_len))
1238 if (!_info_by_dev(dinfo->major, dinfo->minor, 0, &info) ||
1239 !info.exists || info.suspended)
1242 if (!_suspend_node(name, info.major, info.minor,
1243 child->dtree->skip_lockfs,
1244 child->dtree->no_flush, &newinfo)) {
1245 log_error("Unable to suspend %s (%" PRIu32
1246 ":%" PRIu32 ")", name, info.major,
1252 /* Update cached info */
1253 child->info = newinfo;
1256 /* Then suspend any child nodes */
1259 while ((child = dm_tree_next_child(&handle, dnode, 0))) {
1260 if (!(uuid = dm_tree_node_get_uuid(child))) {
1265 /* Ignore if it doesn't belong to this VG */
1266 if (!_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))
1269 if (dm_tree_node_num_children(child, 0))
1270 if (!dm_tree_suspend_children(child, uuid_prefix, uuid_prefix_len))
1277 int dm_tree_activate_children(struct dm_tree_node *dnode,
1278 const char *uuid_prefix,
1279 size_t uuid_prefix_len)
1282 void *handle = NULL;
1283 struct dm_tree_node *child = dnode;
1284 struct dm_info newinfo;
1289 /* Activate children first */
1290 while ((child = dm_tree_next_child(&handle, dnode, 0))) {
1291 if (!(uuid = dm_tree_node_get_uuid(child))) {
1296 if (!_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))
1299 if (dm_tree_node_num_children(child, 0))
1300 if (!dm_tree_activate_children(child, uuid_prefix, uuid_prefix_len))
1306 for (priority = 0; priority < 3; priority++) {
1307 while ((child = dm_tree_next_child(&handle, dnode, 0))) {
1308 if (!(uuid = dm_tree_node_get_uuid(child))) {
1313 if (!_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))
1316 if (priority != child->activation_priority)
1319 if (!(name = dm_tree_node_get_name(child))) {
1325 if (child->props.new_name) {
1326 if (!_rename_node(name, child->props.new_name, child->info.major,
1327 child->info.minor, &child->dtree->cookie,
1328 child->udev_flags)) {
1329 log_error("Failed to rename %s (%" PRIu32
1330 ":%" PRIu32 ") to %s", name, child->info.major,
1331 child->info.minor, child->props.new_name);
1334 child->name = child->props.new_name;
1335 child->props.new_name = NULL;
1338 if (!child->info.inactive_table && !child->info.suspended)
1341 if (!_resume_node(child->name, child->info.major, child->info.minor,
1342 child->props.read_ahead, child->props.read_ahead_flags,
1343 &newinfo, &child->dtree->cookie, child->udev_flags)) {
1344 log_error("Unable to resume %s (%" PRIu32
1345 ":%" PRIu32 ")", child->name, child->info.major,
1351 /* Update cached info */
1352 child->info = newinfo;
1361 static int _create_node(struct dm_tree_node *dnode)
1364 struct dm_task *dmt;
1366 log_verbose("Creating %s", dnode->name);
1368 if (!(dmt = dm_task_create(DM_DEVICE_CREATE))) {
1369 log_error("Create dm_task creation failed for %s", dnode->name);
1373 if (!dm_task_set_name(dmt, dnode->name)) {
1374 log_error("Failed to set device name for %s", dnode->name);
1378 if (!dm_task_set_uuid(dmt, dnode->uuid)) {
1379 log_error("Failed to set uuid for %s", dnode->name);
1383 if (dnode->props.major &&
1384 (!dm_task_set_major(dmt, dnode->props.major) ||
1385 !dm_task_set_minor(dmt, dnode->props.minor))) {
1386 log_error("Failed to set device number for %s creation.", dnode->name);
1390 if (dnode->props.read_only && !dm_task_set_ro(dmt)) {
1391 log_error("Failed to set read only flag for %s", dnode->name);
1395 if (!dm_task_no_open_count(dmt))
1396 log_error("Failed to disable open_count");
1398 if ((r = dm_task_run(dmt)))
1399 r = dm_task_get_info(dmt, &dnode->info);
1402 dm_task_destroy(dmt);
1408 static int _build_dev_string(char *devbuf, size_t bufsize, struct dm_tree_node *node)
1410 if (!dm_format_dev(devbuf, bufsize, node->info.major, node->info.minor)) {
1411 log_error("Failed to format %s device number for %s as dm "
1413 node->name, node->uuid, node->info.major, node->info.minor);
1420 /* simplify string emiting code */
1421 #define EMIT_PARAMS(p, str...)\
1424 if ((w = dm_snprintf(params + p, paramsize - (size_t) p, str)) < 0) {\
1425 stack; /* Out of space */\
1434 * Returns: 1 on success, 0 on failure
1436 static int _emit_areas_line(struct dm_task *dmt __attribute__((unused)),
1437 struct load_segment *seg, char *params,
1438 size_t paramsize, int *pos)
1440 struct seg_area *area;
1441 char devbuf[DM_FORMAT_DEV_BUFSIZE];
1442 unsigned first_time = 1;
1443 const char *logtype, *synctype;
1444 unsigned log_parm_count;
1446 dm_list_iterate_items(area, &seg->areas) {
1447 if (!_build_dev_string(devbuf, sizeof(devbuf), area->dev_node))
1450 switch (seg->type) {
1451 case SEG_REPLICATOR_DEV:
1452 EMIT_PARAMS(*pos, " %d 1 %s", area->rsite_index, devbuf);
1454 EMIT_PARAMS(*pos, " nolog 0");
1456 /* Remote devices */
1457 log_parm_count = (area->flags &
1458 (DM_NOSYNC | DM_FORCESYNC)) ? 2 : 1;
1461 devbuf[0] = 0; /* Only core log parameters */
1464 devbuf[0] = ' '; /* Extra space before device name */
1465 if (!_build_dev_string(devbuf + 1,
1470 log_parm_count++; /* Extra sync log device name parameter */
1473 EMIT_PARAMS(*pos, " %s %u%s %" PRIu64, logtype,
1474 log_parm_count, devbuf, area->region_size);
1476 synctype = (area->flags & DM_NOSYNC) ?
1477 " nosync" : (area->flags & DM_FORCESYNC) ?
1481 EMIT_PARAMS(*pos, "%s", synctype);
1485 EMIT_PARAMS(*pos, "%s%s %" PRIu64, first_time ? "" : " ",
1486 devbuf, area->offset);
1495 static int _replicator_emit_segment_line(const struct load_segment *seg, char *params,
1496 size_t paramsize, int *pos)
1498 const struct load_segment *rlog_seg;
1499 struct replicator_site *rsite;
1500 char rlogbuf[DM_FORMAT_DEV_BUFSIZE];
1501 unsigned parm_count;
1503 if (!seg->log || !_build_dev_string(rlogbuf, sizeof(rlogbuf), seg->log))
1506 rlog_seg = dm_list_item(dm_list_last(&seg->log->props.segs),
1507 struct load_segment);
1509 EMIT_PARAMS(*pos, "%s 4 %s 0 auto %" PRIu64,
1510 seg->rlog_type, rlogbuf, rlog_seg->size);
1512 dm_list_iterate_items(rsite, &seg->rsites) {
1513 parm_count = (rsite->fall_behind_data
1514 || rsite->fall_behind_ios
1515 || rsite->async_timeout) ? 4 : 2;
1517 EMIT_PARAMS(*pos, " blockdev %u %u %s", parm_count, rsite->rsite_index,
1518 (rsite->mode == DM_REPLICATOR_SYNC) ? "synchronous" : "asynchronous");
1520 if (rsite->fall_behind_data)
1521 EMIT_PARAMS(*pos, " data %" PRIu64, rsite->fall_behind_data);
1522 else if (rsite->fall_behind_ios)
1523 EMIT_PARAMS(*pos, " ios %" PRIu32, rsite->fall_behind_ios);
1524 else if (rsite->async_timeout)
1525 EMIT_PARAMS(*pos, " timeout %" PRIu32, rsite->async_timeout);
1532 * Returns: 1 on success, 0 on failure
1534 static int _mirror_emit_segment_line(struct dm_task *dmt, uint32_t major,
1535 uint32_t minor, struct load_segment *seg,
1536 uint64_t *seg_start, char *params,
1539 int block_on_error = 0;
1540 int handle_errors = 0;
1541 int dm_log_userspace = 0;
1543 unsigned log_parm_count;
1545 char logbuf[DM_FORMAT_DEV_BUFSIZE];
1546 const char *logtype;
1547 unsigned kmaj, kmin, krel;
1549 if (uname(&uts) == -1 || sscanf(uts.release, "%u.%u.%u", &kmaj, &kmin, &krel) != 3) {
1550 log_error("Cannot read kernel release version");
1554 if ((seg->flags & DM_BLOCK_ON_ERROR)) {
1556 * Originally, block_on_error was an argument to the log
1557 * portion of the mirror CTR table. It was renamed to
1558 * "handle_errors" and now resides in the 'features'
1559 * section of the mirror CTR table (i.e. at the end).
1561 * We can identify whether to use "block_on_error" or
1562 * "handle_errors" by the dm-mirror module's version
1563 * number (>= 1.12) or by the kernel version (>= 2.6.22).
1565 if (KERNEL_VERSION(kmaj, kmin, krel) >= KERNEL_VERSION(2, 6, 22))
1571 if (seg->clustered) {
1572 /* Cluster mirrors require a UUID */
1577 * Cluster mirrors used to have their own log
1578 * types. Now they are accessed through the
1579 * userspace log type.
1581 * The dm-log-userspace module was added to the
1584 if (KERNEL_VERSION(kmaj, kmin, krel) >= KERNEL_VERSION(2, 6, 31))
1585 dm_log_userspace = 1;
1591 /* [no]sync, block_on_error etc. */
1592 log_parm_count += hweight32(seg->flags);
1594 /* "handle_errors" is a feature arg now */
1598 /* DM_CORELOG does not count in the param list */
1599 if (seg->flags & DM_CORELOG)
1602 if (seg->clustered) {
1603 log_parm_count++; /* For UUID */
1605 if (!dm_log_userspace)
1606 EMIT_PARAMS(pos, "clustered-");
1608 /* For clustered-* type field inserted later */
1617 if (!_build_dev_string(logbuf, sizeof(logbuf), seg->log))
1621 if (dm_log_userspace)
1622 EMIT_PARAMS(pos, "userspace %u %s clustered-%s",
1623 log_parm_count, seg->uuid, logtype);
1625 EMIT_PARAMS(pos, "%s %u", logtype, log_parm_count);
1628 EMIT_PARAMS(pos, " %s", logbuf);
1630 EMIT_PARAMS(pos, " %u", seg->region_size);
1632 if (seg->clustered && !dm_log_userspace)
1633 EMIT_PARAMS(pos, " %s", seg->uuid);
1635 if ((seg->flags & DM_NOSYNC))
1636 EMIT_PARAMS(pos, " nosync");
1637 else if ((seg->flags & DM_FORCESYNC))
1638 EMIT_PARAMS(pos, " sync");
1641 EMIT_PARAMS(pos, " block_on_error");
1643 EMIT_PARAMS(pos, " %u ", seg->mirror_area_count);
1645 if (_emit_areas_line(dmt, seg, params, paramsize, &pos) <= 0)
1649 EMIT_PARAMS(pos, " 1 handle_errors");
1654 static int _emit_segment_line(struct dm_task *dmt, uint32_t major,
1655 uint32_t minor, struct load_segment *seg,
1656 uint64_t *seg_start, char *params,
1661 char originbuf[DM_FORMAT_DEV_BUFSIZE], cowbuf[DM_FORMAT_DEV_BUFSIZE];
1669 /* Mirrors are pretty complicated - now in separate function */
1670 r = _mirror_emit_segment_line(dmt, major, minor, seg, seg_start,
1675 case SEG_REPLICATOR:
1676 if ((r = _replicator_emit_segment_line(seg, params, paramsize,
1682 case SEG_REPLICATOR_DEV:
1683 if (!seg->replicator || !_build_dev_string(originbuf,
1688 EMIT_PARAMS(pos, "%s %" PRIu64, originbuf, seg->rdevice_index);
1691 case SEG_SNAPSHOT_MERGE:
1692 if (!_build_dev_string(originbuf, sizeof(originbuf), seg->origin))
1694 if (!_build_dev_string(cowbuf, sizeof(cowbuf), seg->cow))
1696 EMIT_PARAMS(pos, "%s %s %c %d", originbuf, cowbuf,
1697 seg->persistent ? 'P' : 'N', seg->chunk_size);
1699 case SEG_SNAPSHOT_ORIGIN:
1700 if (!_build_dev_string(originbuf, sizeof(originbuf), seg->origin))
1702 EMIT_PARAMS(pos, "%s", originbuf);
1705 EMIT_PARAMS(pos, "%u %u ", seg->area_count, seg->stripe_size);
1708 EMIT_PARAMS(pos, "%s%s%s%s%s %s %" PRIu64 " ", seg->cipher,
1709 seg->chainmode ? "-" : "", seg->chainmode ?: "",
1710 seg->iv ? "-" : "", seg->iv ?: "", seg->key,
1711 seg->iv_offset != DM_CRYPT_IV_DEFAULT ?
1712 seg->iv_offset : *seg_start);
1718 case SEG_REPLICATOR:
1720 case SEG_SNAPSHOT_ORIGIN:
1721 case SEG_SNAPSHOT_MERGE:
1726 case SEG_REPLICATOR_DEV:
1728 if ((r = _emit_areas_line(dmt, seg, params, paramsize, &pos)) <= 0) {
1735 log_debug("Adding target to (%" PRIu32 ":%" PRIu32 "): %" PRIu64
1736 " %" PRIu64 " %s %s", major, minor,
1737 *seg_start, seg->size, dm_segtypes[seg->type].target, params);
1739 if (!dm_task_add_target(dmt, *seg_start, seg->size, dm_segtypes[seg->type].target, params))
1742 *seg_start += seg->size;
1749 static int _emit_segment(struct dm_task *dmt, uint32_t major, uint32_t minor,
1750 struct load_segment *seg, uint64_t *seg_start)
1753 size_t paramsize = 4096;
1757 if (!(params = dm_malloc(paramsize))) {
1758 log_error("Insufficient space for target parameters.");
1763 ret = _emit_segment_line(dmt, major, minor, seg, seg_start,
1773 log_debug("Insufficient space in params[%" PRIsize_t
1774 "] for target parameters.", paramsize);
1777 } while (paramsize < MAX_TARGET_PARAMSIZE);
1779 log_error("Target parameter size too big. Aborting.");
1783 static int _load_node(struct dm_tree_node *dnode)
1786 struct dm_task *dmt;
1787 struct load_segment *seg;
1788 uint64_t seg_start = 0;
1790 log_verbose("Loading %s table (%" PRIu32 ":%" PRIu32 ")", dnode->name,
1791 dnode->info.major, dnode->info.minor);
1793 if (!(dmt = dm_task_create(DM_DEVICE_RELOAD))) {
1794 log_error("Reload dm_task creation failed for %s", dnode->name);
1798 if (!dm_task_set_major(dmt, dnode->info.major) ||
1799 !dm_task_set_minor(dmt, dnode->info.minor)) {
1800 log_error("Failed to set device number for %s reload.", dnode->name);
1804 if (dnode->props.read_only && !dm_task_set_ro(dmt)) {
1805 log_error("Failed to set read only flag for %s", dnode->name);
1809 if (!dm_task_no_open_count(dmt))
1810 log_error("Failed to disable open_count");
1812 dm_list_iterate_items(seg, &dnode->props.segs)
1813 if (!_emit_segment(dmt, dnode->info.major, dnode->info.minor,
1817 if (!dm_task_suppress_identical_reload(dmt))
1818 log_error("Failed to suppress reload of identical tables.");
1820 if ((r = dm_task_run(dmt))) {
1821 r = dm_task_get_info(dmt, &dnode->info);
1822 if (r && !dnode->info.inactive_table)
1823 log_verbose("Suppressed %s identical table reload.",
1826 if ((dnode->props.size_changed =
1827 (dm_task_get_existing_table_size(dmt) == seg_start) ? 0 : 1))
1828 log_debug("Table size changed from %" PRIu64 " to %"
1830 dm_task_get_existing_table_size(dmt),
1831 seg_start, dnode->name);
1834 dnode->props.segment_count = 0;
1837 dm_task_destroy(dmt);
1842 int dm_tree_preload_children(struct dm_tree_node *dnode,
1843 const char *uuid_prefix,
1844 size_t uuid_prefix_len)
1847 void *handle = NULL;
1848 struct dm_tree_node *child;
1849 struct dm_info newinfo;
1850 int update_devs_flag = 0;
1852 /* Preload children first */
1853 while ((child = dm_tree_next_child(&handle, dnode, 0))) {
1854 /* Skip existing non-device-mapper devices */
1855 if (!child->info.exists && child->info.major)
1858 /* Ignore if it doesn't belong to this VG */
1859 if (child->info.exists &&
1860 !_uuid_prefix_matches(child->uuid, uuid_prefix, uuid_prefix_len))
1863 if (dm_tree_node_num_children(child, 0))
1864 if (!dm_tree_preload_children(child, uuid_prefix, uuid_prefix_len))
1867 /* FIXME Cope if name exists with no uuid? */
1868 if (!child->info.exists) {
1869 if (!_create_node(child)) {
1875 if (!child->info.inactive_table && child->props.segment_count) {
1876 if (!_load_node(child)) {
1882 /* Propagate device size change change */
1883 if (child->props.size_changed)
1884 dnode->props.size_changed = 1;
1886 /* Resume device immediately if it has parents and its size changed */
1887 if (!dm_tree_node_num_children(child, 1) || !child->props.size_changed)
1890 if (!child->info.inactive_table && !child->info.suspended)
1893 if (!_resume_node(child->name, child->info.major, child->info.minor,
1894 child->props.read_ahead, child->props.read_ahead_flags,
1895 &newinfo, &child->dtree->cookie, child->udev_flags)) {
1896 log_error("Unable to resume %s (%" PRIu32
1897 ":%" PRIu32 ")", child->name, child->info.major,
1903 /* Update cached info */
1904 child->info = newinfo;
1907 * Prepare for immediate synchronization with udev and flush all stacked
1908 * dev node operations if requested by immediate_dev_node property. But
1909 * finish processing current level in the tree first.
1911 if (child->props.immediate_dev_node)
1912 update_devs_flag = 1;
1918 if (update_devs_flag) {
1919 if (!dm_udev_wait(dm_tree_get_cookie(dnode)))
1921 dm_tree_set_cookie(dnode, 0);
1922 dm_task_update_nodes();
1929 * Returns 1 if unsure.
1931 int dm_tree_children_use_uuid(struct dm_tree_node *dnode,
1932 const char *uuid_prefix,
1933 size_t uuid_prefix_len)
1935 void *handle = NULL;
1936 struct dm_tree_node *child = dnode;
1939 while ((child = dm_tree_next_child(&handle, dnode, 0))) {
1940 if (!(uuid = dm_tree_node_get_uuid(child))) {
1941 log_error("Failed to get uuid for dtree node.");
1945 if (_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))
1948 if (dm_tree_node_num_children(child, 0))
1949 dm_tree_children_use_uuid(child, uuid_prefix, uuid_prefix_len);
1958 static struct load_segment *_add_segment(struct dm_tree_node *dnode, unsigned type, uint64_t size)
1960 struct load_segment *seg;
1962 if (!(seg = dm_pool_zalloc(dnode->dtree->mem, sizeof(*seg)))) {
1963 log_error("dtree node segment allocation failed");
1969 seg->area_count = 0;
1970 dm_list_init(&seg->areas);
1971 seg->stripe_size = 0;
1972 seg->persistent = 0;
1973 seg->chunk_size = 0;
1978 dm_list_add(&dnode->props.segs, &seg->list);
1979 dnode->props.segment_count++;
1984 int dm_tree_node_add_snapshot_origin_target(struct dm_tree_node *dnode,
1986 const char *origin_uuid)
1988 struct load_segment *seg;
1989 struct dm_tree_node *origin_node;
1991 if (!(seg = _add_segment(dnode, SEG_SNAPSHOT_ORIGIN, size)))
1994 if (!(origin_node = dm_tree_find_node_by_uuid(dnode->dtree, origin_uuid))) {
1995 log_error("Couldn't find snapshot origin uuid %s.", origin_uuid);
1999 seg->origin = origin_node;
2000 if (!_link_tree_nodes(dnode, origin_node))
2003 /* Resume snapshot origins after new snapshots */
2004 dnode->activation_priority = 1;
2009 static int _add_snapshot_target(struct dm_tree_node *node,
2011 const char *origin_uuid,
2012 const char *cow_uuid,
2013 const char *merge_uuid,
2015 uint32_t chunk_size)
2017 struct load_segment *seg;
2018 struct dm_tree_node *origin_node, *cow_node, *merge_node;
2021 seg_type = !merge_uuid ? SEG_SNAPSHOT : SEG_SNAPSHOT_MERGE;
2023 if (!(seg = _add_segment(node, seg_type, size)))
2026 if (!(origin_node = dm_tree_find_node_by_uuid(node->dtree, origin_uuid))) {
2027 log_error("Couldn't find snapshot origin uuid %s.", origin_uuid);
2031 seg->origin = origin_node;
2032 if (!_link_tree_nodes(node, origin_node))
2035 if (!(cow_node = dm_tree_find_node_by_uuid(node->dtree, cow_uuid))) {
2036 log_error("Couldn't find snapshot COW device uuid %s.", cow_uuid);
2040 seg->cow = cow_node;
2041 if (!_link_tree_nodes(node, cow_node))
2044 seg->persistent = persistent ? 1 : 0;
2045 seg->chunk_size = chunk_size;
2048 if (!(merge_node = dm_tree_find_node_by_uuid(node->dtree, merge_uuid))) {
2049 /* not a pure error, merging snapshot may have been deactivated */
2050 log_verbose("Couldn't find merging snapshot uuid %s.", merge_uuid);
2052 seg->merge = merge_node;
2053 /* must not link merging snapshot, would undermine activation_priority below */
2056 /* Resume snapshot-merge (acting origin) after other snapshots */
2057 node->activation_priority = 1;
2059 /* Resume merging snapshot after snapshot-merge */
2060 seg->merge->activation_priority = 2;
2068 int dm_tree_node_add_snapshot_target(struct dm_tree_node *node,
2070 const char *origin_uuid,
2071 const char *cow_uuid,
2073 uint32_t chunk_size)
2075 return _add_snapshot_target(node, size, origin_uuid, cow_uuid,
2076 NULL, persistent, chunk_size);
2079 int dm_tree_node_add_snapshot_merge_target(struct dm_tree_node *node,
2081 const char *origin_uuid,
2082 const char *cow_uuid,
2083 const char *merge_uuid,
2084 uint32_t chunk_size)
2086 return _add_snapshot_target(node, size, origin_uuid, cow_uuid,
2087 merge_uuid, 1, chunk_size);
2090 int dm_tree_node_add_error_target(struct dm_tree_node *node,
2093 if (!_add_segment(node, SEG_ERROR, size))
2099 int dm_tree_node_add_zero_target(struct dm_tree_node *node,
2102 if (!_add_segment(node, SEG_ZERO, size))
2108 int dm_tree_node_add_linear_target(struct dm_tree_node *node,
2111 if (!_add_segment(node, SEG_LINEAR, size))
2117 int dm_tree_node_add_striped_target(struct dm_tree_node *node,
2119 uint32_t stripe_size)
2121 struct load_segment *seg;
2123 if (!(seg = _add_segment(node, SEG_STRIPED, size)))
2126 seg->stripe_size = stripe_size;
2131 int dm_tree_node_add_crypt_target(struct dm_tree_node *node,
2134 const char *chainmode,
2139 struct load_segment *seg;
2141 if (!(seg = _add_segment(node, SEG_CRYPT, size)))
2144 seg->cipher = cipher;
2145 seg->chainmode = chainmode;
2147 seg->iv_offset = iv_offset;
2153 int dm_tree_node_add_mirror_target_log(struct dm_tree_node *node,
2154 uint32_t region_size,
2156 const char *log_uuid,
2157 unsigned area_count,
2160 struct dm_tree_node *log_node = NULL;
2161 struct load_segment *seg;
2163 if (!node->props.segment_count) {
2164 log_error(INTERNAL_ERROR "Attempt to add target area to missing segment.");
2168 seg = dm_list_item(dm_list_last(&node->props.segs), struct load_segment);
2171 if (!(seg->uuid = dm_pool_strdup(node->dtree->mem, log_uuid))) {
2172 log_error("log uuid pool_strdup failed");
2175 if (!(flags & DM_CORELOG)) {
2176 if (!(log_node = dm_tree_find_node_by_uuid(node->dtree, log_uuid))) {
2177 log_error("Couldn't find mirror log uuid %s.", log_uuid);
2182 log_node->props.immediate_dev_node = 1;
2184 if (!_link_tree_nodes(node, log_node))
2189 seg->log = log_node;
2190 seg->region_size = region_size;
2191 seg->clustered = clustered;
2192 seg->mirror_area_count = area_count;
2198 int dm_tree_node_add_mirror_target(struct dm_tree_node *node,
2201 if (!_add_segment(node, SEG_MIRRORED, size))
2207 int dm_tree_node_add_replicator_target(struct dm_tree_node *node,
2209 const char *rlog_uuid,
2210 const char *rlog_type,
2211 unsigned rsite_index,
2212 dm_replicator_mode_t mode,
2213 uint32_t async_timeout,
2214 uint64_t fall_behind_data,
2215 uint32_t fall_behind_ios)
2217 struct load_segment *rseg;
2218 struct replicator_site *rsite;
2220 /* Local site0 - adds replicator segment and links rlog device */
2221 if (rsite_index == REPLICATOR_LOCAL_SITE) {
2222 if (node->props.segment_count) {
2223 log_error(INTERNAL_ERROR "Attempt to add replicator segment to already used node.");
2227 if (!(rseg = _add_segment(node, SEG_REPLICATOR, size)))
2230 if (!(rseg->log = dm_tree_find_node_by_uuid(node->dtree, rlog_uuid))) {
2231 log_error("Missing replicator log uuid %s.", rlog_uuid);
2235 if (!_link_tree_nodes(node, rseg->log))
2238 if (strcmp(rlog_type, "ringbuffer") != 0) {
2239 log_error("Unsupported replicator log type %s.", rlog_type);
2243 if (!(rseg->rlog_type = dm_pool_strdup(node->dtree->mem, rlog_type)))
2246 dm_list_init(&rseg->rsites);
2247 rseg->rdevice_count = 0;
2248 node->activation_priority = 1;
2251 /* Add site to segment */
2252 if (mode == DM_REPLICATOR_SYNC
2253 && (async_timeout || fall_behind_ios || fall_behind_data)) {
2254 log_error("Async parameters passed for synchronnous replicator.");
2258 if (node->props.segment_count != 1) {
2259 log_error(INTERNAL_ERROR "Attempt to add remote site area before setting replicator log.");
2263 rseg = dm_list_item(dm_list_last(&node->props.segs), struct load_segment);
2264 if (rseg->type != SEG_REPLICATOR) {
2265 log_error(INTERNAL_ERROR "Attempt to use non replicator segment %s.",
2266 dm_segtypes[rseg->type].target);
2270 if (!(rsite = dm_pool_zalloc(node->dtree->mem, sizeof(*rsite)))) {
2271 log_error("Failed to allocate remote site segment.");
2275 dm_list_add(&rseg->rsites, &rsite->list);
2276 rseg->rsite_count++;
2279 rsite->async_timeout = async_timeout;
2280 rsite->fall_behind_data = fall_behind_data;
2281 rsite->fall_behind_ios = fall_behind_ios;
2282 rsite->rsite_index = rsite_index;
2287 /* Appends device node to Replicator */
2288 int dm_tree_node_add_replicator_dev_target(struct dm_tree_node *node,
2290 const char *replicator_uuid,
2291 uint64_t rdevice_index,
2292 const char *rdev_uuid,
2293 unsigned rsite_index,
2294 const char *slog_uuid,
2295 uint32_t slog_flags,
2296 uint32_t slog_region_size)
2298 struct seg_area *area;
2299 struct load_segment *rseg;
2300 struct load_segment *rep_seg;
2302 if (rsite_index == REPLICATOR_LOCAL_SITE) {
2303 /* Site index for local target */
2304 if (!(rseg = _add_segment(node, SEG_REPLICATOR_DEV, size)))
2307 if (!(rseg->replicator = dm_tree_find_node_by_uuid(node->dtree, replicator_uuid))) {
2308 log_error("Missing replicator uuid %s.", replicator_uuid);
2312 /* Local slink0 for replicator must be always initialized first */
2313 if (rseg->replicator->props.segment_count != 1) {
2314 log_error(INTERNAL_ERROR "Attempt to use non replicator segment.");
2318 rep_seg = dm_list_item(dm_list_last(&rseg->replicator->props.segs), struct load_segment);
2319 if (rep_seg->type != SEG_REPLICATOR) {
2320 log_error(INTERNAL_ERROR "Attempt to use non replicator segment %s.",
2321 dm_segtypes[rep_seg->type].target);
2324 rep_seg->rdevice_count++;
2326 if (!_link_tree_nodes(node, rseg->replicator))
2329 rseg->rdevice_index = rdevice_index;
2331 /* Local slink0 for replicator must be always initialized first */
2332 if (node->props.segment_count != 1) {
2333 log_error(INTERNAL_ERROR "Attempt to use non replicator-dev segment.");
2337 rseg = dm_list_item(dm_list_last(&node->props.segs), struct load_segment);
2338 if (rseg->type != SEG_REPLICATOR_DEV) {
2339 log_error(INTERNAL_ERROR "Attempt to use non replicator-dev segment %s.",
2340 dm_segtypes[rseg->type].target);
2345 if (!(slog_flags & DM_CORELOG) && !slog_uuid) {
2346 log_error("Unspecified sync log uuid.");
2350 if (!dm_tree_node_add_target_area(node, NULL, rdev_uuid, 0))
2353 area = dm_list_item(dm_list_last(&rseg->areas), struct seg_area);
2355 if (!(slog_flags & DM_CORELOG)) {
2356 if (!(area->slog = dm_tree_find_node_by_uuid(node->dtree, slog_uuid))) {
2357 log_error("Couldn't find sync log uuid %s.", slog_uuid);
2361 if (!_link_tree_nodes(node, area->slog))
2365 area->flags = slog_flags;
2366 area->region_size = slog_region_size;
2367 area->rsite_index = rsite_index;
2372 static int _add_area(struct dm_tree_node *node, struct load_segment *seg, struct dm_tree_node *dev_node, uint64_t offset)
2374 struct seg_area *area;
2376 if (!(area = dm_pool_zalloc(node->dtree->mem, sizeof (*area)))) {
2377 log_error("Failed to allocate target segment area.");
2381 area->dev_node = dev_node;
2382 area->offset = offset;
2384 dm_list_add(&seg->areas, &area->list);
2390 int dm_tree_node_add_target_area(struct dm_tree_node *node,
2391 const char *dev_name,
2395 struct load_segment *seg;
2397 struct dm_tree_node *dev_node;
2399 if ((!dev_name || !*dev_name) && (!uuid || !*uuid)) {
2400 log_error("dm_tree_node_add_target_area called without device");
2405 if (!(dev_node = dm_tree_find_node_by_uuid(node->dtree, uuid))) {
2406 log_error("Couldn't find area uuid %s.", uuid);
2409 if (!_link_tree_nodes(node, dev_node))
2412 if (stat(dev_name, &info) < 0) {
2413 log_error("Device %s not found.", dev_name);
2417 if (!S_ISBLK(info.st_mode)) {
2418 log_error("Device %s is not a block device.", dev_name);
2422 /* FIXME Check correct macro use */
2423 if (!(dev_node = _add_dev(node->dtree, node, MAJOR(info.st_rdev),
2424 MINOR(info.st_rdev), 0)))
2428 if (!node->props.segment_count) {
2429 log_error(INTERNAL_ERROR "Attempt to add target area to missing segment.");
2433 seg = dm_list_item(dm_list_last(&node->props.segs), struct load_segment);
2435 if (!_add_area(node, seg, dev_node, offset))
2441 void dm_tree_set_cookie(struct dm_tree_node *node, uint32_t cookie)
2443 node->dtree->cookie = cookie;
2446 uint32_t dm_tree_get_cookie(struct dm_tree_node *node)
2448 return node->dtree->cookie;