[PATCH] erofs-utils: fix an indefinite wait race
Gao Xiang
hsiangkao at linux.alibaba.com
Tue Aug 20 16:40:49 AEST 2024
Coverity reports: In erofs_mkfs_flushjobs, a thread waits for
a thread-shared condition that may have already been satisfied,
causing a hang.
It might indeed happen if the dfops worker runs with the specific
timing. Let's try to fix it and see if the report is cleared.
Coverity-id: 502330
Fixes: 37e5abcd8720 ("erofs-utils: mkfs: assign root NID in the main thread")
Signed-off-by: Gao Xiang <hsiangkao at linux.alibaba.com>
---
lib/inode.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/lib/inode.c b/lib/inode.c
index b9dbbd6..96f01b9 100644
--- a/lib/inode.c
+++ b/lib/inode.c
@@ -1326,6 +1326,7 @@ struct erofs_mkfs_dfops {
pthread_cond_t full, empty, drain;
struct erofs_mkfs_jobitem *queue;
unsigned int entries, head, tail;
+ bool idle; /* initialize as false before the dfops worker runs */
};
#define EROFS_MT_QUEUE_SIZE 128
@@ -1335,7 +1336,8 @@ static void erofs_mkfs_flushjobs(struct erofs_sb_info *sbi)
struct erofs_mkfs_dfops *q = sbi->mkfs_dfops;
pthread_mutex_lock(&q->lock);
- pthread_cond_wait(&q->drain, &q->lock);
+ if (!q->idle)
+ pthread_cond_wait(&q->drain, &q->lock);
pthread_mutex_unlock(&q->lock);
}
@@ -1345,12 +1347,15 @@ static void *erofs_mkfs_pop_jobitem(struct erofs_mkfs_dfops *q)
pthread_mutex_lock(&q->lock);
while (q->head == q->tail) {
+ /* the worker has handled everything only if sleeping here */
+ q->idle = true;
pthread_cond_signal(&q->drain);
pthread_cond_wait(&q->empty, &q->lock);
}
item = q->queue + q->head;
q->head = (q->head + 1) & (q->entries - 1);
+ q->idle = false;
pthread_cond_signal(&q->full);
pthread_mutex_unlock(&q->lock);
@@ -1812,7 +1817,7 @@ static int erofs_mkfs_build_tree(struct erofs_mkfs_buildtree_ctx *ctx)
int err, err2;
struct erofs_sb_info *sbi = ctx->sbi ? ctx->sbi : ctx->u.root->sbi;
- q = malloc(sizeof(*q));
+ q = calloc(1, sizeof(*q));
if (!q)
return -ENOMEM;
@@ -1827,8 +1832,6 @@ static int erofs_mkfs_build_tree(struct erofs_mkfs_buildtree_ctx *ctx)
pthread_cond_init(&q->full, NULL);
pthread_cond_init(&q->drain, NULL);
- q->head = 0;
- q->tail = 0;
sbi->mkfs_dfops = q;
err = pthread_create(&sbi->dfops_worker, NULL,
z_erofs_mt_dfops_worker, sbi);
--
2.43.5
More information about the Linux-erofs
mailing list