... and defer insertion of `.` and `..` entries when preparing
directory inodes.

Signed-off-by: Gao Xiang <[email protected]>
---
 include/erofs/inode.h |  1 -
 lib/inode.c           | 52 +++++++++++++++++++++----------------------
 lib/rebuild.c         |  4 ++--
 lib/tar.c             |  4 +---
 4 files changed, 28 insertions(+), 33 deletions(-)

diff --git a/include/erofs/inode.h b/include/erofs/inode.h
index fe86101d..b0ac5bee 100644
--- a/include/erofs/inode.h
+++ b/include/erofs/inode.h
@@ -37,7 +37,6 @@ struct erofs_dentry *erofs_d_alloc(struct erofs_inode *parent,
 int erofs_allocate_inode_bh_data(struct erofs_inode *inode, erofs_blk_t 
nblocks);
 bool erofs_dentry_is_wht(struct erofs_sb_info *sbi, struct erofs_dentry *d);
 int erofs_rebuild_dump_tree(struct erofs_inode *dir, bool incremental);
-int erofs_init_empty_dir(struct erofs_inode *dir);
 int __erofs_fill_inode(struct erofs_inode *inode, struct stat *st,
                       const char *path);
 struct erofs_inode *erofs_new_inode(struct erofs_sb_info *sbi);
diff --git a/lib/inode.c b/lib/inode.c
index 4f6715af..cbce712b 100644
--- a/lib/inode.c
+++ b/lib/inode.c
@@ -226,9 +226,14 @@ static int comp_subdir(const void *a, const void *b)
        return cmpsgn(da->namelen, db->namelen);
 }
 
-int erofs_init_empty_dir(struct erofs_inode *dir)
+static int erofs_prepare_dir_file(struct erofs_inode *dir,
+                                 unsigned int nr_subdirs)
 {
-       struct erofs_dentry *d;
+       struct erofs_sb_info *sbi = dir->sbi;
+       struct erofs_dentry *d, *n, **sorted_d;
+       bool dot_omitted = cfg.c_dot_omitted;
+       unsigned int i;
+       unsigned int d_size = 0;
 
        /* dot is pointed to the current dir inode */
        d = erofs_d_alloc(dir, ".");
@@ -244,18 +249,7 @@ int erofs_init_empty_dir(struct erofs_inode *dir)
        d->inode = erofs_igrab(erofs_parent_inode(dir));
        d->type = EROFS_FT_DIR;
 
-       dir->i_nlink = 2;
-       return 0;
-}
-
-static int erofs_prepare_dir_file(struct erofs_inode *dir,
-                                 unsigned int nr_subdirs)
-{
-       struct erofs_sb_info *sbi = dir->sbi;
-       struct erofs_dentry *d, *n, **sorted_d;
-       bool dot_omitted = cfg.c_dot_omitted;
-       unsigned int i;
-       unsigned int d_size = 0;
+       nr_subdirs += 2;
 
        sorted_d = malloc(nr_subdirs * sizeof(d));
        if (!sorted_d)
@@ -1564,11 +1558,7 @@ static int erofs_mkfs_handle_directory(struct 
erofs_inode *dir)
        }
        closedir(_dir);
 
-       ret = erofs_init_empty_dir(dir);
-       if (ret)
-               return ret;
-
-       ret = erofs_prepare_dir_file(dir, nr_subdirs + 2); /* sort subdirs */
+       ret = erofs_prepare_dir_file(dir, nr_subdirs); /* sort subdirs */
        if (ret)
                return ret;
 
@@ -1615,6 +1605,13 @@ bool erofs_dentry_is_wht(struct erofs_sb_info *sbi, 
struct erofs_dentry *d)
        return false;
 }
 
+static void erofs_dentry_kill(struct erofs_dentry *d)
+{
+       list_del(&d->d_child);
+       erofs_d_invalidate(d);
+       free(d);
+}
+
 static int erofs_rebuild_handle_directory(struct erofs_inode *dir,
                                          bool incremental)
 {
@@ -1625,22 +1622,23 @@ static int erofs_rebuild_handle_directory(struct 
erofs_inode *dir,
        int ret;
 
        nr_subdirs = 0;
-       i_nlink = 0;
+       i_nlink = 2;
 
        list_for_each_entry_safe(d, n, &dir->i_subdirs, d_child) {
+               if (is_dot_dotdot(d->name)) {
+                       DBG_BUGON(1);
+                       erofs_dentry_kill(d);
+                       continue;
+               }
                if (delwht && erofs_dentry_is_wht(sbi, d)) {
                        erofs_dbg("remove whiteout %s", d->inode->i_srcpath);
-                       list_del(&d->d_child);
-                       erofs_d_invalidate(d);
-                       free(d);
+                       erofs_dentry_kill(d);
                        continue;
                }
                i_nlink += (d->type == EROFS_FT_DIR);
                ++nr_subdirs;
        }
-
-       DBG_BUGON(i_nlink < 2);         /* should have `.` and `..` */
-       DBG_BUGON(nr_subdirs < i_nlink);
+       DBG_BUGON(nr_subdirs + 2 < i_nlink);
        ret = erofs_prepare_dir_file(dir, nr_subdirs);
        if (ret)
                return ret;
@@ -2134,6 +2132,6 @@ struct erofs_inode *erofs_rebuild_make_root(struct 
erofs_sb_info *sbi)
        root->i_parent = root;
        root->i_mtime = root->sbi->epoch + root->sbi->build_time;
        root->i_mtime_nsec = root->sbi->fixed_nsec;
-       erofs_init_empty_dir(root);
+       root->i_nlink = 2;
        return root;
 }
diff --git a/lib/rebuild.c b/lib/rebuild.c
index c580f81f..26bc9aca 100644
--- a/lib/rebuild.c
+++ b/lib/rebuild.c
@@ -59,7 +59,7 @@ static struct erofs_dentry *erofs_rebuild_mkdir(struct 
erofs_inode *dir,
        inode->i_mtime = dir->i_mtime;
        inode->i_mtime_nsec = dir->i_mtime_nsec;
        inode->dev = dir->dev;
-       erofs_init_empty_dir(inode);
+       inode->i_nlink = 2;
 
        d = erofs_d_alloc(dir, s);
        if (IS_ERR(d)) {
@@ -241,7 +241,7 @@ static int erofs_rebuild_update_inode(struct erofs_sb_info 
*dst_sb,
                inode->u.i_rdev = erofs_new_encode_dev(inode->u.i_rdev);
                break;
        case S_IFDIR:
-               err = erofs_init_empty_dir(inode);
+               inode->i_nlink = 2;
                break;
        case S_IFLNK:
                inode->i_link = malloc(inode->i_size + 1);
diff --git a/lib/tar.c b/lib/tar.c
index 72c12ed0..3146fc9d 100644
--- a/lib/tar.c
+++ b/lib/tar.c
@@ -1122,9 +1122,7 @@ new_inode:
                }
                inode->i_nlink++;
        } else if (!inode->i_nlink) {
-               ret = erofs_init_empty_dir(inode);
-               if (ret)
-                       goto out;
+               inode->i_nlink = 2;
        }
 
        ret = tarerofs_merge_xattrs(&eh.xattrs, &tar->global.xattrs);
-- 
2.43.5


Reply via email to