summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/target/target_core_transport.c21
-rw-r--r--include/target/target_core_base.h2
2 files changed, 22 insertions, 1 deletions
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index c974e1373c77..87d64add7874 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -1991,10 +1991,29 @@ static inline void transport_free_sgl(struct scatterlist *sgl, int nents)
kfree(sgl);
}
+static inline void transport_reset_sgl_orig(struct se_cmd *cmd)
+{
+ /*
+ * Check for saved t_data_sg that may be used for COMPARE_AND_WRITE
+ * emulation, and free + reset pointers if necessary..
+ */
+ if (!cmd->t_data_sg_orig)
+ return;
+
+ kfree(cmd->t_data_sg);
+ cmd->t_data_sg = cmd->t_data_sg_orig;
+ cmd->t_data_sg_orig = NULL;
+ cmd->t_data_nents = cmd->t_data_nents_orig;
+ cmd->t_data_nents_orig = 0;
+}
+
static inline void transport_free_pages(struct se_cmd *cmd)
{
- if (cmd->se_cmd_flags & SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC)
+ if (cmd->se_cmd_flags & SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC) {
+ transport_reset_sgl_orig(cmd);
return;
+ }
+ transport_reset_sgl_orig(cmd);
transport_free_sgl(cmd->t_data_sg, cmd->t_data_nents);
cmd->t_data_sg = NULL;
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
index 4a26a18a24d6..7fdb3fae2961 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -478,7 +478,9 @@ struct se_cmd {
struct work_struct work;
struct scatterlist *t_data_sg;
+ struct scatterlist *t_data_sg_orig;
unsigned int t_data_nents;
+ unsigned int t_data_nents_orig;
void *t_data_vmap;
struct scatterlist *t_bidi_data_sg;
unsigned int t_bidi_data_nents;