summaryrefslogtreecommitdiff
path: root/drivers/scsi/sd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/sd.c')
-rw-r--r--drivers/scsi/sd.c78
1 files changed, 34 insertions, 44 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 8796d908fcdd..bea36adeee17 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -156,7 +156,7 @@ static ssize_t
cache_type_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- int i, ct = -1, rcd, wce, sp;
+ int ct, rcd, wce, sp;
struct scsi_disk *sdkp = to_scsi_disk(dev);
struct scsi_device *sdp = sdkp->device;
char buffer[64];
@@ -179,16 +179,10 @@ cache_type_store(struct device *dev, struct device_attribute *attr,
sdkp->cache_override = 0;
}
- for (i = 0; i < ARRAY_SIZE(sd_cache_types); i++) {
- len = strlen(sd_cache_types[i]);
- if (strncmp(sd_cache_types[i], buf, len) == 0 &&
- buf[len] == '\n') {
- ct = i;
- break;
- }
- }
+ ct = sysfs_match_string(sd_cache_types, buf);
if (ct < 0)
return -EINVAL;
+
rcd = ct & 0x01 ? 1 : 0;
wce = (ct & 0x02) && !sdkp->write_prot ? 1 : 0;
@@ -228,7 +222,7 @@ manage_start_stop_show(struct device *dev, struct device_attribute *attr,
struct scsi_disk *sdkp = to_scsi_disk(dev);
struct scsi_device *sdp = sdkp->device;
- return snprintf(buf, 20, "%u\n", sdp->manage_start_stop);
+ return sprintf(buf, "%u\n", sdp->manage_start_stop);
}
static ssize_t
@@ -252,7 +246,7 @@ allow_restart_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct scsi_disk *sdkp = to_scsi_disk(dev);
- return snprintf(buf, 40, "%d\n", sdkp->device->allow_restart);
+ return sprintf(buf, "%u\n", sdkp->device->allow_restart);
}
static ssize_t
@@ -280,7 +274,7 @@ cache_type_show(struct device *dev, struct device_attribute *attr, char *buf)
struct scsi_disk *sdkp = to_scsi_disk(dev);
int ct = sdkp->RCD + 2*sdkp->WCE;
- return snprintf(buf, 40, "%s\n", sd_cache_types[ct]);
+ return sprintf(buf, "%s\n", sd_cache_types[ct]);
}
static DEVICE_ATTR_RW(cache_type);
@@ -289,7 +283,7 @@ FUA_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct scsi_disk *sdkp = to_scsi_disk(dev);
- return snprintf(buf, 20, "%u\n", sdkp->DPOFUA);
+ return sprintf(buf, "%u\n", sdkp->DPOFUA);
}
static DEVICE_ATTR_RO(FUA);
@@ -299,7 +293,7 @@ protection_type_show(struct device *dev, struct device_attribute *attr,
{
struct scsi_disk *sdkp = to_scsi_disk(dev);
- return snprintf(buf, 20, "%u\n", sdkp->protection_type);
+ return sprintf(buf, "%u\n", sdkp->protection_type);
}
static ssize_t
@@ -342,9 +336,9 @@ protection_mode_show(struct device *dev, struct device_attribute *attr,
}
if (!dif && !dix)
- return snprintf(buf, 20, "none\n");
+ return sprintf(buf, "none\n");
- return snprintf(buf, 20, "%s%u\n", dix ? "dix" : "dif", dif);
+ return sprintf(buf, "%s%u\n", dix ? "dix" : "dif", dif);
}
static DEVICE_ATTR_RO(protection_mode);
@@ -353,7 +347,7 @@ app_tag_own_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct scsi_disk *sdkp = to_scsi_disk(dev);
- return snprintf(buf, 20, "%u\n", sdkp->ATO);
+ return sprintf(buf, "%u\n", sdkp->ATO);
}
static DEVICE_ATTR_RO(app_tag_own);
@@ -363,10 +357,11 @@ thin_provisioning_show(struct device *dev, struct device_attribute *attr,
{
struct scsi_disk *sdkp = to_scsi_disk(dev);
- return snprintf(buf, 20, "%u\n", sdkp->lbpme);
+ return sprintf(buf, "%u\n", sdkp->lbpme);
}
static DEVICE_ATTR_RO(thin_provisioning);
+/* sysfs_match_string() requires dense arrays */
static const char *lbp_mode[] = {
[SD_LBP_FULL] = "full",
[SD_LBP_UNMAP] = "unmap",
@@ -382,7 +377,7 @@ provisioning_mode_show(struct device *dev, struct device_attribute *attr,
{
struct scsi_disk *sdkp = to_scsi_disk(dev);
- return snprintf(buf, 20, "%s\n", lbp_mode[sdkp->provisioning_mode]);
+ return sprintf(buf, "%s\n", lbp_mode[sdkp->provisioning_mode]);
}
static ssize_t
@@ -391,6 +386,7 @@ provisioning_mode_store(struct device *dev, struct device_attribute *attr,
{
struct scsi_disk *sdkp = to_scsi_disk(dev);
struct scsi_device *sdp = sdkp->device;
+ int mode;
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
@@ -403,23 +399,17 @@ provisioning_mode_store(struct device *dev, struct device_attribute *attr,
if (sdp->type != TYPE_DISK)
return -EINVAL;
- if (!strncmp(buf, lbp_mode[SD_LBP_UNMAP], 20))
- sd_config_discard(sdkp, SD_LBP_UNMAP);
- else if (!strncmp(buf, lbp_mode[SD_LBP_WS16], 20))
- sd_config_discard(sdkp, SD_LBP_WS16);
- else if (!strncmp(buf, lbp_mode[SD_LBP_WS10], 20))
- sd_config_discard(sdkp, SD_LBP_WS10);
- else if (!strncmp(buf, lbp_mode[SD_LBP_ZERO], 20))
- sd_config_discard(sdkp, SD_LBP_ZERO);
- else if (!strncmp(buf, lbp_mode[SD_LBP_DISABLE], 20))
- sd_config_discard(sdkp, SD_LBP_DISABLE);
- else
+ mode = sysfs_match_string(lbp_mode, buf);
+ if (mode < 0)
return -EINVAL;
+ sd_config_discard(sdkp, mode);
+
return count;
}
static DEVICE_ATTR_RW(provisioning_mode);
+/* sysfs_match_string() requires dense arrays */
static const char *zeroing_mode[] = {
[SD_ZERO_WRITE] = "write",
[SD_ZERO_WS] = "writesame",
@@ -433,7 +423,7 @@ zeroing_mode_show(struct device *dev, struct device_attribute *attr,
{
struct scsi_disk *sdkp = to_scsi_disk(dev);
- return snprintf(buf, 20, "%s\n", zeroing_mode[sdkp->zeroing_mode]);
+ return sprintf(buf, "%s\n", zeroing_mode[sdkp->zeroing_mode]);
}
static ssize_t
@@ -441,21 +431,17 @@ zeroing_mode_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct scsi_disk *sdkp = to_scsi_disk(dev);
+ int mode;
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
- if (!strncmp(buf, zeroing_mode[SD_ZERO_WRITE], 20))
- sdkp->zeroing_mode = SD_ZERO_WRITE;
- else if (!strncmp(buf, zeroing_mode[SD_ZERO_WS], 20))
- sdkp->zeroing_mode = SD_ZERO_WS;
- else if (!strncmp(buf, zeroing_mode[SD_ZERO_WS16_UNMAP], 20))
- sdkp->zeroing_mode = SD_ZERO_WS16_UNMAP;
- else if (!strncmp(buf, zeroing_mode[SD_ZERO_WS10_UNMAP], 20))
- sdkp->zeroing_mode = SD_ZERO_WS10_UNMAP;
- else
+ mode = sysfs_match_string(zeroing_mode, buf);
+ if (mode < 0)
return -EINVAL;
+ sdkp->zeroing_mode = mode;
+
return count;
}
static DEVICE_ATTR_RW(zeroing_mode);
@@ -466,7 +452,7 @@ max_medium_access_timeouts_show(struct device *dev,
{
struct scsi_disk *sdkp = to_scsi_disk(dev);
- return snprintf(buf, 20, "%u\n", sdkp->max_medium_access_timeouts);
+ return sprintf(buf, "%u\n", sdkp->max_medium_access_timeouts);
}
static ssize_t
@@ -492,7 +478,7 @@ max_write_same_blocks_show(struct device *dev, struct device_attribute *attr,
{
struct scsi_disk *sdkp = to_scsi_disk(dev);
- return snprintf(buf, 20, "%u\n", sdkp->max_ws_blocks);
+ return sprintf(buf, "%u\n", sdkp->max_ws_blocks);
}
static ssize_t
@@ -717,6 +703,7 @@ static void sd_config_discard(struct scsi_disk *sdkp, unsigned int mode)
switch (mode) {
+ case SD_LBP_FULL:
case SD_LBP_DISABLE:
blk_queue_max_discard_sectors(q, 0);
queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, q);
@@ -1842,8 +1829,9 @@ static void sd_eh_reset(struct scsi_cmnd *scmd)
static int sd_eh_action(struct scsi_cmnd *scmd, int eh_disp)
{
struct scsi_disk *sdkp = scsi_disk(scmd->request->rq_disk);
+ struct scsi_device *sdev = scmd->device;
- if (!scsi_device_online(scmd->device) ||
+ if (!scsi_device_online(sdev) ||
!scsi_medium_access_command(scmd) ||
host_byte(scmd->result) != DID_TIME_OUT ||
eh_disp != SUCCESS)
@@ -1869,7 +1857,9 @@ static int sd_eh_action(struct scsi_cmnd *scmd, int eh_disp)
if (sdkp->medium_access_timed_out >= sdkp->max_medium_access_timeouts) {
scmd_printk(KERN_ERR, scmd,
"Medium access timeout failure. Offlining disk!\n");
- scsi_device_set_state(scmd->device, SDEV_OFFLINE);
+ mutex_lock(&sdev->state_mutex);
+ scsi_device_set_state(sdev, SDEV_OFFLINE);
+ mutex_unlock(&sdev->state_mutex);
return SUCCESS;
}