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