From 47e459e622f07c2564e6be8412d75389d2a807b8 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Tue, 20 Aug 2013 10:45:16 -0700 Subject: target: Add transport_reset_sgl_orig() for COMPARE_AND_WRITE After COMPARE_AND_WRITE completes it's comparision, the WRITE payload SGLs head expect to be updated to point from the verify instance of user data, to the write instance of user data. So for this special case, add transport_reset_sgl_orig() usage within transport_free_pages() and add se_cmd->t_data_[sg,nents]_orig members to save the original assignments. Cc: Christoph Hellwig Cc: Hannes Reinecke Cc: Martin Petersen Cc: Chris Mason Cc: James Bottomley Cc: Nicholas Bellinger Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_transport.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) (limited to 'drivers/target/target_core_transport.c') 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; -- cgit v1.2.3