From: Darrick J. Wong <djwong@xxxxxxxxxx> Signed-off-by: Darrick J. Wong <djwong@xxxxxxxxxx> --- libfrog/fsgeom.h | 21 +++++++++++++++++++++ scrub/phase8.c | 46 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/libfrog/fsgeom.h b/libfrog/fsgeom.h index 8c21b240bb2..6c6d6bb815a 100644 --- a/libfrog/fsgeom.h +++ b/libfrog/fsgeom.h @@ -203,4 +203,25 @@ cvt_b_to_agbno( return cvt_daddr_to_agbno(xfd, cvt_btobbt(byteno)); } +/* Convert rtgroup number and rtgroup block to fs block number */ +static inline uint64_t +cvt_rgbno_to_daddr( + struct xfs_fd *xfd, + uint32_t rgno, + uint32_t rgbno) +{ + return cvt_off_fsb_to_bb(xfd, + (uint64_t)rgno * xfd->fsgeom.rgblocks + rgbno); +} + +/* Convert rtgroup number and rtgroup block to a byte location on disk. */ +static inline uint64_t +cvt_rgbno_to_b( + struct xfs_fd *xfd, + xfs_rgnumber_t rgno, + xfs_rgblock_t rgbno) +{ + return cvt_bbtob(cvt_rgbno_to_daddr(xfd, rgno, rgbno)); +} + #endif /* __LIBFROG_FSGEOM_H__ */ diff --git a/scrub/phase8.c b/scrub/phase8.c index a8ea8db706b..cc4901f8614 100644 --- a/scrub/phase8.c +++ b/scrub/phase8.c @@ -48,6 +48,7 @@ fstrim_ok( struct trim_ctl { uint64_t datadev_end_pos; + uint64_t rtdev_end_pos; bool aborted; }; @@ -80,6 +81,35 @@ trim_ag( progress_add(1); } +/* Trim each rt group. */ +static void +trim_rtgroup( + struct workqueue *wq, + xfs_agnumber_t rgno, + void *arg) +{ + struct scrub_ctx *ctx = (struct scrub_ctx *)wq->wq_ctx; + struct trim_ctl *tctl = arg; + uint64_t pos, len, eortg_pos; + int error; + + pos = cvt_rgbno_to_b(&ctx->mnt, rgno, 0); + eortg_pos = cvt_rgbno_to_b(&ctx->mnt, rgno, ctx->mnt.fsgeom.rgblocks); + len = min(tctl->rtdev_end_pos, eortg_pos) - pos; + + error = fstrim(ctx, pos + tctl->datadev_end_pos, len); + if (error) { + char descr[DESCR_BUFSZ]; + + snprintf(descr, sizeof(descr) - 1, _("fstrim rgno %u"), rgno); + str_liberror(ctx, error, descr); + tctl->aborted = true; + return; + } + + progress_add(1); +} + /* Trim the filesystem, if desired. */ int phase8_func( @@ -97,6 +127,8 @@ phase8_func( tctl.datadev_end_pos = cvt_off_fsb_to_b(&ctx->mnt, ctx->mnt.fsgeom.datablocks); + tctl.rtdev_end_pos = cvt_off_fsb_to_b(&ctx->mnt, + ctx->mnt.fsgeom.rtblocks); error = -workqueue_create(&wq, (struct xfs_mount *)ctx, disk_heads(ctx->datadev)); @@ -117,6 +149,18 @@ phase8_func( } } + /* Trim each rtgroup in parallel. */ + for (agno = 0; + agno < ctx->mnt.fsgeom.rgcount && !tctl.aborted; + agno++) { + error = -workqueue_add(&wq, trim_rtgroup, agno, &tctl); + if (error) { + str_liberror(ctx, error, + _("queueing per-rtgroup fstrim work")); + goto out_wq; + } + } + out_wq: err2 = -workqueue_terminate(&wq); if (err2) { @@ -142,7 +186,7 @@ phase8_estimate( *items = 0; if (fstrim_ok(ctx)) - *items = ctx->mnt.fsgeom.agcount; + *items = ctx->mnt.fsgeom.agcount + ctx->mnt.fsgeom.rgcount; *nr_threads = disk_heads(ctx->datadev); *rshift = 0;