target: enhance and export target_alloc_sgl/target_free_sgl
authorChristoph Hellwig <hch@lst.de>
Tue, 3 May 2016 16:01:10 +0000 (18:01 +0200)
committerDoug Ledford <dledford@redhat.com>
Fri, 13 May 2016 17:37:19 +0000 (13:37 -0400)
The SRP target driver will need to allocate and chain it's own SGLs soon.
For this export target_alloc_sgl, and add a new argument to it so that it
can allocate an additional chain entry that doesn't point to a page.  Also
export transport_free_sgl after renaming it to target_free_sgl to free
these SGLs again.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Bart Van Assche <bart.vanassche@sandisk.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
drivers/target/target_core_transport.c
drivers/target/target_core_xcopy.c
include/target/target_core_backend.h
include/target/target_core_fabric.h

index ab2bf12975e1386f51fbd4c94b7d0a79002b7af7..590384a2bf8ba2f6aa99aecdcdfd3ab5ef39534e 100644 (file)
@@ -2195,7 +2195,7 @@ queue_full:
        transport_handle_queue_full(cmd, cmd->se_dev);
 }
 
-static inline void transport_free_sgl(struct scatterlist *sgl, int nents)
+void target_free_sgl(struct scatterlist *sgl, int nents)
 {
        struct scatterlist *sg;
        int count;
@@ -2205,6 +2205,7 @@ static inline void transport_free_sgl(struct scatterlist *sgl, int nents)
 
        kfree(sgl);
 }
