提交 cff549e4 编写于 作者: C Christoph Hellwig 提交者: James Bottomley

scsi: proper state checking and module refcount handling in scsi_device_get

This effectively reverts commits 85b6c7 ("[SCSI] sd: fix cache flushing on
module removal (and individual device removal)" and dc4515ea ("scsi: always
increment reference count").

We now never call scsi_device_get from the shutdown path, and the fact
that we started grabbing reference there in commit 85b6c7 turned out
turned out to create more problems than it solves, and required
workarounds for workarounds for workarounds. Move back to properly checking
the device state and carefully handle module refcounting.
Signed-off-by: NChristoph Hellwig <hch@lst.de>
Reviewed-by: NPaolo Bonzini <pbonzini@redhat.com>
Reviewed-by: NHannes Reinecke <hare@suse.de>
Signed-off-by: NJames Bottomley <JBottomley@Parallels.com>
上级 3d9a1f53
...@@ -972,18 +972,24 @@ EXPORT_SYMBOL(scsi_report_opcode); ...@@ -972,18 +972,24 @@ EXPORT_SYMBOL(scsi_report_opcode);
* Description: Gets a reference to the scsi_device and increments the use count * Description: Gets a reference to the scsi_device and increments the use count
* of the underlying LLDD module. You must hold host_lock of the * of the underlying LLDD module. You must hold host_lock of the
* parent Scsi_Host or already have a reference when calling this. * parent Scsi_Host or already have a reference when calling this.
*
* This will fail if a device is deleted or cancelled, or when the LLD module
* is in the process of being unloaded.
*/ */
int scsi_device_get(struct scsi_device *sdev) int scsi_device_get(struct scsi_device *sdev)
{ {
if (sdev->sdev_state == SDEV_DEL) if (sdev->sdev_state == SDEV_DEL || sdev->sdev_state == SDEV_CANCEL)
return -ENXIO; goto fail;
if (!get_device(&sdev->sdev_gendev)) if (!get_device(&sdev->sdev_gendev))
return -ENXIO; goto fail;
/* We can fail try_module_get if we're doing SCSI operations if (!try_module_get(sdev->host->hostt->module))
* from module exit (like cache flush) */ goto fail_put_device;
__module_get(sdev->host->hostt->module);
return 0; return 0;
fail_put_device:
put_device(&sdev->sdev_gendev);
fail:
return -ENXIO;
} }
EXPORT_SYMBOL(scsi_device_get); EXPORT_SYMBOL(scsi_device_get);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册