diff options
Diffstat (limited to 'drivers/target/tcm_fc/tfc_sess.c')
| -rw-r--r-- | drivers/target/tcm_fc/tfc_sess.c | 115 |
1 files changed, 39 insertions, 76 deletions
diff --git a/drivers/target/tcm_fc/tfc_sess.c b/drivers/target/tcm_fc/tfc_sess.c index a3bd57f2ea3..21ce50880c7 100644 --- a/drivers/target/tcm_fc/tfc_sess.c +++ b/drivers/target/tcm_fc/tfc_sess.c @@ -19,8 +19,6 @@ #include <linux/module.h> #include <linux/moduleparam.h> -#include <linux/version.h> -#include <generated/utsrelease.h> #include <linux/utsname.h> #include <linux/init.h> #include <linux/slab.h> @@ -41,15 +39,10 @@ #include <scsi/libfc.h> #include <target/target_core_base.h> -#include <target/target_core_transport.h> -#include <target/target_core_fabric_ops.h> -#include <target/target_core_device.h> -#include <target/target_core_tpg.h> +#include <target/target_core_fabric.h> #include <target/target_core_configfs.h> -#include <target/target_core_base.h> #include <target/configfs_macros.h> -#include <scsi/libfc.h> #include "tcm_fc.h" static void ft_sess_delete_all(struct ft_tport *); @@ -58,13 +51,14 @@ static void ft_sess_delete_all(struct ft_tport *); * Lookup or allocate target local port. * Caller holds ft_lport_lock. */ -static struct ft_tport *ft_tport_create(struct fc_lport *lport) +static struct ft_tport *ft_tport_get(struct fc_lport *lport) { struct ft_tpg *tpg; struct ft_tport *tport; int i; - tport = rcu_dereference(lport->prov[FC_TYPE_FCP]); + tport = rcu_dereference_protected(lport->prov[FC_TYPE_FCP], + lockdep_is_held(&ft_lport_lock)); if (tport && tport->tpg) return tport; @@ -74,6 +68,7 @@ static struct ft_tport *ft_tport_create(struct fc_lport *lport) if (tport) { tport->tpg = tpg; + tpg->tport = tport; return tport; } @@ -92,16 +87,6 @@ static struct ft_tport *ft_tport_create(struct fc_lport *lport) } /* - * Free tport via RCU. - */ -static void ft_tport_rcu_free(struct rcu_head *rcu) -{ - struct ft_tport *tport = container_of(rcu, struct ft_tport, rcu); - - kfree(tport); -} - -/* * Delete a target local port. * Caller holds ft_lport_lock. */ @@ -120,7 +105,7 @@ static void ft_tport_delete(struct ft_tport *tport) tpg->tport = NULL; tport->tpg = NULL; } - call_rcu(&tport->rcu, ft_tport_rcu_free); + kfree_rcu(tport, rcu); } /* @@ -130,7 +115,7 @@ static void ft_tport_delete(struct ft_tport *tport) void ft_lport_add(struct fc_lport *lport, void *arg) { mutex_lock(&ft_lport_lock); - ft_tport_create(lport); + ft_tport_get(lport); mutex_unlock(&ft_lport_lock); } @@ -185,7 +170,6 @@ static struct ft_sess *ft_sess_get(struct fc_lport *lport, u32 port_id) { struct ft_tport *tport; struct hlist_head *head; - struct hlist_node *pos; struct ft_sess *sess; rcu_read_lock(); @@ -194,17 +178,17 @@ static struct ft_sess *ft_sess_get(struct fc_lport *lport, u32 port_id) goto out; head = &tport->hash[ft_sess_hash(port_id)]; - hlist_for_each_entry_rcu(sess, pos, head, hash) { + hlist_for_each_entry_rcu(sess, head, hash) { if (sess->port_id == port_id) { kref_get(&sess->kref); rcu_read_unlock(); - FT_SESS_DBG("port_id %x found %p\n", port_id, sess); + pr_debug("port_id %x found %p\n", port_id, sess); return sess; } } out: rcu_read_unlock(); - FT_SESS_DBG("port_id %x not found\n", port_id); + pr_debug("port_id %x not found\n", port_id); return NULL; } @@ -217,10 +201,9 @@ static struct ft_sess *ft_sess_create(struct ft_tport *tport, u32 port_id, { struct ft_sess *sess; struct hlist_head *head; - struct hlist_node *pos; head = &tport->hash[ft_sess_hash(port_id)]; - hlist_for_each_entry_rcu(sess, pos, head, hash) + hlist_for_each_entry_rcu(sess, head, hash) if (sess->port_id == port_id) return sess; @@ -228,8 +211,10 @@ static struct ft_sess *ft_sess_create(struct ft_tport *tport, u32 port_id, if (!sess) return NULL; - sess->se_sess = transport_init_session(); - if (!sess->se_sess) { + sess->se_sess = transport_init_session_tags(TCM_FC_DEFAULT_TAGS, + sizeof(struct ft_cmd), + TARGET_PROT_NORMAL); + if (IS_ERR(sess->se_sess)) { kfree(sess); return NULL; } @@ -240,7 +225,7 @@ static struct ft_sess *ft_sess_create(struct ft_tport *tport, u32 port_id, hlist_add_head_rcu(&sess->hash, head); tport->sess_count++; - FT_SESS_DBG("port_id %x sess %p\n", port_id, sess); + pr_debug("port_id %x sess %p\n", port_id, sess); transport_register_session(&tport->tpg->se_tpg, &acl->se_node_acl, sess->se_sess, sess); @@ -269,11 +254,10 @@ static void ft_sess_unhash(struct ft_sess *sess) static struct ft_sess *ft_sess_delete(struct ft_tport *tport, u32 port_id) { struct hlist_head *head; - struct hlist_node *pos; struct ft_sess *sess; head = &tport->hash[ft_sess_hash(port_id)]; - hlist_for_each_entry_rcu(sess, pos, head, hash) { + hlist_for_each_entry_rcu(sess, head, hash) { if (sess->port_id == port_id) { ft_sess_unhash(sess); return sess; @@ -289,12 +273,11 @@ static struct ft_sess *ft_sess_delete(struct ft_tport *tport, u32 port_id) static void ft_sess_delete_all(struct ft_tport *tport) { struct hlist_head *head; - struct hlist_node *pos; struct ft_sess *sess; for (head = tport->hash; head < &tport->hash[FT_SESS_HASH_SIZE]; head++) { - hlist_for_each_entry_rcu(sess, pos, head, hash) { + hlist_for_each_entry_rcu(sess, head, hash) { ft_sess_unhash(sess); transport_deregister_session_configfs(sess->se_sess); ft_sess_put(sess); /* release from table */ @@ -314,7 +297,7 @@ int ft_sess_shutdown(struct se_session *se_sess) { struct ft_sess *sess = se_sess->fabric_sess_ptr; - FT_SESS_DBG("port_id %x\n", sess->port_id); + pr_debug("port_id %x\n", sess->port_id); return 1; } @@ -325,17 +308,15 @@ int ft_sess_shutdown(struct se_session *se_sess) void ft_sess_close(struct se_session *se_sess) { struct ft_sess *sess = se_sess->fabric_sess_ptr; - struct fc_lport *lport; u32 port_id; mutex_lock(&ft_lport_lock); - lport = sess->tport->lport; port_id = sess->port_id; if (port_id == -1) { - mutex_lock(&ft_lport_lock); + mutex_unlock(&ft_lport_lock); return; } - FT_SESS_DBG("port_id %x\n", port_id); + pr_debug("port_id %x\n", port_id); ft_sess_unhash(sess); mutex_unlock(&ft_lport_lock); transport_deregister_session_configfs(se_sess); @@ -344,20 +325,6 @@ void ft_sess_close(struct se_session *se_sess) synchronize_rcu(); /* let transport deregister happen */ } -void ft_sess_stop(struct se_session *se_sess, int sess_sleep, int conn_sleep) -{ - struct ft_sess *sess = se_sess->fabric_sess_ptr; - - FT_SESS_DBG("port_id %x\n", sess->port_id); -} - -int ft_sess_logged_in(struct se_session *se_sess) -{ - struct ft_sess *sess = se_sess->fabric_sess_ptr; - - return sess->port_id != -1; -} - u32 ft_sess_get_index(struct se_session *se_sess) { struct ft_sess *sess = se_sess->fabric_sess_ptr; @@ -373,11 +340,6 @@ u32 ft_sess_get_port_name(struct se_session *se_sess, return ft_format_wwn(buf, len, sess->port_name); } -void ft_sess_set_erl0(struct se_session *se_sess) -{ - /* XXX TBD called when out of memory */ -} - /* * libfc ops involving sessions. */ @@ -390,13 +352,13 @@ static int ft_prli_locked(struct fc_rport_priv *rdata, u32 spp_len, struct ft_node_acl *acl; u32 fcp_parm; - tport = ft_tport_create(rdata->local_port); + tport = ft_tport_get(rdata->local_port); if (!tport) - return 0; /* not a target for this local port */ + goto not_target; /* not a target for this local port */ acl = ft_acl_get(tport->tpg, rdata); if (!acl) - return 0; + goto not_target; /* no target for this remote */ if (!rspp) goto fill; @@ -433,12 +395,18 @@ static int ft_prli_locked(struct fc_rport_priv *rdata, u32 spp_len, /* * OR in our service parameters with other provider (initiator), if any. - * TBD XXX - indicate RETRY capability? */ fill: fcp_parm = ntohl(spp->spp_params); + fcp_parm &= ~FCP_SPPF_RETRY; spp->spp_params = htonl(fcp_parm | FCP_SPPF_TARG_FCN); return FC_SPP_RESP_ACK; + +not_target: + fcp_parm = ntohl(spp->spp_params); + fcp_parm &= ~FCP_SPPF_TARG_FCN; + spp->spp_params = htonl(fcp_parm); + return 0; } /** @@ -458,24 +426,17 @@ static int ft_prli(struct fc_rport_priv *rdata, u32 spp_len, mutex_lock(&ft_lport_lock); ret = ft_prli_locked(rdata, spp_len, rspp, spp); mutex_unlock(&ft_lport_lock); - FT_SESS_DBG("port_id %x flags %x ret %x\n", + pr_debug("port_id %x flags %x ret %x\n", rdata->ids.port_id, rspp ? rspp->spp_flags : 0, ret); return ret; } -static void ft_sess_rcu_free(struct rcu_head *rcu) -{ - struct ft_sess *sess = container_of(rcu, struct ft_sess, rcu); - - transport_deregister_session(sess->se_sess); - kfree(sess); -} - static void ft_sess_free(struct kref *kref) { struct ft_sess *sess = container_of(kref, struct ft_sess, kref); - call_rcu(&sess->rcu, ft_sess_rcu_free); + transport_deregister_session(sess->se_sess); + kfree_rcu(sess, rcu); } void ft_sess_put(struct ft_sess *sess) @@ -492,7 +453,9 @@ static void ft_prlo(struct fc_rport_priv *rdata) struct ft_tport *tport; mutex_lock(&ft_lport_lock); - tport = rcu_dereference(rdata->local_port->prov[FC_TYPE_FCP]); + tport = rcu_dereference_protected(rdata->local_port->prov[FC_TYPE_FCP], + lockdep_is_held(&ft_lport_lock)); + if (!tport) { mutex_unlock(&ft_lport_lock); return; @@ -518,11 +481,11 @@ static void ft_recv(struct fc_lport *lport, struct fc_frame *fp) struct ft_sess *sess; u32 sid = fc_frame_sid(fp); - FT_SESS_DBG("sid %x\n", sid); + pr_debug("sid %x\n", sid); sess = ft_sess_get(lport, sid); if (!sess) { - FT_SESS_DBG("sid %x sess lookup failed\n", sid); + pr_debug("sid %x sess lookup failed\n", sid); /* TBD XXX - if FCP_CMND, send PRLO */ fc_frame_free(fp); return; |
