[WIP] [PATCH v4 04/12] erofs-utils: fuse: clean up path walking

Gao Xiang hsiangkao at aol.com
Sun Nov 15 05:25:09 AEDT 2020


Signed-off-by: Gao Xiang <hsiangkao at aol.com>
---
 fuse/namei.c  | 82 +++++++++++++++++++++------------------------------
 fuse/namei.h  |  2 --
 fuse/read.c   | 16 ++--------
 fuse/readir.c | 10 ++-----
 4 files changed, 39 insertions(+), 71 deletions(-)

diff --git a/fuse/namei.c b/fuse/namei.c
index 5ee3f8d2a4b6..37cf549cd2a6 100644
--- a/fuse/namei.c
+++ b/fuse/namei.c
@@ -17,27 +17,6 @@
 #include "erofs/print.h"
 #include "erofs/io.h"
 
-#define IS_PATH_SEPARATOR(__c)      ((__c) == '/')
-#define MINORBITS	20
-#define MINORMASK	((1U << MINORBITS) - 1)
-#define DT_UNKNOWN	0
-
-static const char *skip_trailing_backslash(const char *path)
-{
-	while (IS_PATH_SEPARATOR(*path))
-		path++;
-	return path;
-}
-
-static uint8_t get_path_token_len(const char *path)
-{
-	uint8_t len = 0;
-
-	while (path[len] != '/' && path[len])
-		len++;
-	return len;
-}
-
 static inline dev_t new_decode_dev(u32 dev)
 {
 	unsigned major = (dev & 0xfff00) >> 8;
@@ -45,7 +24,7 @@ static inline dev_t new_decode_dev(u32 dev)
 	return makedev(major, minor);
 }
 
