@@ -417,11 +417,8 @@ static void disk_scan_partitions(struct gendisk *disk)
417
417
*
418
418
* This function registers the partitioning information in @disk
419
419
* with the kernel.
420
- *
421
- * FIXME: error handling
422
420
*/
423
-
424
- void device_add_disk (struct device * parent , struct gendisk * disk ,
421
+ int device_add_disk (struct device * parent , struct gendisk * disk ,
425
422
const struct attribute_group * * groups )
426
423
427
424
{
@@ -444,27 +441,29 @@ void device_add_disk(struct device *parent, struct gendisk *disk,
444
441
* and all partitions from the extended dev_t space.
445
442
*/
446
443
if (disk -> major ) {
447
- WARN_ON (!disk -> minors );
444
+ if (WARN_ON (!disk -> minors ))
445
+ return - EINVAL ;
448
446
449
447
if (disk -> minors > DISK_MAX_PARTS ) {
450
448
pr_err ("block: can't allocate more than %d partitions\n" ,
451
449
DISK_MAX_PARTS );
452
450
disk -> minors = DISK_MAX_PARTS ;
453
451
}
454
452
} else {
455
- WARN_ON (disk -> minors );
453
+ if (WARN_ON (disk -> minors ))
454
+ return - EINVAL ;
456
455
457
456
ret = blk_alloc_ext_minor ();
458
- if (ret < 0 ) {
459
- WARN_ON (1 );
460
- return ;
461
- }
457
+ if (ret < 0 )
458
+ return ret ;
462
459
disk -> major = BLOCK_EXT_MAJOR ;
463
460
disk -> first_minor = MINOR (ret );
464
461
disk -> flags |= GENHD_FL_EXT_DEVT ;
465
462
}
466
463
467
- disk_alloc_events (disk );
464
+ ret = disk_alloc_events (disk );
465
+ if (ret )
466
+ goto out_free_ext_minor ;
468
467
469
468
/* delay uevents, until we scanned partition table */
470
469
dev_set_uevent_suppress (ddev , 1 );
@@ -474,15 +473,14 @@ void device_add_disk(struct device *parent, struct gendisk *disk,
474
473
dev_set_name (ddev , "%s" , disk -> disk_name );
475
474
if (!(disk -> flags & GENHD_FL_HIDDEN ))
476
475
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 ;
479
479
if (!sysfs_deprecated ) {
480
480
ret = sysfs_create_link (block_depr , & ddev -> kobj ,
481
481
kobject_name (& ddev -> kobj ));
482
- if (ret ) {
483
- device_del (ddev );
484
- return ;
485
- }
482
+ if (ret )
483
+ goto out_device_del ;
486
484
}
487
485
488
486
/*
@@ -492,23 +490,25 @@ void device_add_disk(struct device *parent, struct gendisk *disk,
492
490
*/
493
491
pm_runtime_set_memalloc_noio (ddev , true);
494
492
495
- blk_integrity_add (disk );
493
+ ret = blk_integrity_add (disk );
494
+ if (ret )
495
+ goto out_del_block_link ;
496
496
497
497
disk -> part0 -> bd_holder_dir =
498
498
kobject_create_and_add ("holders" , & ddev -> kobj );
499
+ if (!disk -> part0 -> bd_holder_dir )
500
+ goto out_del_integrity ;
499
501
disk -> slave_dir = kobject_create_and_add ("slaves" , & ddev -> kobj );
502
+ if (!disk -> slave_dir )
503
+ goto out_put_holder_dir ;
500
504
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 ;
510
508
511
- blk_register_queue (disk );
509
+ ret = blk_register_queue (disk );
510
+ if (ret )
511
+ goto out_put_slave_dir ;
512
512
513
513
if (disk -> flags & GENHD_FL_HIDDEN ) {
514
514
/*
@@ -520,13 +520,13 @@ void device_add_disk(struct device *parent, struct gendisk *disk,
520
520
} else {
521
521
ret = bdi_register (disk -> bdi , "%u:%u" ,
522
522
disk -> major , disk -> first_minor );
523
- WARN_ON (ret );
523
+ if (ret )
524
+ goto out_unregister_queue ;
524
525
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 ;
530
530
531
531
bdev_add (disk -> part0 , ddev -> devt );
532
532
disk_scan_partitions (disk );
@@ -541,6 +541,30 @@ void device_add_disk(struct device *parent, struct gendisk *disk,
541
541
542
542
disk_update_readahead (disk );
543
543
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 */
544
568
}
545
569
EXPORT_SYMBOL (device_add_disk );
546
570
0 commit comments