-------- Original Message --------
Subject: Re: [PATCH 1/2] btrfs: Call mount_subtree() even 'subvolid=' mount option is given.
From: Chandan Rajendra <chan...@linux.vnet.ibm.com>
To: Qu Wenruo <quwen...@cn.fujitsu.com>
Date: 2014年07月18日 14:25
On Wednesday 16 Jul 2014 12:07:10 Qu Wenruo wrote:
+/* Find the path for given subvol_objectid.
+ * Caller needs to readlock the root tree and kzalloc PATH_MAX for
+ * subvol_name and namebuf */
+static char *find_subvol_by_id(struct btrfs_root *root, u64 subvol_objectid)
+{
+       struct btrfs_key key;
+       struct btrfs_key found_key;
+       struct btrfs_root_ref *ref;
+       struct btrfs_path *path;
+       char *namebuf = NULL;
+       char *new_buf = NULL;
+       char *subvol_ret = NULL;
+       int ret = 0;
+       u16 namelen = 0;
+
+       path = btrfs_alloc_path();
+       /* Alloc 1 byte for later strlen() calls */
+       subvol_ret = kzalloc(1, GFP_NOFS);
+       if (!path || !subvol_ret) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       key.objectid = subvol_objectid;
+       key.type = BTRFS_ROOT_BACKREF_KEY;
+       key.offset = 0;
+       /* We don't need to lock the tree_root,
+        * if when we do the backref walking, some one deleted/moved
+        * the subvol, we just return -ENOENT or let mount_subtree
+        * return -ENOENT and no disaster will happen.
+        * User should not modify subvolume when trying to mount it */
+       while (key.objectid != BTRFS_FS_TREE_OBJECTID) {
+               ret = btrfs_search_slot_for_read(root, &key, path, 1, 1);
+               if (ret < 0)
+                       goto out;
+               if (ret) {
+                       ret = -ENOENT;
+                       goto out;
+               }
+               btrfs_item_key_to_cpu(path->nodes[0], &found_key,
+                                     path->slots[0]);
+               if (found_key.objectid != key.objectid ||
+                   found_key.type != BTRFS_ROOT_BACKREF_KEY) {
+                       ret = -ENOENT;
+                       goto out;
+               }
+               key.objectid = found_key.offset;
+               ref = btrfs_item_ptr(path->nodes[0], path->slots[0],
+                                    struct btrfs_root_ref);
+               namelen = btrfs_root_ref_name_len(path->nodes[0], ref);
+               /* One for ending '\0' One for '/' */
+               new_buf = krealloc(namebuf, namelen + 2, GFP_NOFS);
+               if (!new_buf) {
+                       ret = -ENOMEM;
+                       goto out;
+               }
+               namebuf = new_buf;
+               read_extent_buffer(path->nodes[0], namebuf,
+                                  (unsigned long)(ref + 1), namelen);
+               btrfs_release_path(path);
+               *(namebuf + namelen) = '/';
+               *(namebuf + namelen + 1) = '\0';
+
+               new_buf = krealloc(subvol_ret, strlen(subvol_ret) + namelen + 2,
+                                  GFP_NOFS);
+               if (!new_buf) {
+                       ret = -ENOMEM;
+                       goto out;
+               }
+               subvol_ret = new_buf;
+               str_append_head(subvol_ret, namebuf);
+       }
+out:
+       kfree(namebuf);
+       btrfs_free_path(path);
+       if (ret < 0) {
+               kfree(subvol_ret);
+               return ERR_PTR(ret);
+       } else
+               return subvol_ret;
+
+}
Hello Qu Wenruo,

If the subvolume being mounted exists in a sub-directory of the parent's
subvolume, then the find_subvol_by_id() fails to contruct the correct
path to the subvolume. Hence mount would fail.

For e.g.

[root@guest0 ~]# btrfs subvolume list /mnt/btrfs/
ID 257 gen 7 top level 5 path dir1/sub1
[root@guest0 ~]# umount /mnt/btrfs
[root@guest0 ~]# mount -o subvolid=257 /dev/loop0 /mnt/btrfs/
mount: mount(2) failed: No such file or directory

Oh, I forgot such situation, thanks for the test.
I'll update the patch to V2 to deal the problem.

Thanks,
Qu
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to