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

Configure Feed

Select the types of activity you want to include in your feed.

mtd: ubi: block: use notifier to create ubiblock from parameter

Use UBI_VOLUME_ADDED notification to create ubiblock device specified
on kernel cmdline or module parameter.
This makes thing more simple and has the advantage that ubiblock devices
on volumes which are not present at the time the ubi module is probed
will still be created.

Suggested-by: Zhihao Cheng <chengzhihao1@huawei.com>
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Signed-off-by: Richard Weinberger <richard@nod.at>

authored by

Daniel Golle and committed by
Richard Weinberger
762d73cd a1de28dd

+106 -85
+68 -68
drivers/mtd/ubi/block.c
··· 65 65 }; 66 66 67 67 /* Numbers of elements set in the @ubiblock_param array */ 68 - static int ubiblock_devs __initdata; 68 + static int ubiblock_devs; 69 69 70 70 /* MTD devices specification parameters */ 71 - static struct ubiblock_param ubiblock_param[UBIBLOCK_MAX_DEVICES] __initdata; 71 + static struct ubiblock_param ubiblock_param[UBIBLOCK_MAX_DEVICES]; 72 72 73 73 struct ubiblock { 74 74 struct ubi_volume_desc *desc; ··· 534 534 return 0; 535 535 } 536 536 537 + static bool 538 + match_volume_desc(struct ubi_volume_info *vi, const char *name, int ubi_num, int vol_id) 539 + { 540 + int err, len, cur_ubi_num, cur_vol_id; 541 + 542 + if (ubi_num == -1) { 543 + /* No ubi num, name must be a vol device path */ 544 + err = ubi_get_num_by_path(name, &cur_ubi_num, &cur_vol_id); 545 + if (err || vi->ubi_num != cur_ubi_num || vi->vol_id != cur_vol_id) 546 + return false; 547 + 548 + return true; 549 + } 550 + 551 + if (vol_id == -1) { 552 + /* Got ubi_num, but no vol_id, name must be volume name */ 553 + if (vi->ubi_num != ubi_num) 554 + return false; 555 + 556 + len = strnlen(name, UBI_VOL_NAME_MAX + 1); 557 + if (len < 1 || vi->name_len != len) 558 + return false; 559 + 560 + if (strcmp(name, vi->name)) 561 + return false; 562 + 563 + return true; 564 + } 565 + 566 + if (vi->ubi_num != ubi_num) 567 + return false; 568 + 569 + if (vi->vol_id != vol_id) 570 + return false; 571 + 572 + return true; 573 + } 574 + 575 + static void 576 + ubiblock_create_from_param(struct ubi_volume_info *vi) 577 + { 578 + int i, ret = 0; 579 + struct ubiblock_param *p; 580 + 581 + /* 582 + * Iterate over ubiblock cmdline parameters. If a parameter matches the 583 + * newly added volume create the ubiblock device for it. 584 + */ 585 + for (i = 0; i < ubiblock_devs; i++) { 586 + p = &ubiblock_param[i]; 587 + 588 + if (!match_volume_desc(vi, p->name, p->ubi_num, p->vol_id)) 589 + continue; 590 + 591 + ret = ubiblock_create(vi); 592 + if (ret) { 593 + pr_err( 594 + "UBI: block: can't add '%s' volume on ubi%d_%d, err=%d\n", 595 + vi->name, p->ubi_num, p->vol_id, ret); 596 + } 597 + break; 598 + } 599 + } 600 + 537 601 static int ubiblock_notify(struct notifier_block *nb, 538 602 unsigned long notification_type, void *ns_ptr) 539 603 { ··· 605 541 606 542 switch (notification_type) { 607 543 case UBI_VOLUME_ADDED: 608 - /* 609 - * We want to enforce explicit block device creation for 610 - * volumes, so when a volume is added we do nothing. 611 - */ 544 + ubiblock_create_from_param(&nt->vi); 612 545 break; 613 546 case UBI_VOLUME_REMOVED: 614 547 ubiblock_remove(&nt->vi); ··· 630 569 static struct notifier_block ubiblock_notifier = { 631 570 .notifier_call = ubiblock_notify, 632 571 }; 633 - 634 - static struct ubi_volume_desc * __init 635 - open_volume_desc(const char *name, int ubi_num, int vol_id) 636 - { 637 - if (ubi_num == -1) 638 - /* No ubi num, name must be a vol device path */ 639 - return ubi_open_volume_path(name, UBI_READONLY); 640 - else if (vol_id == -1) 641 - /* No vol_id, must be vol_name */ 642 - return ubi_open_volume_nm(ubi_num, name, UBI_READONLY); 643 - else 644 - return ubi_open_volume(ubi_num, vol_id, UBI_READONLY); 645 - } 646 - 647 - static void __init ubiblock_create_from_param(void) 648 - { 649 - int i, ret = 0; 650 - struct ubiblock_param *p; 651 - struct ubi_volume_desc *desc; 652 - struct ubi_volume_info vi; 653 - 654 - /* 655 - * If there is an error creating one of the ubiblocks, continue on to 656 - * create the following ubiblocks. This helps in a circumstance where 657 - * the kernel command-line specifies multiple block devices and some 658 - * may be broken, but we still want the working ones to come up. 659 - */ 660 - for (i = 0; i < ubiblock_devs; i++) { 661 - p = &ubiblock_param[i]; 662 - 663 - desc = open_volume_desc(p->name, p->ubi_num, p->vol_id); 664 - if (IS_ERR(desc)) { 665 - pr_err( 666 - "UBI: block: can't open volume on ubi%d_%d, err=%ld\n", 667 - p->ubi_num, p->vol_id, PTR_ERR(desc)); 668 - continue; 669 - } 670 - 671 - ubi_get_volume_info(desc, &vi); 672 - ubi_close_volume(desc); 673 - 674 - ret = ubiblock_create(&vi); 675 - if (ret) { 676 - pr_err( 677 - "UBI: block: can't add '%s' volume on ubi%d_%d, err=%d\n", 678 - vi.name, p->ubi_num, p->vol_id, ret); 679 - continue; 680 - } 681 - } 682 - } 683 572 684 573 static void ubiblock_remove_all(void) 685 574 { ··· 656 645 if (ubiblock_major < 0) 657 646 return ubiblock_major; 658 647 659 - /* 660 - * Attach block devices from 'block=' module param. 661 - * Even if one block device in the param list fails to come up, 662 - * still allow the module to load and leave any others up. 663 - */ 664 - ubiblock_create_from_param(); 665 - 666 - /* 667 - * Block devices are only created upon user requests, so we ignore 668 - * existing volumes. 669 - */ 670 - ret = ubi_register_volume_notifier(&ubiblock_notifier, 1); 648 + ret = ubi_register_volume_notifier(&ubiblock_notifier, 0); 671 649 if (ret) 672 650 goto err_unreg; 673 651 return 0;
+37 -17
drivers/mtd/ubi/kapi.c
··· 280 280 EXPORT_SYMBOL_GPL(ubi_open_volume_nm); 281 281 282 282 /** 283 + * ubi_get_num_by_path - get UBI device and volume number from device path 284 + * @pathname: volume character device node path 285 + * @ubi_num: pointer to UBI device number to be set 286 + * @vol_id: pointer to UBI volume ID to be set 287 + * 288 + * Returns 0 on success and sets ubi_num and vol_id, returns error otherwise. 289 + */ 290 + int ubi_get_num_by_path(const char *pathname, int *ubi_num, int *vol_id) 291 + { 292 + int error; 293 + struct path path; 294 + struct kstat stat; 295 + 296 + error = kern_path(pathname, LOOKUP_FOLLOW, &path); 297 + if (error) 298 + return error; 299 + 300 + error = vfs_getattr(&path, &stat, STATX_TYPE, AT_STATX_SYNC_AS_STAT); 301 + path_put(&path); 302 + if (error) 303 + return error; 304 + 305 + if (!S_ISCHR(stat.mode)) 306 + return -EINVAL; 307 + 308 + *ubi_num = ubi_major2num(MAJOR(stat.rdev)); 309 + *vol_id = MINOR(stat.rdev) - 1; 310 + 311 + if (*vol_id < 0 || *ubi_num < 0) 312 + return -ENODEV; 313 + 314 + return 0; 315 + } 316 + 317 + /** 283 318 * ubi_open_volume_path - open UBI volume by its character device node path. 284 319 * @pathname: volume character device node path 285 320 * @mode: open mode ··· 325 290 struct ubi_volume_desc *ubi_open_volume_path(const char *pathname, int mode) 326 291 { 327 292 int error, ubi_num, vol_id; 328 - struct path path; 329 - struct kstat stat; 330 293 331 294 dbg_gen("open volume %s, mode %d", pathname, mode); 332 295 333 296 if (!pathname || !*pathname) 334 297 return ERR_PTR(-EINVAL); 335 298 336 - error = kern_path(pathname, LOOKUP_FOLLOW, &path); 299 + error = ubi_get_num_by_path(pathname, &ubi_num, &vol_id); 337 300 if (error) 338 301 return ERR_PTR(error); 339 302 340 - error = vfs_getattr(&path, &stat, STATX_TYPE, AT_STATX_SYNC_AS_STAT); 341 - path_put(&path); 342 - if (error) 343 - return ERR_PTR(error); 344 - 345 - if (!S_ISCHR(stat.mode)) 346 - return ERR_PTR(-EINVAL); 347 - 348 - ubi_num = ubi_major2num(MAJOR(stat.rdev)); 349 - vol_id = MINOR(stat.rdev) - 1; 350 - 351 - if (vol_id >= 0 && ubi_num >= 0) 352 - return ubi_open_volume(ubi_num, vol_id, mode); 353 - return ERR_PTR(-ENODEV); 303 + return ubi_open_volume(ubi_num, vol_id, mode); 354 304 } 355 305 EXPORT_SYMBOL_GPL(ubi_open_volume_path); 356 306
+1
drivers/mtd/ubi/ubi.h
··· 955 955 void ubi_do_get_device_info(struct ubi_device *ubi, struct ubi_device_info *di); 956 956 void ubi_do_get_volume_info(struct ubi_device *ubi, struct ubi_volume *vol, 957 957 struct ubi_volume_info *vi); 958 + int ubi_get_num_by_path(const char *pathname, int *ubi_num, int *vol_id); 958 959 /* scan.c */ 959 960 int ubi_compare_lebs(struct ubi_device *ubi, const struct ubi_ainf_peb *aeb, 960 961 int pnum, const struct ubi_vid_hdr *vid_hdr);