target: Add target_alloc_session() helper function
authorNicholas Bellinger <nab@linux-iscsi.org>
Sat, 9 Jan 2016 13:29:24 +0000 (05:29 -0800)
committerNicholas Bellinger <nab@linux-iscsi.org>
Sat, 27 Feb 2016 22:59:42 +0000 (14:59 -0800)
Based on HCH's original patch, this adds a full version to
support percpu-ida tag pre-allocation and callback function
pointer into fabric driver code to complete session setup.

Reported-by: Christoph Hellwig <hch@lst.de>
Cc: Sagi Grimberg <sagig@mellanox.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Hannes Reinecke <hare@suse.de>
Cc: Andy Grover <agrover@redhat.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
drivers/target/target_core_transport.c
include/target/target_core_fabric.h

index 867bc6d0a68a3ecfbd1aab610f01ff73614b3305..f5ad9e063b65eddd208b702fa78fab68fb1ceb7d 100644 (file)
@@ -281,6 +281,17 @@ struct se_session *transport_init_session_tags(unsigned int tag_num,
        struct se_session *se_sess;
        int rc;
 
+       if (tag_num != 0 && !tag_size) {
+               pr_err("init_session_tags called with percpu-ida tag_num:"
+                      " %u, but zero tag_size\n", tag_num);
+               return ERR_PTR(-EINVAL);
+       }
+       if (!tag_num && tag_size) {
+               pr_err("init_session_tags called with percpu-ida tag_size:"
+                      " %u, but zero tag_num\n", tag_size);
+               return ERR_PTR(-EINVAL);
+       }
+
        se_sess = transport_init_session(sup_prot_ops);
        if (IS_ERR(se_sess))
                return se_sess;
@@ -374,6 +385,51 @@ void transport_register_session(
 }
 EXPORT_SYMBOL(transport_register_session);
 
+struct se_session *
+target_alloc_session(struct se_portal_group *tpg,
+                    unsigned int tag_num, unsigned int tag_size,
+                    enum target_prot_op prot_op,
+                    const char *initiatorname, void *private,
+                    int (*callback)(struct se_portal_group *,
+                                    struct se_session *, void *))
+{
+       struct se_session *sess;
+
+       /*
+        * If the fabric driver is using percpu-ida based pre allocation
+        * of I/O descriptor tags, go ahead and perform that setup now..
+        */
+       if (tag_num != 0)
+               sess = transport_init_session_tags(tag_num, tag_size, prot_op);
+       else
+               sess = transport_init_session(prot_op);
+
+       if (IS_ERR(sess))
+               return sess;
+
+       sess->se_node_acl = core_tpg_check_initiator_node_acl(tpg,
+                                       (unsigned char *)initiatorname);
+       if (!sess->se_node_acl) {
+               transport_free_session(sess);
+               return ERR_PTR(-EACCES);
+       }
+       /*
+        * Go ahead and perform any remaining fabric setup that is
+        * required before transport_register_session().
+        */
+       if (callback != NULL) {
+               int rc = callback(tpg, sess, private);
+               if (rc) {
+                       transport_free_session(sess);
+                       return ERR_PTR(rc);
+               }
+       }
+
+       transport_register_session(tpg, sess->se_node_acl, sess, private);
+       return sess;
+}
+EXPORT_SYMBOL(target_alloc_session);
+
 static void target_release_session(struct kref *kref)
 {
        struct se_session *se_sess = container_of(kref,
index 56653408f53bf6648c9f44175552e3dbb1436831..685a51aa98cca1b52abc08a95905d9598135516c 100644 (file)
@@ -108,6 +108,12 @@ void target_unregister_template(const struct target_core_fabric_ops *fo);
 int target_depend_item(struct config_item *item);
 void target_undepend_item(struct config_item *item);
 
+struct se_session *target_alloc_session(struct se_portal_group *,
+               unsigned int, unsigned int, enum target_prot_op prot_op,
+               const char *, void *,
+               int (*callback)(struct se_portal_group *,
+                               struct se_session *, void *));
+
 struct se_session *transport_init_session(enum target_prot_op);
 int transport_alloc_session_tags(struct se_session *, unsigned int,
                unsigned int);