Scsi_debug adapter driver

Introduction

The scsi_debug adapter driver simulates a variable number of SCSI disks, each sharing a common amount of RAM allocated by the driver to act as (volatile) storage. With one SCSI device simulated, it is functionally equivalent to a RAM disk. With multiple SCSI devices simulated, they could be viewed as multiple paths to the same storage device or simply separate devices.

A small but hopefully useful set of SCSI commands are supported along with some crude error checking together with support for autosense (and a REQUEST SENSE command following a status of CHECK CONDITION will also fetch the sense buffer). The number of simulated devices and the shared RAM size for storage can be given as module parameters or boot time options if the scsi_debug driver is built into the kernel.

The original scsi_debug driver found in the lk 2.4 series was written by Eric Youngdale. Eric used it to test the "new" error handling introduced originally in the lk 2.2 series and extended in the lk 2.4 series. There are also hooks through to the user space where nasty error situations could be tested without compromising the kernel. See Eric's site for more information.

This driver replaced Eric's version in lk 2.4.18 .

For the scsi_debug driver in the linux 2.6 kernel series see this page.

If the function of this driver is unclear then the diagram in this accompanying page may help.
 

Details

The module command line and kernel boot time options are the same:
    scsi_debug_num_devs=<n>
    scsi_debug_dev_size_mb=<n>
    scsi_debug_opts=<n>
    scsi_debug_every_nth=<n>
    scsi_debug_delay=<n>

Driver options can be seen with this command: modinfo -p scsi_debug . The "scsi_debug_num_devs" option allows the number of devices to be specified. It should be 1 or greater. Unless Richard Gooch's "many-sd" patch is in place, the upper limit is 128 (less any real SCSI disk devices already present). The default number of devices is 1. The "scsi_debug_dev_size_mb" option allows the size of the shared RAM used to simulate storage to be specified. The unit is megabytes and the default value is 8 (megabytes). The RAM reserved for storage is initialized to zeoes when the driver is loaded.

"scsi_debug_opts" takes a decimal number as an argument which is the "or" of several flags. This is new in 1.58 (soon to be in 0.58). The flags supported are:

The root user may change these "opts" while the driver is running with this syntax:
    $ echo <new_opts>  > /proc/scsi/scsi_debug/<host_number>
The current setting of "opts" and other settings can be seen with this syntax:
    $ cat /proc/scsi/scsi_debug/<host_number>

"scsi_debug_every_nth" takes a decimal number as an argument. When this number is greater than zero and the "every_nth" bit is set in "scsi_debug_opts", then incoming commands are counted and when <n> is reached then the associated command is ignored. This will cause a timeout and associated error processing. Once the command count reaches <n> then it is reset to zero. This means setting "scsi_debug_every_nth" to 1 and "scsi_debug_opts" to 4 will cause every command to be ignored (and hence a timeout). If "scsi_debug_every_nth" is not given it is defaulted to 100, however this will not cause timeouts until the "every_nth" bit is set in "scsi_debug_opts" (which can also be set by writing to /proc/scsi/scsi_debug/<host_number>).

"scsi_debug_delay" is found in version 0.61 (and beyond) for the lk 2.4 series and version 1.61 (and beyond) for the lk 2.5 series. It is the number of jiffies (10 milliseconds on i386) that the driver will delay responses. The default is 1 jiffy. Setting this option to 0 (or negative) will cause the response to be sent back to the mid level before the request function is completed. Both delayed and immediate responses are permitted however delayed responses are more realistic. For delayed responses, a kernel timer is used. [Real adapters would generate an interrupt when the response was ready (i.e. the command had completed).]

The supported SCSI commands are:

The implementations of the above commands are sufficient for the scsi subsystem to detect and attach devices. The fdisk, e2fsck and mount commands also work as do the utilities found in the sg_utils package (see the main page). Crude error processing picks up unsupported commands and attempts to read or write outside the available RAM storage area.

