Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

This reverts commit 8a97712e5314aefe16b3ffb4583a34deaa49de04.

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: Fengguang Wu <fengguang.wu@intel.com>
Acked-by: Tejun Heo <tj@kernel.org>
Acked-by: Martin K. Petersen <martin.petersen@oracle.com>
Acked-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

+1 -7
-3
drivers/scsi/scsi_lib.c
··· 2685 2685 2686 2686 } 2687 2687 sdev->sdev_state = state; 2688 - sysfs_notify(&sdev->sdev_gendev.kobj, NULL, "state"); 2689 2688 return 0; 2690 2689 2691 2690 illegal: ··· 3108 3109 case SDEV_BLOCK: 3109 3110 case SDEV_TRANSPORT_OFFLINE: 3110 3111 sdev->sdev_state = new_state; 3111 - sysfs_notify(&sdev->sdev_gendev.kobj, NULL, "state"); 3112 3112 break; 3113 3113 case SDEV_CREATED_BLOCK: 3114 3114 if (new_state == SDEV_TRANSPORT_OFFLINE || ··· 3115 3117 sdev->sdev_state = new_state; 3116 3118 else 3117 3119 sdev->sdev_state = SDEV_CREATED; 3118 - sysfs_notify(&sdev->sdev_gendev.kobj, NULL, "state"); 3119 3120 break; 3120 3121 case SDEV_CANCEL: 3121 3122 case SDEV_OFFLINE:
+1 -4
drivers/scsi/scsi_transport_srp.c
··· 556 556 */ 557 557 shost_for_each_device(sdev, shost) { 558 558 mutex_lock(&sdev->state_mutex); 559 - if (sdev->sdev_state == SDEV_OFFLINE) { 559 + if (sdev->sdev_state == SDEV_OFFLINE) 560 560 sdev->sdev_state = SDEV_RUNNING; 561 - sysfs_notify(&sdev->sdev_gendev.kobj, 562 - NULL, "state"); 563 - } 564 561 mutex_unlock(&sdev->state_mutex); 565 562 } 566 563 } else if (rport->state == SRP_RPORT_RUNNING) {