[PATCH 1/3] erofs-utils: lib: get rid of erofs_init_empty_dir()

Gao Xiang hsiangkao at linux.alibaba.com
Thu Jul 31 13:16:40 AEST 2025


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

Signed-off-by: Gao Xiang <hsiangkao at linux.alibaba.com>
---
 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



More information about the Linux-erofs mailing list