From: Darrick J. Wong Date: Sun, 22 Feb 2026 22:41:17 +0000 (-0800) Subject: xfs_scrub: use the verify media ioctl during phase 6 if possible X-Git-Tag: v7.0.0~17 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=02760878dd86b939dbcb3818a862a48116c60b66;p=xfsprogs-dev.git xfs_scrub: use the verify media ioctl during phase 6 if possible If the kernel suppots the XFS_IOC_VERIFY_MEDIA ioctl, use that to perform the phase 6 media scan instead of pwrite or the SCSI VERIFY command. This enables better integration with xfs_healer and fsnotify; and reduces the amount of work that userspace has to do. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- diff --git a/scrub/phase1.c b/scrub/phase1.c index 16607af4..abc59489 100644 --- a/scrub/phase1.c +++ b/scrub/phase1.c @@ -213,6 +213,22 @@ no_property: goto summarize; } +/* Does the XFS driver support media scanning its own disks? */ +static void +configure_xfs_verify( + struct scrub_ctx *ctx) +{ + struct xfs_verify_media me = { + /* just probe for support using an empty range */ + .me_start_daddr = 0, + .me_end_daddr = 0, + .me_dev = XFS_DEV_DATA, + }; + + if (ioctl(ctx->mnt.fd, XFS_IOC_VERIFY_MEDIA, &me)) + ctx->no_verify_ioctl = true; +} + /* * Bind to the mountpoint, read the XFS geometry, bind to the block devices. * Anything we've already built will be cleaned up by scrub_cleanup. @@ -379,6 +395,8 @@ _("Unable to find realtime device path.")); } } + configure_xfs_verify(ctx); + /* * Everything's set up, which means any failures recorded after * this point are most probably corruption errors (as opposed to diff --git a/scrub/read_verify.c b/scrub/read_verify.c index 3b3baaf8..66086d6f 100644 --- a/scrub/read_verify.c +++ b/scrub/read_verify.c @@ -225,12 +225,45 @@ verify_simulate_read_error( return 0; } +/* Use the XFS media verification ioctl to do the media scan */ +static ssize_t +ioctl_verify( + int verify_fd, + enum xfs_device dev, + uint64_t start, + uint64_t length, + bool single_step) +{ + const uint64_t orig_start_daddr = BTOBBT(start); + struct xfs_verify_media me = { + .me_start_daddr = orig_start_daddr, + .me_end_daddr = BTOBB(start + length), + .me_dev = dev, + .me_rest_us = bg_mode > 2 ? bg_mode - 1 : 0, + }; + int ret; + + if (single_step) + me.me_flags |= XFS_VERIFY_MEDIA_REPORT; + + ret = ioctl(verify_fd, XFS_IOC_VERIFY_MEDIA, &me); + if (ret < 0) + return ret; + if (me.me_ioerror) { + errno = me.me_ioerror; + return -1; + } + + return BBTOB(me.me_start_daddr - orig_start_daddr); +} + /* Read-verify an extent of a disk device. */ static ssize_t read_verify_one( struct read_verify_pool *rvp, struct read_verify *rv, - ssize_t len) + ssize_t len, + bool single_step) { if (debug) { int ret; @@ -246,8 +279,11 @@ read_verify_one( return len; } - return disk_read_verify(rvp->ctx->verify_disks[rvp->dev], rvp->readbuf, - rv->io_start, len); + if (rvp->ctx->no_verify_ioctl) + return disk_read_verify(rvp->ctx->verify_disks[rvp->dev], + rvp->readbuf, rv->io_start, len); + return ioctl_verify(rvp->ctx->mnt.fd, rvp->dev, rv->io_start, len, + single_step); } /* @@ -279,7 +315,7 @@ read_verify( len = min(rv->io_length, io_max_size); dbg_printf("diskverify %u %"PRIu64" %zu\n", rvp->dev, rv->io_start, len); - sz = read_verify_one(rvp, rv, len); + sz = read_verify_one(rvp, rv, len, io_max_size <= rvp->miniosz); if (sz == len && io_max_size < rvp->miniosz) { /* * If the verify request was 100% successful and less diff --git a/scrub/xfs_scrub.h b/scrub/xfs_scrub.h index 3009a7cd..851b4f37 100644 --- a/scrub/xfs_scrub.h +++ b/scrub/xfs_scrub.h @@ -79,6 +79,7 @@ struct scrub_ctx { /* Data block read verification buffer */ void *readbuf; + bool no_verify_ioctl; /* Mutable scrub state; use lock. */ pthread_mutex_t lock;