Re: [PATCH v2 2/2] fsck.erofs: implement concurrent directory traversal

Gao Xiang <[email protected]> Fri, 24 Jul 2026 23:53:40 +0800
Newsgroups org.ozlabs.lists.linux-erofs
Message-ID <amOKhDBV7eXUlsui@debian>
On Fri, Jul 24, 2026 at 08:05:56PM +0530, Nithurshen wrote:
> Currently, fsck.erofs traverses the filesystem tree and verifies
> inodes synchronously on the main thread. While data decompression is
> offloaded, the main thread remains a bottleneck during the I/O-heavy
> directory walk.
> 
> This patch parallelizes the directory traversal and inode extraction
> processes. To achieve this safely, globally shared states such as
> fsckcfg.extract_path and fsckcfg.dirstack are decoupled and localized
> into individual struct erofsfsck_inode_task payloads. These payloads
> are dispatched to a dedicated traversal worker pool.
> 
> Global statistics and hardlink tables are now secured using native
> erofs_mutex_t primitives. By isolating the traversal producers from
> the pcluster decompression consumers, the pipeline scales across
> directories without thread pool starvation.
> 
> Signed-off-by: Nithurshen <[email protected]>

Checkpatch reports:

WARNING: line length of 123 exceeds 100 columns
#56: FILE: fsck/main.c:28:
+static int erofsfsck_check_inode(erofs_nid_t pnid, erofs_nid_t nid, const char *path, struct erofsfsck_dirstack *dirstack);

ERROR: do not initialise statics to NULL
#73: FILE: fsck/main.c:45:
+static struct erofsfsck_inode_task *traverse_head = NULL;

ERROR: do not initialise statics to NULL
#74: FILE: fsck/main.c:46:
+static struct erofsfsck_inode_task *traverse_tail = NULL;

ERROR: do not initialise statics to 0
#75: FILE: fsck/main.c:47:
+static int traverse_pending_tasks = 0;

ERROR: do not initialise statics to false
#76: FILE: fsck/main.c:48:
+static bool traverse_shutdown = false;

ERROR: do not initialise statics to 0
#79: FILE: fsck/main.c:51:
+static int traverse_final_err = 0;

WARNING: static char array declaration should probably be static const char
#82: FILE: fsck/main.c:54:
+static char erofsfsck_nullstr[] = "";

WARNING: line length of 123 exceeds 100 columns
#205: FILE: fsck/main.c:747:
+static int erofsfsck_enqueue_task(erofs_nid_t pnid, erofs_nid_t nid, const char *path, struct erofsfsck_dirstack *dirstack)

WARNING: Missing a blank line after declarations
#210: FILE: fsck/main.c:752:
+		struct erofsfsck_inode_task *task = malloc(sizeof(*task));
+		if (!task) return -ENOMEM;

ERROR: trailing statements should be on next line
#210: FILE: fsck/main.c:752:
+		if (!task) return -ENOMEM;

ERROR: trailing whitespace
#211: FILE: fsck/main.c:753:
+^I^I$

ERROR: trailing statements should be on next line
#221: FILE: fsck/main.c:763:
+			if (task->path) free(task->path);

ERROR: trailing whitespace
#225: FILE: fsck/main.c:767:
+^I^I$

ERROR: trailing statements should be on next line
#226: FILE: fsck/main.c:768:
+		if (!traverse_tail) traverse_head = traverse_tail = task;

ERROR: trailing statements should be on next line
#239: FILE: fsck/main.c:781:
+	if (err && !traverse_final_err) traverse_final_err = err;

ERROR: trailing whitespace
#249: FILE: fsck/main.c:791:
+^I^I$

ERROR: trailing whitespace
#258: FILE: fsck/main.c:800:
+^I^I$

ERROR: trailing statements should be on next line
#261: FILE: fsck/main.c:803:
+		if (!traverse_head) traverse_tail = NULL;

ERROR: trailing statements should be on next line
#267: FILE: fsck/main.c:809:
+		if (err && !traverse_final_err) traverse_final_err = err;

ERROR: trailing statements should be on next line
#273: FILE: fsck/main.c:815:
+		if (task->path) free(task->path);

ERROR: trailing statements should be on next line
#290: FILE: fsck/main.c:832:
+	if (traverse_num_workers <= 1) return 0;

