scsi: explicitly release bidi buffers
PATCH 1/2 scsi: explicitly release bidi buffers
Instead of trying to guess when we have a BIDI buffer in scsi_release_buffers add a function to explicitly free the BIDI ressoures in the one place that handles them. This avoids needing a special __scsi_release_buffers for the case where we already have freed the request as well.
drivers/scsi/scsi_lib.c +20 -27
@@ -511,8 +511,6 @@ void scsi_run_host_queues(struct Scsi_Host *shost)scsi_run_queue (sdev->request_queue); } -static void __scsi_release_buffers (struct scsi_cmnd *,int ); -/* * Function: scsi_end_request() *
@@ -568,7 +566,7 @@ static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int error,* This will goose the queue request function at the end, so we don't * need to worry about launching another command. */ -__scsi_release_buffers (cmd,0 ); +scsi_release_buffers (cmd);scsi_next_command (cmd);return NULL ; }
@@ -624,30 +622,10 @@ static void scsi_free_sgtable(struct scsi_data_buffer *sdb)__sg_free_table (&sdb->table,SCSI_MAX_SG_SEGMENTS , scsi_sg_free); } -static void __scsi_release_buffers (struct scsi_cmnd *cmd,int do_bidi_check) -{ - -if (cmd->sdb.table.nents) -scsi_free_sgtable (&cmd->sdb); - -memset (&cmd->sdb,0 ,sizeof (cmd->sdb)); - -if (do_bidi_check &&scsi_bidi_cmnd (cmd)) { -struct scsi_data_buffer *bidi_sdb = - cmd->request->next_rq->special; -scsi_free_sgtable (bidi_sdb); -kmem_cache_free (scsi_sdb_cache, bidi_sdb); - cmd->request->next_rq->special =NULL ; - } - -if (scsi_prot_sg_count (cmd)) -scsi_free_sgtable (cmd->prot_sdb); -} -/* * Function: scsi_release_buffers() * -* Purpose: Completion processing for block device I/O requests. +* Purpose: Free resources allocate for a scsi_command. * * Arguments: cmd - command that we are bailing. *
@@ -658,15 +636,29 @@ static void __scsi_release_buffers(struct scsi_cmnd *cmd, int do_bidi_check)* Notes: In the event that an upper level driver rejects a * command, we must release resources allocated during * the __init_io() function. Primarily this would involve -* the scatter-gather table, and potentially any bounce -* buffers. +* the scatter-gather table. */ void scsi_release_buffers (struct scsi_cmnd *cmd) { -__scsi_release_buffers (cmd,1 ); +if (cmd->sdb.table.nents) +scsi_free_sgtable (&cmd->sdb); + +memset (&cmd->sdb,0 ,sizeof (cmd->sdb)); + +if (scsi_prot_sg_count (cmd)) +scsi_free_sgtable (cmd->prot_sdb); }EXPORT_SYMBOL (scsi_release_buffers); +static void scsi_release_bidi_buffers (struct scsi_cmnd *cmd) +{ +struct scsi_data_buffer *bidi_sdb = cmd->request->next_rq->special; + +scsi_free_sgtable (bidi_sdb); +kmem_cache_free (scsi_sdb_cache, bidi_sdb); + cmd->request->next_rq->special =NULL ; +} +/** * __scsi_error_from_host_byte - translate SCSI error code into errno * @cmd: SCSI command (unused)
@@ -799,6 +791,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) req->next_rq->resid_len =scsi_in (cmd)->resid;scsi_release_buffers (cmd); +scsi_release_bidi_buffers (cmd);blk_end_request_all (req,0 );scsi_next_command (cmd);
PATCH 2/2 scsi: remove scsi_end_request
By folding scsi_end_request into its only caller we can significantly clean up the completion logic. We can use simple goto labels now to only have a single place to finish or requeue command there instead of the previous convoluted logic.
drivers/scsi/scsi_lib.c +32 -82
@@ -511,66 +511,6 @@ void scsi_run_host_queues(struct Scsi_Host *shost)scsi_run_queue (sdev->request_queue); } -/* -* Function: scsi_end_request() -* -* Purpose: Post-processing of completed commands (usually invoked at end -* of upper level post-processing and scsi_io_completion). -* -* Arguments: cmd - command that is complete. -* error - 0 if I/O indicates success, < 0 for I/O error. -* bytes - number of bytes of completed I/O -* requeue - indicates whether we should requeue leftovers. -* -* Lock status: Assumed that lock is not held upon entry. -* -* Returns: cmd if requeue required, NULL otherwise. -* -* Notes: This is called for block device requests in order to -* mark some number of sectors as complete. -* -* We are guaranteeing that the request queue will be goosed -* at some point during this call. -* Notes: If cmd was requeued, upon return it will be a stale pointer. -*/ -static struct scsi_cmnd *scsi_end_request (struct scsi_cmnd *cmd,int error, -int bytes,int requeue) -{ -struct request_queue *q = cmd->device->request_queue; -struct request *req = cmd->request; - -/* -* If there are blocks left over at the end, set up the command -* to queue the remainder of them. -*/ -if (blk_end_request (req, error, bytes)) { -/* kill remainder if no retrys */ -if (error &&scsi_noretry_cmd (cmd)) -blk_end_request_all (req, error); -else { -if (requeue) { -/* -* Bleah. Leftovers again. Stick the -* leftovers in the front of the -* queue, and goose the queue again. -*/ -scsi_release_buffers (cmd); -scsi_requeue_command (q, cmd); - cmd =NULL ; - } -return cmd; - } - } - -/* -* This will goose the queue request function at the end, so we don't -* need to worry about launching another command. -*/ -scsi_release_buffers (cmd); -scsi_next_command (cmd); -return NULL ; -} -static inline unsigned int scsi_sgtable_index (unsigned short nents) {unsigned int index;
@@ -716,16 +656,9 @@ static int __scsi_error_from_host_byte(struct scsi_cmnd *cmd, int result)* * Returns: Nothing * -* Notes: This function is matched in terms of capabilities to -* the function that created the scatter-gather list. -* In other words, if there are no bounce buffers -* (the normal case for most drivers), we don't need -* the logic to deal with cleaning up afterwards. -* -* We must call scsi_end_request(). This will finish off -* the specified number of sectors. If we are done, the -* command block will be released and the queue function -* will be goosed. If we are not done then we have to +* Notes: We will finish off the specified number of sectors. If we +* are done, the command block will be released and the queue +* function will be goosed. If we are not done then we have to * figure out what to do next: * * a) We can call scsi_requeue_command(). The request
@@ -734,7 +667,7 @@ static int __scsi_error_from_host_byte(struct scsi_cmnd *cmd, int result)* be used if we made forward progress, or if we want * to switch from READ(10) to READ(6) for example. * -* b) We can call scsi_queue_insert(). The request will +* b) We can call __scsi_queue_insert(). The request will * be put back on the queue and retried using the same * command as before, possibly after a delay. *
@@ -792,6 +725,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)scsi_release_buffers (cmd);scsi_release_bidi_buffers (cmd); +blk_end_request_all (req,0 );scsi_next_command (cmd);
@@ -831,12 +765,25 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) }/* -* A number of bytes were successfully read. If there -* are leftovers and there is some kind of error -* (result != 0), retry the rest. +* If we finished all bytes in the request we are done now. */ -if (scsi_end_request (cmd, error, good_bytes, result ==0 ) ==NULL ) -return ; +if (!blk_end_request (req, error, good_bytes)) + goto next_command; + +/* +* Kill remainder if no retrys. +*/ +if (error &&scsi_noretry_cmd (cmd)) { +blk_end_request_all (req, error); + goto next_command; + } + +/* +* If there had been no error, but we have leftover bytes in the +* requeues just queue the command up again. +*/ +if (result ==0 ) + goto requeue; error =__scsi_error_from_host_byte (cmd, result);
@@ -958,7 +905,6 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)switch (action) {case ACTION_FAIL :/* Give up and fail the remainder of the request */ -scsi_release_buffers (cmd);if (!(req->cmd_flags &REQ_QUIET )) {if (description) scmd_printk(KERN_INFO, cmd, "%s\n",
@@ -968,12 +914,11 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)scsi_print_sense ("" , cmd);scsi_print_command (cmd); } -if (blk_end_request_err (req, error)) -scsi_requeue_command (q, cmd); -else -scsi_next_command (cmd); -break ; +if (!blk_end_request_err (req, error)) + goto next_command; +/*FALLTHRU*/ case ACTION_REPREP : + requeue:/* Unprep the request and put it back at the head of the queue. * A new command will be prepared and issued. */
@@ -989,6 +934,11 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)__scsi_queue_insert (cmd,SCSI_MLQUEUE_DEVICE_BUSY ,0 );break ; } +return ; + +next_command: +scsi_release_buffers (cmd); +scsi_next_command (cmd); } static int scsi_init_sgtable(struct request *req, struct scsi_data_buffer *sdb,
Now that LSF is done can I get anyone excited to review these?
Quoted 103 lines · Christoph Hellwig
Instead of trying to guess when we have a BIDI buffer in
scsi_release_buffersadd a function to explicitly free the BIDI ressoures in the one place that handles them. This avoids needing a special__scsi_release_buffersfor the case where we already have freed the request as well.Signed-off-by Christoph Hellwig <[email protected]>drivers/scsi/scsi_lib.c +20
-28@@ -511,8 +511,6 @@ void scsi_run_host_queues(struct Scsi_Host *shost)scsi_run_queue (sdev->request_queue); } -static void __scsi_release_buffers (struct scsi_cmnd *,int ); -/* * Function: scsi_end_request() * @@ -568,7 +566,7 @@ static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int error,* This will goose the queue request function at the end, so we don't * need to worry about launching another command. */ -__scsi_release_buffers (cmd,0 ); +scsi_release_buffers (cmd);scsi_next_command (cmd);return NULL ; }@@ -624,30 +622,10 @@ static void scsi_free_sgtable(struct scsi_data_buffer *sdb)__sg_free_table (&sdb->table,SCSI_MAX_SG_SEGMENTS , scsi_sg_free); } -static void __scsi_release_buffers (struct scsi_cmnd *cmd,int do_bidi_check) -{ - -if (cmd->sdb.table.nents) -scsi_free_sgtable (&cmd->sdb); - -memset (&cmd->sdb,0 ,sizeof (cmd->sdb)); - -if (do_bidi_check &&scsi_bidi_cmnd (cmd)) { -struct scsi_data_buffer *bidi_sdb = - cmd->request->next_rq->special; -scsi_free_sgtable (bidi_sdb); -kmem_cache_free (scsi_sdb_cache, bidi_sdb); - cmd->request->next_rq->special =NULL ; - } - -if (scsi_prot_sg_count (cmd)) -scsi_free_sgtable (cmd->prot_sdb); -} -/* * Function: scsi_release_buffers() * -* Purpose: Completion processing for block device I/O requests. +* Purpose: Free resources allocate for a scsi_command. * * Arguments: cmd - command that we are bailing. * @@ -658,15 +636,29 @@ static void __scsi_release_buffers(struct scsi_cmnd *cmd, int do_bidi_check)* Notes: In the event that an upper level driver rejects a * command, we must release resources allocated during * the __init_io() function. Primarily this would involve -* the scatter-gather table, and potentially any bounce -* buffers. +* the scatter-gather table. */ void scsi_release_buffers (struct scsi_cmnd *cmd) { -__scsi_release_buffers (cmd,1 ); +if (cmd->sdb.table.nents) +scsi_free_sgtable (&cmd->sdb); + +memset (&cmd->sdb,0 ,sizeof (cmd->sdb)); + +if (scsi_prot_sg_count (cmd)) +scsi_free_sgtable (cmd->prot_sdb); }EXPORT_SYMBOL (scsi_release_buffers); +static void scsi_release_bidi_buffers (struct scsi_cmnd *cmd) +{ +struct scsi_data_buffer *bidi_sdb = cmd->request->next_rq->special; + +scsi_free_sgtable (bidi_sdb); +kmem_cache_free (scsi_sdb_cache, bidi_sdb); + cmd->request->next_rq->special =NULL ; +} +/** * __scsi_error_from_host_byte - translate SCSI error code into errno * @cmd: SCSI command (unused) @@ -799,6 +791,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) req->next_rq->resid_len =scsi_in (cmd)->resid;scsi_release_buffers (cmd); +scsi_release_bidi_buffers (cmd);blk_end_request_all (req,0 );scsi_next_command (cmd); --
Quoted 3 lines
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
---end quoted text---