From: Gao Xiang <hsiang...@linux.alibaba.com> Dispatch deferred ops in another per-sb worker thread. Note that deferred ops are strictly FIFOed.
Signed-off-by: Gao Xiang <hsiang...@linux.alibaba.com> --- include/erofs/internal.h | 6 ++ lib/inode.c | 121 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 124 insertions(+), 3 deletions(-) diff --git a/include/erofs/internal.h b/include/erofs/internal.h index f31e548..ecbbdf6 100644 --- a/include/erofs/internal.h +++ b/include/erofs/internal.h @@ -71,6 +71,7 @@ struct erofs_xattr_prefix_item { #define EROFS_PACKED_NID_UNALLOCATED -1 +struct erofs_mkfs_dfops; struct erofs_sb_info { struct erofs_device_info *devs; char *devname; @@ -124,6 +125,11 @@ struct erofs_sb_info { struct list_head list; u64 saved_by_deduplication; + +#ifdef EROFS_MT_ENABLED + pthread_t dfops_worker; + struct erofs_mkfs_dfops *mkfs_dfops; +#endif }; /* make sure that any user of the erofs headers has atleast 64bit off_t type */ diff --git a/lib/inode.c b/lib/inode.c index 681460c..3c952b2 100644 --- a/lib/inode.c +++ b/lib/inode.c @@ -1165,6 +1165,7 @@ enum erofs_mkfs_jobtype { /* ordered job types */ EROFS_MKFS_JOB_NDIR, EROFS_MKFS_JOB_DIR, EROFS_MKFS_JOB_DIR_BH, + EROFS_MKFS_JOB_MAX }; struct erofs_mkfs_jobitem { @@ -1203,6 +1204,74 @@ static int erofs_mkfs_jobfn(struct erofs_mkfs_jobitem *item) return -EINVAL; } +#ifdef EROFS_MT_ENABLED + +struct erofs_mkfs_dfops { + pthread_t worker; + pthread_mutex_t lock; + pthread_cond_t full, empty; + struct erofs_mkfs_jobitem *queue; + size_t size, elem_size; + size_t head, tail; +}; + +#define EROFS_MT_QUEUE_SIZE 256 + +void *erofs_mkfs_pop_jobitem(struct erofs_mkfs_dfops *q) +{ + struct erofs_mkfs_jobitem *item; + + pthread_mutex_lock(&q->lock); + while (q->head == q->tail) + pthread_cond_wait(&q->empty, &q->lock); + + item = q->queue + q->head; + q->head = (q->head + 1) % q->size; + + pthread_cond_signal(&q->full); + pthread_mutex_unlock(&q->lock); + return item; +} + +void *z_erofs_mt_dfops_worker(void *arg) +{ + struct erofs_sb_info *sbi = arg; + int ret = 0; + + while (1) { + struct erofs_mkfs_jobitem *item; + + item = erofs_mkfs_pop_jobitem(sbi->mkfs_dfops); + if (item->type >= EROFS_MKFS_JOB_MAX) + break; + ret = erofs_mkfs_jobfn(item); + if (ret) + break; + } + pthread_exit((void *)(uintptr_t)ret); +} + +int erofs_mkfs_go(struct erofs_sb_info *sbi, + enum erofs_mkfs_jobtype type, void *elem, int size) +{ + struct erofs_mkfs_jobitem *item; + struct erofs_mkfs_dfops *q = sbi->mkfs_dfops; + + pthread_mutex_lock(&q->lock); + + while ((q->tail + 1) % q->size == q->head) + pthread_cond_wait(&q->full, &q->lock); + + item = q->queue + q->tail; + item->type = type; + memcpy(&item->u, elem, size); + q->tail = (q->tail + 1) % q->size; + + pthread_cond_signal(&q->empty); + pthread_mutex_unlock(&q->lock); + return 0; +} +#else int erofs_mkfs_go(struct erofs_sb_info *sbi, enum erofs_mkfs_jobtype type, void *elem, int size) { @@ -1212,6 +1281,7 @@ int erofs_mkfs_go(struct erofs_sb_info *sbi, memcpy(&item.u, elem, size); return erofs_mkfs_jobfn(&item); } +#endif static int erofs_mkfs_handle_directory(struct erofs_inode *dir) { @@ -1344,7 +1414,11 @@ static int erofs_mkfs_handle_inode(struct erofs_inode *inode) return ret; } -struct erofs_inode *erofs_mkfs_build_tree_from_path(const char *path) +#ifndef EROFS_MT_ENABLED +#define __erofs_mkfs_build_tree_from_path erofs_mkfs_build_tree_from_path +#endif + +struct erofs_inode *__erofs_mkfs_build_tree_from_path(const char *path) { struct erofs_inode *root, *dumpdir; int err; @@ -1361,7 +1435,6 @@ struct erofs_inode *erofs_mkfs_build_tree_from_path(const char *path) err = erofs_mkfs_handle_inode(root); if (err) return ERR_PTR(err); - erofs_fixup_meta_blkaddr(root); do { int err; @@ -1400,10 +1473,52 @@ struct erofs_inode *erofs_mkfs_build_tree_from_path(const char *path) if (err) return ERR_PTR(err); } while (dumpdir); - return root; } +#ifdef EROFS_MT_ENABLED +struct erofs_inode *erofs_mkfs_build_tree_from_path(const char *path) +{ + struct erofs_mkfs_dfops *q; + struct erofs_inode *root; + int err; + + q = malloc(sizeof(*q)); + if (!q) + return ERR_PTR(-ENOMEM); + + q->queue = malloc(q->size * sizeof(*q->queue)); + if (!q->queue) { + free(q); + return ERR_PTR(-ENOMEM); + } + pthread_mutex_init(&q->lock, NULL); + pthread_cond_init(&q->empty, NULL); + pthread_cond_init(&q->full, NULL); + + q->size = EROFS_MT_QUEUE_SIZE; + q->head = 0; + q->tail = 0; + sbi.mkfs_dfops = q; + err = pthread_create(&sbi.dfops_worker, NULL, + z_erofs_mt_dfops_worker, &sbi); + if (err) + goto fail; + root = __erofs_mkfs_build_tree_from_path(path); + + erofs_mkfs_go(&sbi, ~0, NULL, 0); + err = pthread_join(sbi.dfops_worker, NULL); + +fail: + pthread_cond_destroy(&q->empty); + pthread_cond_destroy(&q->full); + pthread_mutex_destroy(&q->lock); + free(q->queue); + free(q); + return err ? ERR_PTR(err) : root; +} +#endif + struct erofs_inode *erofs_mkfs_build_special_from_fd(int fd, const char *name) { struct stat st; -- 2.30.2