diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1998-09-19 19:15:08 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1998-09-19 19:15:08 +0000 |
commit | 03ba4131783cc9e872f8bb26a03f15bc11f27564 (patch) | |
tree | 88db8dba75ae06ba3bad08e42c5e52efc162535c /fs/fcntl.c | |
parent | 257730f99381dd26e10b832fce4c94cae7ac1176 (diff) |
- Merge with Linux 2.1.121.
- Bugfixes.
Diffstat (limited to 'fs/fcntl.c')
-rw-r--r-- | fs/fcntl.c | 50 |
1 files changed, 41 insertions, 9 deletions
diff --git a/fs/fcntl.c b/fs/fcntl.c index a35db83a8..919204088 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -84,7 +84,7 @@ asmlinkage int sys_dup(unsigned int fildes) #define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | FASYNC) -static int setfl(struct file * filp, unsigned long arg) +static int setfl(int fd, struct file * filp, unsigned long arg) { struct inode * inode = filp->f_dentry->d_inode; @@ -98,7 +98,7 @@ static int setfl(struct file * filp, unsigned long arg) /* Did FASYNC state change? */ if ((arg ^ filp->f_flags) & FASYNC) { if (filp->f_op->fasync) - filp->f_op->fasync(filp, (arg & FASYNC) != 0); + filp->f_op->fasync(fd, filp, (arg & FASYNC) != 0); } /* required for strict SunOS emulation */ @@ -137,7 +137,7 @@ asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg) err = filp->f_flags; break; case F_SETFL: - err = setfl(filp, arg); + err = setfl(fd, filp, arg); break; case F_GETLK: err = fcntl_getlk(fd, (struct flock *) arg); @@ -166,6 +166,17 @@ asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg) if (S_ISSOCK (filp->f_dentry->d_inode->i_mode)) err = sock_fcntl (filp, F_SETOWN, arg); break; + case F_GETSIG: + err = filp->f_owner.signum; + break; + case F_SETSIG: + if (arg <= 0 || arg > _NSIG) { + err = -EINVAL; + break; + } + err = 0; + filp->f_owner.signum = arg; + break; default: /* sockets need a few special fcntls. */ if (S_ISSOCK (filp->f_dentry->d_inode->i_mode)) @@ -180,10 +191,13 @@ out: return err; } -static void send_sigio(int pid, uid_t uid, uid_t euid) +static void send_sigio(struct fown_struct *fown, struct fasync_struct *fa) { struct task_struct * p; - + int pid = fown->pid; + uid_t uid = fown->uid; + uid_t euid = fown->euid; + read_lock(&tasklist_lock); for_each_task(p) { int match = p->pid; @@ -195,9 +209,27 @@ static void send_sigio(int pid, uid_t uid, uid_t euid) (euid ^ p->suid) && (euid ^ p->uid) && (uid ^ p->suid) && (uid ^ p->uid)) continue; - send_sig(SIGIO, p, 1); - if (p->state == TASK_INTERRUPTIBLE && signal_pending(p)) - wake_up_process(p); + switch (fown->signum) { + siginfo_t si; + default: + /* Queue a rt signal with the appropriate fd as its + value. We use SI_SIGIO as the source, not + SI_KERNEL, since kernel signals always get + delivered even if we can't queue. Failure to + queue in this case _should_ be reported; we fall + back to SIGIO in that case. --sct */ + si.si_signo = fown->signum; + si.si_errno = 0; + si.si_code = SI_SIGIO; + si.si_pid = pid; + si.si_uid = uid; + si.si_fd = fa->fa_fd; + if (!send_sig_info(fown->signum, &si, p)) + break; + /* fall-through: fall back on the old plain SIGIO signal */ + case 0: + send_sig(SIGIO, p, 1); + } } read_unlock(&tasklist_lock); } @@ -213,7 +245,7 @@ void kill_fasync(struct fasync_struct *fa, int sig) } fown = &fa->fa_file->f_owner; if (fown->pid) - send_sigio(fown->pid, fown->uid, fown->euid); + send_sigio(fown, fa); fa = fa->fa_next; } } |