Modern SCSI devices use vital product page 0x83 for identification. This driver yields both "T10 vendor identification" and "NAA" descriptors. The former yields an ASCII string like "Linux   scsi_debug      4000" where the "4000" is the ((host_no + 1) * 1000) + target_id). In this case "4000" corresponds to host_no==3 and target_id==0 . The "NAA" descriptor is an 8 byte binary value that looks
like this hex sequence: "51 23 45 60 00 00 0f a0" where the IEEE company id is 0x123456 (fake) and the vendor specific identifier in the least signficant bytes is 4000 in hex. [The "4000" is derived the same way for both descriptors.]

Reads and writes are atomic (i.e. a write from one scsi_debug device will not interrupt (split) a read from another scsi_debug device.

Other commands can easily be added so if you have some suggestions, then please contact me.
 

Download and Build information

The tarballs below contain drivers/scsi/scsi_debug.h and drivers/scsi/scsi_debug.c . It is probably best if the original files at that location have their names changed (e.g. "mv scsi_debug.c scsi_debug.c.orig"). The tarball can then be untarred thus:
    $ cd /usr/src/linux
    $ tar xzvf /tmp/scsi_debug_061.tgz

To build it, CONFIG_SCSI_DEBUG needs to be selected in the kernel configuration. It is the last SCSI low level driver listed. [You may also need to select CONFIG_EXPERIMENTAL in the code maturity level section otherwise scsi_debug isn't listed.] Assuming it is being built as a module then the following would be appropriate:
    $ cd /usr/src/linux
    $ make modules
    $ make modules_install

The driver could then be started with:
    $ modprobe scsi_debug scsi_debug_num_devs=12
to simulate 12 scsi disk devices, each sharing the same 8 MB or RAM (i.e. the default RAM size).

Here is a table of the versions of scsi_debug available for the lk 2.4 (production)  series. The version that appears in bold type is the most recent production version of the scsi_debug driver.
 

Linux version scsi_debug version tarball notes
lk 2.4.18 0.57 scsi_debug_057.tgz first rework
lk 2.4.19 0.58 scsi_debug_058.tgz more inquiry+mode_sense, opts, vmalloc
lk 2.4.20 0.61 scsi_debug_061.tgz scsi_debug_every_nth, delay [rework]

For information on the scsi_debug driver in the linux 2.5 (development) series see this page. 

Usage

When the driver is loaded successfully it should be visible just like other SCSI devices:

$ cat /proc/scsi/scsi
Attached devices:
Host: scsi1 Channel: 00 Id: 01 Lun: 00
  Vendor: IBM      Model: DNES-309170W     Rev: SA30
  Type:   Direct-Access                    ANSI SCSI revision: 03
Host: scsi5 Channel: 00 Id: 00 Lun: 00
  Vendor: Linux    Model: scsi_debug       Rev: 0002
  Type:   Direct-Access                    ANSI SCSI revision: 02

In this case there is one real SCSI device (an IBM disk) and one scsi_debug pseudo disk. The fdisk /dev/sdb command can now be used to partition the disk. Assuming one ext2 partition is allocated the whole pseudo disk (8 MB in this case) then the mke2fs /dev/sdb1 command can be used to make an ext2 file system. Now /dev/sdb1 can be mounted and treated like a normal file system. Naturally when the power is turned off anything stored in /dev/sdb1 will be forgotten.

Rather than mounting the pseudo disk, the sg3_utils package (see the main page) could be used to carry out various test on it.

Information about the scsi_debug driver version, its current parameters and some other data can be found in the normal way the Linux SCSI lower level drivers provide data:

# cat /proc/scsi/scsi_debug/3
scsi_debug adapter driver, Version: 1.61 (20020719)
num_devs=1, shared (ram) size=8 MB, opts=0x0, every_nth=100(curr:0)
sector_size=512 bytes, cylinders=64, heads=8, sectors=32, delay=1
number of aborts=0, device_reset=0, bus_resets=0, host_resets=0
 

 Back  to main page

Doug Gilbert (dgilbert@interlog.com)
Last updated: 8th October 2003