IB/srp: Allow SRP disconnect through sysfs
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>
This commit is contained in:
parent
7e1265bfe7
commit
dc1bdbd9b8
4 changed files with 46 additions and 1 deletions
|
@ -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
|
What: /sys/class/srp_remote_ports/port-<h>:<n>/port_id
|
||||||
Date: June 27, 2007
|
Date: June 27, 2007
|
||||||
KernelVersion: 2.6.24
|
KernelVersion: 2.6.24
|
||||||
|
|
|
@ -549,6 +549,13 @@ static void srp_remove_work(struct work_struct *work)
|
||||||
srp_remove_target(target);
|
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)
|
static int srp_connect_target(struct srp_target_port *target)
|
||||||
{
|
{
|
||||||
int retries = 3;
|
int retries = 3;
|
||||||
|
@ -1958,6 +1965,8 @@ static int srp_add_target(struct srp_host *host, struct srp_target_port *target)
|
||||||
return PTR_ERR(rport);
|
return PTR_ERR(rport);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rport->lld_data = target;
|
||||||
|
|
||||||
spin_lock(&host->target_lock);
|
spin_lock(&host->target_lock);
|
||||||
list_add_tail(&target->list, &host->target_list);
|
list_add_tail(&target->list, &host->target_list);
|
||||||
spin_unlock(&host->target_lock);
|
spin_unlock(&host->target_lock);
|
||||||
|
@ -2524,6 +2533,7 @@ static void srp_remove_one(struct ib_device *device)
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct srp_function_template ib_srp_transport_functions = {
|
static struct srp_function_template ib_srp_transport_functions = {
|
||||||
|
.rport_delete = srp_rport_delete,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __init srp_init_module(void)
|
static int __init srp_init_module(void)
|
||||||
|
|
|
@ -38,7 +38,7 @@ struct srp_host_attrs {
|
||||||
#define to_srp_host_attrs(host) ((struct srp_host_attrs *)(host)->shost_data)
|
#define to_srp_host_attrs(host) ((struct srp_host_attrs *)(host)->shost_data)
|
||||||
|
|
||||||
#define SRP_HOST_ATTRS 0
|
#define SRP_HOST_ATTRS 0
|
||||||
#define SRP_RPORT_ATTRS 2
|
#define SRP_RPORT_ATTRS 3
|
||||||
|
|
||||||
struct srp_internal {
|
struct srp_internal {
|
||||||
struct scsi_transport_template t;
|
struct scsi_transport_template t;
|
||||||
|
@ -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 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)
|
static void srp_rport_release(struct device *dev)
|
||||||
{
|
{
|
||||||
struct srp_rport *rport = dev_to_rport(dev);
|
struct srp_rport *rport = dev_to_rport(dev);
|
||||||
|
@ -309,6 +327,8 @@ srp_attach_transport(struct srp_function_template *ft)
|
||||||
count = 0;
|
count = 0;
|
||||||
i->rport_attrs[count++] = &dev_attr_port_id;
|
i->rport_attrs[count++] = &dev_attr_port_id;
|
||||||
i->rport_attrs[count++] = &dev_attr_roles;
|
i->rport_attrs[count++] = &dev_attr_roles;
|
||||||
|
if (ft->rport_delete)
|
||||||
|
i->rport_attrs[count++] = &dev_attr_delete;
|
||||||
i->rport_attrs[count++] = NULL;
|
i->rport_attrs[count++] = NULL;
|
||||||
BUG_ON(count > ARRAY_SIZE(i->rport_attrs));
|
BUG_ON(count > ARRAY_SIZE(i->rport_attrs));
|
||||||
|
|
||||||
|
|
|
@ -14,13 +14,21 @@ struct srp_rport_identifiers {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct srp_rport {
|
struct srp_rport {
|
||||||
|
/* for initiator and target drivers */
|
||||||
|
|
||||||
struct device dev;
|
struct device dev;
|
||||||
|
|
||||||
u8 port_id[16];
|
u8 port_id[16];
|
||||||
u8 roles;
|
u8 roles;
|
||||||
|
|
||||||
|
/* for initiator drivers */
|
||||||
|
|
||||||
|
void *lld_data; /* LLD private data */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct srp_function_template {
|
struct srp_function_template {
|
||||||
|
/* for initiator drivers */
|
||||||
|
void (*rport_delete)(struct srp_rport *rport);
|
||||||
/* for target drivers */
|
/* for target drivers */
|
||||||
int (* tsk_mgmt_response)(struct Scsi_Host *, u64, u64, int);
|
int (* tsk_mgmt_response)(struct Scsi_Host *, u64, u64, int);
|
||||||
int (* it_nexus_response)(struct Scsi_Host *, u64, int);
|
int (* it_nexus_response)(struct Scsi_Host *, u64, int);
|
||||||
|
|
Loading…
Add table
Reference in a new issue