Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target...
[linux-2.6-block.git] / drivers / target / target_core_transport.c
index ab2bf12975e1386f51fbd4c94b7d0a79002b7af7..5ab3967dda43ee989a6a4e5ccf1a553e67a7a0db 100644 (file)
@@ -239,7 +239,6 @@ struct se_session *transport_init_session(enum target_prot_op sup_prot_ops)
        INIT_LIST_HEAD(&se_sess->sess_cmd_list);
        INIT_LIST_HEAD(&se_sess->sess_wait_list);
        spin_lock_init(&se_sess->sess_cmd_lock);
-       kref_init(&se_sess->sess_kref);
        se_sess->sup_prot_ops = sup_prot_ops;
 
        return se_sess;
@@ -430,27 +429,6 @@ target_alloc_session(struct se_portal_group *tpg,
 }
 EXPORT_SYMBOL(target_alloc_session);
 
-static void target_release_session(struct kref *kref)
-{
-       struct se_session *se_sess = container_of(kref,
-                       struct se_session, sess_kref);
-       struct se_portal_group *se_tpg = se_sess->se_tpg;
-
-       se_tpg->se_tpg_tfo->close_session(se_sess);
-}
-
-int target_get_session(struct se_session *se_sess)
-{
-       return kref_get_unless_zero(&se_sess->sess_kref);
-}
-EXPORT_SYMBOL(target_get_session);
-
-void target_put_session(struct se_session *se_sess)
-{
-       kref_put(&se_sess->sess_kref, target_release_session);
-}
-EXPORT_SYMBOL(target_put_session);
-
 ssize_t target_show_dynamic_sessions(struct se_portal_group *se_tpg, char *page)
 {
        struct se_session *se_sess;
@@ -499,8 +477,8 @@ void transport_deregister_session_configfs(struct se_session *se_sess)
        se_nacl = se_sess->se_node_acl;
        if (se_nacl) {
                spin_lock_irqsave(&se_nacl->nacl_sess_lock, flags);
-               if (se_nacl->acl_stop == 0)
-                       list_del(&se_sess->sess_acl_list);
+               if (!list_empty(&se_sess->sess_acl_list))
+                       list_del_init(&se_sess->sess_acl_list);
                /*
                 * If the session list is empty, then clear the pointer.
                 * Otherwise, set the struct se_session pointer from the tail
@@ -2195,7 +2173,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 +2183,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 +2204,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 +2215,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 +2225,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 +2303,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 +2342,7 @@ out:
        kfree(sg);
        return -ENOMEM;
 }
+EXPORT_SYMBOL(target_alloc_sgl);
 
 /*
  * Allocate any required resources to execute the command.  For writes we
@@ -2376,7 +2358,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 +2383,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 +2403,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;
        }