aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/ulp/srp
diff options
context:
space:
mode:
authorBart Van Assche <bvanassche@acm.org>2013-06-28 08:51:26 -0400
committerRoland Dreier <roland@purestorage.com>2013-07-01 13:40:07 -0400
commit96fc248a4c6fe1e5ffac4903b39d2dd5cbe2dc9a (patch)
tree53f84bcd15b51bfc415f9b74331753eb1850bdeb /drivers/infiniband/ulp/srp
parent99e1c1398f44a056b16e78122133988c82b66d97 (diff)
IB/srp: Maintain a single connection per I_T nexus
An SRP target is required to maintain a single connection between initiator and target. This means that if the 'add_target' attribute is used to create a second connection to a target, the first connection will be logged out and that the SCSI error handler will kick in. The SCSI error handler will cause the SRP initiator to reconnect, which will cause I/O over the second connection to fail. Avoid such ping-pong behavior by disabling relogins. If reconnecting manually is necessary, that is possible by deleting and recreating an rport via sysfs. Signed-off-by: Bart Van Assche <bvanassche@acm.org> Signed-off-by: Sebastian Riemer <sebastian.riemer@profitbricks.com> Acked-by: David Dillow <dillowda@ornl.gov> Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/infiniband/ulp/srp')
-rw-r--r--drivers/infiniband/ulp/srp/ib_srp.c44
1 files changed, 42 insertions, 2 deletions
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index 1f331011653e..830ef0037087 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -542,11 +542,11 @@ static void srp_remove_work(struct work_struct *work)
542 542
543 WARN_ON_ONCE(target->state != SRP_TARGET_REMOVED); 543 WARN_ON_ONCE(target->state != SRP_TARGET_REMOVED);
544 544
545 srp_remove_target(target);
546
545 spin_lock(&target->srp_host->target_lock); 547 spin_lock(&target->srp_host->target_lock);
546 list_del(&target->list); 548 list_del(&target->list);
547 spin_unlock(&target->srp_host->target_lock); 549 spin_unlock(&target->srp_host->target_lock);
548
549 srp_remove_target(target);
550} 550}
551 551
552static void srp_rport_delete(struct srp_rport *rport) 552static void srp_rport_delete(struct srp_rport *rport)
@@ -2009,6 +2009,36 @@ static struct class srp_class = {
2009 .dev_release = srp_release_dev 2009 .dev_release = srp_release_dev
2010}; 2010};
2011 2011
2012/**
2013 * srp_conn_unique() - check whether the connection to a target is unique
2014 */
2015static bool srp_conn_unique(struct srp_host *host,
2016 struct srp_target_port *target)
2017{
2018 struct srp_target_port *t;
2019 bool ret = false;
2020
2021 if (target->state == SRP_TARGET_REMOVED)
2022 goto out;
2023
2024 ret = true;
2025
2026 spin_lock(&host->target_lock);
2027 list_for_each_entry(t, &host->target_list, list) {
2028 if (t != target &&
2029 target->id_ext == t->id_ext &&
2030 target->ioc_guid == t->ioc_guid &&
2031 target->initiator_ext == t->initiator_ext) {
2032 ret = false;
2033 break;
2034 }
2035 }
2036 spin_unlock(&host->target_lock);
2037
2038out:
2039 return ret;
2040}
2041
2012/* 2042/*
2013 * Target ports are added by writing 2043 * Target ports are added by writing
2014 * 2044 *
@@ -2265,6 +2295,16 @@ static ssize_t srp_create_target(struct device *dev,
2265 if (ret) 2295 if (ret)
2266 goto err; 2296 goto err;
2267 2297
2298 if (!srp_conn_unique(target->srp_host, target)) {
2299 shost_printk(KERN_INFO, target->scsi_host,
2300 PFX "Already connected to target port with id_ext=%016llx;ioc_guid=%016llx;initiator_ext=%016llx\n",
2301 be64_to_cpu(target->id_ext),
2302 be64_to_cpu(target->ioc_guid),
2303 be64_to_cpu(target->initiator_ext));
2304 ret = -EEXIST;
2305 goto err;
2306 }
2307
2268 if (!host->srp_dev->fmr_pool && !target->allow_ext_sg && 2308 if (!host->srp_dev->fmr_pool && !target->allow_ext_sg &&
2269 target->cmd_sg_cnt < target->sg_tablesize) { 2309 target->cmd_sg_cnt < target->sg_tablesize) {
2270 pr_warn("No FMR pool and no external indirect descriptors, limiting sg_tablesize to cmd_sg_cnt\n"); 2310 pr_warn("No FMR pool and no external indirect descriptors, limiting sg_tablesize to cmd_sg_cnt\n");