diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM index c3e8e1594..f8e7e7bdf 100644 --- a/WHATS_NEW_DM +++ b/WHATS_NEW_DM @@ -1,5 +1,6 @@ Version 1.02.73 - ==================================== + Added dm_tree_node_set_callback() for preload and deactivation hooks. Drop unsupported TRIM message for thin pool. Improve logging for fifo startup in dmeventd. Add few pointer validation in dmsetup. diff --git a/libdm/libdevmapper.h b/libdm/libdevmapper.h index dfbadaa27..7df4db8a6 100644 --- a/libdm/libdevmapper.h +++ b/libdm/libdevmapper.h @@ -688,6 +688,20 @@ void dm_tree_node_set_read_ahead(struct dm_tree_node *dnode, uint32_t read_ahead, uint32_t read_ahead_flags); +/* + * Set node callback hook before de/activation. + * Callback is called before 'activation' of node for activation tree, + * or 'deactivation' of node for deactivation tree. + */ +typedef enum { + DM_NODE_CALLBACK_PRELOADED, /* Node has preload deps */ + DM_NODE_CALLBACK_DEACTIVATED, /* Node is deactivated */ +} dm_node_callback_t; +typedef int (*dm_node_callback_fn) (struct dm_tree_node *node, + dm_node_callback_t type, void *cb_data); +void dm_tree_node_set_callback(struct dm_tree_node *node, + dm_node_callback_fn cb, void *cb_data); + void dm_tree_set_cookie(struct dm_tree_node *node, uint32_t cookie); uint32_t dm_tree_get_cookie(struct dm_tree_node *node); diff --git a/libdm/libdm-deptree.c b/libdm/libdm-deptree.c index e80db2fee..582a14a66 100644 --- a/libdm/libdm-deptree.c +++ b/libdm/libdm-deptree.c @@ -263,6 +263,10 @@ struct dm_tree_node { * Note: only direct child is allowed */ struct dm_tree_node *presuspend_node; + + /* Callback */ + dm_node_callback_fn callback; + void *callback_data; }; struct dm_tree { @@ -1588,6 +1592,14 @@ static int _dm_tree_deactivate_children(struct dm_tree_node *dnode, } else if (info.suspended) dec_suspended(); + if (child->callback && + !child->callback(child, DM_NODE_CALLBACK_DEACTIVATED, + child->callback_data)) { + r = 0; + // FIXME: break tree shutdown or continue? + // hmm what about _node_clear_table()? + } + if (dm_tree_node_num_children(child, 0)) { if (!_dm_tree_deactivate_children(child, uuid_prefix, uuid_prefix_len, level + 1)) return_0; @@ -2445,10 +2457,16 @@ int dm_tree_preload_children(struct dm_tree_node *dnode, update_devs_flag = 1; } - if (update_devs_flag) { + if (update_devs_flag || + (!dnode->info.exists && dnode->callback)) { if (!dm_udev_wait(dm_tree_get_cookie(dnode))) stack; dm_tree_set_cookie(dnode, 0); + + if (!dnode->info.exists && dnode->callback && + !dnode->callback(child, DM_NODE_CALLBACK_PRELOADED, + dnode->callback_data)) + return_0; } return r; @@ -3245,3 +3263,10 @@ int dm_tree_node_add_null_area(struct dm_tree_node *node, uint64_t offset) return 1; } + +void dm_tree_node_set_callback(struct dm_tree_node *dnode, + dm_node_callback_fn cb, void *data) +{ + dnode->callback = cb; + dnode->callback_data = data; +}