Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Bart Van Assche and committed by
Roland Dreier
dc1bdbd9 7e1265bf

+46 -1
+7
Documentation/ABI/stable/sysfs-transport-srp
··· 1 + What: /sys/class/srp_remote_ports/port-<h>:<n>/delete 2 + Date: June 1, 2012 3 + KernelVersion: 3.7 4 + Contact: linux-scsi@vger.kernel.org, linux-rdma@vger.kernel.org 5 + Description: Instructs an SRP initiator to disconnect from a target and to 6 + remove all LUNs imported from that target. 7 + 1 8 What: /sys/class/srp_remote_ports/port-<h>:<n>/port_id 2 9 Date: June 27, 2007 3 10 KernelVersion: 2.6.24
+10
drivers/infiniband/ulp/srp/ib_srp.c
··· 549 549 srp_remove_target(target); 550 550 } 551 551 552 + static void srp_rport_delete(struct srp_rport *rport) 553 + { 554 + struct srp_target_port *target = rport->lld_data; 555 + 556 + srp_queue_remove_work(target); 557 + } 558 + 552 559 static int srp_connect_target(struct srp_target_port *target) 553 560 { 554 561 int retries = 3; ··· 1965 1958 return PTR_ERR(rport); 1966 1959 } 1967 1960 1961 + rport->lld_data = target; 1962 + 1968 1963 spin_lock(&host->target_lock); 1969 1964 list_add_tail(&target->list, &host->target_list); 1970 1965 spin_unlock(&host->target_lock); ··· 2533 2524 } 2534 2525 2535 2526 static struct srp_function_template ib_srp_transport_functions = { 2527 + .rport_delete = srp_rport_delete, 2536 2528 }; 2537 2529 2538 2530 static int __init srp_init_module(void)
+21 -1
drivers/scsi/scsi_transport_srp.c
··· 38 38 #define to_srp_host_attrs(host) ((struct srp_host_attrs *)(host)->shost_data) 39 39 40 40 #define SRP_HOST_ATTRS 0 41 - #define SRP_RPORT_ATTRS 2 41 + #define SRP_RPORT_ATTRS 3 42 42 43 43 struct srp_internal { 44 44 struct scsi_transport_template t; ··· 115 115 } 116 116 117 117 static DEVICE_ATTR(roles, S_IRUGO, show_srp_rport_roles, NULL); 118 + 119 + static ssize_t store_srp_rport_delete(struct device *dev, 120 + struct device_attribute *attr, 121 + const char *buf, size_t count) 122 + { 123 + struct srp_rport *rport = transport_class_to_srp_rport(dev); 124 + struct Scsi_Host *shost = dev_to_shost(dev); 125 + struct srp_internal *i = to_srp_internal(shost->transportt); 126 + 127 + if (i->f->rport_delete) { 128 + i->f->rport_delete(rport); 129 + return count; 130 + } else { 131 + return -ENOSYS; 132 + } 133 + } 134 + 135 + static DEVICE_ATTR(delete, S_IWUSR, NULL, store_srp_rport_delete); 118 136 119 137 static void srp_rport_release(struct device *dev) 120 138 { ··· 327 309 count = 0; 328 310 i->rport_attrs[count++] = &dev_attr_port_id; 329 311 i->rport_attrs[count++] = &dev_attr_roles; 312 + if (ft->rport_delete) 313 + i->rport_attrs[count++] = &dev_attr_delete; 330 314 i->rport_attrs[count++] = NULL; 331 315 BUG_ON(count > ARRAY_SIZE(i->rport_attrs)); 332 316
+8
include/scsi/scsi_transport_srp.h
··· 14 14 }; 15 15 16 16 struct srp_rport { 17 + /* for initiator and target drivers */ 18 + 17 19 struct device dev; 18 20 19 21 u8 port_id[16]; 20 22 u8 roles; 23 + 24 + /* for initiator drivers */ 25 + 26 + void *lld_data; /* LLD private data */ 21 27 }; 22 28 23 29 struct srp_function_template { 30 + /* for initiator drivers */ 31 + void (*rport_delete)(struct srp_rport *rport); 24 32 /* for target drivers */ 25 33 int (* tsk_mgmt_response)(struct Scsi_Host *, u64, u64, int); 26 34 int (* it_nexus_response)(struct Scsi_Host *, u64, int);