diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2005-10-14 11:23:27 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.(none)> | 2005-10-16 16:35:11 -0400 |
commit | 7c72ce81870ded9365f4bc5caa98ef1591dd18dd (patch) | |
tree | ff1eae57d11693f7e2d36efd3fdc26efa45e1419 /drivers/scsi | |
parent | d16794f6ac8d9b50f62e02a6e6175ae1a30d0ccd (diff) |
[SCSI] Fix leak of Scsi_Cmnds
When a request is deferred in scsi_init_io because the sg table could not
be allocated, the associated scsi_cmnd is not released and the request is
not marked with REQ_DONTPREP. When the command is retried, if
scsi_prep_fn decides to kill it then the scsi_cmnd will never be released.
This patch (as573) changes scsi_init_io so that it calls scsi_put_command
before deferring a request.
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/scsi_lib.c | 7 |
1 files changed, 4 insertions, 3 deletions
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index dc9c772bc874..0074f28c37b2 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c | |||
@@ -97,7 +97,6 @@ int scsi_insert_special_req(struct scsi_request *sreq, int at_head) | |||
97 | } | 97 | } |
98 | 98 | ||
99 | static void scsi_run_queue(struct request_queue *q); | 99 | static void scsi_run_queue(struct request_queue *q); |
100 | static void scsi_release_buffers(struct scsi_cmnd *cmd); | ||
101 | 100 | ||
102 | /* | 101 | /* |
103 | * Function: scsi_unprep_request() | 102 | * Function: scsi_unprep_request() |
@@ -1040,8 +1039,10 @@ static int scsi_init_io(struct scsi_cmnd *cmd) | |||
1040 | * if sg table allocation fails, requeue request later. | 1039 | * if sg table allocation fails, requeue request later. |
1041 | */ | 1040 | */ |
1042 | sgpnt = scsi_alloc_sgtable(cmd, GFP_ATOMIC); | 1041 | sgpnt = scsi_alloc_sgtable(cmd, GFP_ATOMIC); |
1043 | if (unlikely(!sgpnt)) | 1042 | if (unlikely(!sgpnt)) { |
1043 | scsi_unprep_request(req); | ||
1044 | return BLKPREP_DEFER; | 1044 | return BLKPREP_DEFER; |
1045 | } | ||
1045 | 1046 | ||
1046 | cmd->request_buffer = (char *) sgpnt; | 1047 | cmd->request_buffer = (char *) sgpnt; |
1047 | cmd->request_bufflen = req->nr_sectors << 9; | 1048 | cmd->request_bufflen = req->nr_sectors << 9; |
@@ -1245,8 +1246,8 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req) | |||
1245 | */ | 1246 | */ |
1246 | ret = scsi_init_io(cmd); | 1247 | ret = scsi_init_io(cmd); |
1247 | switch(ret) { | 1248 | switch(ret) { |
1249 | /* For BLKPREP_KILL/DEFER the cmd was released */ | ||
1248 | case BLKPREP_KILL: | 1250 | case BLKPREP_KILL: |
1249 | /* BLKPREP_KILL return also releases the command */ | ||
1250 | goto kill; | 1251 | goto kill; |
1251 | case BLKPREP_DEFER: | 1252 | case BLKPREP_DEFER: |
1252 | goto defer; | 1253 | goto defer; |