aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_sysfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/scsi_sysfs.c')
-rw-r--r--drivers/scsi/scsi_sysfs.c33
1 files changed, 23 insertions, 10 deletions
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index d6984df71f1c..bf53356f41f0 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -114,7 +114,7 @@ static int check_set(unsigned long long *val, char *src)
{
char *last;
- if (strncmp(src, "-", 20) == 0) {
+ if (strcmp(src, "-") == 0) {
*val = SCAN_WILD_CARD;
} else {
/*
@@ -303,6 +303,8 @@ store_host_reset(struct device *dev, struct device_attribute *attr,
if (sht->host_reset)
ret = sht->host_reset(shost, type);
+ else
+ ret = -EOPNOTSUPP;
exit_store_host_reset:
if (ret == 0)
@@ -426,6 +428,7 @@ static void scsi_device_dev_release_usercontext(struct work_struct *work)
struct scsi_device *sdev;
struct device *parent;
struct list_head *this, *tmp;
+ struct scsi_vpd *vpd_pg80 = NULL, *vpd_pg83 = NULL;
unsigned long flags;
sdev = container_of(work, struct scsi_device, ew.work);
@@ -454,8 +457,17 @@ static void scsi_device_dev_release_usercontext(struct work_struct *work)
/* NULL queue means the device can't be used */
sdev->request_queue = NULL;
- kfree(sdev->vpd_pg83);
- kfree(sdev->vpd_pg80);
+ mutex_lock(&sdev->inquiry_mutex);
+ rcu_swap_protected(sdev->vpd_pg80, vpd_pg80,
+ lockdep_is_held(&sdev->inquiry_mutex));
+ rcu_swap_protected(sdev->vpd_pg83, vpd_pg83,
+ lockdep_is_held(&sdev->inquiry_mutex));
+ mutex_unlock(&sdev->inquiry_mutex);
+
+ if (vpd_pg83)
+ kfree_rcu(vpd_pg83, rcu);
+ if (vpd_pg80)
+ kfree_rcu(vpd_pg80, rcu);
kfree(sdev->inquiry);
kfree(sdev);
@@ -793,15 +805,16 @@ show_vpd_##_page(struct file *filp, struct kobject *kobj, \
{ \
struct device *dev = container_of(kobj, struct device, kobj); \
struct scsi_device *sdev = to_scsi_device(dev); \
- int ret; \
- if (!sdev->vpd_##_page) \
- return -EINVAL; \
+ struct scsi_vpd *vpd_page; \
+ int ret = -EINVAL; \
+ \
rcu_read_lock(); \
- ret = memory_read_from_buffer(buf, count, &off, \
- rcu_dereference(sdev->vpd_##_page), \
- sdev->vpd_##_page##_len); \
+ vpd_page = rcu_dereference(sdev->vpd_##_page); \
+ if (vpd_page) \
+ ret = memory_read_from_buffer(buf, count, &off, \
+ vpd_page->data, vpd_page->len); \
rcu_read_unlock(); \
- return ret; \
+ return ret; \
} \
static struct bin_attribute dev_attr_vpd_##_page = { \
.attr = {.name = __stringify(vpd_##_page), .mode = S_IRUGO }, \