- Reduced memory footprints;
 - Optimize dname sorting and strlen(dname).

Signed-off-by: Gao Xiang <hsiang...@linux.alibaba.com>
---
 include/erofs/internal.h |  4 +++-
 lib/inode.c              | 29 +++++++++++++++++++++--------
 2 files changed, 24 insertions(+), 9 deletions(-)

diff --git a/include/erofs/internal.h b/include/erofs/internal.h
index 2edc1b4..596e363 100644
--- a/include/erofs/internal.h
+++ b/include/erofs/internal.h
@@ -314,15 +314,17 @@ static inline struct erofs_inode 
*erofs_parent_inode(struct erofs_inode *inode)
 
 #define IS_ROOT(x)     ((x) == erofs_parent_inode(x))
 
+#define EROFS_DENTRY_NAME_ALIGNMENT    4
 struct erofs_dentry {
        struct list_head d_child;       /* child of parent list */
        union {
                struct erofs_inode *inode;
                erofs_nid_t nid;
        };
-       char name[EROFS_NAME_LEN];
+       unsigned char namelen;
        u8 type;
        bool validnid;
+       char name[];
 };
 
 static inline bool is_dot_dotdot_len(const char *name, unsigned int len)
diff --git a/lib/inode.c b/lib/inode.c
index 7ee5d78..e51c0fc 100644
--- a/lib/inode.c
+++ b/lib/inode.c
@@ -160,14 +160,22 @@ unsigned int erofs_iput(struct erofs_inode *inode)
 struct erofs_dentry *erofs_d_alloc(struct erofs_inode *parent,
                                   const char *name)
 {
-       struct erofs_dentry *d = malloc(sizeof(*d));
+       unsigned int namelen = strlen(name);
+       unsigned int fsz = round_up(namelen + 1, EROFS_DENTRY_NAME_ALIGNMENT);
+       struct erofs_dentry *d;
 
+       if (namelen > EROFS_NAME_LEN) {
+               DBG_BUGON(1);
+               return ERR_PTR(-ENAMETOOLONG);
+       }
+       d = malloc(sizeof(*d) + fsz);
        if (!d)
                return ERR_PTR(-ENOMEM);
 
-       strncpy(d->name, name, EROFS_NAME_LEN - 1);
-       d->name[EROFS_NAME_LEN - 1] = '\0';
+       memcpy(d->name, name, namelen);
+       memset(d->name + namelen, 0, fsz - namelen);
        d->inode = NULL;
+       d->namelen = namelen;
        d->type = EROFS_FT_UNKNOWN;
        d->validnid = false;
        list_add_tail(&d->d_child, &parent->i_subdirs);
@@ -208,10 +216,16 @@ int erofs_allocate_inode_bh_data(struct erofs_inode 
*inode, erofs_blk_t nblocks)
 static int comp_subdir(const void *a, const void *b)
 {
        const struct erofs_dentry *da, *db;
+       int commonlen, sign;
 
        da = *((const struct erofs_dentry **)a);
        db = *((const struct erofs_dentry **)b);
-       return strcmp(da->name, db->name);
+       commonlen = min(round_up(da->namelen, EROFS_DENTRY_NAME_ALIGNMENT),
+                       round_up(db->namelen, EROFS_DENTRY_NAME_ALIGNMENT));
+       sign = memcmp(da->name, db->name, commonlen);
+       if (sign)
+               return sign;
+       return cmpsgn(da->namelen, db->namelen);
 }
 
 int erofs_init_empty_dir(struct erofs_inode *dir)
@@ -260,7 +274,7 @@ static int erofs_prepare_dir_file(struct erofs_inode *dir,
 
        /* let's calculate dir size */
        list_for_each_entry(d, &dir->i_subdirs, d_child) {
-               int len = strlen(d->name) + sizeof(struct erofs_dirent);
+               int len = d->namelen + sizeof(struct erofs_dirent);
 
                if (erofs_blkoff(sbi, d_size) + len > erofs_blksiz(sbi))
                        d_size = round_up(d_size, erofs_blksiz(sbi));
@@ -283,7 +297,7 @@ static void fill_dirblock(char *buf, unsigned int size, 
unsigned int q,
 
        /* write out all erofs_dirents + filenames */
        while (head != end) {
-               const unsigned int namelen = strlen(head->name);
+               const unsigned int namelen = head->namelen;
                struct erofs_dirent d = {
                        .nid = cpu_to_le64(head->nid),
                        .nameoff = cpu_to_le16(q),
@@ -438,8 +452,7 @@ static int erofs_write_dir_file(struct erofs_inode *dir)
                return ret;
 
        list_for_each_entry(d, &dir->i_subdirs, d_child) {
-               const unsigned int len = strlen(d->name) +
-                       sizeof(struct erofs_dirent);
+               unsigned int len = d->namelen + sizeof(struct erofs_dirent);
 
                /* XXX: a bit hacky, but to avoid another traversal */
                if (d->validnid && d->type == EROFS_FT_DIR) {
-- 
2.43.5

Reply via email to