@@ -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__ */
@@ -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;