Brian King wrote: > Douglas Gilbert wrote: >>> I have a SCSI disk, which I want to spin down when the system is not in >>> use. I do this by using sdparm, scsi-spin or sg-utils. These tools all >>> spin down the SCSI drive by using an IOCTL. >>> >>> Problem is that the kernel doesn't spin the drive back up. When a >>> process requests data from the disk (a simple ls), the kernel responds >>> with an I/O error. After some of these errors, reiserfs marks the drive >>> read-only. > > Setting sdev->allow_restart in struct scsi_device will cause sense > key/code/qual of 02/04/02 (not ready, initialization command required) > to wake up the scsi error handler and will force scsi core to issue > a start unit command to the disk. I added this a while back to handle > ipr raid arrays which need a start unit command each time the adapter > gets reset. It would be easy enough for sd to use this, either > all the time, or only when directed to, or we could add a sysfs attribute > to the disk to enable/disable this behavior. Please try the attached patch. It adds a sysfs device attribute "allow_restart". If you set it to 1, then scsi core will issue a start unit when it sees 02/04/02 sense data. The attribute is in the same place as the FUA and cache_type attributes (eg. /sys/block/sdc/device/scsi_disk:1:1:9:0/allow_restart). -- Brian King eServer Storage I/O IBM Linux Technology Center
Signed-off-by: Brian King <brking@xxxxxxxxxx> --- linux-2.6-bjking1/drivers/scsi/sd.c | 26 ++++++++++++++++++++++++++ 1 files changed, 26 insertions(+) diff -puN drivers/scsi/sd.c~sd_allow_restart_sysfs_attr drivers/scsi/sd.c --- linux-2.6/drivers/scsi/sd.c~sd_allow_restart_sysfs_attr 2006-06-05 12:33:06.000000000 -0500 +++ linux-2.6-bjking1/drivers/scsi/sd.c 2006-06-05 12:34:22.000000000 -0500 @@ -208,6 +208,23 @@ static ssize_t sd_store_cache_type(struc return count; } +static ssize_t sd_store_allow_restart(struct class_device *cdev, const char *buf, + size_t count) +{ + struct scsi_disk *sdkp = to_scsi_disk(cdev); + struct scsi_device *sdp = sdkp->device; + + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + + if (sdp->type != TYPE_DISK) + return -EINVAL; + + sdp->allow_restart = simple_strtoul(buf, NULL, 10); + + return count; +} + static ssize_t sd_show_cache_type(struct class_device *cdev, char *buf) { struct scsi_disk *sdkp = to_scsi_disk(cdev); @@ -223,10 +240,19 @@ static ssize_t sd_show_fua(struct class_ return snprintf(buf, 20, "%u\n", sdkp->DPOFUA); } +static ssize_t sd_show_allow_restart(struct class_device *cdev, char *buf) +{ + struct scsi_disk *sdkp = to_scsi_disk(cdev); + + return snprintf(buf, 40, "%d\n", sdkp->device->allow_restart); +} + static struct class_device_attribute sd_disk_attrs[] = { __ATTR(cache_type, S_IRUGO|S_IWUSR, sd_show_cache_type, sd_store_cache_type), __ATTR(FUA, S_IRUGO, sd_show_fua, NULL), + __ATTR(allow_restart, S_IRUGO|S_IWUSR, sd_show_allow_restart, + sd_store_allow_restart), __ATTR_NULL, }; _