Support a remove of a target from user level. Signed-off-by: Ishai Rabinovitz <[EMAIL PROTECTED]> 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 _______________________________________________ openib-general mailing list openib-general@openib.org http://openib.org/mailman/listinfo/openib-general
To unsubscribe, please visit http://openib.org/mailman/listinfo/openib-general