Measure Repeated SCSI Reads Safely with sg_read

sg_read repeats SCSI reads against a file or device so you can measure throughput or command overhead. You will finish with a repeatable way to read the same blocks from a test file, and a controlled pattern for measuring SCSI read throughput or command overhead. The installed command comes from sg3-utils package version 1.46-3ubuntu4; its own version output reports 1.36 20191220. That distinction matters because this is an old utility, not a general replacement for dd or modern storage benchmarks.

Allow about fifteen minutes. You need a shell, the sg3-utils package, and either a seekable test file or a SCSI generic device. The file workflow needs no elevated privileges. Reading a real device may require access to /dev/sg* and can create significant I/O, so plan a quiet test window. These examples never write data, but performance tests can still disturb cache behaviour and competing workloads.

1. Confirm the installed interface

Check the binary before building a command around it:

$ sg_read --version
sg_read: : 1.36 20191220

The command uses named arguments such as if=, count= and bs=, not the positional syntax of ordinary dd. if= is mandatory, and the input must be a seekable file, a block device or an SCSI generic device. Standard input is not accepted.

Checkpoint: run sg_read --help and confirm that your local usage text agrees with the examples below. The man page documents --help and --version; this installed build also accepts the short forms shown by its help output.

2. Make a harmless file-based test

Start with a file so that you can verify units without touching a disk device. Create a temporary file with known size outside the article's working directory:

$ dd if=/dev/zero of=/tmp/sg-read-sample.bin bs=512 count=4096 status=none
$ stat -c '%n %s bytes' /tmp/sg-read-sample.bin
/tmp/sg-read-sample.bin 2097152 bytes

Now read 1024 blocks, in transfers of 128 blocks:

$ sg_read if=/tmp/sg-read-sample.bin bs=512 bpt=128 count=1024
1024+0 records in

The exact completion line can vary slightly by build, but a successful run exits with status 0. Check it immediately:

$ printf '%s\n' "$?"
0

bs is the size of one logical block, while count is a number of blocks, not bytes. This example reads 512 KiB in total. bpt limits the number fetched by one read operation, and defaults to 128. Every operation starts at the same logical block address unless you give skip, so this is a repeated-read test rather than a sequential scan.

3. Select the starting block deliberately

Use skip when the beginning of the input is not the region you want to exercise:

$ sg_read if=/tmp/sg-read-sample.bin bs=512 bpt=64 skip=1024 count=256 time=1
time from first command to end was ... secs, ... MB/sec

The ellipses represent measured values, not literal input. Here each transfer begins at block 1024, and 256 blocks are requested in total. Keep skip + count within the available file or device range. The program may report an input error once the range is exceeded; it does not turn an invalid range into a safe no-op.

time=1 starts timing with the first command. For cache experiments, time=2 starts with the second command, excluding the first read from the throughput interval. This can help separate an initial media fetch from subsequent cached reads, but it does not prove that every later read came from a particular cache layer.

4. Read a real SCSI device only after checking the target

Stop here if you do not know which device you are opening. A wrong /dev/sg* path can target a live disk, tape drive or other SCSI device. The command is read-oriented, but dpo=1 and fua=1 change flags in the SCSI READ command and can change device-side cache handling. Do not add them casually, and do not use an unverified device path in a copy-and-paste command.

After identifying a safe target, a representative read-only measurement is:

$ sg_read if=/dev/sgX bs=512 bpt=128 count=4096 mmap=1 time=2 verbose=1

Replace /dev/sgX with the device you have explicitly checked. mmap=1 requests memory-mapped I/O and is active for an SCSI generic device. It cannot be combined with dio=1. The default is indirect I/O. Direct I/O is only attempted with dio=1, and the man page warns that the kernel setting /proc/scsi/sg/allow_dio may cause it to fall back to indirect I/O.

Ordinary users may get a permissions error. Use elevated privileges only when your device permissions require it:

$ sudo sg_read if=/dev/sgX bs=512 bpt=128 count=4096 time=2

Do not use sudo to compensate for an uncertain target. It changes access, not which device the path names.

5. Measure command overhead without transferring data

For an SCSI generic device, bpt=0 makes count the number of zero-block SCSI READ commands. With a negative count, the absolute value is used for zero-block commands in the cases documented by the man page:

$ sg_read if=/dev/sgX bpt=0 count=10000 time=1

These commands are intended to measure command latency and transport overhead. They are not a substitute for a data-integrity test and should still be run against a device you have permission to exercise. A six-byte READ command does not treat zero blocks in the same way as the 10, 12 and 16 byte variants, so leave cdbsz at its default unless you have a specific SCSI compatibility reason to change it.

6. Interpret the limits and recover cleanly

The utility uses 32-bit integers for logical block addresses and counts. The installed man page therefore warns that it cannot address beyond 2 TiB on a device with 512-byte logical blocks. For larger or more capable jobs, investigate sg_dd or ddpt instead.

If a run is too long, press Ctrl-C. The utility reports remaining blocks before applying the signal's normal action. SIGUSR1 reports the same progress information while continuing, where your shell can send it to the process. Remove only the temporary file created for the file test:

$ rm -- /tmp/sg-read-sample.bin

This removes no device data and does not undo any device cache state. Stop a benchmark and let the system settle before comparing results with another workload.

Done means