Hi All, I found that there's a potential bug in libdm when I try to swap sub volume's name. By executing the following code, the function dm_tree_activate_children() will go into infinite loop since that _rename_conflict_exists() still reports "resolvable=1" in this case. logical_volume *parent = ...; logical_volume *child1 = seg_lv(parent, 0); logical_volume *child2 = seg_lv(parent, 1); char const *tmp = child1->name; child1->name = child2->name; child2->name = tmp; resume_lv(cmd, parent); Although this scenario might not happen through command-line operation, some programmers might need this feature. I think that this issue could be resolve in libdm by assigning a temporary name, as the following patch does. Is it safe to do this? diff --git libdm/libdm-deptree.c libdm/libdm-deptree.c index 1335351..b0c5f13 100644 --- a/libdm/libdm-deptree.c +++ b/libdm/libdm-deptree.c @@ -1771,7 +1771,8 @@ static int _rename_conflict_exists(struct dm_tree_node *parent, } if (!strcmp(node->props.new_name, sibling_name)) { - if (sibling->props.new_name) + if (sibling->props.new_name && + strcmp(sibling->props.new_name, dm_tree_node_get_name(node))) *resolvable = 1; return 1; } @@ -1790,8 +1791,10 @@ int dm_tree_activate_children(struct dm_tree_node *dnode, struct dm_tree_node *child = dnode; struct dm_info newinfo; const char *name; + const char *new_name = NULL; const char *uuid; int priority; + int rename_conflict = 0; /* Activate children first */ while ((child = dm_tree_next_child(&handle, dnode, 0))) { @@ -1831,12 +1834,21 @@ int dm_tree_activate_children(struct dm_tree_node *dnode, /* Rename? */ if (child->props.new_name) { - if (_rename_conflict_exists(dnode, child, &resolvable_name_conflict) && - resolvable_name_conflict) { - awaiting_peer_rename++; - continue; + rename_conflict = _rename_conflict_exists(dnode, child, &resolvable_name_conflict); + if (rename_conflict) { + if (resolvable_name_conflict) { + awaiting_peer_rename++; + continue; + } else { + /* assign a temporary name for swapping names */ + new_name = dm_pool_zalloc(dnode->dtree->mem, strlen(child->props.new_name) + 5); + dm_snprintf((char*)new_name, strlen(child->props.new_name) + 5, "%s_tmp", child->props.new_name); + awaiting_peer_rename++; + } + } else { + new_name = child->props.new_name; } - if (!_rename_node(name, child->props.new_name, child->info.major, + if (!_rename_node(name, new_name, child->info.major, child->info.minor, &child->dtree->cookie, child->udev_flags)) { log_error("Failed to rename %s (%" PRIu32 @@ -1844,8 +1856,10 @@ int dm_tree_activate_children(struct dm_tree_node *dnode, child->info.minor, child->props.new_name); return 0; } - child->name = child->props.new_name; - child->props.new_name = NULL; + child->name = new_name; + + if (!rename_conflict) + child->props.new_name = NULL; } if (!child->info.inactive_table && !child->info.suspended) Thanks, Ming-Hung Tsai _______________________________________________ linux-lvm mailing list linux-lvm@redhat.com https://www.redhat.com/mailman/listinfo/linux-lvm read the LVM HOW-TO at http://tldp.org/HOWTO/LVM-HOWTO/