[openib-general] [PATCH 04/12] SRP: Changing ibsrpdm
Ishai Rabinovitz
ishai at mellanox.co.il
Mon May 1 04:27:39 PDT 2006
Do not add the same target twice.
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-04-25 15:17:34.000000000 +0300
+++ last_stable/drivers/infiniband/ulp/srp/ib_srp.c 2006-04-25 15:19:37.000000000 +0300
@@ -1478,7 +1478,8 @@ static int srp_parse_options(const char
printk(KERN_WARNING PFX "bad max sect parameter '%s'\n", p);
goto out;
}
- target->scsi_host->max_sectors = token;
+ if (target->scsi_host != NULL)
+ target->scsi_host->max_sectors = token;
break;
default:
@@ -1503,20 +1504,89 @@ out:
return ret;
}
+/* srp_find_target - If the target exists return it in target,
+ otherwise target is set to NULL.
+ host->target_mutex should be hold */
+static int srp_find_target(const char *buf, struct srp_host *host,
+ struct srp_target_port **target)
+{
+ struct srp_target_port *target_to_find, *curr_target;
+ int ret, i;
+
+ target_to_find = kzalloc(sizeof *target_to_find, GFP_KERNEL);
+ ret = srp_parse_options(buf, target_to_find);
+ if (ret)
+ goto free;
+
+ list_for_each_entry(curr_target, &host->target_list, list)
+ if (target_to_find->ioc_guid == curr_target->ioc_guid &&
+ target_to_find->id_ext == curr_target->id_ext &&
+ target_to_find->path.pkey == curr_target->path.pkey &&
+ target_to_find->service_id == curr_target->service_id) {
+ for (i = 0; i < 16; ++i)
+ if (target_to_find->path.dgid.raw[i] != curr_target->path.dgid.raw[i])
+ break;
+ if (i == 16) {
+ *target = curr_target;
+ goto free;
+ }
+ }
+
+ *target = NULL;
+
+free:
+ kfree(target_to_find);
+ return 0;
+}
+
static ssize_t srp_create_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 Scsi_Host *target_host;
- struct srp_target_port *target;
+ struct srp_target_port *target, *existing_target = NULL;
int ret;
int i;
+ /* first check if the target already exists */
+
+ mutex_lock(&host->target_mutex);
+ ret = srp_find_target(buf, host, &existing_target);
+ if (ret)
+ goto unlock_mutex;
+
+ if (existing_target) {
+ /* target already exists */
+ spin_lock_irq(existing_target->scsi_host->host_lock);
+ switch (existing_target->state) {
+ case SRP_TARGET_LIVE:
+ printk(KERN_WARNING PFX "target %s already exists\n",
+ buf);
+ ret = -EEXIST;
+ break;
+ case SRP_TARGET_CONNECTING:
+ /* It is in the middle of reconnecting */
+ ret = -EALREADY;
+ break;
+ case SRP_TARGET_DEAD:
+ /* It will be removed soon - create a new one */
+ case SRP_TARGET_REMOVED:
+ /* target is dead, create a new one */
+ break;
+ }
+ spin_unlock_irq(existing_target->scsi_host->host_lock);
+ if (ret)
+ goto unlock_mutex;
+ }
+
+ /* really create the target */
target_host = scsi_host_alloc(&srp_template,
sizeof (struct srp_target_port));
- if (!target_host)
- return -ENOMEM;
+ if (!target_host) {
+ ret = -ENOMEM;
+ goto unlock_mutex;
+ }
target_host->max_lun = SRP_MAX_LUN;
@@ -1533,7 +1603,7 @@ static ssize_t srp_create_target(struct
ret = srp_parse_options(buf, target);
if (ret)
- goto err;
+ goto err_put_scsi_host;
ib_get_cached_gid(host->dev, host->port, 0, &target->path.sgid);
@@ -1554,7 +1624,7 @@ static ssize_t srp_create_target(struct
ret = srp_create_target_ib(target);
if (ret)
- goto err;
+ goto err_put_scsi_host;
target->cm_id = ib_create_cm_id(host->dev, srp_cm_handler, target);
if (IS_ERR(target->cm_id)) {
@@ -1572,7 +1642,8 @@ static ssize_t srp_create_target(struct
if (ret)
goto err_disconnect;
- return count;
+ ret = count;
+ goto unlock_mutex;
err_disconnect:
srp_disconnect_target(target);
@@ -1583,9 +1654,12 @@ err_cm_id:
err_free:
srp_free_target_ib(target);
-err:
+err_put_scsi_host:
scsi_host_put(target_host);
+unlock_mutex:
+ mutex_unlock(&host->target_mutex);
+
return ret;
}
--
Ishai Rabinovitz
More information about the general
mailing list