Skip to content

Commit

Permalink
IB/srp: Allow SRP disconnect through sysfs
Browse files Browse the repository at this point in the history
Make it possible to disconnect the IB RC connection used by the SRP
protocol to communicate with a target.

Have the SRP transport layer create a sysfs "delete" attribute for
initiator drivers that support this functionality.

Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Acked-by: David Dillow <dillowda@ornl.gov>
Cc: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Cc: Robert Jennings <rcj@linux.vnet.ibm.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
  • Loading branch information
Bart Van Assche authored and Roland Dreier committed Dec 1, 2012
1 parent 7e1265b commit dc1bdbd
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 1 deletion.
7 changes: 7 additions & 0 deletions Documentation/ABI/stable/sysfs-transport-srp
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
What: /sys/class/srp_remote_ports/port-<h>:<n>/delete
Date: June 1, 2012
KernelVersion: 3.7
Contact: linux-scsi@vger.kernel.org, linux-rdma@vger.kernel.org
Description: Instructs an SRP initiator to disconnect from a target and to
remove all LUNs imported from that target.

What: /sys/class/srp_remote_ports/port-<h>:<n>/port_id
Date: June 27, 2007
KernelVersion: 2.6.24
Expand Down
10 changes: 10 additions & 0 deletions drivers/infiniband/ulp/srp/ib_srp.c
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,13 @@ static void srp_remove_work(struct work_struct *work)
srp_remove_target(target);
}

static void srp_rport_delete(struct srp_rport *rport)
{
struct srp_target_port *target = rport->lld_data;

srp_queue_remove_work(target);
}

static int srp_connect_target(struct srp_target_port *target)
{
int retries = 3;
Expand Down Expand Up @@ -1958,6 +1965,8 @@ static int srp_add_target(struct srp_host *host, struct srp_target_port *target)
return PTR_ERR(rport);
}

rport->lld_data = target;

spin_lock(&host->target_lock);
list_add_tail(&target->list, &host->target_list);
spin_unlock(&host->target_lock);
Expand Down Expand Up @@ -2524,6 +2533,7 @@ static void srp_remove_one(struct ib_device *device)
}

static struct srp_function_template ib_srp_transport_functions = {
.rport_delete = srp_rport_delete,
};

static int __init srp_init_module(void)
Expand Down
22 changes: 21 additions & 1 deletion drivers/scsi/scsi_transport_srp.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ struct srp_host_attrs {
#define to_srp_host_attrs(host) ((struct srp_host_attrs *)(host)->shost_data)

#define SRP_HOST_ATTRS 0
#define SRP_RPORT_ATTRS 2
#define SRP_RPORT_ATTRS 3

struct srp_internal {
struct scsi_transport_template t;
Expand Down Expand Up @@ -116,6 +116,24 @@ show_srp_rport_roles(struct device *dev, struct device_attribute *attr,

static DEVICE_ATTR(roles, S_IRUGO, show_srp_rport_roles, NULL);

static ssize_t store_srp_rport_delete(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct srp_rport *rport = transport_class_to_srp_rport(dev);
struct Scsi_Host *shost = dev_to_shost(dev);
struct srp_internal *i = to_srp_internal(shost->transportt);

if (i->f->rport_delete) {
i->f->rport_delete(rport);
return count;
} else {
return -ENOSYS;
}
}

static DEVICE_ATTR(delete, S_IWUSR, NULL, store_srp_rport_delete);

static void srp_rport_release(struct device *dev)
{
struct srp_rport *rport = dev_to_rport(dev);
Expand Down Expand Up @@ -309,6 +327,8 @@ srp_attach_transport(struct srp_function_template *ft)
count = 0;
i->rport_attrs[count++] = &dev_attr_port_id;
i->rport_attrs[count++] = &dev_attr_roles;
if (ft->rport_delete)
i->rport_attrs[count++] = &dev_attr_delete;
i->rport_attrs[count++] = NULL;
BUG_ON(count > ARRAY_SIZE(i->rport_attrs));

Expand Down
8 changes: 8 additions & 0 deletions include/scsi/scsi_transport_srp.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,21 @@ struct srp_rport_identifiers {
};

struct srp_rport {
/* for initiator and target drivers */

struct device dev;

u8 port_id[16];
u8 roles;

/* for initiator drivers */

void *lld_data; /* LLD private data */
};

struct srp_function_template {
/* for initiator drivers */
void (*rport_delete)(struct srp_rport *rport);
/* for target drivers */
int (* tsk_mgmt_response)(struct Scsi_Host *, u64, u64, int);
int (* it_nexus_response)(struct Scsi_Host *, u64, int);
Expand Down

0 comments on commit dc1bdbd

Please sign in to comment.