[PATCH v1 2/2] erofs-utils: introduce erofs_subdirs to one dir for sort
Li Guifu
bluce.lee at aliyun.com
Thu May 6 00:26:15 AEST 2021
The structure erofs_subdirs has a dir number and a list_head,
the list_head is the same with i_subdirs in the inode.
Using erofs_subdirs as a temp place for dentrys under the dir,
and then sort it before replace to i_subdirs
Signed-off-by: Li Guifu <bluce.lee at aliyun.com>
---
include/erofs/internal.h | 5 +++
lib/inode.c | 95 +++++++++++++++++++++++++---------------
2 files changed, 64 insertions(+), 36 deletions(-)
diff --git a/include/erofs/internal.h b/include/erofs/internal.h
index 1339341..7cd42ca 100644
--- a/include/erofs/internal.h
+++ b/include/erofs/internal.h
@@ -172,6 +172,11 @@ struct erofs_inode {
#endif
};
+struct erofs_subdirs {
+ struct list_head i_subdirs;
+ unsigned int nr_subdirs;
+};
+
static inline bool is_inode_layout_compression(struct erofs_inode *inode)
{
return erofs_inode_is_data_compressed(inode->datalayout);
diff --git a/lib/inode.c b/lib/inode.c
index 787e5b4..3e138a6 100644
--- a/lib/inode.c
+++ b/lib/inode.c
@@ -96,7 +96,7 @@ unsigned int erofs_iput(struct erofs_inode *inode)
return 0;
}
-struct erofs_dentry *erofs_d_alloc(struct erofs_inode *parent,
+struct erofs_dentry *erofs_d_alloc(struct erofs_subdirs *subdirs,
const char *name)
{
struct erofs_dentry *d = malloc(sizeof(*d));
@@ -107,7 +107,8 @@ struct erofs_dentry *erofs_d_alloc(struct erofs_inode *parent,
strncpy(d->name, name, EROFS_NAME_LEN - 1);
d->name[EROFS_NAME_LEN - 1] = '\0';
- list_add_tail(&d->d_child, &parent->i_subdirs);
+ list_add_tail(&d->d_child, &subdirs->i_subdirs);
+ subdirs->nr_subdirs++;
return d;
}
@@ -150,38 +151,12 @@ static int comp_subdir(const void *a, const void *b)
return strcmp(da->name, db->name);
}
-int erofs_prepare_dir_file(struct erofs_inode *dir, unsigned int nr_subdirs)
+int erofs_prepare_dir_file(struct erofs_inode *dir)
{
- struct erofs_dentry *d, *n, **sorted_d;
- unsigned int d_size, i_nlink, i;
+ struct erofs_dentry *d;
+ unsigned int d_size, i_nlink;
int ret;
- /* dot is pointed to the current dir inode */
- d = erofs_d_alloc(dir, ".");
- d->inode = erofs_igrab(dir);
- d->type = EROFS_FT_DIR;
-
- /* dotdot is pointed to the parent dir */
- d = erofs_d_alloc(dir, "..");
- d->inode = erofs_igrab(dir->i_parent);
- d->type = EROFS_FT_DIR;
-
- /* sort subdirs */
- nr_subdirs += 2;
- sorted_d = malloc(nr_subdirs * sizeof(d));
- if (!sorted_d)
- return -ENOMEM;
- i = 0;
- list_for_each_entry_safe(d, n, &dir->i_subdirs, d_child) {
- list_del(&d->d_child);
- sorted_d[i++] = d;
- }
- DBG_BUGON(i != nr_subdirs);
- qsort(sorted_d, nr_subdirs, sizeof(d), comp_subdir);
- for (i = 0; i < nr_subdirs; i++)
- list_add_tail(&sorted_d[i]->d_child, &dir->i_subdirs);
- free(sorted_d);
-
/* let's calculate dir size and update i_nlink */
d_size = 0;
i_nlink = 0;
@@ -926,13 +901,58 @@ void erofs_d_invalidate(struct erofs_dentry *d)
erofs_iput(inode);
}
+void erofs_subdirs_init(struct erofs_inode *dir, struct erofs_subdirs *subdirs)
+{
+ struct erofs_dentry *d;
+
+ subdirs->nr_subdirs = 0;
+ init_list_head(&subdirs->i_subdirs);
+
+ /* dot is pointed to the current dir inode */
+ d = erofs_d_alloc(subdirs, ".");
+ d->inode = erofs_igrab(dir);
+ d->type = EROFS_FT_DIR;
+
+ /* dotdot is pointed to the parent dir */
+ d = erofs_d_alloc(subdirs, "..");
+ d->inode = erofs_igrab(dir->i_parent);
+ d->type = EROFS_FT_DIR;
+}
+
+static int erofs_subdirs_sorted(struct erofs_subdirs *subdirs)
+{
+ struct erofs_dentry *d, *n, **sorted_d;
+ unsigned int i;
+ const unsigned int nr_subdirs = subdirs->nr_subdirs;
+
+ if (nr_subdirs == 0) return 0;
+
+ sorted_d = malloc(nr_subdirs * sizeof(d));
+ if (!sorted_d)
+ return -ENOMEM;
+ i = 0;
+ list_for_each_entry_safe(d, n, &subdirs->i_subdirs, d_child) {
+ list_del(&d->d_child);
+ sorted_d[i++] = d;
+ }
+
+ DBG_BUGON(i != nr_subdirs);
+ DBG_BUGON(!list_empty(&subdirs->i_subdirs));
+
+ qsort(sorted_d, nr_subdirs, sizeof(d), comp_subdir);
+ for (i = 0; i < nr_subdirs; i++)
+ list_add_tail(&sorted_d[i]->d_child, &subdirs->i_subdirs);
+ free(sorted_d);
+ return 0;
+}
+
struct erofs_inode *erofs_mkfs_build_tree(struct erofs_inode *dir)
{
int ret;
DIR *_dir;
struct dirent *dp;
struct erofs_dentry *d;
- unsigned int nr_subdirs;
+ struct erofs_subdirs subdirs;
ret = erofs_prepare_xattr_ibody(dir);
if (ret < 0)
@@ -972,7 +992,7 @@ struct erofs_inode *erofs_mkfs_build_tree(struct erofs_inode *dir)
return ERR_PTR(-errno);
}
- nr_subdirs = 0;
+ erofs_subdirs_init(dir, &subdirs);
while (1) {
/*
* set errno to 0 before calling readdir() in order to
@@ -991,12 +1011,11 @@ struct erofs_inode *erofs_mkfs_build_tree(struct erofs_inode *dir)
if (erofs_is_exclude_path(dir->i_srcpath, dp->d_name))
continue;
- d = erofs_d_alloc(dir, dp->d_name);
+ d = erofs_d_alloc(&subdirs, dp->d_name);
if (IS_ERR(d)) {
ret = PTR_ERR(d);
goto err_closedir;
}
- nr_subdirs++;
/* to count i_nlink for directories */
d->type = (dp->d_type == DT_DIR ?
@@ -1009,7 +1028,11 @@ struct erofs_inode *erofs_mkfs_build_tree(struct erofs_inode *dir)
}
closedir(_dir);
- ret = erofs_prepare_dir_file(dir, nr_subdirs);
+ ret = erofs_subdirs_sorted(&subdirs);
+ if (ret) goto err;
+
+ list_replace(&subdirs.i_subdirs, &dir->i_subdirs);
+ ret = erofs_prepare_dir_file(dir);
if (ret)
goto err;
--
2.17.1
More information about the Linux-erofs
mailing list