+EXPORT_SYMBOL(target_free_sgl);
 
 static inline void transport_reset_sgl_orig(struct se_cmd *cmd)
 {
@@ -2225,7 +2226,7 @@ static inline void transport_reset_sgl_orig(struct se_cmd *cmd)
 static inline void transport_free_pages(struct se_cmd *cmd)
 {
        if (!(cmd->se_cmd_flags & SCF_PASSTHROUGH_PROT_SG_TO_MEM_NOALLOC)) {
-               transport_free_sgl(cmd->t_prot_sg, cmd->t_prot_nents);
+               target_free_sgl(cmd->t_prot_sg, cmd->t_prot_nents);
                cmd->t_prot_sg = NULL;
                cmd->t_prot_nents = 0;
        }
@@ -2236,7 +2237,7 @@ static inline void transport_free_pages(struct se_cmd *cmd)
                 * SG_TO_MEM_NOALLOC to function with COMPARE_AND_WRITE
                 */
                if (cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE) {
-                       transport_free_sgl(cmd->t_bidi_data_sg,
+                       target_free_sgl(cmd->t_bidi_data_sg,
                                           cmd->t_bidi_data_nents);
                        cmd->t_bidi_data_sg = NULL;
                        cmd->t_bidi_data_nents = 0;
@@ -2246,11 +2247,11 @@ static inline void transport_free_pages(struct se_cmd *cmd)
        }
        transport_reset_sgl_orig(cmd);
 
-       transport_free_sgl(cmd->t_data_sg, cmd->t_data_nents);
+       target_free_sgl(cmd->t_data_sg, cmd->t_data_nents);
        cmd->t_data_sg = NULL;
        cmd->t_data_nents = 0;
 
-       transport_free_sgl(cmd->t_bidi_data_sg, cmd->t_bidi_data_nents);
+       target_free_sgl(cmd->t_bidi_data_sg, cmd->t_bidi_data_nents);
        cmd->t_bidi_data_sg = NULL;
        cmd->t_bidi_data_nents = 0;
 }
@@ -2324,20 +2325,22 @@ EXPORT_SYMBOL(transport_kunmap_data_sg);
 
 int
 target_alloc_sgl(struct scatterlist **sgl, unsigned int *nents, u32 length,
-                bool zero_page)
+                bool zero_page, bool chainable)
 {
        struct scatterlist *sg;
        struct page *page;
        gfp_t zero_flag = (zero_page) ? __GFP_ZERO : 0;
-       unsigned int nent;
+       unsigned int nalloc, nent;
        int i = 0;
 
-       nent = DIV_ROUND_UP(length, PAGE_SIZE);
-       sg = kmalloc(sizeof(struct scatterlist) * nent, GFP_KERNEL);
+       nalloc = nent = DIV_ROUND_UP(length, PAGE_SIZE);
+       if (chainable)
+               nalloc++;
+       sg = kmalloc_array(nalloc, sizeof(struct scatterlist), GFP_KERNEL);
        if (!sg)
                return -ENOMEM;
 
-       sg_init_table(sg, nent);
+       sg_init_table(sg, nalloc);
 
        while (length) {
                u32 page_len = min_t(u32, length, PAGE_SIZE);
@@ -2361,6 +2364,7 @@ out:
        kfree(sg);
        return -ENOMEM;
 }
+EXPORT_SYMBOL(target_alloc_sgl);
 
 /*
  * Allocate any required resources to execute the command.  For writes we
@@ -2376,7 +2380,7 @@ transport_generic_new_cmd(struct se_cmd *cmd)
        if (cmd->prot_op != TARGET_PROT_NORMAL &&
            !(cmd->se_cmd_flags & SCF_PASSTHROUGH_PROT_SG_TO_MEM_NOALLOC)) {
                ret = target_alloc_sgl(&cmd->t_prot_sg, &cmd->t_prot_nents,
-                                      cmd->prot_length, true);
+                                      cmd->prot_length, true, false);
                if (ret < 0)
                        return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
        }
@@ -2401,13 +2405,13 @@ transport_generic_new_cmd(struct se_cmd *cmd)
 
                        ret = target_alloc_sgl(&cmd->t_bidi_data_sg,
                                               &cmd->t_bidi_data_nents,
-                                              bidi_length, zero_flag);
+                                              bidi_length, zero_flag, false);
                        if (ret < 0)
                                return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
                }
 
                ret = target_alloc_sgl(&cmd->t_data_sg, &cmd->t_data_nents,
-                                      cmd->data_length, zero_flag);
+                                      cmd->data_length, zero_flag, false);
                if (ret < 0)
                        return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
        } else if ((cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE) &&
@@ -2421,7 +2425,7 @@ transport_generic_new_cmd(struct se_cmd *cmd)
 
                ret = target_alloc_sgl(&cmd->t_bidi_data_sg,
                                       &cmd->t_bidi_data_nents,
-                                      caw_length, zero_flag);
+                                      caw_length, zero_flag, false);
                if (ret < 0)
                        return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
        }
index 47fe94ee10b82d876fedef726308738dc62f5805..75cd85426ae3a27f276947f667794acb7c9454d0 100644 (file)
@@ -563,7 +563,7 @@ static int target_xcopy_setup_pt_cmd(
 
        if (alloc_mem) {
                rc = target_alloc_sgl(&cmd->t_data_sg, &cmd->t_data_nents,
-                                     cmd->data_length, false);
+                                     cmd->data_length, false, false);
                if (rc < 0) {
                        ret = rc;
                        goto out;
index 28ee5c2e6bcd7b08abeda34669cc2da17f4dcf9a..d8ab5101fad5533876339f788b75d855d382bc4f 100644 (file)
@@ -85,7 +85,6 @@ extern struct configfs_attribute *passthrough_attrib_attrs[];
 void   *transport_kmap_data_sg(struct se_cmd *);
 void   transport_kunmap_data_sg(struct se_cmd *);
 /* core helpers also used by xcopy during internal command setup */
-int    target_alloc_sgl(struct scatterlist **, unsigned int *, u32, bool);
 sense_reason_t transport_generic_map_mem_to_cmd(struct se_cmd *,
                struct scatterlist *, u32, struct scatterlist *, u32);
 
index 8ff6d40a294fd5a1fcbd8f10d0139d289c00d741..78d88f03b2960b4655d44dfeb575f61d7ba9cf07 100644 (file)
@@ -185,6 +185,10 @@ int        core_tpg_set_initiator_node_tag(struct se_portal_group *,
 int    core_tpg_register(struct se_wwn *, struct se_portal_group *, int);
 int    core_tpg_deregister(struct se_portal_group *);
 
+int    target_alloc_sgl(struct scatterlist **sgl, unsigned int *nents,
+               u32 length, bool zero_page, bool chainable);
+void   target_free_sgl(struct scatterlist *sgl, int nents);
+
 /*
  * The LIO target core uses DMA_TO_DEVICE to mean that data is going
  * to the target (eg handling a WRITE) and DMA_FROM_DEVICE to mean