@@ -417,11 +417,8 @@ static void disk_scan_partitions(struct gendisk *disk)
417417 *
418418 * This function registers the partitioning information in @disk
419419 * with the kernel.
420- *
421- * FIXME: error handling
422420 */
423-
424- void device_add_disk (struct device * parent , struct gendisk * disk ,
421+ int device_add_disk (struct device * parent , struct gendisk * disk ,
425422 const struct attribute_group * * groups )
426423
427424{
@@ -444,27 +441,29 @@ void device_add_disk(struct device *parent, struct gendisk *disk,
444441 * and all partitions from the extended dev_t space.
445442 */
446443 if (disk -> major ) {
447- WARN_ON (!disk -> minors );
444+ if (WARN_ON (!disk -> minors ))
445+ return - EINVAL ;
448446
449447 if (disk -> minors > DISK_MAX_PARTS ) {
450448 pr_err ("block: can't allocate more than %d partitions\n" ,
451449 DISK_MAX_PARTS );
452450 disk -> minors = DISK_MAX_PARTS ;
453451 }
454452 } else {
455- WARN_ON (disk -> minors );
453+ if (WARN_ON (disk -> minors ))
454+ return - EINVAL ;
456455
457456 ret = blk_alloc_ext_minor ();
458- if (ret < 0 ) {
459- WARN_ON (1 );
460- return ;
461- }
457+ if (ret < 0 )
458+ return ret ;
462459 disk -> major = BLOCK_EXT_MAJOR ;
463460 disk -> first_minor = MINOR (ret );
464461 disk -> flags |= GENHD_FL_EXT_DEVT ;
465462 }
466463
467- disk_alloc_events (disk );
464+ ret = disk_alloc_events (disk );
465+ if (ret )
466+ goto out_free_ext_minor ;
468467
469468 /* delay uevents, until we scanned partition table */
470469 dev_set_uevent_suppress (ddev , 1 );
@@ -474,15 +473,14 @@ void device_add_disk(struct device *parent, struct gendisk *disk,
474473 dev_set_name (ddev , "%s" , disk -> disk_name );
475474 if (!(disk -> flags & GENHD_FL_HIDDEN ))
476475 ddev -> devt = MKDEV (disk -> major , disk -> first_minor );
477- if (device_add (ddev ))
478- return ;
476+ ret = device_add (ddev );
477+ if (ret )
478+ goto out_disk_release_events ;
479479 if (!sysfs_deprecated ) {
480480 ret = sysfs_create_link (block_depr , & ddev -> kobj ,
481481 kobject_name (& ddev -> kobj ));
482- if (ret ) {
483- device_del (ddev );
484- return ;
485- }
482+ if (ret )
483+ goto out_device_del ;
486484 }
487485
488486 /*
@@ -492,23 +490,25 @@ void device_add_disk(struct device *parent, struct gendisk *disk,
492490 */
493491 pm_runtime_set_memalloc_noio (ddev , true);
494492
495- blk_integrity_add (disk );
493+ ret = blk_integrity_add (disk );
494+ if (ret )
495+ goto out_del_block_link ;
496496
497497 disk -> part0 -> bd_holder_dir =
498498 kobject_create_and_add ("holders" , & ddev -> kobj );
499+ if (!disk -> part0 -> bd_holder_dir )
500+ goto out_del_integrity ;
499501 disk -> slave_dir = kobject_create_and_add ("slaves" , & ddev -> kobj );
502+ if (!disk -> slave_dir )
503+ goto out_put_holder_dir ;
500504
501- /*
502- * XXX: this is a mess, can't wait for real error handling in add_disk.
503- * Make sure ->slave_dir is NULL if we failed some of the registration
504- * so that the cleanup in bd_unlink_disk_holder works properly.
505- */
506- if (bd_register_pending_holders (disk ) < 0 ) {
507- kobject_put (disk -> slave_dir );
508- disk -> slave_dir = NULL ;
509- }
505+ ret = bd_register_pending_holders (disk );
506+ if (ret < 0 )
507+ goto out_put_slave_dir ;
510508
511- blk_register_queue (disk );
509+ ret = blk_register_queue (disk );
510+ if (ret )
511+ goto out_put_slave_dir ;
512512
513513 if (disk -> flags & GENHD_FL_HIDDEN ) {
514514 /*
@@ -520,13 +520,13 @@ void device_add_disk(struct device *parent, struct gendisk *disk,
520520 } else {
521521 ret = bdi_register (disk -> bdi , "%u:%u" ,
522522 disk -> major , disk -> first_minor );
523- WARN_ON (ret );
523+ if (ret )
524+ goto out_unregister_queue ;
524525 bdi_set_owner (disk -> bdi , ddev );
525- if (disk -> bdi -> dev ) {
526- ret = sysfs_create_link (& ddev -> kobj ,
527- & disk -> bdi -> dev -> kobj , "bdi" );
528- WARN_ON (ret );
529- }
526+ ret = sysfs_create_link (& ddev -> kobj ,
527+ & disk -> bdi -> dev -> kobj , "bdi" );
528+ if (ret )
529+ goto out_unregister_bdi ;
530530
531531 bdev_add (disk -> part0 , ddev -> devt );
532532 disk_scan_partitions (disk );
@@ -541,6 +541,30 @@ void device_add_disk(struct device *parent, struct gendisk *disk,
541541
542542 disk_update_readahead (disk );
543543 disk_add_events (disk );
544+ return 0 ;
545+
546+ out_unregister_bdi :
547+ if (!(disk -> flags & GENHD_FL_HIDDEN ))
548+ bdi_unregister (disk -> bdi );
549+ out_unregister_queue :
550+ blk_unregister_queue (disk );
551+ out_put_slave_dir :
552+ kobject_put (disk -> slave_dir );
553+ out_put_holder_dir :
554+ kobject_put (disk -> part0 -> bd_holder_dir );
555+ out_del_integrity :
556+ blk_integrity_del (disk );
557+ out_del_block_link :
558+ if (!sysfs_deprecated )
559+ sysfs_remove_link (block_depr , dev_name (ddev ));
560+ out_device_del :
561+ device_del (ddev );
562+ out_disk_release_events :
563+ disk_release_events (disk );
564+ out_free_ext_minor :
565+ if (disk -> major == BLOCK_EXT_MAJOR )
566+ blk_free_ext_minor (disk -> first_minor );
567+ return WARN_ON_ONCE (ret ); /* keep until all callers handle errors */
544568}
545569EXPORT_SYMBOL (device_add_disk );
546570
0 commit comments