diff --git a/WHATS_NEW b/WHATS_NEW index f9f8a0feb..80fc3d45f 100644 --- a/WHATS_NEW +++ b/WHATS_NEW @@ -1,5 +1,6 @@ Version 2.02.67 - =============================== + Added dm_tree_node_set_presuspend_node() to presuspend child in deactivate. Initial libdm support for Replicator target (API is not stable yet). Extend process_each_lv_in_vg() with support for list of failed lvnames. Return ECMD_FAILED for break in process_each_lv() and process_each_segment_in_lv(). diff --git a/libdm/.exported_symbols b/libdm/.exported_symbols index 090e6332d..4eb3bd09a 100644 --- a/libdm/.exported_symbols +++ b/libdm/.exported_symbols @@ -82,6 +82,7 @@ dm_tree_node_add_mirror_target_log dm_tree_node_add_target_area dm_tree_node_add_replicator_target dm_tree_node_add_replicator_dev_target +dm_tree_node_set_presuspend_node dm_tree_node_set_read_ahead dm_tree_skip_lockfs dm_tree_use_no_flush_suspend diff --git a/libdm/libdevmapper.h b/libdm/libdevmapper.h index e0b773922..0b67a0f15 100644 --- a/libdm/libdevmapper.h +++ b/libdm/libdevmapper.h @@ -474,6 +474,9 @@ int dm_tree_node_add_replicator_dev_target(struct dm_tree_node *node, uint32_t slog_region_size); /* End of Replicator API */ +void dm_tree_node_set_presuspend_node(struct dm_tree_node *node, + struct dm_tree_node *presuspend_node); + int dm_tree_node_add_target_area(struct dm_tree_node *node, const char *dev_name, const char *dlid, diff --git a/libdm/libdm-deptree.c b/libdm/libdm-deptree.c index 6cbb80628..3cf68b9bf 100644 --- a/libdm/libdm-deptree.c +++ b/libdm/libdm-deptree.c @@ -168,6 +168,12 @@ struct dm_tree_node { void *context; /* External supplied context */ struct load_properties props; /* For creation/table (re)load */ + + /* + * If presuspend of child node is needed + * Note: only direct child is allowed + */ + struct dm_tree_node *presuspend_node; }; struct dm_tree { @@ -684,6 +690,12 @@ void dm_tree_node_set_read_ahead(struct dm_tree_node *dnode, dnode->props.read_ahead_flags = read_ahead_flags; } +void dm_tree_node_set_presuspend_node(struct dm_tree_node *node, + struct dm_tree_node *presuspend_node) +{ + node->presuspend_node = presuspend_node; +} + int dm_tree_add_dev(struct dm_tree *dtree, uint32_t major, uint32_t minor) { return _add_dev(dtree, &dtree->root, major, minor, 0) ? 1 : 0; @@ -794,6 +806,10 @@ static int _children_suspended(struct dm_tree_node *node, if (!_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len)) continue; + /* Ignore if parent node wants to presuspend this node */ + if (dlink->node->presuspend_node == node) + continue; + if (!(dinfo = dm_tree_node_get_info(dlink->node))) { stack; /* FIXME Is this normal? */ return 0; @@ -1095,6 +1111,11 @@ static int _dm_tree_deactivate_children(struct dm_tree_node *dnode, continue; } + /* Suspend child node first if requested */ + if (child->presuspend_node && + !dm_tree_suspend_children(child, uuid_prefix, uuid_prefix_len)) + continue; + if (!_deactivate_node(name, info.major, info.minor, &child->dtree->cookie, child->udev_flags)) { log_error("Unable to deactivate %s (%" PRIu32