]> git-server-git.apps.pok.os.sepia.ceph.com Git - xfsprogs-dev.git/commitdiff
xfs_scrub: use the verify media ioctl during phase 6 if possible
authorDarrick J. Wong <djwong@kernel.org>
Sun, 22 Feb 2026 22:41:17 +0000 (14:41 -0800)
committerDarrick J. Wong <djwong@kernel.org>
Thu, 9 Apr 2026 22:30:19 +0000 (15:30 -0700)
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" <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
scrub/phase1.c
scrub/read_verify.c
scrub/xfs_scrub.h

index 16607af4c5f025947c0a4378fcc5b7c1c3aa51d8..abc594898bf2c5eb5be923be5d729f2e5ad8c404 100644 (file)
@@ -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
index 3b3baaf8980c4e54d2435e9d1e67e8925cef280e..66086d6fe2d56d40e5e2f70fe22d4131e9967833 100644 (file)
@@ -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
index 3009a7cd2d97d06de261fb24673eb8ee7ae11ae2..851b4f37db48e411bfde050fd6464602b26a5cfe 100644 (file)
@@ -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;