]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
target: Add transport_reset_sgl_orig() for COMPARE_AND_WRITE
authorNicholas Bellinger <nab@daterainc.com>
Tue, 20 Aug 2013 17:45:16 +0000 (10:45 -0700)
committerNicholas Bellinger <nab@linux-iscsi.org>
Mon, 9 Sep 2013 21:29:33 +0000 (14:29 -0700)
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 <hch@lst.de>
Cc: Hannes Reinecke <hare@suse.de>
Cc: Martin Petersen <martin.petersen@oracle.com>
Cc: Chris Mason <chris.mason@fusionio.com>
Cc: James Bottomley <JBottomley@Parallels.com>
Cc: Nicholas Bellinger <nab@linux-iscsi.org>
Signed-off-by: Nicholas Bellinger <nab@daterainc.com>
drivers/target/target_core_transport.c
include/target/target_core_base.h

index c974e1373c77275ac34b42289f30a7a9a869a145..87d64add7874337eaf80cd117e7ccd0a29ed2b00 100644 (file)
@@ -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;
index 4a26a18a24d662c4720cc1dc9532668659c0fc61..7fdb3fae2961b6c08b226b934a52f0a576b6fcce 100644 (file)
@@ -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;