Commit 7c72ce81 authored by Alan Stern's avatar Alan Stern Committed by James Bottomley

[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: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent d16794f6
...@@ -97,7 +97,6 @@ int scsi_insert_special_req(struct scsi_request *sreq, int at_head) ...@@ -97,7 +97,6 @@ int scsi_insert_special_req(struct scsi_request *sreq, int at_head)
} }
static void scsi_run_queue(struct request_queue *q); static void scsi_run_queue(struct request_queue *q);
static void scsi_release_buffers(struct scsi_cmnd *cmd);
/* /*
* Function: scsi_unprep_request() * Function: scsi_unprep_request()
...@@ -1040,8 +1039,10 @@ static int scsi_init_io(struct scsi_cmnd *cmd) ...@@ -1040,8 +1039,10 @@ static int scsi_init_io(struct scsi_cmnd *cmd)
* if sg table allocation fails, requeue request later. * if sg table allocation fails, requeue request later.
*/ */
sgpnt = scsi_alloc_sgtable(cmd, GFP_ATOMIC); sgpnt = scsi_alloc_sgtable(cmd, GFP_ATOMIC);
if (unlikely(!sgpnt)) if (unlikely(!sgpnt)) {
scsi_unprep_request(req);
return BLKPREP_DEFER; return BLKPREP_DEFER;
}
cmd->request_buffer = (char *) sgpnt; cmd->request_buffer = (char *) sgpnt;
cmd->request_bufflen = req->nr_sectors << 9; cmd->request_bufflen = req->nr_sectors << 9;
...@@ -1245,8 +1246,8 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req) ...@@ -1245,8 +1246,8 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req)
*/ */
ret = scsi_init_io(cmd); ret = scsi_init_io(cmd);
switch(ret) { switch(ret) {
/* For BLKPREP_KILL/DEFER the cmd was released */
case BLKPREP_KILL: case BLKPREP_KILL:
/* BLKPREP_KILL return also releases the command */
goto kill; goto kill;
case BLKPREP_DEFER: case BLKPREP_DEFER:
goto defer; goto defer;
......
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