Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target...
[cascardo/linux.git] / drivers / target / target_core_transport.c
index 4fdcee2..9f3608e 100644 (file)
@@ -341,7 +341,6 @@ void __transport_register_session(
                                        &buf[0], PR_REG_ISID_LEN);
                        se_sess->sess_bin_isid = get_unaligned_be64(&buf[0]);
                }
-               kref_get(&se_nacl->acl_kref);
 
                spin_lock_irq(&se_nacl->nacl_sess_lock);
                /*
@@ -384,9 +383,9 @@ static void target_release_session(struct kref *kref)
        se_tpg->se_tpg_tfo->close_session(se_sess);
 }
 
-void target_get_session(struct se_session *se_sess)
+int target_get_session(struct se_session *se_sess)
 {
-       kref_get(&se_sess->sess_kref);
+       return kref_get_unless_zero(&se_sess->sess_kref);
 }
 EXPORT_SYMBOL(target_get_session);
 
@@ -432,6 +431,7 @@ void target_put_nacl(struct se_node_acl *nacl)
 {
        kref_put(&nacl->acl_kref, target_complete_nacl);
 }
+EXPORT_SYMBOL(target_put_nacl);
 
 void transport_deregister_session_configfs(struct se_session *se_sess)
 {
@@ -464,6 +464,15 @@ EXPORT_SYMBOL(transport_deregister_session_configfs);
 
 void transport_free_session(struct se_session *se_sess)
 {
+       struct se_node_acl *se_nacl = se_sess->se_node_acl;
+       /*
+        * Drop the se_node_acl->nacl_kref obtained from within
+        * core_tpg_get_initiator_node_acl().
+        */
+       if (se_nacl) {
+               se_sess->se_node_acl = NULL;
+               target_put_nacl(se_nacl);
+       }
        if (se_sess->sess_cmd_map) {
                percpu_ida_destroy(&se_sess->sess_tag_pool);
                kvfree(se_sess->sess_cmd_map);
@@ -478,7 +487,7 @@ void transport_deregister_session(struct se_session *se_sess)
        const struct target_core_fabric_ops *se_tfo;
        struct se_node_acl *se_nacl;
        unsigned long flags;
-       bool comp_nacl = true, drop_nacl = false;
+       bool drop_nacl = false;
 
        if (!se_tpg) {
                transport_free_session(se_sess);
@@ -502,7 +511,6 @@ void transport_deregister_session(struct se_session *se_sess)
        if (se_nacl && se_nacl->dynamic_node_acl) {
                if (!se_tfo->tpg_check_demo_mode_cache(se_tpg)) {
                        list_del(&se_nacl->acl_list);
-                       se_tpg->num_node_acls--;
                        drop_nacl = true;
                }
        }
@@ -511,18 +519,16 @@ void transport_deregister_session(struct se_session *se_sess)
        if (drop_nacl) {
                core_tpg_wait_for_nacl_pr_ref(se_nacl);
                core_free_device_list_for_node(se_nacl, se_tpg);
+               se_sess->se_node_acl = NULL;
                kfree(se_nacl);
-               comp_nacl = false;
        }
        pr_debug("TARGET_CORE[%s]: Deregistered fabric_sess\n",
                se_tpg->se_tpg_tfo->get_fabric_name());
        /*
         * If last kref is dropping now for an explicit NodeACL, awake sleeping
         * ->acl_free_comp caller to wakeup configfs se_node_acl->acl_group
-        * removal context.
+        * removal context from within transport_free_session() code.
         */
-       if (se_nacl && comp_nacl)
-               target_put_nacl(se_nacl);
 
        transport_free_session(se_sess);
 }
@@ -715,7 +721,10 @@ void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status)
        cmd->transport_state |= (CMD_T_COMPLETE | CMD_T_ACTIVE);
        spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 
-       queue_work(target_completion_wq, &cmd->work);
+       if (cmd->cpuid == -1)
+               queue_work(target_completion_wq, &cmd->work);
+       else
+               queue_work_on(cmd->cpuid, target_completion_wq, &cmd->work);
 }
 EXPORT_SYMBOL(target_complete_cmd);
 
@@ -1309,7 +1318,7 @@ EXPORT_SYMBOL(target_setup_cmd_from_cdb);
 
 /*
  * Used by fabric module frontends to queue tasks directly.
- * Many only be used from process context only
+ * May only be used from process context.
  */
 int transport_handle_cdb_direct(
        struct se_cmd *cmd)
@@ -1582,7 +1591,7 @@ static void target_complete_tmr_failure(struct work_struct *work)
 int target_submit_tmr(struct se_cmd *se_cmd, struct se_session *se_sess,
                unsigned char *sense, u64 unpacked_lun,
                void *fabric_tmr_ptr, unsigned char tm_type,
-               gfp_t gfp, unsigned int tag, int flags)
+               gfp_t gfp, u64 tag, int flags)
 {
        struct se_portal_group *se_tpg;
        int ret;