summaryrefslogtreecommitdiffstats
path: root/fs/fcntl.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1999-12-04 03:58:56 +0000
committerRalf Baechle <ralf@linux-mips.org>1999-12-04 03:58:56 +0000
commit1d67e90f19a7acfd9a05dc59678e7d0c5090bd0d (patch)
tree357efc7b93f8f5102110d20d293f41360ec212fc /fs/fcntl.c
parentaea27b2e18d69af87e673972246e66657b4fa274 (diff)
Merge with Linux 2.3.21.
Diffstat (limited to 'fs/fcntl.c')
-rw-r--r--fs/fcntl.c42
1 files changed, 32 insertions, 10 deletions
diff --git a/fs/fcntl.c b/fs/fcntl.c
index 26c9bf4a0..255267da8 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -8,6 +8,8 @@
#include <linux/file.h>
#include <linux/smp_lock.h>
+#include <asm/poll.h>
+#include <asm/siginfo.h>
#include <asm/uaccess.h>
extern int sock_fcntl (struct file *, unsigned int cmd, unsigned long arg);
@@ -255,8 +257,22 @@ out:
return err;
}
+/* Table to convert sigio signal codes into poll band bitmaps */
+
+static int band_table[NSIGPOLL+1] = {
+ ~0,
+ POLLIN | POLLRDNORM, /* POLL_IN */
+ POLLOUT | POLLWRNORM | POLLWRBAND, /* POLL_OUT */
+ POLLIN | POLLRDNORM | POLLMSG, /* POLL_MSG */
+ POLLERR, /* POLL_ERR */
+ POLLPRI | POLLRDBAND, /* POLL_PRI */
+ POLLHUP | POLLERR /* POLL_HUP */
+};
+
static void send_sigio_to_task(struct task_struct *p,
- struct fown_struct *fown, struct fasync_struct *fa)
+ struct fown_struct *fown,
+ struct fasync_struct *fa,
+ int reason)
{
if ((fown->euid != 0) &&
(fown->euid ^ p->suid) && (fown->euid ^ p->uid) &&
@@ -273,9 +289,11 @@ static void send_sigio_to_task(struct task_struct *p,
back to SIGIO in that case. --sct */
si.si_signo = fown->signum;
si.si_errno = 0;
- si.si_code = SI_SIGIO;
- si.si_pid = fown->pid;
- si.si_uid = fown->uid;
+ si.si_code = reason;
+ if (reason < 0 || reason > NSIGPOLL)
+ si.si_band = ~0;
+ else
+ si.si_band = band_table[reason];
si.si_fd = fa->fa_fd;
if (!send_sig_info(fown->signum, &si, p))
break;
@@ -285,14 +303,15 @@ static void send_sigio_to_task(struct task_struct *p,
}
}
-static void send_sigio(struct fown_struct *fown, struct fasync_struct *fa)
+static void send_sigio(struct fown_struct *fown, struct fasync_struct *fa,
+ int band)
{
struct task_struct * p;
int pid = fown->pid;
read_lock(&tasklist_lock);
if ( (pid > 0) && (p = find_task_by_pid(pid)) ) {
- send_sigio_to_task(p, fown, fa);
+ send_sigio_to_task(p, fown, fa, band);
goto out;
}
for_each_task(p) {
@@ -301,13 +320,13 @@ static void send_sigio(struct fown_struct *fown, struct fasync_struct *fa)
match = -p->pgrp;
if (pid != match)
continue;
- send_sigio_to_task(p, fown, fa);
+ send_sigio_to_task(p, fown, fa, band);
}
out:
read_unlock(&tasklist_lock);
}
-void kill_fasync(struct fasync_struct *fa, int sig)
+void kill_fasync(struct fasync_struct *fa, int sig, int band)
{
while (fa) {
struct fown_struct * fown;
@@ -317,8 +336,11 @@ void kill_fasync(struct fasync_struct *fa, int sig)
return;
}
fown = &fa->fa_file->f_owner;
- if (fown->pid)
- send_sigio(fown, fa);
+ /* Don't send SIGURG to processes which have not set a
+ queued signum: SIGURG has its own default signalling
+ mechanism. */
+ if (fown->pid && !(sig == SIGURG && fown->signum == 0))
+ send_sigio(fown, fa, band);
fa = fa->fa_next;
}
}