From: Mike Christie <[email protected]>

bc core and the rbd backend driver want seperate scatterlists
for the write phase of COMPARE_AND_WRITE. This moves the sbc
code to a helper function.

Signed-off-by: Mike Christie <[email protected]>
---
 drivers/target/target_core_sbc.c     | 73 ++++++++++++++++++++++++------------
 include/target/target_core_backend.h |  1 +
 2 files changed, 49 insertions(+), 25 deletions(-)

diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c
index 9a001e6..f803068 100644
--- a/drivers/target/target_core_sbc.c
+++ b/drivers/target/target_core_sbc.c
@@ -428,12 +428,58 @@ static sense_reason_t compare_and_write_post(struct 
se_cmd *cmd, bool success)
        return TCM_NO_SENSE;
 }
 
+/**
+ * sbc_create_compare_and_write_sg - alloc and prep a sg for the write phase
+ * @cmd: se_cmd to copy scatterlist from.
+ *
+ * Takes the cmd's scatterlist and creates a new sg with only the write
+ * portion.
+*/
+struct scatterlist *sbc_create_compare_and_write_sg(struct se_cmd *cmd)
+{
+       struct se_device *dev = cmd->se_dev;
+       unsigned int block_size = dev->dev_attrib.block_size;
+       unsigned int len = cmd->t_task_nolb * block_size;
+       struct scatterlist *write_sg;
+       struct sg_mapping_iter m;
+       int i = 0;
+
+       write_sg = kmalloc(sizeof(struct scatterlist) * cmd->t_data_nents,
+                          GFP_KERNEL);
+       if (!write_sg) {
+               pr_err("Unable to allocate compare_and_write sg\n");
+               return NULL;
+       }
+       sg_init_table(write_sg, cmd->t_data_nents);
+
+       sg_miter_start(&m, cmd->t_data_sg, cmd->t_data_nents, SG_MITER_TO_SG);
+       /*
+        * Currently assumes NoLB=1 and SGLs are PAGE_SIZE..
+        */
+       while (len) {
+               sg_miter_next(&m);
+
+               if (block_size < PAGE_SIZE) {
+                       sg_set_page(&write_sg[i], m.page, block_size,
+                                   block_size);
+               } else {
+                       sg_miter_next(&m);
+                       sg_set_page(&write_sg[i], m.page, block_size, 0);
+               }
+               len -= block_size;
+               i++;
+       }
+       sg_miter_stop(&m);
+
+       return write_sg;
+}
+EXPORT_SYMBOL(sbc_create_compare_and_write_sg);
+
 static sense_reason_t compare_and_write_callback(struct se_cmd *cmd, bool 
success)
 {
        struct se_device *dev = cmd->se_dev;
        struct scatterlist *write_sg = NULL, *sg;
        unsigned char *buf = NULL, *addr;
-       struct sg_mapping_iter m;
        unsigned int offset = 0, len;
        unsigned int nlbas = cmd->t_task_nolb;
        unsigned int block_size = dev->dev_attrib.block_size;
@@ -469,14 +515,12 @@ static sense_reason_t compare_and_write_callback(struct 
se_cmd *cmd, bool succes
                goto out;
        }
 
-       write_sg = kmalloc(sizeof(struct scatterlist) * cmd->t_data_nents,
-                          GFP_KERNEL);
+       write_sg = sbc_create_compare_and_write_sg(cmd);
        if (!write_sg) {
                pr_err("Unable to allocate compare_and_write sg\n");
                ret = TCM_OUT_OF_RESOURCES;
                goto out;
        }
-       sg_init_table(write_sg, cmd->t_data_nents);
        /*
         * Setup verify and write data payloads from total NumberLBAs.
         */
@@ -513,27 +557,6 @@ static sense_reason_t compare_and_write_callback(struct 
se_cmd *cmd, bool succes
                        break;
        }
 
-       i = 0;
-       len = cmd->t_task_nolb * block_size;
-       sg_miter_start(&m, cmd->t_data_sg, cmd->t_data_nents, SG_MITER_TO_SG);
-       /*
-        * Currently assumes NoLB=1 and SGLs are PAGE_SIZE..
-        */
-       while (len) {
-               sg_miter_next(&m);
-
-               if (block_size < PAGE_SIZE) {
-                       sg_set_page(&write_sg[i], m.page, block_size,
-                                   block_size);
-               } else {
-                       sg_miter_next(&m);
-                       sg_set_page(&write_sg[i], m.page, block_size,
-                                   0);
-               }
-               len -= block_size;
-               i++;
-       }
-       sg_miter_stop(&m);
        /*
         * Save the original SGL + nents values before updating to new
         * assignments, to be released in transport_free_pages() ->
diff --git a/include/target/target_core_backend.h 
b/include/target/target_core_backend.h
index c98f6e6..d8895e2 100644
--- a/include/target/target_core_backend.h
+++ b/include/target/target_core_backend.h
@@ -61,6 +61,7 @@ void  target_complete_cmd(struct se_cmd *, u8);
 void   target_complete_cmd_with_sense(struct se_cmd *, sense_reason_t);
 void   target_complete_cmd_with_length(struct se_cmd *, u8, int);
 
+struct scatterlist *sbc_create_compare_and_write_sg(struct se_cmd *);
 sense_reason_t spc_parse_cdb(struct se_cmd *cmd, unsigned int *size);
 sense_reason_t spc_emulate_report_luns(struct se_cmd *cmd);
 sense_reason_t spc_emulate_inquiry_std(struct se_cmd *, unsigned char *);
-- 
1.8.3.1

--
To unsubscribe from this list: send the line "unsubscribe ceph-devel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to