]> git-server-git.apps.pok.os.sepia.ceph.com Git - xfsprogs-dev.git/commitdiff
xfs_scrub: drop SCSI_VERIFY code from disk.
authorDarrick J. Wong <djwong@kernel.org>
Tue, 17 Mar 2026 17:48:57 +0000 (10:48 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Thu, 9 Apr 2026 22:30:19 +0000 (15:30 -0700)
Now that we have a media verification ioctl in the kernel, drop the
SCSI_VERIFY code, which enables us to drop the dependency on sg and
obviates the need to fix some unit-handling bugs in the HDIO_GETGEO
code.

A subsequent patch will enable larger verification IO sizes, which this
old code cannot handle.

Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
doc/README-env-vars.txt
scrub/disk.c
scrub/disk.h
scrub/read_verify.c
scrub/xfs_scrub.c

index eec59a82513f36c2b133edd886a2af0d274223ac..6862dcad71e217d36653f952c71d9c2e39a5b7d0 100644 (file)
@@ -17,7 +17,6 @@ Known debug tweaks (pass -d and set the environment variable):
 XFS_SCRUB_FORCE_ERROR        -- pretend all metadata is corrupt
 XFS_SCRUB_FORCE_REPAIR       -- repair all metadata even if it's ok
 XFS_SCRUB_NO_KERNEL          -- pretend there is no kernel ioctl
-XFS_SCRUB_NO_SCSI_VERIFY     -- disable SCSI VERIFY (if present)
 XFS_SCRUB_PHASE              -- run only this scrub phase
 XFS_SCRUB_THREADS            -- start exactly this number of threads
 
index afce801d3f20768fbd5c435a31cb6eda5409d5d6..ca37724249e551ef82e325c42d213d8803a52884 100644 (file)
@@ -10,8 +10,6 @@
 #include <fcntl.h>
 #include <sys/types.h>
 #include <sys/statvfs.h>
-#include <scsi/sg.h>
-#include <linux/hdreg.h>
 #include "platform_defs.h"
 #include "libfrog/util.h"
 #include "libfrog/paths.h"
@@ -78,113 +76,12 @@ disk_heads(
        return __disk_heads(disk);
 }
 
-/*
- * Execute a SCSI VERIFY(16) to verify disk contents.
- * For devices that support this command, this can sharply reduce the
- * runtime of the data block verification phase if the storage device's
- * internal bandwidth exceeds its link bandwidth.  However, it only
- * works if we're talking to a raw SCSI device, and only if we trust the
- * firmware.
- */
-#define SENSE_BUF_LEN          64
-#define VERIFY16_CMDLEN        16
-#define VERIFY16_CMD           0x8F
-
-#ifndef SG_FLAG_Q_AT_TAIL
-# define SG_FLAG_Q_AT_TAIL     0x10
-#endif
-static int
-disk_scsi_verify(
-       struct disk             *disk,
-       uint64_t                startblock, /* lba */
-       uint64_t                blockcount) /* lba */
-{
-       struct sg_io_hdr        iohdr;
-       unsigned char           cdb[VERIFY16_CMDLEN];
-       unsigned char           sense[SENSE_BUF_LEN];
-       uint64_t                llba;
-       uint64_t                veri_len = blockcount;
-       int                     error;
-
-       assert(!debug_tweak_on("XFS_SCRUB_NO_SCSI_VERIFY"));
-
-       llba = startblock + (disk->d_start >> BBSHIFT);
-
-       /* Borrowed from sg_verify */
-       cdb[0] = VERIFY16_CMD;
-       cdb[1] = 0; /* skip PI, DPO, and byte check. */
-       cdb[2] = (llba >> 56) & 0xff;
-       cdb[3] = (llba >> 48) & 0xff;
-       cdb[4] = (llba >> 40) & 0xff;
-       cdb[5] = (llba >> 32) & 0xff;
-       cdb[6] = (llba >> 24) & 0xff;
-       cdb[7] = (llba >> 16) & 0xff;
-       cdb[8] = (llba >> 8) & 0xff;
-       cdb[9] = llba & 0xff;
-       cdb[10] = (veri_len >> 24) & 0xff;
-       cdb[11] = (veri_len >> 16) & 0xff;
-       cdb[12] = (veri_len >> 8) & 0xff;
-       cdb[13] = veri_len & 0xff;
-       cdb[14] = 0;
-       cdb[15] = 0;
-       memset(sense, 0, SENSE_BUF_LEN);
-
-       /* v3 SG_IO */
-       memset(&iohdr, 0, sizeof(iohdr));
-       iohdr.interface_id = 'S';
-       iohdr.dxfer_direction = SG_DXFER_NONE;
-       iohdr.cmdp = cdb;
-       iohdr.cmd_len = VERIFY16_CMDLEN;
-       iohdr.sbp = sense;
-       iohdr.mx_sb_len = SENSE_BUF_LEN;
-       iohdr.flags |= SG_FLAG_Q_AT_TAIL;
-       iohdr.timeout = 30000; /* 30s */
-
-       error = ioctl(disk->d_fd, SG_IO, &iohdr);
-       if (error < 0)
-               return error;
-
-       dbg_printf("VERIFY(16) fd %d lba %"PRIu64" len %"PRIu64" info %x "
-                       "status %d masked %d msg %d host %d driver %d "
-                       "duration %d resid %d\n",
-                       disk->d_fd, startblock, blockcount, iohdr.info,
-                       iohdr.status, iohdr.masked_status, iohdr.msg_status,
-                       iohdr.host_status, iohdr.driver_status, iohdr.duration,
-                       iohdr.resid);
-
-       if (iohdr.info & SG_INFO_CHECK) {
-               dbg_printf("status: msg %x host %x driver %x\n",
-                               iohdr.msg_status, iohdr.host_status,
-                               iohdr.driver_status);
-               errno = EIO;
-               return -1;
-       }
-
-       return blockcount << BBSHIFT;
-}
-
-/* Test the availability of the kernel scrub ioctl. */
-static bool
-disk_can_scsi_verify(
-       struct disk             *disk)
-{
-       int                     error;
-
-       if (debug_tweak_on("XFS_SCRUB_NO_SCSI_VERIFY"))
-               return false;
-
-       error = disk_scsi_verify(disk, 0, 1);
-       return error == 0;
-}
-
 /* Open a disk device and discover its geometry. */
 struct disk *
 disk_open(
        const char              *pathname)
 {
-       struct hd_geometry      bdgeo;
        struct disk             *disk;
-       bool                    suspicious_disk = false;
        int                     error;
 
        disk = calloc(1, sizeof(struct disk));
@@ -214,32 +111,11 @@ disk_open(
                error = ioctl(disk->d_fd, BLKBSZGET, &disk->d_blksize);
                if (error)
                        disk->d_blksize = 0;
-               error = ioctl(disk->d_fd, HDIO_GETGEO, &bdgeo);
-               if (!error) {
-                       /*
-                        * dm devices will pass through ioctls, which means
-                        * we can't use SCSI VERIFY unless the start is 0.
-                        * Most dm devices don't set geometry (unlike scsi
-                        * and nvme) so use a zeroed out CHS to screen them
-                        * out.
-                        */
-                       if (bdgeo.start != 0 &&
-                           (unsigned long long)bdgeo.heads * bdgeo.sectors *
-                                       bdgeo.sectors == 0)
-                               suspicious_disk = true;
-                       disk->d_start = bdgeo.start << BBSHIFT;
-               } else
-                       disk->d_start = 0;
        } else {
                disk->d_size = disk->d_sb.st_size;
                disk->d_blksize = disk->d_sb.st_blksize;
-               disk->d_start = 0;
        }
 
-       /* Can we issue SCSI VERIFY? */
-       if (!suspicious_disk && disk_can_scsi_verify(disk))
-               disk->d_flags |= DISK_FLAG_SCSI_VERIFY;
-
        return disk;
 out_close:
        close(disk->d_fd);
@@ -262,10 +138,6 @@ disk_close(
        return error;
 }
 
-#define BTOLBAT(d, bytes)      ((uint64_t)(bytes) >> (d)->d_lbalog)
-#define LBASIZE(d)             (1ULL << (d)->d_lbalog)
-#define BTOLBA(d, bytes)       (((uint64_t)(bytes) + LBASIZE(d) - 1) >> (d)->d_lbalog)
-
 /* Read-verify an extent of a disk device. */
 ssize_t
 disk_read_verify(
@@ -274,10 +146,5 @@ disk_read_verify(
        uint64_t                start,
        uint64_t                length)
 {
-       /* Convert to logical block size. */
-       if (disk->d_flags & DISK_FLAG_SCSI_VERIFY)
-               return disk_scsi_verify(disk, BTOLBAT(disk, start),
-                               BTOLBA(disk, length));
-
        return pread(disk->d_fd, buf, length, start);
 }
index 73c73ab57fb5c772d9a83cacacf42dea492a5ef2..a9155bf1f75eb4fdb67e65edb4871952f6bdaf22 100644 (file)
@@ -6,7 +6,6 @@
 #ifndef XFS_SCRUB_DISK_H_
 #define XFS_SCRUB_DISK_H_
 
-#define DISK_FLAG_SCSI_VERIFY  0x1
 struct disk {
        struct stat     d_sb;
        int             d_fd;
@@ -15,7 +14,6 @@ struct disk {
        unsigned int    d_flags;
        unsigned int    d_blksize;      /* bytes */
        uint64_t        d_size;         /* bytes */
-       uint64_t        d_start;        /* bytes */
 };
 
 unsigned int disk_heads(struct disk *disk);
index 3334f8d8c79ca22b2c7e8fe506f6b8aa8d388ea2..01a3a8859c5fa868fc2889f384a88367e0e49eb5 100644 (file)
  * pool takes care of issuing multiple IOs to the device, if possible.
  */
 
-/*
- * Perform all IO in 32M chunks.  This cannot exceed 65536 sectors
- * because that's the biggest SCSI VERIFY(16) we dare to send.
- */
+/* Perform all verification IO in 32M chunks. */
 #define RVP_IO_MAX_SIZE                (33554432)
 
 /*
index b74dc1635141aa14e6745b941f3376920430dc98..aae24ec83c1c75b8d0f585e53f96e52dfe1f5352 100644 (file)
  * XFS_SCRUB_FORCE_ERROR       -- pretend all metadata is corrupt
  * XFS_SCRUB_FORCE_REPAIR      -- repair all metadata even if it's ok
  * XFS_SCRUB_NO_KERNEL         -- pretend there is no kernel ioctl
- * XFS_SCRUB_NO_SCSI_VERIFY    -- disable SCSI VERIFY (if present)
  * XFS_SCRUB_PHASE             -- run only this scrub phase
  * XFS_SCRUB_THREADS           -- start exactly this number of threads
  * XFS_SCRUB_DISK_ERROR_INTERVAL-- simulate a disk error every this many bytes