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 -- chandan -- 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