[PATCH 3/3] erofs-utils: mkfs: handle early exit of the dfops worker

Gao Xiang hsiangkao at linux.alibaba.com
Sat Jun 14 12:32:59 AEST 2025


Otherwise, the main thread will be stuck due to the full queue.

Signed-off-by: Gao Xiang <hsiangkao at linux.alibaba.com>
---
 lib/inode.c | 23 +++++++++++++++++++----
 1 file changed, 19 insertions(+), 4 deletions(-)

diff --git a/lib/inode.c b/lib/inode.c
index 39ffebc..db26236 100644
--- a/lib/inode.c
+++ b/lib/inode.c
@@ -1393,6 +1393,7 @@ struct erofs_mkfs_dfops {
 	struct erofs_mkfs_jobitem *queue;
 	unsigned int entries, head, tail;
 	bool idle;	/* initialize as false before the dfops worker runs */
+	bool exited;
 };
 
 static void erofs_mkfs_flushjobs(struct erofs_sb_info *sbi)
@@ -1443,6 +1444,10 @@ static void *z_erofs_mt_dfops_worker(void *arg)
 		ret = erofs_mkfs_jobfn(item);
 		erofs_mkfs_pop_jobitem(dfops);
 	} while (!ret);
+
+	dfops->exited = true;
+	if (ret < 0)
+		pthread_cond_signal(&dfops->full);
 	pthread_exit((void *)(uintptr_t)(ret < 0 ? ret : 0));
 }
 
@@ -1454,8 +1459,13 @@ static int erofs_mkfs_go(struct erofs_sb_info *sbi,
 
 	pthread_mutex_lock(&q->lock);
 
-	while (q->tail - q->head >= q->entries)
+	while (q->tail - q->head >= q->entries) {
+		if (q->exited) {
+			pthread_mutex_unlock(&q->lock);
+			return -ECHILD;
+		}
 		pthread_cond_wait(&q->full, &q->lock);
+	}
 
 	item = q->queue + (q->tail++ & (q->entries - 1));
 	item->type = type;
@@ -1912,9 +1922,10 @@ static int erofs_get_fdlimit(void)
 
 static int erofs_mkfs_build_tree(struct erofs_mkfs_buildtree_ctx *ctx)
 {
+	struct erofs_sb_info *sbi = ctx->sbi ? ctx->sbi : ctx->u.root->sbi;
 	struct erofs_mkfs_dfops *q;
 	int err, err2;
-	struct erofs_sb_info *sbi = ctx->sbi ? ctx->sbi : ctx->u.root->sbi;
+	void *retval;
 
 	q = calloc(1, sizeof(*q));
 	if (!q)
@@ -1946,9 +1957,13 @@ static int erofs_mkfs_build_tree(struct erofs_mkfs_buildtree_ctx *ctx)
 
 	err = __erofs_mkfs_build_tree(ctx);
 	erofs_mkfs_go(sbi, ~0, NULL, 0);
-	err2 = pthread_join(sbi->dfops_worker, NULL);
-	if (!err)
+	err2 = pthread_join(sbi->dfops_worker, &retval);
+	DBG_BUGON(!q->exited);
+	if (!err || err == -ECHILD) {
 		err = err2;
+		if (!err)
+			err = (intptr_t)retval;
+	}
 
 fail:
 	pthread_cond_destroy(&q->empty);
-- 
2.43.5



More information about the Linux-erofs mailing list