return seg->area_count;
}
-/*
- * Resume sub-LVs first, then top-level LV
- */
-static int _bottom_up_resume(struct logical_volume *lv)
-{
- uint32_t s;
- struct lv_segment *seg = first_seg(lv);
-
- if (seg_is_raid(seg) && (seg->area_count > 1)) {
- for (s = 0; s < seg->area_count; s++)
- if (!resume_lv(lv->vg->cmd, seg_lv(seg, s)) ||
- !resume_lv(lv->vg->cmd, seg_metalv(seg, s)))
- return_0;
- }
-
- return resume_lv(lv->vg->cmd, lv);
-}
-
static int _activate_sublv_preserving_excl(struct logical_volume *top_lv,
struct logical_volume *sub_lv)
{
}
}
- /*
- * Resume the remaining LVs
- * We must start by resuming the sub-LVs first (which would
- * otherwise be handled automatically) because the shifting
- * of positions could otherwise cause name collisions. For
- * example, if position 0 of a 3-way array is removed, position
- * 1 and 2 must be shifted and renamed 0 and 1. If position 2
- * tries to rename first, it will collide with the existing
- * position 1.
- */
- if (!_bottom_up_resume(lv)) {
+ if (!resume_lv(lv->vg->cmd, lv)) {
log_error("Failed to resume %s/%s after committing changes",
lv->vg->name, lv->name);
return 0;
if (!resume_lv(cmd, lvl->lv))
return_0;
- /*
- * Resume the remaining LVs
- * We must start by resuming the sub-LVs first (which would
- * otherwise be handled automatically) because the shifting
- * of positions could otherwise cause name collisions. For
- * example, if position 0 of a 3-way array is split, position
- * 1 and 2 must be shifted and renamed 0 and 1. If position 2
- * tries to rename first, it will collide with the existing
- * position 1.
- */
- if (!_bottom_up_resume(lv)) {
+ if (!resume_lv(lv->vg->cmd, lv)) {
log_error("Failed to resume %s/%s after committing changes",
lv->vg->name, lv->name);
return 0;
return r;
}
+/*
+ * _rename_conflict_exists
+ * @dnode
+ * @node
+ * @resolvable
+ *
+ * Check if there is a rename conflict with existing peers in
+ * this tree. 'resolvable' is set if the conflicting node will
+ * also be undergoing a rename. (Allowing that node to rename
+ * first would clear the conflict.)
+ *
+ * Returns: 1 if conflict, 0 otherwise
+ */
+static int _rename_conflict_exists(struct dm_tree_node *parent,
+ struct dm_tree_node *node,
+ int *resolvable)
+{
+ void *handle = NULL;
+ const char *name = dm_tree_node_get_name(node);
+ const char *sibling_name;
+ struct dm_tree_node *sibling;
+
+ *resolvable = 0;
+
+ if (!name)
+ return_0;
+
+ while ((sibling = dm_tree_next_child(&handle, parent, 0))) {
+ if (sibling == node)
+ continue;
+
+ if (!(sibling_name = dm_tree_node_get_name(sibling))) {
+ stack;
+ continue;
+ }
+
+ if (!strcmp(node->props.new_name, sibling_name)) {
+ if (sibling->props.new_name)
+ *resolvable = 1;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
int dm_tree_activate_children(struct dm_tree_node *dnode,
const char *uuid_prefix,
size_t uuid_prefix_len)
{
int r = 1;
+ int resolvable_name_conflict, awaiting_peer_rename = 0;
void *handle = NULL;
struct dm_tree_node *child = dnode;
struct dm_info newinfo;
handle = NULL;
for (priority = 0; priority < 3; priority++) {
+ awaiting_peer_rename = 0;
while ((child = dm_tree_next_child(&handle, dnode, 0))) {
if (priority != child->activation_priority)
continue;
/* Rename? */
if (child->props.new_name) {
+ if (_rename_conflict_exists(dnode, child, &resolvable_name_conflict) &&
+ resolvable_name_conflict) {
+ awaiting_peer_rename++;
+ continue;
+ }
if (!_rename_node(name, child->props.new_name, child->info.major,
child->info.minor, &child->dtree->cookie,
child->udev_flags)) {
/* Update cached info */
child->info = newinfo;
}
+ if (awaiting_peer_rename)
+ priority--; /* redo priority level */
}
/*