-int erofs_iget_by_nid(erofs_nid_t nid, struct erofs_vnode *vi)
+static int erofs_iget_by_nid(erofs_nid_t nid, struct erofs_vnode *vi)
 {
 	int ret, ifmt;
 	char buf[EROFS_BLKSIZ];
@@ -136,14 +115,20 @@ struct erofs_dirent *find_target_dirent(erofs_nid_t pnid,
 	return NULL;
 }
 
-int erofs_namei(erofs_nid_t *nid,
+struct nameidata {
+	erofs_nid_t	nid;
+	unsigned int	ftype;
+};
+
+int erofs_namei(struct nameidata *nd,
 		const char *name, unsigned int len)
 {
+	erofs_nid_t nid = nd->nid;
 	int ret;
 	char buf[EROFS_BLKSIZ];
 	struct erofs_vnode v;
 
-	ret = erofs_iget_by_nid(*nid, &v);
+	ret = erofs_iget_by_nid(nid, &v);
 	if (ret)
 		return ret;
 
@@ -154,7 +139,7 @@ int erofs_namei(erofs_nid_t *nid,
 			.u = {
 				.i_blkaddr = v.raw_blkaddr,
 			},
-			.nid = v.nid,
+			.nid = nid,
 			.i_size = v.i_size,
 			.datalayout = v.datalayout,
 			.inode_isize = v.inode_isize,
@@ -175,17 +160,17 @@ int erofs_namei(erofs_nid_t *nid,
 			if (nameoff < sizeof(struct erofs_dirent) ||
 			    nameoff >= PAGE_SIZE) {
 				erofs_err("invalid de[0].nameoff %u @ nid %llu",
-					  nameoff, *nid | 0ULL);
+					  nameoff, nid | 0ULL);
 				return -EFSCORRUPTED;
 			}
 
-			de = find_target_dirent(*nid, buf, name, len,
+			de = find_target_dirent(nid, buf, name, len,
 						nameoff, maxsize);
 			if (IS_ERR(de))
 				return PTR_ERR(de);
 
 			if (de) {
-				*nid = le64_to_cpu(de->nid);
+				nd->nid = le64_to_cpu(de->nid);
 				return 0;
 			}
 			offset += maxsize;
@@ -194,44 +179,43 @@ int erofs_namei(erofs_nid_t *nid,
 	return -ENOENT;
 }
 
-extern struct dcache_entry root_entry;
-int walk_path(const char *_path, erofs_nid_t *out_nid)
+static int link_path_walk(const char *name, struct nameidata *nd)
 {
-	int ret;
-	erofs_nid_t nid = sbi.root_nid;
-	const char *path = _path;
+	nd->nid = sbi.root_nid;
+
+	while (*name == '/')
+		name++;
 
-	for (;;) {
-		uint8_t path_len;
+	/* At this point we know we have a real path component. */
+	while (*name != '\0') {
+		const char *p = name;
+		int ret;
 
-		path = skip_trailing_backslash(path);
-		path_len = get_path_token_len(path);
-		if (path_len == 0)
-			break;
+		do {
+			++p;
+		} while (*p != '\0' && *p != '/');
 
-		ret = erofs_namei(&nid, path, path_len);
+		DBG_BUGON(p <= name);
+		ret = erofs_namei(nd, name, p - name);
 		if (ret)
 			return ret;
 
-		path += path_len;
+		name = p;
+		/* Skip until no more slashes. */
+		for (name = p; *name == '/'; ++name);
 	}
-
-	erofs_dbg("find path = %s nid=%llu", _path, nid | 0ULL);
-
-	*out_nid = nid;
 	return 0;
-
 }
 
 int erofs_iget_by_path(const char *path, struct erofs_vnode *v)
 {
 	int ret;
-	erofs_nid_t nid;
+	struct nameidata nd;
 
-	ret = walk_path(path, &nid);
+	ret = link_path_walk(path, &nd);
 	if (ret)
 		return ret;
 
-	return erofs_iget_by_nid(nid, v);
+	return erofs_iget_by_nid(nd.nid, v);
 }
 
diff --git a/fuse/namei.h b/fuse/namei.h
index 2625ec58d434..bd5adfda2969 100644
--- a/fuse/namei.h
+++ b/fuse/namei.h
@@ -11,7 +11,5 @@
 #include "erofs_fs.h"
 
 int erofs_iget_by_path(const char *path, struct erofs_vnode *v);
-int erofs_iget_by_nid(erofs_nid_t nid, struct erofs_vnode *v);
-int walk_path(const char *path, erofs_nid_t *out_nid);
 
 #endif
diff --git a/fuse/read.c b/fuse/read.c
index 10a26d84c37c..aa5221a60d4e 100644
--- a/fuse/read.c
+++ b/fuse/read.c
@@ -116,21 +116,16 @@ int erofs_read(const char *path, char *buffer, size_t size, off_t offset,
 	       struct fuse_file_info *fi)
 {
 	int ret;
-	erofs_nid_t nid;
 	struct erofs_vnode v;
 
 	UNUSED(fi);
 	erofs_info("path:%s size=%zd offset=%llu", path, size, (long long)offset);
 
-	ret = walk_path(path, &nid);
+	ret = erofs_iget_by_path(path, &v);
 	if (ret)
 		return ret;
 
-	ret = erofs_iget_by_nid(nid, &v);
-	if (ret)
-		return ret;
-
-	erofs_info("path:%s nid=%llu mode=%u", path, (unsigned long long)nid, v.datalayout);
+	erofs_info("path:%s nid=%llu mode=%u", path, v.nid | 0ULL, v.datalayout);
 	switch (v.datalayout) {
 	case EROFS_INODE_FLAT_PLAIN:
 	case EROFS_INODE_FLAT_INLINE:
@@ -148,15 +143,10 @@ int erofs_read(const char *path, char *buffer, size_t size, off_t offset,
 int erofs_readlink(const char *path, char *buffer, size_t size)
 {
 	int ret;
-	erofs_nid_t nid;
 	size_t lnksz;
 	struct erofs_vnode v;
 
-	ret = walk_path(path, &nid);
-	if (ret)
-		return ret;
-
-	ret = erofs_iget_by_nid(nid, &v);
+	ret = erofs_iget_by_path(path, &v);
 	if (ret)
 		return ret;
 
diff --git a/fuse/readir.c b/fuse/readir.c
index 5281c8b80e59..1d28016a8900 100644
--- a/fuse/readir.c
+++ b/fuse/readir.c
@@ -66,7 +66,6 @@ int erofs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
 		  off_t offset, struct fuse_file_info *fi)
 {
 	int ret;
-	erofs_nid_t nid;
 	struct erofs_vnode v;
 	char dirsbuf[EROFS_BLKSIZ];
 	uint32_t dir_nr, dir_off, nr_cnt;
@@ -74,14 +73,11 @@ int erofs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
 	erofs_dbg("readdir:%s offset=%llu", path, (long long)offset);
 	UNUSED(fi);
 
-	ret = walk_path(path, &nid);
+	ret = erofs_iget_by_path(path, &v);
 	if (ret)
 		return ret;
 
-	erofs_dbg("path=%s nid = %llu", path, (unsigned long long)nid);
-	ret = erofs_iget_by_nid(nid, &v);
-	if (ret)
-		return ret;
+	erofs_dbg("path=%s nid = %llu", path, v.nid | 0ULL);
 
 	if (!S_ISDIR(v.i_mode))
 		return -ENOTDIR;
@@ -107,7 +103,7 @@ int erofs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
 	if (v.datalayout == EROFS_INODE_FLAT_INLINE) {
 		off_t addr;
 
-		addr = iloc(nid) + v.inode_isize + v.xattr_isize;
+		addr = iloc(v.nid) + v.inode_isize + v.xattr_isize;
 
 		memset(dirsbuf, 0, sizeof(dirsbuf));
 		ret = dev_read(dirsbuf, addr, dir_off);
-- 
2.24.0



More information about the Linux-erofs mailing list