linux-lvm.redhat.com archive mirror
 help / color / mirror / Atom feed
From: "M.H. Tsai" <mingnus@gmail.com>
To: linux-lvm@redhat.com
Subject: [linux-lvm] libdm cannot swap names between two child volumes
Date: Thu, 4 Jun 2015 18:02:39 +0800	[thread overview]
Message-ID: <CAAYit8QCcaGvb5QPw_Xuk+oavthHR1c32oB0GsGd+Ypk0rPtRg@mail.gmail.com> (raw)

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

             reply	other threads:[~2015-06-04 10:02 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-06-04 10:02 M.H. Tsai [this message]
2015-06-04 12:14 ` [linux-lvm] libdm cannot swap names between two child volumes Zdenek Kabelac
2015-06-05  3:32   ` M.H. Tsai
2015-06-05  8:04     ` Zdenek Kabelac
2015-06-08  2:09       ` M.H. Tsai
2015-06-08  7:17         ` Zdenek Kabelac
2015-06-11  2:54           ` M.H. Tsai
2015-06-11  7:46             ` Zdenek Kabelac

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CAAYit8QCcaGvb5QPw_Xuk+oavthHR1c32oB0GsGd+Ypk0rPtRg@mail.gmail.com \
    --to=mingnus@gmail.com \
    --cc=linux-lvm@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).