[openib-general] [PATCH 05/12] SRP: Changing ibsrpdm

Ishai Rabinovitz ishai at mellanox.co.il
Mon May 1 04:28:12 PDT 2006


Support a remove of a target from user level.

Signed-off-by: Ishai Rabinovitz <ishai at mellanox.co.il>
Index: last_stable/drivers/infiniband/ulp/srp/ib_srp.c
===================================================================
--- last_stable.orig/drivers/infiniband/ulp/srp/ib_srp.c	2006-05-01 12:30:01.000000000 +0300
+++ last_stable/drivers/infiniband/ulp/srp/ib_srp.c	2006-05-01 12:36:22.000000000 +0300
@@ -960,10 +960,12 @@ static int srp_queuecommand(struct scsi_
 	long req_index;
 	int len;
 
-	if (target->state == SRP_TARGET_CONNECTING)
+	if (target->state == SRP_TARGET_CONNECTING ||
+	    target->state == SRP_TARGET_RECONNECTING)
 		goto err;
 
 	if (target->state == SRP_TARGET_DEAD ||
+	    target->state == SRP_TARGET_DISCONNECTED ||
 	    target->state == SRP_TARGET_REMOVED) {
 		scmnd->result = DID_BAD_TARGET << 16;
 		done(scmnd);
@@ -1254,6 +1256,7 @@ static int srp_send_tsk_mgmt(struct scsi
 	spin_lock_irq(target->scsi_host->host_lock);
 
 	if (target->state == SRP_TARGET_DEAD ||
+	    target->state == SRP_TARGET_DISCONNECTED ||
 	    target->state == SRP_TARGET_REMOVED) {
 		scmnd->result = DID_BAD_TARGET << 16;
 		goto out;
@@ -1359,6 +1362,7 @@ static ssize_t show_ioc_guid(struct clas
 	struct srp_target_port *target = host_to_target(class_to_shost(cdev));
 
 	if (target->state == SRP_TARGET_DEAD ||
+	    target->state == SRP_TARGET_DISCONNECTED ||
 	    target->state == SRP_TARGET_REMOVED)
 		return -ENODEV;
 
@@ -1371,6 +1375,7 @@ static ssize_t show_service_id(struct cl
 	struct srp_target_port *target = host_to_target(class_to_shost(cdev));
 
 	if (target->state == SRP_TARGET_DEAD ||
+	    target->state == SRP_TARGET_DISCONNECTED ||
 	    target->state == SRP_TARGET_REMOVED)
 		return -ENODEV;
 
@@ -1383,6 +1388,7 @@ static ssize_t show_pkey(struct class_de
 	struct srp_target_port *target = host_to_target(class_to_shost(cdev));
 
 	if (target->state == SRP_TARGET_DEAD ||
+	    target->state == SRP_TARGET_DISCONNECTED ||
 	    target->state == SRP_TARGET_REMOVED)
 		return -ENODEV;
 
@@ -1394,6 +1400,8 @@ static ssize_t show_dgid(struct class_de
 	struct srp_target_port *target = host_to_target(class_to_shost(cdev));
 
 	if (target->state == SRP_TARGET_DEAD ||
+	    target->state == SRP_TARGET_DISCONNECTED ||
+	    target->state == SRP_TARGET_DISCONNECTED ||
 	    target->state == SRP_TARGET_REMOVED)
 		return -ENODEV;
 
@@ -1447,11 +1455,11 @@ static int srp_add_target(struct srp_hos
 	if (scsi_add_host(target->scsi_host, host->dev->dev->dma_device))
 		return -ENODEV;
 
-	mutex_lock(&host->target_mutex);
 	list_add_tail(&target->list, &host->target_list);
-	mutex_unlock(&host->target_mutex);
 
+	spin_lock_irq(target->scsi_host->host_lock);
 	target->state = SRP_TARGET_LIVE;
+	spin_unlock_irq(target->scsi_host->host_lock);
 
 	/* XXX: are we supposed to have a definition of SCAN_WILD_CARD ?? */
 	scsi_scan_target(&target->scsi_host->shost_gendev,
@@ -1642,7 +1650,6 @@ static ssize_t srp_create_target(struct 
 {
 	struct srp_host *host =
 		container_of(class_dev, struct srp_host, class_dev);
-	struct Scsi_Host *target_host;
 	struct srp_target_port *target, *existing_target = NULL;
 	int ret;
 	int i;
@@ -1663,6 +1670,7 @@ static ssize_t srp_create_target(struct 
 			       buf);
 			ret = -EEXIST;
 			break;
+		case SRP_TARGET_RECONNECTING:
 		case SRP_TARGET_CONNECTING:
 		        /* It is in the middle of reconnecting */
 			ret = -EALREADY;
@@ -1671,6 +1679,10 @@ static ssize_t srp_create_target(struct 
 		        /* It will be removed soon - create a new one */
 		case SRP_TARGET_REMOVED:
 			/* target is dead, create a new one */
+			existing_target = NULL;
+			break;
+		case SRP_TARGET_DISCONNECTED:
+			existing_target->state = SRP_TARGET_RECONNECTING;
 			break;
 		}
  		spin_unlock_irq(existing_target->scsi_host->host_lock);
@@ -1678,26 +1690,30 @@ static ssize_t srp_create_target(struct 
 			goto unlock_mutex;
 	}
 
-	/* really create the target */
-	target_host = scsi_host_alloc(&srp_template,
-				      sizeof (struct srp_target_port));
-	if (!target_host) {
-		ret = -ENOMEM;
-		goto unlock_mutex;
-	}
-
-	target_host->max_lun = SRP_MAX_LUN;
-
-	target = host_to_target(target_host);
-	memset(target, 0, sizeof *target);
+ 	if (!existing_target) {
+ 		struct Scsi_Host *target_host;
 
-	target->scsi_host  = target_host;
-	target->srp_host   = host;
-
-	for (i = 0; i < SRP_SQ_SIZE - 1; ++i)
-		target->req_ring[i].next = i + 1;
-	target->req_ring[SRP_SQ_SIZE - 1].next = -1;
-	INIT_LIST_HEAD(&target->req_queue);
+ 		target_host = scsi_host_alloc(&srp_template,
+ 					      sizeof (struct srp_target_port));
+ 		if (!target_host) {
+ 			ret = -ENOMEM;
+ 			goto unlock_mutex;
+ 		}
+
+ 		target_host->max_lun = SRP_MAX_LUN;
+
+ 		target = host_to_target(target_host);
+ 		memset(target, 0, sizeof *target);
+
+ 		target->scsi_host  = target_host;
+ 		target->srp_host   = host;
+
+ 		for (i = 0; i < SRP_SQ_SIZE - 1; ++i)
+ 			target->req_ring[i].next = i + 1;
+ 		target->req_ring[SRP_SQ_SIZE - 1].next = -1;
+ 		INIT_LIST_HEAD(&target->req_queue);
+ 	} else
+		target = existing_target;
 
 	ret = srp_parse_options(buf, target);
 	if (ret)
@@ -1736,9 +1752,15 @@ static ssize_t srp_create_target(struct 
 		goto err_cm_id;
 	}
 
-	ret = srp_add_target(host, target);
-	if (ret)
-		goto err_disconnect;
+	if (!existing_target) {
+		ret = srp_add_target(host, target);
+		if (ret)
+			goto err_disconnect;
+	} else {
+ 		spin_lock_irq(target->scsi_host->host_lock);
+		target->state = SRP_TARGET_LIVE;
+ 		spin_unlock_irq(target->scsi_host->host_lock);
+	}
 
 	ret = count;
 	goto unlock_mutex;
@@ -1753,7 +1775,9 @@ err_free:
 	srp_free_target_ib(target);
 
 err_put_scsi_host:
-	scsi_host_put(target_host);
+	if (existing_target)
+		list_del(&target->list);
+	scsi_host_put(target->scsi_host);
 
 unlock_mutex:
 	mutex_unlock(&host->target_mutex);
@@ -1763,6 +1787,62 @@ unlock_mutex:
 
 static CLASS_DEVICE_ATTR(add_target, S_IWUSR, NULL, srp_create_target);
 
+static ssize_t srp_remove_target(struct class_device *class_dev,
+				 const char *buf, size_t count)
+{
+	struct srp_host *host =
+		container_of(class_dev, struct srp_host, class_dev);
+	struct srp_target_port *existing_target;
+	int ret;
+
+	/* first check if the target exists */
+
+	mutex_lock(&host->target_mutex);
+	ret = srp_find_target(buf, host, &existing_target);
+	if (ret)
+		goto unlock_mutex;
+
+	if (!existing_target)  {
+		printk(KERN_WARNING PFX "target %s does not exist\n", buf);
+		ret = -ENOENT;
+		goto unlock_mutex;
+	}
+
+	spin_lock_irq(existing_target->scsi_host->host_lock);
+
+	switch (existing_target->state) {
+	case SRP_TARGET_REMOVED:
+	case SRP_TARGET_DEAD:
+	case SRP_TARGET_DISCONNECTED:
+		/* target not exists */
+		printk(KERN_WARNING PFX "target %s does not exist\n", buf);
+		ret = -ENOENT;
+		break;
+
+	case SRP_TARGET_RECONNECTING:
+	case SRP_TARGET_CONNECTING:
+		ret = -EAGAIN; /* So the caller will try again later -
+				  after the connection ends one way or another */
+		break;
+
+	case SRP_TARGET_LIVE:
+		existing_target->state = SRP_TARGET_DISCONNECTED;
+		spin_unlock_irq(existing_target->scsi_host->host_lock);
+		mutex_unlock(&host->target_mutex);
+		srp_disconnect_target(existing_target);
+		ib_destroy_cm_id(existing_target->cm_id);
+		srp_free_target_ib(existing_target);
+		return count;
+	}
+
+	spin_unlock_irq(existing_target->scsi_host->host_lock);
+unlock_mutex:
+	mutex_unlock(&host->target_mutex);
+	return ret;
+}
+
+static CLASS_DEVICE_ATTR(remove_target, S_IWUSR, NULL, srp_remove_target);
+
 static ssize_t show_ibdev(struct class_device *class_dev, char *buf)
 {
 	struct srp_host *host =
@@ -1809,6 +1889,8 @@ static struct srp_host *srp_add_port(str
 		goto free_host;
 	if (class_device_create_file(&host->class_dev, &class_device_attr_add_target))
 		goto err_class;
+	if (class_device_create_file(&host->class_dev, &class_device_attr_remove_target))
+		goto err_class;
 	if (class_device_create_file(&host->class_dev, &class_device_attr_ibdev))
 		goto err_class;
 	if (class_device_create_file(&host->class_dev, &class_device_attr_port))
Index: last_stable/drivers/infiniband/ulp/srp/ib_srp.h
===================================================================
--- last_stable.orig/drivers/infiniband/ulp/srp/ib_srp.h	2006-05-01 12:30:01.000000000 +0300
+++ last_stable/drivers/infiniband/ulp/srp/ib_srp.h	2006-05-01 12:31:06.000000000 +0300
@@ -78,8 +78,10 @@ enum {
 enum srp_target_state {
 	SRP_TARGET_LIVE,
 	SRP_TARGET_CONNECTING,
+	SRP_TARGET_RECONNECTING,
+	SRP_TARGET_DISCONNECTED,
 	SRP_TARGET_DEAD,
-	SRP_TARGET_REMOVED
+	SRP_TARGET_REMOVED,
 };
 
 struct srp_device {
-- 
Ishai Rabinovitz



More information about the general mailing list