From 4c961dc45bb5d35cdefa8f0f94ebd8453a9d6cc4 Mon Sep 17 00:00:00 2001
From: Bart Van Assche <bart.vanassche@sandisk.com>
Date: Wed, 10 May 2017 15:01:38 -0700
Subject: [PATCH 5/5] target/tcm_loop: Make TMF processing slightly faster
Target drivers must guarantee that struct se_cmd and struct se_tmr_req
exist as long as target_tmr_work() is in progress. This is why the
tcm_loop driver today passes 1 as second argument to
transport_generic_free_cmd() from inside the TMF code. Instead of
making the TMF code wait, make the TMF code obtain two references
(SCF_ACK_KREF) and drop one reference from inside the .check_stop_free()
callback.
Signed-off-by: Bart Van Assche <bart.vanassche@sandisk.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Hannes Reinecke <hare@suse.com>
Cc: David Disseldorp <ddiss@suse.de>
---
drivers/target/loopback/tcm_loop.c | 27 +++++++++++----------------
1 file changed, 11 insertions(+), 16 deletions(-)
@@ -51,27 +51,18 @@ static int tcm_loop_queue_status(struct se_cmd *se_cmd);
*/
static int tcm_loop_check_stop_free(struct se_cmd *se_cmd)
{
- /*
- * Do not release struct se_cmd's containing a valid TMR
- * pointer. These will be released directly in tcm_loop_device_reset()
- * with transport_generic_free_cmd().
- */
- if (se_cmd->se_cmd_flags & SCF_SCSI_TMR_CDB)
- return 0;
- /*
- * Release the struct se_cmd, which will make a callback to release
- * struct tcm_loop_cmd * in tcm_loop_deallocate_core_cmd()
- */
- transport_generic_free_cmd(se_cmd, 0);
- return 1;
+ return transport_generic_free_cmd(se_cmd, 0);
}
static void tcm_loop_release_cmd(struct se_cmd *se_cmd)
{
struct tcm_loop_cmd *tl_cmd = container_of(se_cmd,
struct tcm_loop_cmd, tl_se_cmd);
+ struct se_tmr_req *se_tmr = se_cmd->se_tmr_req;
+ struct tcm_loop_tmr *tl_tmr = se_tmr ? se_tmr->fabric_tmr_ptr : NULL;
kmem_cache_free(tcm_loop_cmd_cache, tl_cmd);
+ kfree(tl_tmr);
}
static int tcm_loop_show_info(struct seq_file *m, struct Scsi_Host *host)
@@ -251,19 +242,23 @@ static int tcm_loop_issue_tmr(struct tcm_loop_tpg *tl_tpg,
rc = target_submit_tmr(se_cmd, se_sess, NULL, 0 /* unpacked_lun */,
tl_tmr, tmr, GFP_KERNEL, TCM_SIMPLE_TAG,
- 0 /*flags*/);
+ TARGET_SCF_ACK_KREF);
if (rc < 0)
goto release;
wait_for_completion(&tl_tmr->done);
ret = se_cmd->se_tmr_req->response;
+ target_put_sess_cmd(se_cmd);
+
+out:
+ return ret;
release:
if (se_cmd)
- transport_generic_free_cmd(se_cmd, 1);
+ transport_generic_free_cmd(se_cmd, 0);
else
kmem_cache_free(tcm_loop_cmd_cache, tl_cmd);
kfree(tl_tmr);
- return ret;
+ goto out;
}
static int tcm_loop_abort_task(struct scsi_cmnd *sc)
--
2.12.2