diff options
author | Christof Schmitt <christof.schmitt@de.ibm.com> | 2009-08-18 09:43:30 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2009-09-05 09:49:46 -0400 |
commit | 0fac3f477b6b520ae7d972ceb6e958e6807c8e1a (patch) | |
tree | bef6ee15c92486613dd918de6a8ff00311fc379d | |
parent | f4395b652636398eb4712e6f3caf79c9a6c02e21 (diff) |
[SCSI] zfcp: Handle failures during device allocation correctly
dev_set_name tries to allocate memory, so check the return value for
allocation failures. After dev_set_name succeeds, call device_register
as next step to be able to use put_device during error handling.
Reviewed-by: Swen Schillig <swen@vnet.ibm.com>
Signed-off-by: Christof Schmitt <christof.schmitt@de.ibm.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
-rw-r--r-- | drivers/s390/scsi/zfcp_aux.c | 65 |
1 files changed, 29 insertions, 36 deletions
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index a7954443ec19..1be6bf7e8ce6 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c | |||
@@ -274,6 +274,13 @@ struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, u64 fcp_lun) | |||
274 | { | 274 | { |
275 | struct zfcp_unit *unit; | 275 | struct zfcp_unit *unit; |
276 | 276 | ||
277 | read_lock_irq(&zfcp_data.config_lock); | ||
278 | if (zfcp_get_unit_by_lun(port, fcp_lun)) { | ||
279 | read_unlock_irq(&zfcp_data.config_lock); | ||
280 | return ERR_PTR(-EINVAL); | ||
281 | } | ||
282 | read_unlock_irq(&zfcp_data.config_lock); | ||
283 | |||
277 | unit = kzalloc(sizeof(struct zfcp_unit), GFP_KERNEL); | 284 | unit = kzalloc(sizeof(struct zfcp_unit), GFP_KERNEL); |
278 | if (!unit) | 285 | if (!unit) |
279 | return ERR_PTR(-ENOMEM); | 286 | return ERR_PTR(-ENOMEM); |
@@ -285,8 +292,11 @@ struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, u64 fcp_lun) | |||
285 | unit->port = port; | 292 | unit->port = port; |
286 | unit->fcp_lun = fcp_lun; | 293 | unit->fcp_lun = fcp_lun; |
287 | 294 | ||
288 | dev_set_name(&unit->sysfs_device, "0x%016llx", | 295 | if (dev_set_name(&unit->sysfs_device, "0x%016llx", |
289 | (unsigned long long) fcp_lun); | 296 | (unsigned long long) fcp_lun)) { |
297 | kfree(unit); | ||
298 | return ERR_PTR(-ENOMEM); | ||
299 | } | ||
290 | unit->sysfs_device.parent = &port->sysfs_device; | 300 | unit->sysfs_device.parent = &port->sysfs_device; |
291 | unit->sysfs_device.release = zfcp_sysfs_unit_release; | 301 | unit->sysfs_device.release = zfcp_sysfs_unit_release; |
292 | dev_set_drvdata(&unit->sysfs_device, unit); | 302 | dev_set_drvdata(&unit->sysfs_device, unit); |
@@ -302,13 +312,6 @@ struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, u64 fcp_lun) | |||
302 | unit->latencies.cmd.channel.min = 0xFFFFFFFF; | 312 | unit->latencies.cmd.channel.min = 0xFFFFFFFF; |
303 | unit->latencies.cmd.fabric.min = 0xFFFFFFFF; | 313 | unit->latencies.cmd.fabric.min = 0xFFFFFFFF; |
304 | 314 | ||
305 | read_lock_irq(&zfcp_data.config_lock); | ||
306 | if (zfcp_get_unit_by_lun(port, fcp_lun)) { | ||
307 | read_unlock_irq(&zfcp_data.config_lock); | ||
308 | goto err_out_free; | ||
309 | } | ||
310 | read_unlock_irq(&zfcp_data.config_lock); | ||
311 | |||
312 | if (device_register(&unit->sysfs_device)) { | 315 | if (device_register(&unit->sysfs_device)) { |
313 | put_device(&unit->sysfs_device); | 316 | put_device(&unit->sysfs_device); |
314 | return ERR_PTR(-EINVAL); | 317 | return ERR_PTR(-EINVAL); |
@@ -317,7 +320,7 @@ struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, u64 fcp_lun) | |||
317 | if (sysfs_create_group(&unit->sysfs_device.kobj, | 320 | if (sysfs_create_group(&unit->sysfs_device.kobj, |
318 | &zfcp_sysfs_unit_attrs)) { | 321 | &zfcp_sysfs_unit_attrs)) { |
319 | device_unregister(&unit->sysfs_device); | 322 | device_unregister(&unit->sysfs_device); |
320 | return ERR_PTR(-EIO); | 323 | return ERR_PTR(-EINVAL); |
321 | } | 324 | } |
322 | 325 | ||
323 | zfcp_unit_get(unit); | 326 | zfcp_unit_get(unit); |
@@ -332,10 +335,6 @@ struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, u64 fcp_lun) | |||
332 | zfcp_port_get(port); | 335 | zfcp_port_get(port); |
333 | 336 | ||
334 | return unit; | 337 | return unit; |
335 | |||
336 | err_out_free: | ||
337 | kfree(unit); | ||
338 | return ERR_PTR(-EINVAL); | ||
339 | } | 338 | } |
340 | 339 | ||
341 | /** | 340 | /** |
@@ -642,7 +641,13 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn, | |||
642 | u32 status, u32 d_id) | 641 | u32 status, u32 d_id) |
643 | { | 642 | { |
644 | struct zfcp_port *port; | 643 | struct zfcp_port *port; |
645 | int retval; | 644 | |
645 | read_lock_irq(&zfcp_data.config_lock); | ||
646 | if (zfcp_get_port_by_wwpn(adapter, wwpn)) { | ||
647 | read_unlock_irq(&zfcp_data.config_lock); | ||
648 | return ERR_PTR(-EINVAL); | ||
649 | } | ||
650 | read_unlock_irq(&zfcp_data.config_lock); | ||
646 | 651 | ||
647 | port = kzalloc(sizeof(struct zfcp_port), GFP_KERNEL); | 652 | port = kzalloc(sizeof(struct zfcp_port), GFP_KERNEL); |
648 | if (!port) | 653 | if (!port) |
@@ -663,31 +668,24 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn, | |||
663 | atomic_set_mask(status | ZFCP_STATUS_COMMON_REMOVE, &port->status); | 668 | atomic_set_mask(status | ZFCP_STATUS_COMMON_REMOVE, &port->status); |
664 | atomic_set(&port->refcount, 0); | 669 | atomic_set(&port->refcount, 0); |
665 | 670 | ||
666 | dev_set_name(&port->sysfs_device, "0x%016llx", | 671 | if (dev_set_name(&port->sysfs_device, "0x%016llx", |
667 | (unsigned long long)wwpn); | 672 | (unsigned long long)wwpn)) { |
673 | kfree(port); | ||
674 | return ERR_PTR(-ENOMEM); | ||
675 | } | ||
668 | port->sysfs_device.parent = &adapter->ccw_device->dev; | 676 | port->sysfs_device.parent = &adapter->ccw_device->dev; |
669 | |||
670 | port->sysfs_device.release = zfcp_sysfs_port_release; | 677 | port->sysfs_device.release = zfcp_sysfs_port_release; |
671 | dev_set_drvdata(&port->sysfs_device, port); | 678 | dev_set_drvdata(&port->sysfs_device, port); |
672 | 679 | ||
673 | read_lock_irq(&zfcp_data.config_lock); | ||
674 | if (zfcp_get_port_by_wwpn(adapter, wwpn)) { | ||
675 | read_unlock_irq(&zfcp_data.config_lock); | ||
676 | goto err_out_free; | ||
677 | } | ||
678 | read_unlock_irq(&zfcp_data.config_lock); | ||
679 | |||
680 | if (device_register(&port->sysfs_device)) { | 680 | if (device_register(&port->sysfs_device)) { |
681 | put_device(&port->sysfs_device); | 681 | put_device(&port->sysfs_device); |
682 | goto err_out; | 682 | return ERR_PTR(-EINVAL); |
683 | } | 683 | } |
684 | 684 | ||
685 | retval = sysfs_create_group(&port->sysfs_device.kobj, | 685 | if (sysfs_create_group(&port->sysfs_device.kobj, |
686 | &zfcp_sysfs_port_attrs); | 686 | &zfcp_sysfs_port_attrs)) { |
687 | |||
688 | if (retval) { | ||
689 | device_unregister(&port->sysfs_device); | 687 | device_unregister(&port->sysfs_device); |
690 | goto err_out; | 688 | return ERR_PTR(-EINVAL); |
691 | } | 689 | } |
692 | 690 | ||
693 | zfcp_port_get(port); | 691 | zfcp_port_get(port); |
@@ -701,11 +699,6 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn, | |||
701 | 699 | ||
702 | zfcp_adapter_get(adapter); | 700 | zfcp_adapter_get(adapter); |
703 | return port; | 701 | return port; |
704 | |||
705 | err_out_free: | ||
706 | kfree(port); | ||
707 | err_out: | ||
708 | return ERR_PTR(-EINVAL); | ||
709 | } | 702 | } |
710 | 703 | ||
711 | /** | 704 | /** |