diff options
author | Neil Brown <neilb@suse.de> | 2005-09-01 23:13:54 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.(none)> | 2005-09-09 11:29:22 -0400 |
commit | 286f3e13a1dc7f32407629fbd7aabc8ea78c62b5 (patch) | |
tree | 2ccc7b80111e1aac738ac67528ea3d53ac54ff0a /drivers | |
parent | 903f4fed858a7b56b260cbd55d174fe54d188fb7 (diff) |
[SCSI] fix possible deadlock in scsi_lib.c
If a filesystem, while writing out data, decides that it is good
to issue a cache flush on a SCSI drive (or other 'sd' device), it will
call blkdev_issue_flush which calls ->issue_flush_fn which is
scsi_issue_flush_fn.
This calls sd_issue_flush which calls sd_sync_cache, which calls
scsi_execute_request.
This will (as sshdr != NULL) call
kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL)
If memory is tight, the presence of GFP_KERNEL may cause write
requests to be sent to some filesystem to free up memory, however if
that filesystem is waiting for the issue_flush_fn to complete, you
could get a deadlock.
I wonder if it might be more appropriate to use GFP_NOIO as in the
following patch.
I wonder if it might be even more appropriate to cope better with a
kmalloc failure, especially as in this use, sd_sync_cache only will
use the sense information to print out a more informative error
message.
Signed-off-by: Neil Brown <neilb@suse.de>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/scsi_lib.c | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 77f2d444f7e0..2ad60f1dbc63 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c | |||
@@ -339,7 +339,7 @@ int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd, | |||
339 | int result; | 339 | int result; |
340 | 340 | ||
341 | if (sshdr) { | 341 | if (sshdr) { |
342 | sense = kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL); | 342 | sense = kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_NOIO); |
343 | if (!sense) | 343 | if (!sense) |
344 | return DRIVER_ERROR << 24; | 344 | return DRIVER_ERROR << 24; |
345 | memset(sense, 0, SCSI_SENSE_BUFFERSIZE); | 345 | memset(sense, 0, SCSI_SENSE_BUFFERSIZE); |