diff mbox series

[v3,26/30] fs: btrfs: Introduce function to resolve path in one subvolume

Message ID 20200624160316.5001-27-marek.behun@nic.cz
State New
Headers show
Series PLEASE TEST fs: btrfs: Re-implement btrfs support using code from btrfs-progs | expand

Commit Message

Marek BehĂșn June 24, 2020, 4:03 p.m. UTC
From: Qu Wenruo <wqu at suse.com>

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 <wqu at suse.com>
Reviewed-by: Marek Beh?n <marek.behun at nic.cz>
---
 fs/btrfs/compat.h    |  1 +
 fs/btrfs/subvolume.c | 68 +++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 68 insertions(+), 1 deletion(-)
diff mbox series

Patch

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 <linux/limits.h> 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 <malloc.h>
+#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)
 {