V4L/DVB (4373): Correctly handle sysfs error leg file removal in pvrusb2
authorMike Isely <isely@pobox.com>
Sun, 23 Jul 2006 00:26:30 +0000 (21:26 -0300)
committerMauro Carvalho Chehab <mchehab@infradead.org>
Sat, 29 Jul 2006 20:22:37 +0000 (17:22 -0300)
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>
drivers/media/video/pvrusb2/pvrusb2-sysfs.c

index ef46d4f..d1dda5c 100644 (file)
@@ -44,12 +44,16 @@ struct pvr2_sysfs {
        struct kobj_type ktype;
        struct class_device_attribute attr_v4l_minor_number;
        struct class_device_attribute attr_unit_number;
+       int v4l_minor_number_created_ok;
+       int unit_number_created_ok;
 };
 
 #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
 struct pvr2_sysfs_debugifc {
        struct class_device_attribute attr_debugcmd;
        struct class_device_attribute attr_debuginfo;
+       int debugcmd_created_ok;
+       int debuginfo_created_ok;
 };
 #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
 
@@ -67,6 +71,7 @@ struct pvr2_sysfs_ctl_item {
        struct pvr2_sysfs_ctl_item *item_next;
        struct attribute *attr_gen[7];
        struct attribute_group grp;
+       int created_ok;
        char name[80];
 };
 
@@ -487,6 +492,7 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id)
        struct pvr2_sysfs_func_set *fp;
        struct pvr2_ctrl *cptr;
        unsigned int cnt,acnt;
+       int ret;
 
        if ((ctl_id < 0) || (ctl_id >= (sizeof(funcs)/sizeof(funcs[0])))) {
                return;
@@ -589,7 +595,13 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id)
        cip->grp.name = cip->name;
        cip->grp.attrs = cip->attr_gen;
 
-       sysfs_create_group(&sfp->class_dev->kobj,&cip->grp);
+       ret = sysfs_create_group(&sfp->class_dev->kobj,&cip->grp);
+       if (ret) {
+               printk(KERN_WARNING "%s: sysfs_create_group error: %d\n",
+                      __FUNCTION__, ret);
+               return;
+       }
+       cip->created_ok = !0;
 }
 
 #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
@@ -616,22 +628,33 @@ static void pvr2_sysfs_add_debugifc(struct pvr2_sysfs *sfp)
        dip->attr_debuginfo.show = debuginfo_show;
        sfp->debugifc = dip;
        ret = class_device_create_file(sfp->class_dev,&dip->attr_debugcmd);
-       if (ret < 0)
+       if (ret < 0) {
                printk(KERN_WARNING "%s: class_device_create_file error: %d\n",
                       __FUNCTION__, ret);
+       } else {
+               dip->debugcmd_created_ok = !0;
+       }
        ret = class_device_create_file(sfp->class_dev,&dip->attr_debuginfo);
-       if (ret < 0)
+       if (ret < 0) {
                printk(KERN_WARNING "%s: class_device_create_file error: %d\n",
                       __FUNCTION__, ret);
+       } else {
+               dip->debuginfo_created_ok = !0;
+       }
 }
 
 
 static void pvr2_sysfs_tear_down_debugifc(struct pvr2_sysfs *sfp)
 {
        if (!sfp->debugifc) return;
-       class_device_remove_file(sfp->class_dev,
-                                &sfp->debugifc->attr_debuginfo);
-       class_device_remove_file(sfp->class_dev,&sfp->debugifc->attr_debugcmd);
+       if (sfp->debugifc->debuginfo_created_ok) {
+               class_device_remove_file(sfp->class_dev,
+                                        &sfp->debugifc->attr_debuginfo);
+       }
+       if (sfp->debugifc->debugcmd_created_ok) {
+               class_device_remove_file(sfp->class_dev,
+                                        &sfp->debugifc->attr_debugcmd);
+       }
        kfree(sfp->debugifc);
        sfp->debugifc = NULL;
 }
@@ -653,7 +676,9 @@ static void pvr2_sysfs_tear_down_controls(struct pvr2_sysfs *sfp)
        struct pvr2_sysfs_ctl_item *cip1,*cip2;
        for (cip1 = sfp->item_first; cip1; cip1 = cip2) {
                cip2 = cip1->item_next;
-               sysfs_remove_group(&sfp->class_dev->kobj,&cip1->grp);
+               if (cip1->created_ok) {
+                       sysfs_remove_group(&sfp->class_dev->kobj,&cip1->grp);
+               }
                pvr2_sysfs_trace("Destroying pvr2_sysfs_ctl_item id=%p",cip1);
                kfree(cip1);
        }
@@ -683,8 +708,14 @@ static void class_dev_destroy(struct pvr2_sysfs *sfp)
        pvr2_sysfs_tear_down_debugifc(sfp);
 #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
        pvr2_sysfs_tear_down_controls(sfp);
-       class_device_remove_file(sfp->class_dev,&sfp->attr_v4l_minor_number);
-       class_device_remove_file(sfp->class_dev,&sfp->attr_unit_number);
+       if (sfp->v4l_minor_number_created_ok) {
+               class_device_remove_file(sfp->class_dev,
+                                        &sfp->attr_v4l_minor_number);
+       }
+       if (sfp->unit_number_created_ok) {
+               class_device_remove_file(sfp->class_dev,
+                                        &sfp->attr_unit_number);
+       }
        pvr2_sysfs_trace("Destroying class_dev id=%p",sfp->class_dev);
        sfp->class_dev->class_data = NULL;
        class_device_unregister(sfp->class_dev);
@@ -756,10 +787,14 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
        sfp->attr_v4l_minor_number.attr.mode = S_IRUGO;
        sfp->attr_v4l_minor_number.show = v4l_minor_number_show;
        sfp->attr_v4l_minor_number.store = NULL;
-       ret = class_device_create_file(sfp->class_dev,&sfp->attr_v4l_minor_number);
-       if (ret < 0)
+       ret = class_device_create_file(sfp->class_dev,
+                                      &sfp->attr_v4l_minor_number);
+       if (ret < 0) {
                printk(KERN_WARNING "%s: class_device_create_file error: %d\n",
                       __FUNCTION__, ret);
+       } else {
+               sfp->v4l_minor_number_created_ok = !0;
+       }
 
        sfp->attr_unit_number.attr.owner = THIS_MODULE;
        sfp->attr_unit_number.attr.name = "unit_number";
@@ -767,9 +802,12 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
        sfp->attr_unit_number.show = unit_number_show;
        sfp->attr_unit_number.store = NULL;
        ret = class_device_create_file(sfp->class_dev,&sfp->attr_unit_number);
-       if (ret < 0)
+       if (ret < 0) {
                printk(KERN_WARNING "%s: class_device_create_file error: %d\n",
                       __FUNCTION__, ret);
+       } else {
+               sfp->unit_number_created_ok = !0;
+       }
 
        pvr2_sysfs_add_controls(sfp);
 #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC