diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-06-19 22:45:37 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-06-19 22:45:37 +0000 |
commit | 6d403070f28cd44860fdb3a53be5da0275c65cf4 (patch) | |
tree | 0d0e7fe7b5fb7568d19e11d7d862b77a866ce081 /fs/fcntl.c | |
parent | ecf1bf5f6c2e668d03b0a9fb026db7aa41e292e1 (diff) |
Merge with 2.4.0-test1-ac21 + pile of MIPS cleanups to make merging
possible. Chainsawed RM200 kernel to compile again. Jazz machine
status unknown.
Diffstat (limited to 'fs/fcntl.c')
-rw-r--r-- | fs/fcntl.c | 57 |
1 files changed, 55 insertions, 2 deletions
diff --git a/fs/fcntl.c b/fs/fcntl.c index ab758c566..37e32a012 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -7,6 +7,7 @@ #include <linux/mm.h> #include <linux/file.h> #include <linux/smp_lock.h> +#include <linux/slab.h> #include <asm/poll.h> #include <asm/siginfo.h> @@ -251,8 +252,8 @@ asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg) err = sock_fcntl (filp, cmd, arg); break; } - fput(filp); unlock_kernel(); + fput(filp); out: return err; } @@ -330,7 +331,52 @@ out: read_unlock(&tasklist_lock); } -void kill_fasync(struct fasync_struct *fa, int sig, int band) +/* + * fasync_helper() is used by some character device drivers (mainly mice) + * to set up the fasync queue. It returns negative on error, 0 if it did + * no changes and positive if it added/deleted the entry. + */ +static rwlock_t fasync_lock = RW_LOCK_UNLOCKED; +int fasync_helper(int fd, struct file * filp, int on, struct fasync_struct **fapp) +{ + struct fasync_struct *fa, **fp; + struct fasync_struct *new = NULL; + int result = 0; + + if (on) { + new = kmalloc(sizeof(struct fasync_struct), GFP_KERNEL); + if (!new) + return -ENOMEM; + } + write_lock_irq(&fasync_lock); + for (fp = fapp; (fa = *fp) != NULL; fp = &fa->fa_next) { + if (fa->fa_file == filp) { + if(on) { + fa->fa_fd = fd; + kfree(new); + } else { + *fp = fa->fa_next; + kfree(fa); + result = 1; + } + goto out; + } + } + + if (on) { + new->magic = FASYNC_MAGIC; + new->fa_file = filp; + new->fa_fd = fd; + new->fa_next = *fapp; + *fapp = new; + result = 1; + } +out: + write_unlock_irq(&fasync_lock); + return result; +} + +void __kill_fasync(struct fasync_struct *fa, int sig, int band) { while (fa) { struct fown_struct * fown; @@ -348,3 +394,10 @@ void kill_fasync(struct fasync_struct *fa, int sig, int band) fa = fa->fa_next; } } + +void kill_fasync(struct fasync_struct **fp, int sig, int band) +{ + read_lock(&fasync_lock); + __kill_fasync(*fp, sig, band); + read_unlock(&fasync_lock); +} |