diff options
| author | Linus Torvalds <torvalds@athlon.transmeta.com> | 2002-02-04 20:30:06 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@athlon.transmeta.com> | 2002-02-04 20:30:06 -0800 |
| commit | 3ea86172d8f6ae13a896f78ec3f029bb410eacf2 (patch) | |
| tree | 72346dfc1ca3054384f3e790a65729e7bbe900d3 /fs/devfs/base.c | |
| parent | 595cf06fad2068ed3e97caabbb92ebe71ffd97d9 (diff) | |
v2.4.13.7 -> v2.4.13.8
- Andrea: fix races in do_wp_page, free_swap_and_cache
- me: clena up page dirty handling
- Tim Waugh: parport IRQ probing and documentation fixes
- Greg KH: USB updates
- Michael Warfield: computone driver update
- Randy Dunlap: add knowledge about some new io-apics
- Richard Henderson: alpha updates
- Trond Myklebust: make readdir xdr verify the reply packet
- Paul Mackerras: PPC update
- Jens Axboe: make cpqarray and cciss play nice with the request layer
- Massimo Dal Zotto: SMM driver for Dell Inspiron 8000
- Richard Gooch: devfs symlink deadlock fix
- Anton Altaparmakov: make NTFS compile on sparc
Diffstat (limited to 'fs/devfs/base.c')
| -rw-r--r-- | fs/devfs/base.c | 31 |
1 files changed, 27 insertions, 4 deletions
diff --git a/fs/devfs/base.c b/fs/devfs/base.c index b25dbb434bd1..ee94c388344d 100644 --- a/fs/devfs/base.c +++ b/fs/devfs/base.c @@ -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@atnf.csiro.au> + Fixed race in <devfsd_ioctl> when setting event mask. + 20011103 Richard Gooch <rgooch@atnf.csiro.au> + 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 @@ static int devfs_follow_link (struct dentry *dentry, struct nameidata *nd) { 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 @@ static int devfsd_ioctl (struct inode *inode, struct file *file, { 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 @@ static int devfsd_ioctl (struct inode *inode, struct file *file, 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; |