ERROR: trailing whitespace
#291: FILE: fsck/main.c:833:
+^I$

ERROR: trailing statements should be on next line
#293: FILE: fsck/main.c:835:
+	if (!traverse_workers) return -ENOMEM;

ERROR: trailing whitespace
#294: FILE: fsck/main.c:836:
+^I$

ERROR: trailing whitespace
#309: FILE: fsck/main.c:851:
+^I^I$

ERROR: trailing whitespace
#312: FILE: fsck/main.c:854:
+^I^I$

ERROR: trailing statements should be on next line
#327: FILE: fsck/main.c:869:
+	if (traverse_num_workers <= 1) return traverse_final_err;

WARNING: Missing a blank line after declarations
#333: FILE: fsck/main.c:875:
+	int err = traverse_final_err;
+	erofs_mutex_unlock(&traverse_mtx);

ERROR: "foo* bar" should be "foo *bar"
#345: FILE: fsck/main.c:887:
+	char* path = NULL;

WARNING: line length of 101 exceeds 100 columns
#414: FILE: fsck/main.c:1025:
+					erofs_err("failed to remove: %s (%s)",path, strerror(errno));

ERROR: space required after that ',' (ctx:VxV)
#414: FILE: fsck/main.c:1025:
+					erofs_err("failed to remove: %s (%s)",path, strerror(errno));
 					                                     ^

WARNING: line length of 103 exceeds 100 columns
#422: FILE: fsck/main.c:1030:
+				erofs_err("failed to set permissions: %s (%s)", path, strerror(errno));

WARNING: suspect code indent for conditional statements (0, 16)
#548: FILE: fsck/main.c:1164:
+if (fctx->path) {
+		size_t prev_len = strlen(fctx->path);

WARNING: Missing a blank line after declarations
#551: FILE: fsck/main.c:1167:
+		size_t curr_len = prev_len + ctx->de_namelen + 1;
+		if (curr_len >= PATH_MAX) {

WARNING: line length of 116 exceeds 100 columns
#552: FILE: fsck/main.c:1168:
+			erofs_err("unable to fsck since the path is too long (%llu)", (unsigned long long)curr_len);

ERROR: trailing statements should be on next line
#556: FILE: fsck/main.c:1172:
+		if (!newpath) return -ENOMEM;

WARNING: braces {} are not necessary for single statement blocks
#575: FILE: fsck/main.c:1178:
+		if (!is_root) {
+			newpath[offset++] = '/';
+		}

ERROR: trailing statements should be on next line
#589: FILE: fsck/main.c:1187:
+	if (newpath) free(newpath);

WARNING: line length of 122 exceeds 100 columns
#645: FILE: fsck/main.c:1242:
+static int erofsfsck_check_inode(erofs_nid_t pnid, erofs_nid_t nid, const char *path, struct erofsfsck_dirstack *dirstack)

ERROR: trailing statements should be on next line
#701: FILE: fsck/main.c:1297:
+		if (ret == -ECANCELED) ret = 0;

ERROR: trailing whitespace
#753: FILE: fsck/main.c:1421:
+^I^I^Ierr = erofsfsck_enqueue_task(g_sbi.packed_nid, g_sbi.packed_nid, $

WARNING: Missing a blank line after declarations
#753: FILE: fsck/main.c:1421:
+			struct erofsfsck_dirstack empty_dirstack = {0};
+			err = erofsfsck_enqueue_task(g_sbi.packed_nid, g_sbi.packed_nid, 

WARNING: line length of 103 exceeds 100 columns
#772: FILE: fsck/main.c:1449:
+		err = erofsfsck_enqueue_task(pnid, fsckcfg.nid, fsckcfg.extract_path, &empty_dirstack);

WARNING: Missing a blank line after declarations
#772: FILE: fsck/main.c:1449:
+		struct erofsfsck_dirstack empty_dirstack = {0};
+		err = erofsfsck_enqueue_task(pnid, fsckcfg.nid, fsckcfg.extract_path, &empty_dirstack);

WARNING: Missing a blank line after declarations
#774: FILE: fsck/main.c:1451:
+		int wait_err = erofsfsck_traverse_mt_wait();
+		if (wait_err && !err)

WARNING: adding a line without newline at end of file
#824: FILE: include/erofs/cond.h:31:
+#endif