per@xxxxxxxxxxx writes:
> I've been having problems with devfs since kernel 2.4.11 (ie. devfs
> version 117). The problem (which I can easily reproduce) occurs if I
> start X and then start a number of xterms. Then /dev becomes
> unreadable and all xterms hangs. Any further access to /dev by any
> program will produce an unkillable process. E.g. "ls /dev" will hang
> and if I switch to another vc and do "kill -9" on the ls process
> nothing happens. And as a result, I can't even do a clean shutdown
> since init, umount, etc all access /dev.
Please try the appended patch and let me know if it fixes the
problem. If not, please re-submit your bug report in full.
Regards,
Richard....
Permanent: rgooch@xxxxxxxxxxxxx
Current: rgooch@xxxxxxxxxxxxxxx
diff -urN linux-2.4.14-pre7/Documentation/filesystems/devfs/ChangeLog
linux/Documentation/filesystems/devfs/ChangeLog
--- linux-2.4.14-pre7/Documentation/filesystems/devfs/ChangeLog Thu Oct 11
00:23:24 2001
+++ linux/Documentation/filesystems/devfs/ChangeLog Sat Nov 3 01:29:39 2001
@@ -1771,3 +1771,10 @@
- Fixed buffer underrun in <try_modload>
- Moved down_read() from <search_for_entry_in_dir> to <find_entry>
+===============================================================================
+Changes for patch v196
+
+- Fixed race in <devfsd_ioctl> when setting event mask
+ Thanks to Kari Hurtta <hurtta@xxxxxxxxxxxxxxx>
+
+- Avoid deadlock in <devfs_follow_link> by using temporary buffer
diff -urN linux-2.4.14-pre7/fs/devfs/base.c linux/fs/devfs/base.c
--- linux-2.4.14-pre7/fs/devfs/base.c Thu Oct 11 00:23:24 2001
+++ linux/fs/devfs/base.c Sat Nov 3 01:40:10 2001
@@ -555,6 +555,11 @@
Fixed buffer underrun in <try_modload>.
Moved down_read() from <search_for_entry_in_dir> to <find_entry>
v0.119
+ 20011029 Richard Gooch <rgooch@xxxxxxxxxxxxx>
+ Fixed race in <devfsd_ioctl> when setting event mask.
+ 20011103 Richard Gooch <rgooch@xxxxxxxxxxxxx>
+ Avoid deadlock in <devfs_follow_link> by using temporary buffer.
+ v0.120
*/
#include <linux/types.h>
#include <linux/errno.h>
@@ -587,7 +592,7 @@
#include <asm/bitops.h>
#include <asm/atomic.h>
-#define DEVFS_VERSION "0.119 (20011009)"
+#define DEVFS_VERSION "0.120 (20011103)"
#define DEVFS_NAME "devfs"
@@ -3029,13 +3034,25 @@
{
int err;
struct devfs_entry *de;
+ char *copy;
de = get_devfs_entry_from_vfs_inode (dentry->d_inode, TRUE);
if (!de) return -ENODEV;
down_read (&symlink_rwsem);
- err = de->registered ? vfs_follow_link (nd,
- de->u.symlink.linkname) : -ENODEV;
+ if (!de->registered)
+ {
+ up_read (&symlink_rwsem);
+ return -ENODEV;
+ }
+ copy = kmalloc (de->u.symlink.length + 1, GFP_KERNEL);
+ if (copy) memcpy (copy, de->u.symlink.linkname, de->u.symlink.length + 1);
up_read (&symlink_rwsem);
+ if (copy)
+ {
+ err = vfs_follow_link (nd, copy);
+ kfree (copy);
+ }
+ else err = -ENOMEM;
return err;
} /* End Function devfs_follow_link */
@@ -3212,7 +3229,6 @@
{
int ival;
struct fs_info *fs_info = inode->i_sb->u.generic_sbp;
- static spinlock_t lock = SPIN_LOCK_UNLOCKED;
switch (cmd)
{
@@ -3226,7 +3242,14 @@
doesn't matter who gets in first, as long as only one gets it */
if (fs_info->devfsd_task == NULL)
{
+ static spinlock_t lock = SPIN_LOCK_UNLOCKED;
+
if ( !spin_trylock (&lock) ) return -EBUSY;
+ if (fs_info->devfsd_task != NULL)
+ { /* We lost the race... */
+ spin_unlock (&lock);
+ return -EBUSY;
+ }
fs_info->devfsd_task = current;
spin_unlock (&lock);
fs_info->devfsd_file = file;
|