From 52ef9e7cb317fcb7f8b63f1bec7271e40341ce98 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Tue, 7 Jan 2014 12:38:32 +0000 Subject: staging: comedi: fix bug destroying subdevice files after parent `comedi_free_board_dev()` is called (via `comedi_auto_unconfig()` --> `comedi_release_hardware_device()`) when an auto-configured comedi device is removed. This destroys the main sysfs class device and then calls `comedi_device_cleanup()` to clean up the comedi device. For comedi devices that have comedi subdevices that asynchronous commands, the clean up involves destroying the sysfs class devices associated with those subdevices. There is a bug in the above sequence because the sysfs class devices associated with the comedi subdevices are children of the sysfs class device associated with the main comedi device. Therefore they will have been automatically destroyed when the main sysfs class device is destroyed. When they are destroyed again as part of the clean-up, they will not be found, leading to a warning and a stack trace similar to this: ------------[ cut here ]------------ WARNING: CPU: 1 PID: 1213 at fs/sysfs/group.c:214 sysfs_remove_group+0x4e/0xa7() sysfs group ffffffff817504c0 not found for kobject 'comedi4_subd0' Modules linked in: nfsd auth_rpcgss oid_registry exportfs nfs_acl lockd bridge stp llc sunrpc fuse binfmt_misc cpufreq_userspace sr_mod snd_hda_codec_analog cdrom powernow_k8 kvm_amd kvm amplc_pci230(C) 8255(C) comedi(C) pcmcia xhci_hcd ehci_pci pcmcia_core ohci_pci ohci_hcd ehci_hcd usbcore snd_hda_intel snd_hda_codec snd_pcm k8temp snd_page_alloc 8139too snd_timer snd soundcore mii usb_common forcedeth pata_amd CPU: 1 PID: 1213 Comm: kworker/u4:6 Tainted: G C 3.13.0-rc5-ija1+ #20 Hardware name: System manufacturer System Product Name/M2N-E, BIOS ASUS M2N-E ACPI BIOS Revision 5001 03/23/2010 Workqueue: sysfsd sysfs_schedule_callback_work 0000000000000000 ffff8800bf17fb38 ffffffff814672ce ffff8800bf17fb80 ffff8800bf17fb70 ffffffff8103470b ffffffff8114f780 0000000000000000 ffffffff817504c0 ffff8800bf39f410 ffff880139b68670 ffff8800bf17fbd0 Call Trace: [] dump_stack+0x45/0x56 [] warn_slowpath_common+0x7a/0x93 [] ? sysfs_remove_group+0x4e/0xa7 [] warn_slowpath_fmt+0x47/0x49 [] ? sysfs_get_dirent_ns+0x5e/0x66 [] sysfs_remove_group+0x4e/0xa7 [] dpm_sysfs_remove+0x37/0x3b [] device_del+0x3e/0x173 [] device_unregister+0xd/0x18 [] device_destroy+0x33/0x37 [] comedi_free_subdevice_minor+0x80/0x92 [comedi] [] comedi_device_detach+0x79/0x152 [comedi] [] comedi_device_cleanup+0x36/0x57 [comedi] [] comedi_free_board_dev+0x31/0x3c [comedi] [] comedi_release_hardware_device+0x5a/0x73 [comedi] [] comedi_auto_unconfig+0xe/0x10 [comedi] [] comedi_pci_auto_unconfig+0x10/0x12 [comedi] [] pci_device_remove+0x40/0x8a [] __device_release_driver+0x84/0xda [] device_release_driver+0x1e/0x2b [] pci_stop_bus_device+0x44/0x87 [] pci_stop_and_remove_bus_device+0xd/0x18 [] remove_callback+0x20/0x2f [] sysfs_schedule_callback_work+0xf/0x70 [] process_one_work+0x1d6/0x34c [] worker_thread+0x1cf/0x2b5 [] ? rescuer_thread+0x258/0x258 [] kthread+0xd6/0xde [] ? kthread_create_on_node+0x160/0x160 [] ret_from_fork+0x7c/0xb0 [] ? kthread_create_on_node+0x160/0x160 ---[ end trace 94722aa2936a7adf ]--- To correct the bug, rearrange `comedi_free_board_dev()` to destroy the main sysfs class device *after* the clean-up operation. Thanks to Bernd Porr for finding the bug and his initial attempt to fix it. Reported-by: Bernd Porr Signed-off-by: Ian Abbott Cc: Bernd Porr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/staging/comedi/comedi_fops.c') diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index d7f63c483ad3..c22c617b0da1 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -153,11 +153,11 @@ static struct comedi_device *comedi_clear_board_minor(unsigned minor) static void comedi_free_board_dev(struct comedi_device *dev) { if (dev) { + comedi_device_cleanup(dev); if (dev->class_dev) { device_destroy(comedi_class, MKDEV(COMEDI_MAJOR, dev->minor)); } - comedi_device_cleanup(dev); comedi_dev_put(dev); } } -- cgit v1.2.3-55-g7522