diff options
Diffstat (limited to 'drivers/s390/scsi/zfcp_unit.c')
| -rw-r--r-- | drivers/s390/scsi/zfcp_unit.c | 41 |
1 files changed, 26 insertions, 15 deletions
diff --git a/drivers/s390/scsi/zfcp_unit.c b/drivers/s390/scsi/zfcp_unit.c index 20796ebc33c..39f5446f721 100644 --- a/drivers/s390/scsi/zfcp_unit.c +++ b/drivers/s390/scsi/zfcp_unit.c @@ -4,7 +4,7 @@ * Tracking of manually configured LUNs and helper functions to * register the LUNs with the SCSI midlayer. * - * Copyright IBM Corporation 2010 + * Copyright IBM Corp. 2010 */ #include "zfcp_def.h" @@ -104,7 +104,7 @@ static void zfcp_unit_release(struct device *dev) { struct zfcp_unit *unit = container_of(dev, struct zfcp_unit, dev); - put_device(&unit->port->dev); + atomic_dec(&unit->port->units); kfree(unit); } @@ -119,40 +119,49 @@ static void zfcp_unit_release(struct device *dev) int zfcp_unit_add(struct zfcp_port *port, u64 fcp_lun) { struct zfcp_unit *unit; + int retval = 0; + + mutex_lock(&zfcp_sysfs_port_units_mutex); + if (atomic_read(&port->units) == -1) { + /* port is already gone */ + retval = -ENODEV; + goto out; + } unit = zfcp_unit_find(port, fcp_lun); if (unit) { put_device(&unit->dev); - return -EEXIST; + retval = -EEXIST; + goto out; } unit = kzalloc(sizeof(struct zfcp_unit), GFP_KERNEL); - if (!unit) - return -ENOMEM; + if (!unit) { + retval = -ENOMEM; + goto out; + } unit->port = port; unit->fcp_lun = fcp_lun; unit->dev.parent = &port->dev; unit->dev.release = zfcp_unit_release; + unit->dev.groups = zfcp_unit_attr_groups; INIT_WORK(&unit->scsi_work, zfcp_unit_scsi_scan_work); if (dev_set_name(&unit->dev, "0x%016llx", (unsigned long long) fcp_lun)) { kfree(unit); - return -ENOMEM; + retval = -ENOMEM; + goto out; } - get_device(&port->dev); - if (device_register(&unit->dev)) { put_device(&unit->dev); - return -ENOMEM; + retval = -ENOMEM; + goto out; } - if (sysfs_create_group(&unit->dev.kobj, &zfcp_sysfs_unit_attrs)) { - device_unregister(&unit->dev); - return -EINVAL; - } + atomic_inc(&port->units); /* under zfcp_sysfs_port_units_mutex ! */ write_lock_irq(&port->unit_list_lock); list_add_tail(&unit->list, &port->unit_list); @@ -160,7 +169,9 @@ int zfcp_unit_add(struct zfcp_port *port, u64 fcp_lun) zfcp_unit_scsi_scan(unit); - return 0; +out: + mutex_unlock(&zfcp_sysfs_port_units_mutex); + return retval; } /** @@ -238,7 +249,7 @@ int zfcp_unit_remove(struct zfcp_port *port, u64 fcp_lun) put_device(&unit->dev); - zfcp_device_unregister(&unit->dev, &zfcp_sysfs_unit_attrs); + device_unregister(&unit->dev); return 0; } |
