From patchwork Wed Jun 24 16:03:12 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Marek_Beh=C3=BAn?= X-Patchwork-Id: 242894 List-Id: U-Boot discussion From: marek.behun at nic.cz (=?UTF-8?q?Marek=20Beh=C3=BAn?=) Date: Wed, 24 Jun 2020 18:03:12 +0200 Subject: [PATCH U-BOOT v3 26/30] fs: btrfs: Introduce function to resolve path in one subvolume In-Reply-To: <20200624160316.5001-1-marek.behun@nic.cz> References: <20200624160316.5001-1-marek.behun@nic.cz> Message-ID: <20200624160316.5001-27-marek.behun@nic.cz> From: Qu Wenruo This patch introduces a new function, get_path_in_subvolume(), which resolves inode number into path inside a subvolume. This function will be later used for btrfs subvolume list functionality. Signed-off-by: Qu Wenruo Reviewed-by: Marek Beh?n --- fs/btrfs/compat.h | 1 + fs/btrfs/subvolume.c | 68 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/fs/btrfs/compat.h b/fs/btrfs/compat.h index 2dbeb90d33..321681814f 100644 --- a/fs/btrfs/compat.h +++ b/fs/btrfs/compat.h @@ -24,6 +24,7 @@ static inline void error(const char *fmt, ...) /* No so have to define it here */ #define XATTR_NAME_MAX 255 +#define PATH_MAX 4096 /* * Macros to generate set/get funcs for the struct fields diff --git a/fs/btrfs/subvolume.c b/fs/btrfs/subvolume.c index 0e72577d0d..b446e729cd 100644 --- a/fs/btrfs/subvolume.c +++ b/fs/btrfs/subvolume.c @@ -5,8 +5,74 @@ * 2017 Marek Behun, CZ.NIC, marek.behun at nic.cz */ -#include "btrfs.h" #include +#include "ctree.h" +#include "btrfs.h" + +/* + * Resolve the path of ino inside subvolume @root into @path_ret. + * + * @path_ret must be at least PATH_MAX size. + */ +static int get_path_in_subvol(struct btrfs_root *root, u64 ino, char *path_ret) +{ + struct btrfs_path path; + struct btrfs_key key; + char *tmp; + u64 cur = ino; + int ret = 0; + + tmp = malloc(PATH_MAX); + if (!tmp) + return -ENOMEM; + tmp[0] = '\0'; + + btrfs_init_path(&path); + while (cur != BTRFS_FIRST_FREE_OBJECTID) { + struct btrfs_inode_ref *iref; + int name_len; + + btrfs_release_path(&path); + key.objectid = cur; + key.type = BTRFS_INODE_REF_KEY; + key.offset = (u64)-1; + + ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0); + /* Impossible */ + if (ret == 0) + ret = -EUCLEAN; + if (ret < 0) + goto out; + ret = btrfs_previous_item(root, &path, cur, + BTRFS_INODE_REF_KEY); + if (ret > 0) + ret = -ENOENT; + if (ret < 0) + goto out; + + strncpy(tmp, path_ret, PATH_MAX); + iref = btrfs_item_ptr(path.nodes[0], path.slots[0], + struct btrfs_inode_ref); + name_len = btrfs_inode_ref_name_len(path.nodes[0], + iref); + if (name_len > BTRFS_NAME_LEN) { + ret = -ENAMETOOLONG; + goto out; + } + read_extent_buffer(path.nodes[0], path_ret, + (unsigned long)(iref + 1), name_len); + path_ret[name_len] = '/'; + path_ret[name_len + 1] = '\0'; + strncat(path_ret, tmp, PATH_MAX); + + btrfs_item_key_to_cpu(path.nodes[0], &key, path.slots[0]); + cur = key.offset; + } +out: + btrfs_release_path(&path); + free(tmp); + return ret; +} static int get_subvol_name(u64 subvolid, char *name, int max_len) {