Existing mechanism was not able to trace root volume issue.
Simplify the functionality by using simply using activated flag
and trace the dtree in reverse order.
Version 1.02.181 -
===================================
+ Enhance tracking of activated devices when preloading dm tree.
Fix bug in construction of cache table line (regression from 1.02.159).
Version 1.02.179 - 11th August 2021
dm_node_callback_fn callback;
void *callback_data;
- /*
- * TODO:
- * Add advanced code which tracks of send ioctls and their
- * proper revert operation for more advanced recovery
- * Current code serves mostly only to recovery when
- * thin pool metadata check fails and command would
- * have left active thin data and metadata subvolumes.
- */
- struct dm_list activated; /* Head of activated nodes for preload revert */
- struct dm_list activated_list; /* List of activated nodes for preload revert */
+ int activated; /* tracks activation during preload */
};
struct dm_tree {
dtree->root.dtree = dtree;
dm_list_init(&dtree->root.uses);
dm_list_init(&dtree->root.used_by);
- dm_list_init(&dtree->root.activated);
dtree->skip_lockfs = 0;
dtree->no_flush = 0;
dtree->mem = dmem;
dm_list_init(&node->uses);
dm_list_init(&node->used_by);
- dm_list_init(&node->activated);
dm_list_init(&node->props.segs);
dev = MKDEV(info->major, info->minor);
}
if (r)
- dm_list_add_h(&parent->activated, &dnode->activated_list);
+ dnode->activated = 1;
out:
dm_task_destroy(dmt);
return r;
}
-/*
- * Currently try to deactivate only nodes created during preload.
- * New node is always attached to the front of activated_list
- */
-static int _dm_tree_revert_activated(struct dm_tree_node *parent)
+/* Try to deactivate only nodes created during preload. */
+static int _dm_tree_revert_activated(struct dm_tree_node *dnode)
{
+ void *handle = NULL;
struct dm_tree_node *child;
- dm_list_iterate_items_gen(child, &parent->activated, activated_list) {
- log_debug_activation("Reverting %s.", _node_name(child));
- if (child->callback) {
- log_debug_activation("Dropping callback for %s.", _node_name(child));
- child->callback = NULL;
- }
- if (!_deactivate_node(child->name, child->info.major, child->info.minor,
- &child->dtree->cookie, child->udev_flags, 0)) {
- log_error("Unable to deactivate %s.", _node_name(child));
- return 0;
+ while ((child = dm_tree_next_child(&handle, dnode, 0))) {
+ if (child->activated) {
+ if (child->callback) {
+ log_debug_activation("Dropping callback for %s.", _node_name(child));
+ child->callback = NULL;
+ }
+
+ log_debug_activation("Reverting %s.", _node_name(child));
+ if (!_deactivate_node(child->name, child->info.major, child->info.minor,
+ &child->dtree->cookie, child->udev_flags, 0)) {
+ log_debug_activation("Unable to deactivate %s.", _node_name(child));
+ return 0;
+ }
}
- if (!_dm_tree_revert_activated(child))
+
+ if (dm_tree_node_num_children(child, 0) &&
+ !_dm_tree_revert_activated(child))
return_0;
}
dm_node_callback_fn callback;
void *callback_data;
- /*
- * TODO:
- * Add advanced code which tracks of send ioctls and their
- * proper revert operation for more advanced recovery
- * Current code serves mostly only to recovery when
- * thin pool metadata check fails and command would
- * have left active thin data and metadata subvolumes.
- */
- struct dm_list activated; /* Head of activated nodes for preload revert */
- struct dm_list activated_list; /* List of activated nodes for preload revert */
+ int activated; /* tracks activation during preload */
};
struct dm_tree {
dtree->root.dtree = dtree;
dm_list_init(&dtree->root.uses);
dm_list_init(&dtree->root.used_by);
- dm_list_init(&dtree->root.activated);
dtree->skip_lockfs = 0;
dtree->no_flush = 0;
dtree->mem = dmem;
dm_list_init(&node->uses);
dm_list_init(&node->used_by);
- dm_list_init(&node->activated);
dm_list_init(&node->props.segs);
dev = MKDEV(info->major, info->minor);
}
if (r)
- dm_list_add_h(&parent->activated, &dnode->activated_list);
+ dnode->activated = 1;
out:
dm_task_destroy(dmt);
return r;
}
-/*
- * Currently try to deactivate only nodes created during preload.
- * New node is always attached to the front of activated_list
- */
-static int _dm_tree_revert_activated(struct dm_tree_node *parent)
+/* Try to deactivate only nodes created during preload. */
+static int _dm_tree_revert_activated(struct dm_tree_node *dnode)
{
+ void *handle = NULL;
struct dm_tree_node *child;
- dm_list_iterate_items_gen(child, &parent->activated, activated_list) {
- log_debug_activation("Reverting %s.", _node_name(child));
- if (child->callback) {
- log_debug_activation("Dropping callback for %s.", _node_name(child));
- child->callback = NULL;
- }
- if (!_deactivate_node(child->name, child->info.major, child->info.minor,
- &child->dtree->cookie, child->udev_flags, 0)) {
- log_error("Unable to deactivate %s.", _node_name(child));
- return 0;
+ while ((child = dm_tree_next_child(&handle, dnode, 0))) {
+ if (child->activated) {
+ if (child->callback) {
+ log_debug_activation("Dropping callback for %s.", _node_name(child));
+ child->callback = NULL;
+ }
+
+ log_debug_activation("Reverting %s.", _node_name(child));
+ if (!_deactivate_node(child->name, child->info.major, child->info.minor,
+ &child->dtree->cookie, child->udev_flags, 0)) {
+ log_debug_activation("Unable to deactivate %s.", _node_name(child));
+ return 0;
+ }
}
- if (!_dm_tree_revert_activated(child))
+
+ if (dm_tree_node_num_children(child, 0) &&
+ !_dm_tree_revert_activated(child))
return_0;
}