static ssize_t zfcp_sysfs_unit_remove_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct zfcp_port *port = dev_get_drvdata(dev); struct zfcp_unit *unit; u64 fcp_lun; LIST_HEAD(unit_remove_lh); struct scsi_device *sdev; mutex_lock(&zfcp_data.config_mutex); if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_REMOVE) { mutex_unlock(&zfcp_data.config_mutex); return -EBUSY; } if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun)) { mutex_unlock(&zfcp_data.config_mutex); return -EINVAL; } read_lock_irq(&zfcp_data.config_lock); unit = zfcp_get_unit_by_lun(port, fcp_lun); read_unlock_irq(&zfcp_data.config_lock); if (!unit) { mutex_unlock(&zfcp_data.config_mutex); return -ENXIO; } zfcp_unit_get(unit); mutex_unlock(&zfcp_data.config_mutex); sdev = scsi_device_lookup(port->adapter->scsi_host, 0, port->starget_id, scsilun_to_int((struct scsi_lun *)&fcp_lun)); if (sdev) { scsi_remove_device(sdev); scsi_device_put(sdev); } mutex_lock(&zfcp_data.config_mutex); zfcp_unit_put(unit); if (atomic_read(&unit->refcount)) { mutex_unlock(&zfcp_data.config_mutex); return -ENXIO; } write_lock_irq(&zfcp_data.config_lock); atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &unit->status); list_move(&unit->list, &unit_remove_lh); write_unlock_irq(&zfcp_data.config_lock); mutex_unlock(&zfcp_data.config_mutex); zfcp_erp_unit_shutdown(unit, 0, "syurs_1", NULL); zfcp_erp_wait(unit->port->adapter); zfcp_unit_dequeue(unit); return (ssize_t)count; }
static ssize_t zfcp_sysfs_unit_remove_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct zfcp_port *port = dev_get_drvdata(dev); struct zfcp_unit *unit; u64 fcp_lun; int retval = 0; LIST_HEAD(unit_remove_lh); mutex_lock(&zfcp_data.config_mutex); if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_REMOVE) { retval = -EBUSY; goto out; } if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun)) { retval = -EINVAL; goto out; } write_lock_irq(&zfcp_data.config_lock); unit = zfcp_get_unit_by_lun(port, fcp_lun); if (unit) { write_unlock_irq(&zfcp_data.config_lock); flush_work(&unit->scsi_work); write_lock_irq(&zfcp_data.config_lock); if (atomic_read(&unit->refcount) == 0) { zfcp_unit_get(unit); atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &unit->status); list_move(&unit->list, &unit_remove_lh); } else { unit = NULL; } } write_unlock_irq(&zfcp_data.config_lock); if (!unit) { retval = -ENXIO; goto out; } zfcp_erp_unit_shutdown(unit, 0, "syurs_1", NULL); zfcp_erp_wait(unit->port->adapter); zfcp_unit_put(unit); zfcp_unit_dequeue(unit); out: mutex_unlock(&zfcp_data.config_mutex); return retval ? retval : (ssize_t) count; }
/** * zfcp_sysfs_unit_remove_store - remove a unit from sysfs tree * @dev: pointer to belonging device * @buf: pointer to input buffer * @count: number of bytes in buffer */ static ssize_t zfcp_sysfs_unit_remove_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct zfcp_port *port; struct zfcp_unit *unit; fcp_lun_t fcp_lun; char *endp; int retval = 0; down(&zfcp_data.config_sema); port = dev_get_drvdata(dev); if (atomic_test_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status)) { retval = -EBUSY; goto out; } fcp_lun = simple_strtoull(buf, &endp, 0); if ((endp + 1) < (buf + count)) { retval = -EINVAL; goto out; } write_lock_irq(&zfcp_data.config_lock); unit = zfcp_get_unit_by_lun(port, fcp_lun); if (unit && (atomic_read(&unit->refcount) == 0)) { zfcp_unit_get(unit); atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &unit->status); list_move(&unit->list, &port->unit_remove_lh); } else { unit = NULL; } write_unlock_irq(&zfcp_data.config_lock); if (!unit) { retval = -ENXIO; goto out; } zfcp_erp_unit_shutdown(unit, 0); zfcp_erp_wait(unit->port->adapter); zfcp_unit_put(unit); zfcp_unit_dequeue(unit); out: up(&zfcp_data.config_sema); return retval ? retval : (ssize_t) count; }
static ssize_t zfcp_sysfs_unit_remove_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct zfcp_port *port = container_of(dev, struct zfcp_port, dev); struct zfcp_unit *unit; u64 fcp_lun; int retval = -EINVAL; struct scsi_device *sdev; if (!(port && get_device(&port->dev))) return -EBUSY; if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun)) goto out; unit = zfcp_get_unit_by_lun(port, fcp_lun); if (!unit) goto out; else retval = 0; sdev = scsi_device_lookup(port->adapter->scsi_host, 0, port->starget_id, scsilun_to_int((struct scsi_lun *)&fcp_lun)); if (sdev) { scsi_remove_device(sdev); scsi_device_put(sdev); } write_lock_irq(&port->unit_list_lock); list_del(&unit->list); write_unlock_irq(&port->unit_list_lock); put_device(&unit->dev); zfcp_erp_unit_shutdown(unit, 0, "syurs_1", NULL); zfcp_device_unregister(&unit->dev, &zfcp_sysfs_unit_attrs); out: put_device(&port->dev); return retval ? retval : (ssize_t) count; }