Commit a817e73f authored by Linus Torvalds's avatar Linus Torvalds

Revert "scsi: make 'state' device attribute pollable"

This reverts commit 8a97712e.

This commit added a call to sysfs_notify() from within
scsi_device_set_state(), which in turn turns out to make libata very
unhappy, because ata_eh_detach_dev() does

        spin_lock_irqsave(ap->lock, flags);
        ..
        if (ata_scsi_offline_dev(dev)) {
                dev->flags |= ATA_DFLAG_DETACHED;
                ap->pflags |= ATA_PFLAG_SCSI_HOTPLUG;
        }

and ata_scsi_offline_dev() then does that scsi_device_set_state() to set
it offline.

So now we called sysfs_notify() from within a spinlocked region, which
really doesn't work.  The 0day robot reported this as:

   BUG: sleeping function called from invalid context at kernel/locking/mutex.c:238

because sysfs_notify() ends up calling kernfs_find_and_get_ns() which
then does mutex_lock(&kernfs_mutex)..

The pollability of the device state isn't critical, so revert this all
for now, and maybe we'll do it differently in the future.
Reported-by: default avatarFengguang Wu <fengguang.wu@intel.com>
Acked-by: default avatarTejun Heo <tj@kernel.org>
Acked-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
Acked-by: default avatarHannes Reinecke <hare@suse.de>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent e4880bc5
...@@ -2685,7 +2685,6 @@ scsi_device_set_state(struct scsi_device *sdev, enum scsi_device_state state) ...@@ -2685,7 +2685,6 @@ scsi_device_set_state(struct scsi_device *sdev, enum scsi_device_state state)
} }
sdev->sdev_state = state; sdev->sdev_state = state;
sysfs_notify(&sdev->sdev_gendev.kobj, NULL, "state");
return 0; return 0;
illegal: illegal:
...@@ -3109,7 +3108,6 @@ int scsi_internal_device_unblock_nowait(struct scsi_device *sdev, ...@@ -3109,7 +3108,6 @@ int scsi_internal_device_unblock_nowait(struct scsi_device *sdev,
case SDEV_BLOCK: case SDEV_BLOCK:
case SDEV_TRANSPORT_OFFLINE: case SDEV_TRANSPORT_OFFLINE:
sdev->sdev_state = new_state; sdev->sdev_state = new_state;
sysfs_notify(&sdev->sdev_gendev.kobj, NULL, "state");
break; break;
case SDEV_CREATED_BLOCK: case SDEV_CREATED_BLOCK:
if (new_state == SDEV_TRANSPORT_OFFLINE || if (new_state == SDEV_TRANSPORT_OFFLINE ||
...@@ -3117,7 +3115,6 @@ int scsi_internal_device_unblock_nowait(struct scsi_device *sdev, ...@@ -3117,7 +3115,6 @@ int scsi_internal_device_unblock_nowait(struct scsi_device *sdev,
sdev->sdev_state = new_state; sdev->sdev_state = new_state;
else else
sdev->sdev_state = SDEV_CREATED; sdev->sdev_state = SDEV_CREATED;
sysfs_notify(&sdev->sdev_gendev.kobj, NULL, "state");
break; break;
case SDEV_CANCEL: case SDEV_CANCEL:
case SDEV_OFFLINE: case SDEV_OFFLINE:
......
...@@ -556,11 +556,8 @@ int srp_reconnect_rport(struct srp_rport *rport) ...@@ -556,11 +556,8 @@ int srp_reconnect_rport(struct srp_rport *rport)
*/ */
shost_for_each_device(sdev, shost) { shost_for_each_device(sdev, shost) {
mutex_lock(&sdev->state_mutex); mutex_lock(&sdev->state_mutex);
if (sdev->sdev_state == SDEV_OFFLINE) { if (sdev->sdev_state == SDEV_OFFLINE)
sdev->sdev_state = SDEV_RUNNING; sdev->sdev_state = SDEV_RUNNING;
sysfs_notify(&sdev->sdev_gendev.kobj,
NULL, "state");
}
mutex_unlock(&sdev->state_mutex); mutex_unlock(&sdev->state_mutex);
} }
} else if (rport->state == SRP_RPORT_RUNNING) { } else if (rport->state == SRP_RPORT_RUNNING) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment