[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