Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mtd: utilize new cdev_device_add helper function

This is not as straightforward a conversion as the others
in this series. These drivers did not originally make use of
kobj.parent so they likely suffered from a use after free bug if
someone unregistered the devices while they are being used.

In order to make the conversions, switch from device_register
to device_initialize / cdev_device_add.

In build.c, this patch unwinds a complicated mess of extra
get_device/put_devices and reference tracking by moving device_initialize
early in the attach process. Then it always uses put_device and instead of
using device_unregister and extra get_devices everywhere we just use
cdev_device_del and one put_device once everything is completely done.
This simplifies things dramatically and makes it easier to reason about.

In vmt.c, the patch pushes device initialization up to the beginning of the
device creation and then that function only needs to use put_device
in the error path which simplifies things a good deal.

Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Logan Gunthorpe and committed by
Greg Kroah-Hartman
493cfaea 857313e5

+33 -107
+17 -74
drivers/mtd/ubi/build.c
··· 421 421 } 422 422 423 423 /** 424 - * ubi_sysfs_init - initialize sysfs for an UBI device. 425 - * @ubi: UBI device description object 426 - * @ref: set to %1 on exit in case of failure if a reference to @ubi->dev was 427 - * taken 428 - * 429 - * This function returns zero in case of success and a negative error code in 430 - * case of failure. 431 - */ 432 - static int ubi_sysfs_init(struct ubi_device *ubi, int *ref) 433 - { 434 - int err; 435 - 436 - ubi->dev.release = dev_release; 437 - ubi->dev.devt = ubi->cdev.dev; 438 - ubi->dev.class = &ubi_class; 439 - ubi->dev.groups = ubi_dev_groups; 440 - dev_set_name(&ubi->dev, UBI_NAME_STR"%d", ubi->ubi_num); 441 - err = device_register(&ubi->dev); 442 - if (err) 443 - return err; 444 - 445 - *ref = 1; 446 - return 0; 447 - } 448 - 449 - /** 450 - * ubi_sysfs_close - close sysfs for an UBI device. 451 - * @ubi: UBI device description object 452 - */ 453 - static void ubi_sysfs_close(struct ubi_device *ubi) 454 - { 455 - device_unregister(&ubi->dev); 456 - } 457 - 458 - /** 459 424 * kill_volumes - destroy all user volumes. 460 425 * @ubi: UBI device description object 461 426 */ ··· 436 471 /** 437 472 * uif_init - initialize user interfaces for an UBI device. 438 473 * @ubi: UBI device description object 439 - * @ref: set to %1 on exit in case of failure if a reference to @ubi->dev was 440 - * taken, otherwise set to %0 441 474 * 442 475 * This function initializes various user interfaces for an UBI device. If the 443 476 * initialization fails at an early stage, this function frees all the 444 - * resources it allocated, returns an error, and @ref is set to %0. However, 445 - * if the initialization fails after the UBI device was registered in the 446 - * driver core subsystem, this function takes a reference to @ubi->dev, because 447 - * otherwise the release function ('dev_release()') would free whole @ubi 448 - * object. The @ref argument is set to %1 in this case. The caller has to put 449 - * this reference. 477 + * resources it allocated, returns an error. 450 478 * 451 479 * This function returns zero in case of success and a negative error code in 452 480 * case of failure. 453 481 */ 454 - static int uif_init(struct ubi_device *ubi, int *ref) 482 + static int uif_init(struct ubi_device *ubi) 455 483 { 456 484 int i, err; 457 485 dev_t dev; 458 486 459 - *ref = 0; 460 487 sprintf(ubi->ubi_name, UBI_NAME_STR "%d", ubi->ubi_num); 461 488 462 489 /* ··· 465 508 return err; 466 509 } 467 510 511 + ubi->dev.devt = dev; 512 + 468 513 ubi_assert(MINOR(dev) == 0); 469 514 cdev_init(&ubi->cdev, &ubi_cdev_operations); 470 515 dbg_gen("%s major is %u", ubi->ubi_name, MAJOR(dev)); 471 516 ubi->cdev.owner = THIS_MODULE; 472 517 473 - err = cdev_add(&ubi->cdev, dev, 1); 474 - if (err) { 475 - ubi_err(ubi, "cannot add character device"); 476 - goto out_unreg; 477 - } 478 - 479 - err = ubi_sysfs_init(ubi, ref); 518 + dev_set_name(&ubi->dev, UBI_NAME_STR "%d", ubi->ubi_num); 519 + err = cdev_device_add(&ubi->cdev, &ubi->dev); 480 520 if (err) 481 - goto out_sysfs; 521 + goto out_unreg; 482 522 483 523 for (i = 0; i < ubi->vtbl_slots; i++) 484 524 if (ubi->volumes[i]) { ··· 490 536 491 537 out_volumes: 492 538 kill_volumes(ubi); 493 - out_sysfs: 494 - if (*ref) 495 - get_device(&ubi->dev); 496 - ubi_sysfs_close(ubi); 497 - cdev_del(&ubi->cdev); 539 + cdev_device_del(&ubi->cdev, &ubi->dev); 498 540 out_unreg: 499 541 unregister_chrdev_region(ubi->cdev.dev, ubi->vtbl_slots + 1); 500 542 ubi_err(ubi, "cannot initialize UBI %s, error %d", ··· 509 559 static void uif_close(struct ubi_device *ubi) 510 560 { 511 561 kill_volumes(ubi); 512 - ubi_sysfs_close(ubi); 513 - cdev_del(&ubi->cdev); 562 + cdev_device_del(&ubi->cdev, &ubi->dev); 514 563 unregister_chrdev_region(ubi->cdev.dev, ubi->vtbl_slots + 1); 515 564 } 516 565 ··· 806 857 int vid_hdr_offset, int max_beb_per1024) 807 858 { 808 859 struct ubi_device *ubi; 809 - int i, err, ref = 0; 860 + int i, err; 810 861 811 862 if (max_beb_per1024 < 0 || max_beb_per1024 > MAX_MTD_UBI_BEB_LIMIT) 812 863 return -EINVAL; ··· 867 918 ubi = kzalloc(sizeof(struct ubi_device), GFP_KERNEL); 868 919 if (!ubi) 869 920 return -ENOMEM; 921 + 922 + device_initialize(&ubi->dev); 923 + ubi->dev.release = dev_release; 924 + ubi->dev.class = &ubi_class; 925 + ubi->dev.groups = ubi_dev_groups; 870 926 871 927 ubi->mtd = mtd; 872 928 ubi->ubi_num = ubi_num; ··· 949 995 /* Make device "available" before it becomes accessible via sysfs */ 950 996 ubi_devices[ubi_num] = ubi; 951 997 952 - err = uif_init(ubi, &ref); 998 + err = uif_init(ubi); 953 999 if (err) 954 1000 goto out_detach; 955 1001 ··· 999 1045 out_debugfs: 1000 1046 ubi_debugfs_exit_dev(ubi); 1001 1047 out_uif: 1002 - get_device(&ubi->dev); 1003 - ubi_assert(ref); 1004 1048 uif_close(ubi); 1005 1049 out_detach: 1006 1050 ubi_devices[ubi_num] = NULL; ··· 1008 1056 out_free: 1009 1057 vfree(ubi->peb_buf); 1010 1058 vfree(ubi->fm_buf); 1011 - if (ref) 1012 - put_device(&ubi->dev); 1013 - else 1014 - kfree(ubi); 1059 + put_device(&ubi->dev); 1015 1060 return err; 1016 1061 } 1017 1062 ··· 1068 1119 */ 1069 1120 if (ubi->bgt_thread) 1070 1121 kthread_stop(ubi->bgt_thread); 1071 - 1072 - /* 1073 - * Get a reference to the device in order to prevent 'dev_release()' 1074 - * from freeing the @ubi object. 1075 - */ 1076 - get_device(&ubi->dev); 1077 1122 1078 1123 ubi_debugfs_exit_dev(ubi); 1079 1124 uif_close(ubi);
+16 -33
drivers/mtd/ubi/vmt.c
··· 155 155 */ 156 156 int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) 157 157 { 158 - int i, err, vol_id = req->vol_id, do_free = 1; 158 + int i, err, vol_id = req->vol_id; 159 159 struct ubi_volume *vol; 160 160 struct ubi_vtbl_record vtbl_rec; 161 161 struct ubi_eba_table *eba_tbl = NULL; 162 - dev_t dev; 163 162 164 163 if (ubi->ro_mode) 165 164 return -EROFS; ··· 166 167 vol = kzalloc(sizeof(struct ubi_volume), GFP_KERNEL); 167 168 if (!vol) 168 169 return -ENOMEM; 170 + 171 + device_initialize(&vol->dev); 172 + vol->dev.release = vol_release; 173 + vol->dev.parent = &ubi->dev; 174 + vol->dev.class = &ubi_class; 175 + vol->dev.groups = volume_dev_groups; 169 176 170 177 spin_lock(&ubi->volumes_lock); 171 178 if (vol_id == UBI_VOL_NUM_AUTO) { ··· 273 268 /* Register character device for the volume */ 274 269 cdev_init(&vol->cdev, &ubi_vol_cdev_operations); 275 270 vol->cdev.owner = THIS_MODULE; 276 - dev = MKDEV(MAJOR(ubi->cdev.dev), vol_id + 1); 277 - err = cdev_add(&vol->cdev, dev, 1); 278 - if (err) { 279 - ubi_err(ubi, "cannot add character device"); 280 - goto out_mapping; 281 - } 282 271 283 - vol->dev.release = vol_release; 284 - vol->dev.parent = &ubi->dev; 285 - vol->dev.devt = dev; 286 - vol->dev.class = &ubi_class; 287 - vol->dev.groups = volume_dev_groups; 288 - 272 + vol->dev.devt = MKDEV(MAJOR(ubi->cdev.dev), vol_id + 1); 289 273 dev_set_name(&vol->dev, "%s_%d", ubi->ubi_name, vol->vol_id); 290 - err = device_register(&vol->dev); 274 + err = cdev_device_add(&vol->cdev, &vol->dev); 291 275 if (err) { 292 - ubi_err(ubi, "cannot register device"); 293 - goto out_cdev; 276 + ubi_err(ubi, "cannot add device"); 277 + goto out_mapping; 294 278 } 295 279 296 280 /* Fill volume table record */ ··· 312 318 * We have registered our device, we should not free the volume 313 319 * description object in this function in case of an error - it is 314 320 * freed by the release function. 315 - * 316 - * Get device reference to prevent the release function from being 317 - * called just after sysfs has been closed. 318 321 */ 319 - do_free = 0; 320 - get_device(&vol->dev); 321 - device_unregister(&vol->dev); 322 - out_cdev: 323 - cdev_del(&vol->cdev); 322 + cdev_device_del(&vol->cdev, &vol->dev); 324 323 out_mapping: 325 - if (do_free) 326 - ubi_eba_destroy_table(eba_tbl); 324 + ubi_eba_destroy_table(eba_tbl); 327 325 out_acc: 328 326 spin_lock(&ubi->volumes_lock); 329 327 ubi->rsvd_pebs -= vol->reserved_pebs; 330 328 ubi->avail_pebs += vol->reserved_pebs; 331 329 out_unlock: 332 330 spin_unlock(&ubi->volumes_lock); 333 - if (do_free) 334 - kfree(vol); 335 - else 336 - put_device(&vol->dev); 331 + put_device(&vol->dev); 337 332 ubi_err(ubi, "cannot create volume %d, error %d", vol_id, err); 338 333 return err; 339 334 } ··· 374 391 goto out_err; 375 392 } 376 393 377 - cdev_del(&vol->cdev); 378 - device_unregister(&vol->dev); 394 + cdev_device_del(&vol->cdev, &vol->dev); 395 + put_device(&vol->dev); 379 396 380 397 spin_lock(&ubi->volumes_lock); 381 398 ubi->rsvd_pebs -= reserved_pebs;