[PATCH v2 2/2] erofs-utils: fix up nlink for d_type unsupported fses

Gao Xiang hsiangkao at linux.alibaba.com
Mon Mar 20 02:14:17 AEDT 2023


i_mode should be used instead for some old random fs.

Signed-off-by: Gao Xiang <hsiangkao at linux.alibaba.com>
---
changes since v1:
 - should bump nlink for "." and ".." as well.

 lib/inode.c | 38 +++++++++++++++++---------------------
 1 file changed, 17 insertions(+), 21 deletions(-)

diff --git a/lib/inode.c b/lib/inode.c
index 0f49f6e..7167f19 100644
--- a/lib/inode.c
+++ b/lib/inode.c
@@ -182,7 +182,7 @@ static int comp_subdir(const void *a, const void *b)
 int erofs_prepare_dir_file(struct erofs_inode *dir, unsigned int nr_subdirs)
 {
 	struct erofs_dentry *d, *n, **sorted_d;
-	unsigned int d_size, i_nlink, i;
+	unsigned int d_size, i;
 
 	/* dot is pointed to the current dir inode */
 	d = erofs_d_alloc(dir, ".");
@@ -214,28 +214,16 @@ int erofs_prepare_dir_file(struct erofs_inode *dir, unsigned int nr_subdirs)
 		list_add_tail(&sorted_d[i]->d_child, &dir->i_subdirs);
 	free(sorted_d);
 
-	/* let's calculate dir size and update i_nlink */
+	/* let's calculate dir size */
 	d_size = 0;
-	i_nlink = 0;
 	list_for_each_entry(d, &dir->i_subdirs, d_child) {
 		int len = strlen(d->name) + sizeof(struct erofs_dirent);
 
 		if ((d_size & (erofs_blksiz() - 1)) + len > erofs_blksiz())
 			d_size = round_up(d_size, erofs_blksiz());
 		d_size += len;
-
-		i_nlink += (d->type == EROFS_FT_DIR);
 	}
 	dir->i_size = d_size;
-	/*
-	 * if there're too many subdirs as compact form, set nlink=1
-	 * rather than upgrade to use extented form instead.
-	 */
-	if (i_nlink > USHRT_MAX &&
-	    dir->inode_isize == sizeof(struct erofs_inode_compact))
-		dir->i_nlink = 1;
-	else
-		dir->i_nlink = i_nlink;
 
 	/* no compression for all dirs */
 	dir->datalayout = EROFS_INODE_FLAT_INLINE;
@@ -1039,7 +1027,7 @@ static int erofs_mkfs_build_tree(struct erofs_inode *dir, struct list_head *dirs
 	DIR *_dir;
 	struct dirent *dp;
 	struct erofs_dentry *d;
-	unsigned int nr_subdirs;
+	unsigned int nr_subdirs, i_nlink;
 
 	ret = erofs_prepare_xattr_ibody(dir);
 	if (ret < 0)
@@ -1100,10 +1088,6 @@ static int erofs_mkfs_build_tree(struct erofs_inode *dir, struct list_head *dirs
 			goto err_closedir;
 		}
 		nr_subdirs++;
-
-		/* to count i_nlink for directories */
-		d->type = (dp->d_type == DT_DIR ?
-			EROFS_FT_DIR : EROFS_FT_UNKNOWN);
 	}
 
 	if (errno) {
@@ -1124,13 +1108,16 @@ static int erofs_mkfs_build_tree(struct erofs_inode *dir, struct list_head *dirs
 	if (IS_ROOT(dir))
 		erofs_fixup_meta_blkaddr(dir);
 
+	i_nlink = 0;
 	list_for_each_entry(d, &dir->i_subdirs, d_child) {
 		char buf[PATH_MAX];
 		unsigned char ftype;
 		struct erofs_inode *inode;
 
-		if (is_dot_dotdot(d->name))
+		if (is_dot_dotdot(d->name)) {
+			++i_nlink;
 			continue;
+		}
 
 		ret = snprintf(buf, PATH_MAX, "%s/%s",
 			       dir->i_srcpath, d->name);
@@ -1159,12 +1146,21 @@ fail:
 			++dir->subdirs_queued;
 		}
 		ftype = erofs_mode_to_ftype(inode->i_mode);
-		DBG_BUGON(ftype == EROFS_FT_DIR && d->type != ftype);
+		i_nlink += (ftype == EROFS_FT_DIR);
 		d->inode = inode;
 		d->type = ftype;
 		erofs_info("file %s/%s dumped (type %u)",
 			   dir->i_srcpath, d->name, d->type);
 	}
+	/*
+	 * if there're too many subdirs as compact form, set nlink=1
+	 * rather than upgrade to use extented form instead.
+	 */
+	if (i_nlink > USHRT_MAX &&
+	    dir->inode_isize == sizeof(struct erofs_inode_compact))
+		dir->i_nlink = 1;
+	else
+		dir->i_nlink = i_nlink;
 	return 0;
 
 err_closedir:
-- 
2.24.4



More information about the Linux-erofs mailing list