|
@@ -104,7 +104,7 @@ static void zfcp_unit_release(struct device *dev)
|
|
{
|
|
{
|
|
struct zfcp_unit *unit = container_of(dev, struct zfcp_unit, dev);
|
|
struct zfcp_unit *unit = container_of(dev, struct zfcp_unit, dev);
|
|
|
|
|
|
- put_device(&unit->port->dev);
|
|
|
|
|
|
+ atomic_dec(&unit->port->units);
|
|
kfree(unit);
|
|
kfree(unit);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -119,16 +119,27 @@ static void zfcp_unit_release(struct device *dev)
|
|
int zfcp_unit_add(struct zfcp_port *port, u64 fcp_lun)
|
|
int zfcp_unit_add(struct zfcp_port *port, u64 fcp_lun)
|
|
{
|
|
{
|
|
struct zfcp_unit *unit;
|
|
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);
|
|
unit = zfcp_unit_find(port, fcp_lun);
|
|
if (unit) {
|
|
if (unit) {
|
|
put_device(&unit->dev);
|
|
put_device(&unit->dev);
|
|
- return -EEXIST;
|
|
|
|
|
|
+ retval = -EEXIST;
|
|
|
|
+ goto out;
|
|
}
|
|
}
|
|
|
|
|
|
unit = kzalloc(sizeof(struct zfcp_unit), GFP_KERNEL);
|
|
unit = kzalloc(sizeof(struct zfcp_unit), GFP_KERNEL);
|
|
- if (!unit)
|
|
|
|
- return -ENOMEM;
|
|
|
|
|
|
+ if (!unit) {
|
|
|
|
+ retval = -ENOMEM;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
|
|
unit->port = port;
|
|
unit->port = port;
|
|
unit->fcp_lun = fcp_lun;
|
|
unit->fcp_lun = fcp_lun;
|
|
@@ -139,28 +150,33 @@ int zfcp_unit_add(struct zfcp_port *port, u64 fcp_lun)
|
|
if (dev_set_name(&unit->dev, "0x%016llx",
|
|
if (dev_set_name(&unit->dev, "0x%016llx",
|
|
(unsigned long long) fcp_lun)) {
|
|
(unsigned long long) fcp_lun)) {
|
|
kfree(unit);
|
|
kfree(unit);
|
|
- return -ENOMEM;
|
|
|
|
|
|
+ retval = -ENOMEM;
|
|
|
|
+ goto out;
|
|
}
|
|
}
|
|
|
|
|
|
- get_device(&port->dev);
|
|
|
|
-
|
|
|
|
if (device_register(&unit->dev)) {
|
|
if (device_register(&unit->dev)) {
|
|
put_device(&unit->dev);
|
|
put_device(&unit->dev);
|
|
- return -ENOMEM;
|
|
|
|
|
|
+ retval = -ENOMEM;
|
|
|
|
+ goto out;
|
|
}
|
|
}
|
|
|
|
|
|
if (sysfs_create_group(&unit->dev.kobj, &zfcp_sysfs_unit_attrs)) {
|
|
if (sysfs_create_group(&unit->dev.kobj, &zfcp_sysfs_unit_attrs)) {
|
|
device_unregister(&unit->dev);
|
|
device_unregister(&unit->dev);
|
|
- return -EINVAL;
|
|
|
|
|
|
+ retval = -EINVAL;
|
|
|
|
+ goto out;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ atomic_inc(&port->units); /* under zfcp_sysfs_port_units_mutex ! */
|
|
|
|
+
|
|
write_lock_irq(&port->unit_list_lock);
|
|
write_lock_irq(&port->unit_list_lock);
|
|
list_add_tail(&unit->list, &port->unit_list);
|
|
list_add_tail(&unit->list, &port->unit_list);
|
|
write_unlock_irq(&port->unit_list_lock);
|
|
write_unlock_irq(&port->unit_list_lock);
|
|
|
|
|
|
zfcp_unit_scsi_scan(unit);
|
|
zfcp_unit_scsi_scan(unit);
|
|
|
|
|
|
- return 0;
|
|
|
|
|
|
+out:
|
|
|
|
+ mutex_unlock(&zfcp_sysfs_port_units_mutex);
|
|
|
|
+ return retval;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|