Commit 08d41808362a3663c0856c9720ad940a61156fb5
Committed by
Mauro Carvalho Chehab
1 parent
d94fc9a08e
Exists in
master
and in
4 other branches
V4L/DVB (4373): Correctly handle sysfs error leg file removal in pvrusb2
Take note of which sysfs files / groups that the pvrusb2 successfully creates and only delete those specific items when tearing things down. (Previously we just blindly tore everything down every time.) Signed-off-by: Mike Isely <isely@pobox.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Showing 1 changed file with 50 additions and 12 deletions Side-by-side Diff
drivers/media/video/pvrusb2/pvrusb2-sysfs.c
| ... | ... | @@ -44,12 +44,16 @@ |
| 44 | 44 | struct kobj_type ktype; |
| 45 | 45 | struct class_device_attribute attr_v4l_minor_number; |
| 46 | 46 | struct class_device_attribute attr_unit_number; |
| 47 | + int v4l_minor_number_created_ok; | |
| 48 | + int unit_number_created_ok; | |
| 47 | 49 | }; |
| 48 | 50 | |
| 49 | 51 | #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC |
| 50 | 52 | struct pvr2_sysfs_debugifc { |
| 51 | 53 | struct class_device_attribute attr_debugcmd; |
| 52 | 54 | struct class_device_attribute attr_debuginfo; |
| 55 | + int debugcmd_created_ok; | |
| 56 | + int debuginfo_created_ok; | |
| 53 | 57 | }; |
| 54 | 58 | #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ |
| 55 | 59 | |
| ... | ... | @@ -67,6 +71,7 @@ |
| 67 | 71 | struct pvr2_sysfs_ctl_item *item_next; |
| 68 | 72 | struct attribute *attr_gen[7]; |
| 69 | 73 | struct attribute_group grp; |
| 74 | + int created_ok; | |
| 70 | 75 | char name[80]; |
| 71 | 76 | }; |
| 72 | 77 | |
| ... | ... | @@ -487,6 +492,7 @@ |
| 487 | 492 | struct pvr2_sysfs_func_set *fp; |
| 488 | 493 | struct pvr2_ctrl *cptr; |
| 489 | 494 | unsigned int cnt,acnt; |
| 495 | + int ret; | |
| 490 | 496 | |
| 491 | 497 | if ((ctl_id < 0) || (ctl_id >= (sizeof(funcs)/sizeof(funcs[0])))) { |
| 492 | 498 | return; |
| ... | ... | @@ -589,7 +595,13 @@ |
| 589 | 595 | cip->grp.name = cip->name; |
| 590 | 596 | cip->grp.attrs = cip->attr_gen; |
| 591 | 597 | |
| 592 | - sysfs_create_group(&sfp->class_dev->kobj,&cip->grp); | |
| 598 | + ret = sysfs_create_group(&sfp->class_dev->kobj,&cip->grp); | |
| 599 | + if (ret) { | |
| 600 | + printk(KERN_WARNING "%s: sysfs_create_group error: %d\n", | |
| 601 | + __FUNCTION__, ret); | |
| 602 | + return; | |
| 603 | + } | |
| 604 | + cip->created_ok = !0; | |
| 593 | 605 | } |
| 594 | 606 | |
| 595 | 607 | #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC |
| 596 | 608 | |
| 597 | 609 | |
| 598 | 610 | |
| 599 | 611 | |
| ... | ... | @@ -616,22 +628,33 @@ |
| 616 | 628 | dip->attr_debuginfo.show = debuginfo_show; |
| 617 | 629 | sfp->debugifc = dip; |
| 618 | 630 | ret = class_device_create_file(sfp->class_dev,&dip->attr_debugcmd); |
| 619 | - if (ret < 0) | |
| 631 | + if (ret < 0) { | |
| 620 | 632 | printk(KERN_WARNING "%s: class_device_create_file error: %d\n", |
| 621 | 633 | __FUNCTION__, ret); |
| 634 | + } else { | |
| 635 | + dip->debugcmd_created_ok = !0; | |
| 636 | + } | |
| 622 | 637 | ret = class_device_create_file(sfp->class_dev,&dip->attr_debuginfo); |
| 623 | - if (ret < 0) | |
| 638 | + if (ret < 0) { | |
| 624 | 639 | printk(KERN_WARNING "%s: class_device_create_file error: %d\n", |
| 625 | 640 | __FUNCTION__, ret); |
| 641 | + } else { | |
| 642 | + dip->debuginfo_created_ok = !0; | |
| 643 | + } | |
| 626 | 644 | } |
| 627 | 645 | |
| 628 | 646 | |
| 629 | 647 | static void pvr2_sysfs_tear_down_debugifc(struct pvr2_sysfs *sfp) |
| 630 | 648 | { |
| 631 | 649 | if (!sfp->debugifc) return; |
| 632 | - class_device_remove_file(sfp->class_dev, | |
| 633 | - &sfp->debugifc->attr_debuginfo); | |
| 634 | - class_device_remove_file(sfp->class_dev,&sfp->debugifc->attr_debugcmd); | |
| 650 | + if (sfp->debugifc->debuginfo_created_ok) { | |
| 651 | + class_device_remove_file(sfp->class_dev, | |
| 652 | + &sfp->debugifc->attr_debuginfo); | |
| 653 | + } | |
| 654 | + if (sfp->debugifc->debugcmd_created_ok) { | |
| 655 | + class_device_remove_file(sfp->class_dev, | |
| 656 | + &sfp->debugifc->attr_debugcmd); | |
| 657 | + } | |
| 635 | 658 | kfree(sfp->debugifc); |
| 636 | 659 | sfp->debugifc = NULL; |
| 637 | 660 | } |
| ... | ... | @@ -653,7 +676,9 @@ |
| 653 | 676 | struct pvr2_sysfs_ctl_item *cip1,*cip2; |
| 654 | 677 | for (cip1 = sfp->item_first; cip1; cip1 = cip2) { |
| 655 | 678 | cip2 = cip1->item_next; |
| 656 | - sysfs_remove_group(&sfp->class_dev->kobj,&cip1->grp); | |
| 679 | + if (cip1->created_ok) { | |
| 680 | + sysfs_remove_group(&sfp->class_dev->kobj,&cip1->grp); | |
| 681 | + } | |
| 657 | 682 | pvr2_sysfs_trace("Destroying pvr2_sysfs_ctl_item id=%p",cip1); |
| 658 | 683 | kfree(cip1); |
| 659 | 684 | } |
| ... | ... | @@ -683,8 +708,14 @@ |
| 683 | 708 | pvr2_sysfs_tear_down_debugifc(sfp); |
| 684 | 709 | #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ |
| 685 | 710 | pvr2_sysfs_tear_down_controls(sfp); |
| 686 | - class_device_remove_file(sfp->class_dev,&sfp->attr_v4l_minor_number); | |
| 687 | - class_device_remove_file(sfp->class_dev,&sfp->attr_unit_number); | |
| 711 | + if (sfp->v4l_minor_number_created_ok) { | |
| 712 | + class_device_remove_file(sfp->class_dev, | |
| 713 | + &sfp->attr_v4l_minor_number); | |
| 714 | + } | |
| 715 | + if (sfp->unit_number_created_ok) { | |
| 716 | + class_device_remove_file(sfp->class_dev, | |
| 717 | + &sfp->attr_unit_number); | |
| 718 | + } | |
| 688 | 719 | pvr2_sysfs_trace("Destroying class_dev id=%p",sfp->class_dev); |
| 689 | 720 | sfp->class_dev->class_data = NULL; |
| 690 | 721 | class_device_unregister(sfp->class_dev); |
| 691 | 722 | |
| ... | ... | @@ -756,10 +787,14 @@ |
| 756 | 787 | sfp->attr_v4l_minor_number.attr.mode = S_IRUGO; |
| 757 | 788 | sfp->attr_v4l_minor_number.show = v4l_minor_number_show; |
| 758 | 789 | sfp->attr_v4l_minor_number.store = NULL; |
| 759 | - ret = class_device_create_file(sfp->class_dev,&sfp->attr_v4l_minor_number); | |
| 760 | - if (ret < 0) | |
| 790 | + ret = class_device_create_file(sfp->class_dev, | |
| 791 | + &sfp->attr_v4l_minor_number); | |
| 792 | + if (ret < 0) { | |
| 761 | 793 | printk(KERN_WARNING "%s: class_device_create_file error: %d\n", |
| 762 | 794 | __FUNCTION__, ret); |
| 795 | + } else { | |
| 796 | + sfp->v4l_minor_number_created_ok = !0; | |
| 797 | + } | |
| 763 | 798 | |
| 764 | 799 | sfp->attr_unit_number.attr.owner = THIS_MODULE; |
| 765 | 800 | sfp->attr_unit_number.attr.name = "unit_number"; |
| 766 | 801 | |
| ... | ... | @@ -767,9 +802,12 @@ |
| 767 | 802 | sfp->attr_unit_number.show = unit_number_show; |
| 768 | 803 | sfp->attr_unit_number.store = NULL; |
| 769 | 804 | ret = class_device_create_file(sfp->class_dev,&sfp->attr_unit_number); |
| 770 | - if (ret < 0) | |
| 805 | + if (ret < 0) { | |
| 771 | 806 | printk(KERN_WARNING "%s: class_device_create_file error: %d\n", |
| 772 | 807 | __FUNCTION__, ret); |
| 808 | + } else { | |
| 809 | + sfp->unit_number_created_ok = !0; | |
| 810 | + } | |
| 773 | 811 | |
| 774 | 812 | pvr2_sysfs_add_controls(sfp); |
| 775 | 813 | #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC |