[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