From 40998193560dab6c3ce8d25f4fa58a23e252ef38 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 19 Oct 2015 16:35:46 +0200 Subject: scsi: restart list search after unlock in scsi_remove_target When dropping a lock while iterating a list we must restart the search as other threads could have manipulated the list under us. Without this we can get stuck in an endless loop. This bug was introduced by commit bc3f02a795d3b4faa99d37390174be2a75d091bd Author: Dan Williams Date: Tue Aug 28 22:12:10 2012 -0700 [SCSI] scsi_remove_target: fix softlockup regression on hot remove Which was itself trying to fix a reported soft lockup issue http://thread.gmane.org/gmane.linux.kernel/1348679 However, we believe even with this revert of the original patch, the soft lockup problem has been fixed by commit f2495e228fce9f9cec84367547813cbb0d6db15a Author: James Bottomley Date: Tue Jan 21 07:01:41 2014 -0800 [SCSI] dual scan thread bug fix Thanks go to Dan Williams for tracking all this prior history down. Reported-by: Johannes Thumshirn Signed-off-by: Christoph Hellwig Tested-by: Johannes Thumshirn Reviewed-by: Johannes Thumshirn Fixes: bc3f02a795d3b4faa99d37390174be2a75d091bd Cc: stable@vger.kernel.org Signed-off-by: James Bottomley --- drivers/scsi/scsi_sysfs.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) (limited to 'drivers/scsi/scsi_sysfs.c') diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index b333389f248f..d3b34d871f4c 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -1158,31 +1158,23 @@ static void __scsi_remove_target(struct scsi_target *starget) void scsi_remove_target(struct device *dev) { struct Scsi_Host *shost = dev_to_shost(dev->parent); - struct scsi_target *starget, *last = NULL; + struct scsi_target *starget; unsigned long flags; - /* remove targets being careful to lookup next entry before - * deleting the last - */ +restart: spin_lock_irqsave(shost->host_lock, flags); list_for_each_entry(starget, &shost->__targets, siblings) { if (starget->state == STARGET_DEL) continue; if (starget->dev.parent == dev || &starget->dev == dev) { - /* assuming new targets arrive at the end */ kref_get(&starget->reap_ref); spin_unlock_irqrestore(shost->host_lock, flags); - if (last) - scsi_target_reap(last); - last = starget; __scsi_remove_target(starget); - spin_lock_irqsave(shost->host_lock, flags); + scsi_target_reap(starget); + goto restart; } } spin_unlock_irqrestore(shost->host_lock, flags); - - if (last) - scsi_target_reap(last); } EXPORT_SYMBOL(scsi_remove_target); -- cgit v1.2.3 From 92e6246c8e02f4ce9960731e2411e49c1f0fabbf Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Mon, 9 Nov 2015 10:56:57 +0100 Subject: scsi: Export SCSI Inquiry data to sysfs Export the RAW SCSI Inquiry to sysfs as binfile. This way the data can be used by userland without the need to have and ioctl or use the sg_inq tool. Here is an example of the provided data linux:~ # hexdump /sys/class/scsi_device/1\:0\:0\:0/device/inquiry 0000000 8005 3205 001f 0000 4551 554d 2020 2020 0000010 4551 554d 4420 4456 522d 4d4f 2020 2020 0000020 2e32 2e33 0000024 Signed-off-by: Johannes Thumshirn Reviewed-by: Hannes Reinecke Reviewed-by: Christoph Hellwig Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_sysfs.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'drivers/scsi/scsi_sysfs.c') diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index b333389f248f..fdcf0abe613f 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -773,6 +773,29 @@ static struct bin_attribute dev_attr_vpd_##_page = { \ sdev_vpd_pg_attr(pg83); sdev_vpd_pg_attr(pg80); +static ssize_t show_inquiry(struct file *filep, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct scsi_device *sdev = to_scsi_device(dev); + + if (!sdev->inquiry) + return -EINVAL; + + return memory_read_from_buffer(buf, count, &off, sdev->inquiry, + sdev->inquiry_len); +} + +static struct bin_attribute dev_attr_inquiry = { + .attr = { + .name = "inquiry", + .mode = S_IRUGO, + }, + .size = 0, + .read = show_inquiry, +}; + static ssize_t show_iostat_counterbits(struct device *dev, struct device_attribute *attr, char *buf) @@ -957,6 +980,7 @@ static struct attribute *scsi_sdev_attrs[] = { static struct bin_attribute *scsi_sdev_bin_attrs[] = { &dev_attr_vpd_pg83, &dev_attr_vpd_pg80, + &dev_attr_inquiry, NULL }; static struct attribute_group scsi_sdev_attr_group = { -- cgit v1.2.3 From 863e02d0e173bb9d8cea6861be22820b25c076cc Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter Date: Tue, 27 Oct 2015 10:49:54 +0100 Subject: scsi_sysfs: Fix queue_ramp_up_period return code Writing a number to /sys/bus/scsi/devices//queue_ramp_up_period returns the value of that number instead of the number of bytes written. This behavior can confuse programs expecting POSIX write() semantics. Fix this by returning the number of bytes written instead. Signed-off-by: Peter Oberparleiter Reviewed-by: Hannes Reinecke Cc: stable@vger.kernel.org Reviewed-by: Matthew R. Ochs Reviewed-by: Ewan D. Milne Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_sysfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi/scsi_sysfs.c') diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index fdcf0abe613f..8b7fa8aece66 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -921,7 +921,7 @@ sdev_store_queue_ramp_up_period(struct device *dev, return -EINVAL; sdev->queue_ramp_up_period = msecs_to_jiffies(period); - return period; + return count; } static DEVICE_ATTR(queue_ramp_up_period, S_IRUGO | S_IWUSR, -- cgit v1.2.3 From bf2cf3baa20b0a6cd2d08707ef05dc0e992a8aa0 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Fri, 18 Sep 2015 17:23:42 -0700 Subject: scsi: Fix a bdi reregistration race Unregister and reregister BDI devices in the proper order. This patch avoids that the following kernel warning can get triggered: WARNING: CPU: 7 PID: 203 at fs/sysfs/dir.c:31 sysfs_warn_dup+0x68/0x80() sysfs: cannot create duplicate filename '/devices/virtual/bdi/8:32' Workqueue: events_unbound async_run_entry_fn Call Trace: [] dump_stack+0x4c/0x65 [] warn_slowpath_common+0x8a/0xc0 [] warn_slowpath_fmt+0x46/0x50 [] sysfs_warn_dup+0x68/0x80 [] sysfs_create_dir_ns+0x7e/0x90 [] kobject_add_internal+0xa8/0x320 [] kobject_add+0x60/0xb0 [] device_add+0x107/0x5e0 [] device_create_groups_vargs+0xd8/0x100 [] device_create_vargs+0x1c/0x20 [] bdi_register+0x63/0x2a0 [] bdi_register_dev+0x27/0x30 [] add_disk+0x1a9/0x4e0 [] sd_probe_async+0x119/0x1d0 [sd_mod] [] async_run_entry_fn+0x4a/0x140 [] process_one_work+0x1d8/0x7c0 [] worker_thread+0x114/0x460 [] kthread+0xf8/0x110 [] ret_from_fork+0x3f/0x70 See also patch "block: destroy bdi before blockdev is unregistered" (commit ID 6cd18e711dd8). Signed-off-by: Bart Van Assche Reviewed-by: Hannes Reinecke Cc: Signed-off-by: James Bottomley --- drivers/scsi/scsi_sysfs.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'drivers/scsi/scsi_sysfs.c') diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index d3b34d871f4c..0efc21d271b4 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -1084,9 +1084,7 @@ void __scsi_remove_device(struct scsi_device *sdev) device_unregister(&sdev->sdev_dev); transport_remove_device(dev); scsi_dh_remove_device(sdev); - device_del(dev); - } else - put_device(&sdev->sdev_dev); + } /* * Stop accepting new requests and wait until all queuecommand() and @@ -1097,6 +1095,16 @@ void __scsi_remove_device(struct scsi_device *sdev) blk_cleanup_queue(sdev->request_queue); cancel_work_sync(&sdev->requeue_work); + /* + * Remove the device after blk_cleanup_queue() has been called such + * a possible bdi_register() call with the same name occurs after + * blk_cleanup_queue() has called bdi_destroy(). + */ + if (sdev->is_visible) + device_del(dev); + else + put_device(&sdev->sdev_dev); + if (sdev->host->hostt->slave_destroy) sdev->host->hostt->slave_destroy(sdev); transport_destroy_device(dev); -- cgit v1.2.3 From 5cb9b40d6127fed91b00abe44498f19f6ed6a77f Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter Date: Mon, 26 Oct 2015 15:54:23 +0100 Subject: scsi_sysfs: Fix queue_ramp_up_period return code Writing a number to /sys/bus/scsi/devices//queue_ramp_up_period returns the value of that number instead of the number of bytes written. This behavior can confuse programs expecting POSIX write() semantics. Fix this by returning the number of bytes written instead. Signed-off-by: Peter Oberparleiter Reviewed-by: Hannes Reinecke Reviewed-by: Ewan D. Milne Signed-off-by: James Bottomley --- drivers/scsi/scsi_sysfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi/scsi_sysfs.c') diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 0efc21d271b4..db8b21b14117 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -898,7 +898,7 @@ sdev_store_queue_ramp_up_period(struct device *dev, return -EINVAL; sdev->queue_ramp_up_period = msecs_to_jiffies(period); - return period; + return count; } static DEVICE_ATTR(queue_ramp_up_period, S_IRUGO | S_IWUSR, -- cgit v1.2.3