summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/kern/init_sysent.c4
-rw-r--r--sys/kern/kern_descrip.c26
-rw-r--r--sys/kern/kern_exec.c7
-rw-r--r--sys/kern/kern_exit.c5
-rw-r--r--sys/kern/kern_fork.c5
-rw-r--r--sys/kern/kern_sig.c52
-rw-r--r--sys/kern/sys_pipe.c67
-rw-r--r--sys/kern/syscalls.c4
-rw-r--r--sys/kern/syscalls.master5
-rw-r--r--sys/kern/uipc_socket.c109
-rw-r--r--sys/kern/uipc_socket2.c2
-rw-r--r--sys/kern/uipc_syscalls.c4
-rw-r--r--sys/kern/vfs_aio.c107
-rw-r--r--sys/kern/vfs_vnops.c78
-rw-r--r--sys/miscfs/fifofs/fifo_vnops.c86
-rw-r--r--sys/sys/aio.h7
-rw-r--r--sys/sys/file.h1
-rw-r--r--sys/sys/filedesc.h7
-rw-r--r--sys/sys/proc.h2
-rw-r--r--sys/sys/select.h3
-rw-r--r--sys/sys/socketvar.h3
-rw-r--r--sys/sys/syscall-hide.h4
-rw-r--r--sys/sys/syscall.h6
-rw-r--r--sys/sys/syscall.mk6
-rw-r--r--sys/sys/sysproto.h15
-rw-r--r--sys/ufs/ufs/ufs_readwrite.c9
-rw-r--r--sys/ufs/ufs/ufs_vnops.c46
27 files changed, 623 insertions, 47 deletions
diff --git a/sys/kern/init_sysent.c b/sys/kern/init_sysent.c
index b469c91feeda..e1f85f13c998 100644
--- a/sys/kern/init_sysent.c
+++ b/sys/kern/init_sysent.c
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: src/sys/kern/syscalls.master,v 1.72.2.1 2000/05/01 11:15:10 peter Exp
+ * created from FreeBSD: src/sys/kern/syscalls.master,v 1.74 2000/04/16 18:53:12 jlemon Exp
*/
#include "opt_compat.h"
@@ -382,4 +382,6 @@ struct sysent sysent[] = {
{ 2, (sy_call_t *)aio_waitcomplete }, /* 359 = aio_waitcomplete */
{ 3, (sy_call_t *)getresuid }, /* 360 = getresuid */
{ 3, (sy_call_t *)getresgid }, /* 361 = getresgid */
+ { 0, (sy_call_t *)kqueue }, /* 362 = kqueue */
+ { 6, (sy_call_t *)kevent }, /* 363 = kevent */
};
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index 1de896e9fffe..f0095c97ddac 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -56,6 +56,7 @@
#include <sys/malloc.h>
#include <sys/unistd.h>
#include <sys/resourcevar.h>
+#include <sys/event.h>
#include <vm/vm.h>
#include <vm/vm_extern.h>
@@ -504,6 +505,8 @@ close(p, uap)
if (fd < fdp->fd_freefile)
fdp->fd_freefile = fd;
*pf = 0;
+ if (fd < fdp->fd_knlistsize)
+ knote_fdclose(p, fd);
return (closef(fp, p));
}
@@ -830,9 +833,7 @@ fdinit(p)
newfdp->fd_fd.fd_ofiles = newfdp->fd_dfiles;
newfdp->fd_fd.fd_ofileflags = newfdp->fd_dfileflags;
newfdp->fd_fd.fd_nfiles = NDFILE;
-
- newfdp->fd_fd.fd_freefile = 0;
- newfdp->fd_fd.fd_lastfile = 0;
+ newfdp->fd_fd.fd_knlistsize = -1;
return (&newfdp->fd_fd);
}
@@ -899,6 +900,21 @@ fdcopy(p)
newfdp->fd_nfiles = i;
bcopy(fdp->fd_ofiles, newfdp->fd_ofiles, i * sizeof(struct file **));
bcopy(fdp->fd_ofileflags, newfdp->fd_ofileflags, i * sizeof(char));
+
+ /*
+ * kq descriptors cannot be copied.
+ */
+ if (newfdp->fd_knlistsize != -1) {
+ fpp = newfdp->fd_ofiles;
+ for (i = newfdp->fd_lastfile; i-- >= 0; fpp++)
+ if (*fpp != NULL && (*fpp)->f_type == DTYPE_KQUEUE)
+ *fpp = NULL;
+ newfdp->fd_knlist = NULL;
+ newfdp->fd_knlistsize = -1;
+ newfdp->fd_knhash = NULL;
+ newfdp->fd_knhashmask = 0;
+ }
+
fpp = newfdp->fd_ofiles;
for (i = newfdp->fd_lastfile; i-- >= 0; fpp++)
if (*fpp != NULL)
@@ -933,6 +949,10 @@ fdfree(p)
vrele(fdp->fd_rdir);
if (fdp->fd_jdir)
vrele(fdp->fd_jdir);
+ if (fdp->fd_knlist)
+ FREE(fdp->fd_knlist, M_TEMP);
+ if (fdp->fd_knhash)
+ FREE(fdp->fd_knhash, M_TEMP);
FREE(fdp, M_FILEDESC);
}
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index ba88695e7ee5..c65c8bd48330 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -47,7 +47,6 @@
#include <sys/shm.h>
#include <sys/sysctl.h>
#include <sys/vnode.h>
-#include <sys/buf.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
@@ -58,7 +57,6 @@
#include <vm/vm_kern.h>
#include <vm/vm_extern.h>
#include <vm/vm_object.h>
-#include <vm/vm_zone.h>
#include <vm/vm_pager.h>
#include <machine/reg.h>
@@ -311,6 +309,11 @@ interpret:
p->p_textvp = ndp->ni_vp;
/*
+ * notify others that we exec'd
+ */
+ KNOTE(&p->p_klist, NOTE_EXEC);
+
+ /*
* If tracing the process, trap to debugger so breakpoints
* can be set before the program executes.
*/
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index 9c2005c926cd..9115f9775a36 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -307,6 +307,11 @@ exit1(p, rv)
switchticks = ticks;
/*
+ * notify interested parties of our demise.
+ */
+ KNOTE(&p->p_klist, NOTE_EXIT);
+
+ /*
* Notify parent that we're gone. If parent has the PS_NOCLDWAIT
* flag set, notify process 1 instead (and hope it will handle
* this situation).
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
index fc69d282ec2e..62296b27d60e 100644
--- a/sys/kern/kern_fork.c
+++ b/sys/kern/kern_fork.c
@@ -509,6 +509,11 @@ again:
PRELE(p1);
/*
+ * tell any interested parties about the new process
+ */
+ KNOTE(&p1->p_klist, NOTE_FORK | p2->p_pid);
+
+ /*
* Preserve synchronization semantics of vfork. If waiting for
* child to exec or exit, set P_PPWAIT on child, and sleep on our
* proc (in case of exit).
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index c3bb68f73753..880ecc753299 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -49,6 +49,7 @@
#include <sys/resourcevar.h>
#include <sys/namei.h>
#include <sys/vnode.h>
+#include <sys/event.h>
#include <sys/proc.h>
#include <sys/pioctl.h>
#include <sys/systm.h>
@@ -62,7 +63,6 @@
#include <sys/sysctl.h>
#include <sys/malloc.h>
-#include <vm/vm_zone.h>
#include <machine/cpu.h>
#ifdef SMP
@@ -82,6 +82,13 @@ static int sig_ffs __P((sigset_t *set));
static int sigprop __P((int sig));
static void stop __P((struct proc *));
+static int filt_sigattach(struct knote *kn);
+static void filt_sigdetach(struct knote *kn);
+static int filt_signal(struct knote *kn, long hint);
+
+struct filterops sig_filtops =
+ { 0, filt_sigattach, filt_sigdetach, filt_signal };
+
static int kern_logsigexit = 1;
SYSCTL_INT(_kern, KERN_LOGSIGEXIT, logsigexit, CTLFLAG_RW,
&kern_logsigexit, 0,
@@ -996,6 +1003,8 @@ psignal(p, sig)
panic("psignal signal number");
}
+ KNOTE(&p->p_klist, NOTE_SIGNAL | sig);
+
prop = sigprop(sig);
/*
@@ -1682,3 +1691,44 @@ pgsigio(sigio, sig, checkctty)
psignal(p, sig);
}
}
+
+static int
+filt_sigattach(struct knote *kn)
+{
+ struct proc *p = curproc;
+
+ kn->kn_ptr.p_proc = p;
+ kn->kn_flags |= EV_CLEAR; /* automatically set */
+
+ /* XXX lock the proc here while adding to the list? */
+ SLIST_INSERT_HEAD(&p->p_klist, kn, kn_selnext);
+
+ return (0);
+}
+
+static void
+filt_sigdetach(struct knote *kn)
+{
+ struct proc *p = kn->kn_ptr.p_proc;
+
+ SLIST_REMOVE(&p->p_klist, kn, knote, kn_selnext);
+}
+
+/*
+ * signal knotes are shared with proc knotes, so we apply a mask to
+ * the hint in order to differentiate them from process hints. This
+ * could be avoided by using a signal-specific knote list, but probably
+ * isn't worth the trouble.
+ */
+static int
+filt_signal(struct knote *kn, long hint)
+{
+
+ if (hint & NOTE_SIGNAL) {
+ hint &= ~NOTE_SIGNAL;
+
+ if (kn->kn_id == hint)
+ kn->kn_data++;
+ }
+ return (kn->kn_data != 0);
+}
diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c
index a181b5a70e49..be868830f2d0 100644
--- a/sys/kern/sys_pipe.c
+++ b/sys/kern/sys_pipe.c
@@ -65,6 +65,7 @@
#include <sys/pipe.h>
#include <sys/vnode.h>
#include <sys/uio.h>
+#include <sys/event.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
@@ -100,6 +101,16 @@ static int pipe_ioctl __P((struct file *fp, u_long cmd, caddr_t data, struct pro
static struct fileops pipeops =
{ pipe_read, pipe_write, pipe_ioctl, pipe_poll, pipe_stat, pipe_close };
+static int filt_pipeattach(struct knote *kn);
+static void filt_pipedetach(struct knote *kn);
+static int filt_piperead(struct knote *kn, long hint);
+static int filt_pipewrite(struct knote *kn, long hint);
+
+struct filterops pipe_rwfiltops[] = {
+ { 1, filt_pipeattach, filt_pipedetach, filt_piperead },
+ { 1, filt_pipeattach, filt_pipedetach, filt_pipewrite },
+};
+
/*
* Default pipe buffer size(s), this can be kind-of large now because pipe
* space is pageable. The pipe code will try to maintain locality of
@@ -316,6 +327,7 @@ pipeselwakeup(cpipe)
}
if ((cpipe->pipe_state & PIPE_ASYNC) && cpipe->pipe_sigio)
pgsigio(cpipe->pipe_sigio, SIGIO, 0);
+ KNOTE(&cpipe->pipe_sel.si_note, 0);
}
/* ARGSUSED */
@@ -1159,3 +1171,58 @@ pipeclose(cpipe)
zfree(pipe_zone, cpipe);
}
}
+
+static int
+filt_pipeattach(struct knote *kn)
+{
+ struct pipe *rpipe = (struct pipe *)kn->kn_fp->f_data;
+
+ SLIST_INSERT_HEAD(&rpipe->pipe_sel.si_note, kn, kn_selnext);
+ return (0);
+}
+
+static void
+filt_pipedetach(struct knote *kn)
+{
+ struct pipe *rpipe = (struct pipe *)kn->kn_fp->f_data;
+
+ SLIST_REMOVE(&rpipe->pipe_sel.si_note, kn, knote, kn_selnext);
+}
+
+/*ARGSUSED*/
+static int
+filt_piperead(struct knote *kn, long hint)
+{
+ struct pipe *rpipe = (struct pipe *)kn->kn_fp->f_data;
+ struct pipe *wpipe = rpipe->pipe_peer;
+
+ kn->kn_data = rpipe->pipe_buffer.cnt;
+ if ((kn->kn_data == 0) && (rpipe->pipe_state & PIPE_DIRECTW))
+ kn->kn_data = rpipe->pipe_map.cnt;
+
+ if ((rpipe->pipe_state & PIPE_EOF) ||
+ (wpipe == NULL) || (wpipe->pipe_state & PIPE_EOF)) {
+ kn->kn_flags |= EV_EOF;
+ return (1);
+ }
+ return (kn->kn_data > 0);
+}
+
+/*ARGSUSED*/
+static int
+filt_pipewrite(struct knote *kn, long hint)
+{
+ struct pipe *rpipe = (struct pipe *)kn->kn_fp->f_data;
+ struct pipe *wpipe = rpipe->pipe_peer;
+
+ if ((wpipe == NULL) || (wpipe->pipe_state & PIPE_EOF)) {
+ kn->kn_data = 0;
+ kn->kn_flags |= EV_EOF;
+ return (1);
+ }
+ kn->kn_data = wpipe->pipe_buffer.size - wpipe->pipe_buffer.cnt;
+ if ((wpipe->pipe_state & PIPE_DIRECTW) == 0)
+ kn->kn_data = 0;
+
+ return (kn->kn_data >= PIPE_BUF);
+}
diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c
index b3f5facf7607..70013a30040a 100644
--- a/sys/kern/syscalls.c
+++ b/sys/kern/syscalls.c
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: src/sys/kern/syscalls.master,v 1.72.2.1 2000/05/01 11:15:10 peter Exp
+ * created from FreeBSD: src/sys/kern/syscalls.master,v 1.74 2000/04/16 18:53:12 jlemon Exp
*/
char *syscallnames[] = {
@@ -369,4 +369,6 @@ char *syscallnames[] = {
"aio_waitcomplete", /* 359 = aio_waitcomplete */
"getresuid", /* 360 = getresuid */
"getresgid", /* 361 = getresgid */
+ "kqueue", /* 362 = kqueue */
+ "kevent", /* 363 = kevent */
};
diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master
index 6e6ce514d4e6..5a62eb2a5aaa 100644
--- a/sys/kern/syscalls.master
+++ b/sys/kern/syscalls.master
@@ -513,3 +513,8 @@
359 STD BSD { int aio_waitcomplete(struct aiocb **aiocbp, struct timespec *timeout); }
360 STD BSD { int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); }
361 STD BSD { int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); }
+362 STD BSD { int kqueue(void); }
+363 STD BSD { int kevent(int fd, \
+ int nchanges, struct kevent **changelist, \
+ int nevents, struct kevent *eventlist, \
+ struct timespec *timeout); }
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c
index e4433be4a602..76495e19244f 100644
--- a/sys/kern/uipc_socket.c
+++ b/sys/kern/uipc_socket.c
@@ -40,8 +40,10 @@
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/domain.h>
+#include <sys/file.h> /* for struct knote */
#include <sys/kernel.h>
#include <sys/malloc.h>
+#include <sys/event.h>
#include <sys/poll.h>
#include <sys/proc.h>
#include <sys/protosw.h>
@@ -55,6 +57,22 @@
#include <machine/limits.h>
+static int filt_sorattach(struct knote *kn);
+static void filt_sordetach(struct knote *kn);
+static int filt_soread(struct knote *kn, long hint);
+static int filt_sowattach(struct knote *kn);
+static void filt_sowdetach(struct knote *kn);
+static int filt_sowrite(struct knote *kn, long hint);
+static int filt_solisten(struct knote *kn, long hint);
+
+static struct filterops solisten_filtops =
+ { 1, filt_sorattach, filt_sordetach, filt_solisten };
+
+struct filterops so_rwfiltops[] = {
+ { 1, filt_sorattach, filt_sordetach, filt_soread },
+ { 1, filt_sowattach, filt_sowdetach, filt_sowrite },
+};
+
struct vm_zone *socket_zone;
so_gen_t so_gencnt; /* generation count for sockets */
@@ -1388,3 +1406,94 @@ sopoll(struct socket *so, int events, struct ucred *cred, struct proc *p)
splx(s);
return (revents);
}
+
+static int
+filt_sorattach(struct knote *kn)
+{
+ struct socket *so = (struct socket *)kn->kn_fp->f_data;
+ int s = splnet();
+
+ if (so->so_options & SO_ACCEPTCONN)
+ kn->kn_fop = &solisten_filtops;
+ SLIST_INSERT_HEAD(&so->so_rcv.sb_sel.si_note, kn, kn_selnext);
+ so->so_rcv.sb_flags |= SB_KNOTE;
+ splx(s);
+ return (0);
+}
+
+static void
+filt_sordetach(struct knote *kn)
+{
+ struct socket *so = (struct socket *)kn->kn_fp->f_data;
+ int s = splnet();
+
+ SLIST_REMOVE(&so->so_rcv.sb_sel.si_note, kn, knote, kn_selnext);
+ if (SLIST_EMPTY(&so->so_rcv.sb_sel.si_note))
+ so->so_rcv.sb_flags &= ~SB_KNOTE;
+ splx(s);
+}
+
+/*ARGSUSED*/
+static int
+filt_soread(struct knote *kn, long hint)
+{
+ struct socket *so = (struct socket *)kn->kn_fp->f_data;
+
+ kn->kn_data = so->so_rcv.sb_cc;
+ if (so->so_state & SS_CANTRCVMORE) {
+ kn->kn_flags |= EV_EOF;
+ return (1);
+ }
+ return (kn->kn_data > 0);
+}
+
+static int
+filt_sowattach(struct knote *kn)
+{
+ struct socket *so = (struct socket *)kn->kn_fp->f_data;
+ int s = splnet();
+
+ SLIST_INSERT_HEAD(&so->so_snd.sb_sel.si_note, kn, kn_selnext);
+ so->so_snd.sb_flags |= SB_KNOTE;
+ splx(s);
+ return (0);
+}
+
+static void
+filt_sowdetach(struct knote *kn)
+{
+ struct socket *so = (struct socket *)kn->kn_fp->f_data;
+ int s = splnet();
+
+ SLIST_REMOVE(&so->so_snd.sb_sel.si_note, kn, knote, kn_selnext);
+ if (SLIST_EMPTY(&so->so_snd.sb_sel.si_note))
+ so->so_snd.sb_flags &= ~SB_KNOTE;
+ splx(s);
+}
+
+/*ARGSUSED*/
+static int
+filt_sowrite(struct knote *kn, long hint)
+{
+ struct socket *so = (struct socket *)kn->kn_fp->f_data;
+
+ kn->kn_data = sbspace(&so->so_snd);
+ if (so->so_state & SS_CANTSENDMORE) {
+ kn->kn_flags |= EV_EOF;
+ return (1);
+ }
+ if (((so->so_state & SS_ISCONNECTED) == 0) &&
+ (so->so_proto->pr_flags & PR_CONNREQUIRED))
+ return (0);
+ return (kn->kn_data >= so->so_snd.sb_lowat);
+}
+
+/*ARGSUSED*/
+static int
+filt_solisten(struct knote *kn, long hint)
+{
+ struct socket *so = (struct socket *)kn->kn_fp->f_data;
+
+ kn->kn_data = so->so_qlen - so->so_incqlen;
+ return (! TAILQ_EMPTY(&so->so_comp));
+}
diff --git a/sys/kern/uipc_socket2.c b/sys/kern/uipc_socket2.c
index 93d1fdacec5a..6184c233782e 100644
--- a/sys/kern/uipc_socket2.c
+++ b/sys/kern/uipc_socket2.c
@@ -51,6 +51,7 @@
#include <sys/signalvar.h>
#include <sys/sysctl.h>
#include <sys/aio.h> /* for aio_swake proto */
+#include <sys/event.h>
int maxsockets;
@@ -340,6 +341,7 @@ sowakeup(so, sb)
(*so->so_upcall)(so, so->so_upcallarg, M_DONTWAIT);
if (sb->sb_flags & SB_AIO)
aio_swake(so, sb);
+ KNOTE(&sb->sb_sel.si_note, 0);
}
/*
diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c
index 268125f94773..298bbe12b386 100644
--- a/sys/kern/uipc_syscalls.c
+++ b/sys/kern/uipc_syscalls.c
@@ -46,6 +46,7 @@
#include <sys/sysproto.h>
#include <sys/malloc.h>
#include <sys/filedesc.h>
+#include <sys/event.h>
#include <sys/proc.h>
#include <sys/fcntl.h>
#include <sys/file.h>
@@ -256,6 +257,9 @@ accept1(p, uap, compat)
} else
p->p_retval[0] = fd;
+ /* connection has been removed from the listen queue */
+ KNOTE(&head->so_rcv.sb_sel.si_note, 0);
+
so->so_state &= ~SS_COMP;
so->so_head = NULL;
if (head->so_sigio != NULL)
diff --git a/sys/kern/vfs_aio.c b/sys/kern/vfs_aio.c
index 9ef54a7a6d13..6c5bab565ee3 100644
--- a/sys/kern/vfs_aio.c
+++ b/sys/kern/vfs_aio.c
@@ -38,6 +38,7 @@
#include <sys/sysctl.h>
#include <sys/vnode.h>
#include <sys/conf.h>
+#include <sys/event.h>
#include <vm/vm.h>
#include <vm/vm_extern.h>
@@ -210,6 +211,13 @@ static int aio_fphysio(struct proc *p, struct aiocblist *aiocbe, int type);
static int aio_qphysio(struct proc *p, struct aiocblist *iocb);
static void aio_daemon(void *uproc);
+static int filt_aioattach(struct knote *kn);
+static void filt_aiodetach(struct knote *kn);
+static int filt_aio(struct knote *kn, long hint);
+
+struct filterops aio_filtops =
+ { 0, filt_aioattach, filt_aiodetach, filt_aio };
+
SYSINIT(aio, SI_SUB_VFS, SI_ORDER_ANY, aio_onceonly, NULL);
static vm_zone_t kaio_zone = 0, aiop_zone = 0, aiocb_zone = 0, aiol_zone = 0;
@@ -328,6 +336,9 @@ aio_free_entry(struct aiocblist *aiocbe)
num_buf_aio--;
}
+ /* aiocbe is going away, we need to destroy any knotes */
+ knote_remove(p, &aiocbe->klist);
+
if ((ki->kaio_flags & KAIO_WAKEUP) || ((ki->kaio_flags & KAIO_RUNDOWN)
&& ((ki->kaio_buffer_count == 0) && (ki->kaio_queue_count == 0)))) {
ki->kaio_flags &= ~KAIO_WAKEUP;
@@ -806,6 +817,7 @@ aio_daemon(void *uproc)
plist);
}
splx(s);
+ KNOTE(&aiocbe->klist, 0);
if (aiocbe->jobflags & AIOCBLIST_RUNDOWN) {
wakeup(aiocbe);
@@ -933,7 +945,7 @@ aio_qphysio(struct proc *p, struct aiocblist *aiocbe)
struct aio_liojob *lj;
int fd;
int s;
- int cnt;
+ int cnt, notify;
cb = &aiocbe->uaiocb;
fdp = p->p_fd;
@@ -1034,6 +1046,7 @@ aio_qphysio(struct proc *p, struct aiocblist *aiocbe)
/* Perform transfer. */
BUF_STRATEGY(bp, 0);
+ notify = 0;
s = splbio();
/*
@@ -1059,9 +1072,12 @@ aio_qphysio(struct proc *p, struct aiocblist *aiocbe)
TAILQ_REMOVE(&aio_bufjobs, aiocbe, list);
TAILQ_REMOVE(&ki->kaio_bufqueue, aiocbe, plist);
TAILQ_INSERT_TAIL(&ki->kaio_bufdone, aiocbe, plist);
+ notify = 1;
}
}
splx(s);
+ if (notify)
+ KNOTE(&aiocbe->klist, 0);
return 0;
doerror:
@@ -1174,7 +1190,7 @@ _aio_aqueue(struct proc *p, struct aiocb *job, struct aio_liojob *lj, int type)
unsigned int fd;
struct socket *so;
int s;
- int error;
+ int error = 0;
int opcode;
struct aiocblist *aiocbe;
struct aioproclist *aiop;
@@ -1187,6 +1203,7 @@ _aio_aqueue(struct proc *p, struct aiocb *job, struct aio_liojob *lj, int type)
aiocbe->inputcharge = 0;
aiocbe->outputcharge = 0;
+ SLIST_INIT(&aiocbe->klist);
suword(&job->_aiocb_private.status, -1);
suword(&job->_aiocb_private.error, 0);
@@ -1272,6 +1289,45 @@ _aio_aqueue(struct proc *p, struct aiocb *job, struct aio_liojob *lj, int type)
return EINVAL;
}
+ /*
+ * XXX
+ * Figure out how to do this properly. This currently won't
+ * work on the alpha, since we're passing in a pointer via
+ * aio_lio_opcode, which is an int.
+ */
+ {
+ struct kevent kev, *kevp;
+ struct kqueue *kq;
+
+ kevp = (struct kevent *)job->aio_lio_opcode;
+ if (kevp == NULL)
+ goto no_kqueue;
+
+ error = copyin((caddr_t)kevp, (caddr_t)&kev, sizeof(kev));
+ if (error)
+ goto aqueue_fail;
+
+ if ((u_int)kev.ident >= fdp->fd_nfiles ||
+ (fp = fdp->fd_ofiles[kev.ident]) == NULL ||
+ (fp->f_type != DTYPE_KQUEUE)) {
+ error = EBADF;
+ goto aqueue_fail;
+ }
+ kq = (struct kqueue *)fp->f_data;
+ kev.ident = (u_long)aiocbe;
+ kev.filter = EVFILT_AIO;
+ kev.flags = EV_ADD | EV_ENABLE | EV_FLAG1;
+ error = kqueue_register(kq, &kev, p);
+aqueue_fail:
+ if (error) {
+ TAILQ_INSERT_HEAD(&aio_freejobs, aiocbe, list);
+ if (type == 0)
+ suword(&job->_aiocb_private.error, error);
+ return (error);
+ }
+no_kqueue:
+ }
+
suword(&job->_aiocb_private.error, EINPROGRESS);
aiocbe->uaiocb._aiocb_private.error = EINPROGRESS;
aiocbe->userproc = p;
@@ -1629,6 +1685,7 @@ aio_cancel(struct proc *p, struct aio_cancel_args *uap)
cbe->uaiocb._aiocb_private.status=-1;
cbe->uaiocb._aiocb_private.error=ECANCELED;
cancelled++;
+/* XXX cancelled, knote? */
if (cbe->uaiocb.aio_sigevent.sigev_notify ==
SIGEV_SIGNAL)
psignal(cbe->userproc, cbe->uaiocb.aio_sigevent.sigev_signo);
@@ -1667,6 +1724,7 @@ aio_cancel(struct proc *p, struct aio_cancel_args *uap)
cbe->jobstate = JOBST_JOBFINISHED;
cbe->uaiocb._aiocb_private.status = -1;
cbe->uaiocb._aiocb_private.error = ECANCELED;
+/* XXX cancelled, knote? */
if (cbe->uaiocb.aio_sigevent.sigev_notify ==
SIGEV_SIGNAL)
psignal(cbe->userproc, cbe->uaiocb.aio_sigevent.sigev_signo);
@@ -2174,7 +2232,8 @@ aio_physwakeup(struct buf *bp)
TAILQ_REMOVE(&aio_bufjobs, aiocbe, list);
TAILQ_REMOVE(&ki->kaio_bufqueue, aiocbe, plist);
TAILQ_INSERT_TAIL(&ki->kaio_bufdone, aiocbe, plist);
-
+
+ KNOTE(&aiocbe->klist, 0);
/* Do the wakeup. */
if (ki->kaio_flags & (KAIO_RUNDOWN|KAIO_WAKEUP)) {
ki->kaio_flags &= ~KAIO_WAKEUP;
@@ -2267,3 +2326,45 @@ aio_waitcomplete(struct proc *p, struct aio_waitcomplete_args *uap)
}
#endif /* VFS_AIO */
}
+
+static int
+filt_aioattach(struct knote *kn)
+{
+ struct aiocblist *aiocbe = (struct aiocblist *)kn->kn_id;
+
+ /*
+ * The aiocbe pointer must be validated before using it, so
+ * registration is restricted to the kernel; the user cannot
+ * set EV_FLAG1.
+ */
+ if ((kn->kn_flags & EV_FLAG1) == 0)
+ return (EPERM);
+ kn->kn_flags &= ~EV_FLAG1;
+
+ SLIST_INSERT_HEAD(&aiocbe->klist, kn, kn_selnext);
+
+ return (0);
+}
+
+static void
+filt_aiodetach(struct knote *kn)
+{
+ struct aiocblist *aiocbe = (struct aiocblist *)kn->kn_id;
+ int s = splhigh(); /* XXX no clue, so overkill */
+
+ SLIST_REMOVE(&aiocbe->klist, kn, knote, kn_selnext);
+ splx(s);
+}
+
+/*ARGSUSED*/
+static int
+filt_aio(struct knote *kn, long hint)
+{
+ struct aiocblist *aiocbe = (struct aiocblist *)kn->kn_id;
+
+ kn->kn_data = 0; /* XXX data returned? */
+ if (aiocbe->jobstate != JOBST_JOBFINISHED)
+ return (0);
+ kn->kn_flags |= EV_EOF;
+ return (1);
+}
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index 1b4a5e07f73c..0f9713854b5f 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -52,7 +52,9 @@
#include <sys/filio.h>
#include <sys/ttycom.h>
#include <sys/conf.h>
-#include <vm/vm_zone.h>
+
+#include <ufs/ufs/quota.h>
+#include <ufs/ufs/inode.h>
static int vn_closefile __P((struct file *fp, struct proc *p));
static int vn_ioctl __P((struct file *fp, u_long com, caddr_t data,
@@ -68,6 +70,25 @@ static int vn_write __P((struct file *fp, struct uio *uio,
struct fileops vnops =
{ vn_read, vn_write, vn_ioctl, vn_poll, vn_statfile, vn_closefile };
+static int filt_nullattach(struct knote *kn);
+static int filt_vnattach(struct knote *kn);
+static void filt_vndetach(struct knote *kn);
+static int filt_vnode(struct knote *kn, long hint);
+static int filt_vnread(struct knote *kn, long hint);
+
+struct filterops vn_filtops =
+ { 1, filt_vnattach, filt_vndetach, filt_vnode };
+
+/*
+ * XXX
+ * filt_vnread is ufs-specific, so the attach routine should really
+ * switch out to different filterops based on the vn filetype
+ */
+struct filterops vn_rwfiltops[] = {
+ { 1, filt_vnattach, filt_vndetach, filt_vnread },
+ { 1, filt_nullattach, NULL, NULL },
+};
+
/*
* Common code for vnode open operations.
* Check permissions, and call the VOP_OPEN or VOP_CREATE routine.
@@ -639,3 +660,58 @@ vn_closefile(fp, p)
return (vn_close(((struct vnode *)fp->f_data), fp->f_flag,
fp->f_cred, p));
}
+
+static int
+filt_vnattach(struct knote *kn)
+{
+ struct vnode *vp;
+
+ if (kn->kn_fp->f_type != DTYPE_VNODE &&
+ kn->kn_fp->f_type != DTYPE_FIFO)
+ return (EBADF);
+
+ vp = (struct vnode *)kn->kn_fp->f_data;
+
+ simple_lock(&vp->v_pollinfo.vpi_lock);
+ SLIST_INSERT_HEAD(&vp->v_pollinfo.vpi_selinfo.si_note, kn, kn_selnext);
+ simple_unlock(&vp->v_pollinfo.vpi_lock);
+
+ return (0);
+}
+
+static void
+filt_vndetach(struct knote *kn)
+{
+ struct vnode *vp = (struct vnode *)kn->kn_fp->f_data;
+
+ simple_lock(&vp->v_pollinfo.vpi_lock);
+ SLIST_REMOVE(&vp->v_pollinfo.vpi_selinfo.si_note,
+ kn, knote, kn_selnext);
+ simple_unlock(&vp->v_pollinfo.vpi_lock);
+}
+
+static int
+filt_vnode(struct knote *kn, long hint)
+{
+
+ if (kn->kn_sfflags & hint)
+ kn->kn_fflags |= hint;
+ return (kn->kn_fflags != 0);
+}
+
+static int
+filt_nullattach(struct knote *kn)
+{
+ return (ENXIO);
+}
+
+/*ARGSUSED*/
+static int
+filt_vnread(struct knote *kn, long hint)
+{
+ struct vnode *vp = (struct vnode *)kn->kn_fp->f_data;
+ struct inode *ip = VTOI(vp);
+
+ kn->kn_data = ip->i_size - kn->kn_fp->f_offset;
+ return (kn->kn_data != 0);
+}
diff --git a/sys/miscfs/fifofs/fifo_vnops.c b/sys/miscfs/fifofs/fifo_vnops.c
index b64f957b4960..5bd13a771d48 100644
--- a/sys/miscfs/fifofs/fifo_vnops.c
+++ b/sys/miscfs/fifofs/fifo_vnops.c
@@ -46,6 +46,7 @@
#include <sys/filio.h>
#include <sys/fcntl.h>
#include <sys/file.h>
+#include <sys/event.h>
#include <sys/poll.h>
#include <sys/un.h>
#include <miscfs/fifofs/fifo.h>
@@ -75,6 +76,17 @@ static int fifo_bmap __P((struct vop_bmap_args *));
static int fifo_pathconf __P((struct vop_pathconf_args *));
static int fifo_advlock __P((struct vop_advlock_args *));
+static int filt_fiforattach(struct knote *kn);
+static void filt_fifordetach(struct knote *kn);
+static int filt_fiforead(struct knote *kn, long hint);
+static int filt_fifowattach(struct knote *kn);
+static void filt_fifowdetach(struct knote *kn);
+static int filt_fifowrite(struct knote *kn, long hint);
+
+struct filterops fifo_rwfiltops[] = {
+ { 1, filt_fiforattach, filt_fifordetach, filt_fiforead },
+ { 1, filt_fifowattach, filt_fifowdetach, filt_fifowrite },
+};
vop_t **fifo_vnodeop_p;
static struct vnodeopv_entry_desc fifo_vnodeop_entries[] = {
@@ -343,6 +355,80 @@ fifo_ioctl(ap)
return (0);
}
+static int
+filt_fiforattach(struct knote *kn)
+{
+ struct vnode *vn = (struct vnode *)kn->kn_fp->f_data;
+ struct socket *so = (struct socket *)vn->v_fifoinfo->fi_readsock;
+
+ SLIST_INSERT_HEAD(&so->so_rcv.sb_sel.si_note, kn, kn_selnext);
+ so->so_rcv.sb_flags |= SB_KNOTE;
+ return (0);
+}
+
+static void
+filt_fifordetach(struct knote *kn)
+{
+ struct vnode *vn = (struct vnode *)kn->kn_fp->f_data;
+ struct socket *so = (struct socket *)vn->v_fifoinfo->fi_readsock;
+
+ SLIST_REMOVE(&so->so_rcv.sb_sel.si_note, kn, knote, kn_selnext);
+ if (SLIST_EMPTY(&so->so_rcv.sb_sel.si_note))
+ so->so_rcv.sb_flags &= ~SB_KNOTE;
+}
+
+static int
+filt_fiforead(struct knote *kn, long hint)
+{
+ struct vnode *vn = (struct vnode *)kn->kn_fp->f_data;
+ struct socket *so = (struct socket *)vn->v_fifoinfo->fi_readsock;
+
+ kn->kn_data = so->so_rcv.sb_cc;
+ if (so->so_state & SS_CANTRCVMORE) {
+ kn->kn_flags |= EV_EOF;
+ return (1);
+ }
+ kn->kn_flags &= ~EV_EOF;
+ return (kn->kn_data > 0);
+}
+
+static int
+filt_fifowattach(struct knote *kn)
+{
+ struct vnode *vn = (struct vnode *)kn->kn_fp->f_data;
+ struct socket *so = (struct socket *)vn->v_fifoinfo->fi_writesock;
+
+ SLIST_INSERT_HEAD(&so->so_snd.sb_sel.si_note, kn, kn_selnext);
+ so->so_rcv.sb_flags |= SB_KNOTE;
+ return (0);
+}
+
+static void
+filt_fifowdetach(struct knote *kn)
+{
+ struct vnode *vn = (struct vnode *)kn->kn_fp->f_data;
+ struct socket *so = (struct socket *)vn->v_fifoinfo->fi_readsock;
+
+ SLIST_REMOVE(&so->so_snd.sb_sel.si_note, kn, knote, kn_selnext);
+ if (SLIST_EMPTY(&so->so_snd.sb_sel.si_note))
+ so->so_snd.sb_flags &= ~SB_KNOTE;
+}
+
+static int
+filt_fifowrite(struct knote *kn, long hint)
+{
+ struct vnode *vn = (struct vnode *)kn->kn_fp->f_data;
+ struct socket *so = (struct socket *)vn->v_fifoinfo->fi_readsock;
+
+ kn->kn_data = sbspace(&so->so_snd);
+ if (so->so_state & SS_CANTSENDMORE) {
+ kn->kn_flags |= EV_EOF;
+ return (1);
+ }
+ kn->kn_flags &= ~EV_EOF;
+ return (kn->kn_data >= so->so_snd.sb_lowat);
+}
+
/* ARGSUSED */
static int
fifo_poll(ap)
diff --git a/sys/sys/aio.h b/sys/sys/aio.h
index e905c899e14f..946ac0bec4c8 100644
--- a/sys/sys/aio.h
+++ b/sys/sys/aio.h
@@ -22,7 +22,6 @@
#include <sys/time.h>
#include <sys/types.h>
#include <sys/signal.h>
-#include <sys/socketvar.h>
/*
* Returned by aio_cancel:
@@ -168,11 +167,15 @@ struct aiocblist {
struct aioproclist *jobaioproc;/* AIO process descriptor */
struct aio_liojob *lio; /* Optional lio job */
struct aiocb *uuaiocb; /* Pointer in userspace of aiocb */
+ struct klist klist; /* list of knotes */
struct aiocb uaiocb; /* Kernel I/O control block */
};
-void aio_proc_rundown(struct proc *p);
+/* Forward declarations for prototypes below. */
+struct socket;
+struct sockbuf;
+void aio_proc_rundown(struct proc *p);
void aio_swake(struct socket *, struct sockbuf *);
#endif
diff --git a/sys/sys/file.h b/sys/sys/file.h
index 798642500ce7..7ad7a8158b4f 100644
--- a/sys/sys/file.h
+++ b/sys/sys/file.h
@@ -60,6 +60,7 @@ struct file {
#define DTYPE_SOCKET 2 /* communications endpoint */
#define DTYPE_PIPE 3 /* pipe */
#define DTYPE_FIFO 4 /* fifo (named pipe) */
+#define DTYPE_KQUEUE 5 /* event queue */
short f_type; /* descriptor type */
short f_count; /* reference count */
short f_msgcount; /* references from message queue */
diff --git a/sys/sys/filedesc.h b/sys/sys/filedesc.h
index 43630baa9452..9b07cfeddba2 100644
--- a/sys/sys/filedesc.h
+++ b/sys/sys/filedesc.h
@@ -56,6 +56,8 @@
#define NDFILE 20
#define NDEXTENT 50 /* 250 bytes in 256-byte alloc. */
+struct klist;
+
struct filedesc {
struct file **fd_ofiles; /* file structures for open files */
char *fd_ofileflags; /* per-process open file flags */
@@ -67,6 +69,11 @@ struct filedesc {
u_short fd_freefile; /* approx. next free file */
u_short fd_cmask; /* mask for file creation */
u_short fd_refcnt; /* reference count */
+
+ int fd_knlistsize; /* size of knlist */
+ struct klist *fd_knlist; /* list of attached knotes */
+ u_long fd_knhashmask; /* size of knhash */
+ struct klist *fd_knhash; /* hash table for attached knotes */
};
/*
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index 4c2eead9f775..65b47f287e19 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -52,6 +52,7 @@
#include <sys/time.h> /* For structs itimerval, timeval. */
#endif
#include <sys/ucred.h>
+#include <sys/event.h> /* For struct klist */
/*
* One structure allocated per session.
@@ -205,6 +206,7 @@ struct proc {
sigset_t p_oldsigmask; /* saved mask from before sigpause */
int p_sig; /* for core dump/debugger XXX */
u_long p_code; /* for core dump/debugger XXX */
+ struct klist p_klist; /* knotes attached to this process */
/* End area that is zeroed on creation. */
#define p_endzero p_startcopy
diff --git a/sys/sys/select.h b/sys/sys/select.h
index 8f58d858ba07..4909a341f5b0 100644
--- a/sys/sys/select.h
+++ b/sys/sys/select.h
@@ -37,12 +37,15 @@
#ifndef _SYS_SELECT_H_
#define _SYS_SELECT_H_
+#include <sys/event.h> /* for struct klist */
+
/*
* Used to maintain information about processes that wish to be
* notified when I/O becomes possible.
*/
struct selinfo {
pid_t si_pid; /* process to be notified */
+ struct klist si_note; /* kernel note list */
short si_flags; /* see below */
};
#define SI_COLL 0x0001 /* collision occurred */
diff --git a/sys/sys/socketvar.h b/sys/sys/socketvar.h
index 1b6d94ce348c..add6eb6c988e 100644
--- a/sys/sys/socketvar.h
+++ b/sys/sys/socketvar.h
@@ -104,6 +104,7 @@ struct socket {
#define SB_UPCALL 0x20 /* someone wants an upcall */
#define SB_NOINTR 0x40 /* operations not interruptible */
#define SB_AIO 0x80 /* AIO operations queued */
+#define SB_KNOTE 0x100 /* kernel note attached */
void (*so_upcall) __P((struct socket *, void *, int));
void *so_upcallarg;
@@ -172,7 +173,7 @@ struct xsocket {
* Do we need to notify the other side when I/O is possible?
*/
#define sb_notify(sb) (((sb)->sb_flags & (SB_WAIT | SB_SEL | SB_ASYNC | \
- SB_UPCALL | SB_AIO)) != 0)
+ SB_UPCALL | SB_AIO | SB_KNOTE)) != 0)
/*
* How much space is there in a socket buffer (so->so_snd or so->so_rcv)?
diff --git a/sys/sys/syscall-hide.h b/sys/sys/syscall-hide.h
index 8e7f99990385..1612418fd382 100644
--- a/sys/sys/syscall-hide.h
+++ b/sys/sys/syscall-hide.h
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: src/sys/kern/syscalls.master,v 1.72.2.1 2000/05/01 11:15:10 peter Exp
+ * created from FreeBSD: src/sys/kern/syscalls.master,v 1.74 2000/04/16 18:53:12 jlemon Exp
*/
HIDE_POSIX(fork)
@@ -278,3 +278,5 @@ HIDE_BSD(extattr_delete_file)
HIDE_BSD(aio_waitcomplete)
HIDE_BSD(getresuid)
HIDE_BSD(getresgid)
+HIDE_BSD(kqueue)
+HIDE_BSD(kevent)
diff --git a/sys/sys/syscall.h b/sys/sys/syscall.h
index 6149f4c5dba6..d5359581e048 100644
--- a/sys/sys/syscall.h
+++ b/sys/sys/syscall.h
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: src/sys/kern/syscalls.master,v 1.72.2.1 2000/05/01 11:15:10 peter Exp
+ * created from FreeBSD: src/sys/kern/syscalls.master,v 1.74 2000/04/16 18:53:12 jlemon Exp
*/
#define SYS_syscall 0
@@ -283,4 +283,6 @@
#define SYS_aio_waitcomplete 359
#define SYS_getresuid 360
#define SYS_getresgid 361
-#define SYS_MAXSYSCALL 362
+#define SYS_kqueue 362
+#define SYS_kevent 363
+#define SYS_MAXSYSCALL 364
diff --git a/sys/sys/syscall.mk b/sys/sys/syscall.mk
index d9a0371d6bcb..6924a70dd271 100644
--- a/sys/sys/syscall.mk
+++ b/sys/sys/syscall.mk
@@ -1,7 +1,7 @@
# FreeBSD system call names.
# DO NOT EDIT-- this file is automatically generated.
# $FreeBSD$
-# created from FreeBSD: src/sys/kern/syscalls.master,v 1.72.2.1 2000/05/01 11:15:10 peter Exp
+# created from FreeBSD: src/sys/kern/syscalls.master,v 1.74 2000/04/16 18:53:12 jlemon Exp
MIASM = \
syscall.o \
exit.o \
@@ -233,4 +233,6 @@ MIASM = \
extattr_delete_file.o \
aio_waitcomplete.o \
getresuid.o \
- getresgid.o
+ getresgid.o \
+ kqueue.o \
+ kevent.o
diff --git a/sys/sys/sysproto.h b/sys/sys/sysproto.h
index dbbd4911fd97..50ef14149220 100644
--- a/sys/sys/sysproto.h
+++ b/sys/sys/sysproto.h
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: src/sys/kern/syscalls.master,v 1.72.2.1 2000/05/01 11:15:10 peter Exp
+ * created from FreeBSD: src/sys/kern/syscalls.master,v 1.74 2000/04/16 18:53:12 jlemon Exp
*/
#ifndef _SYS_SYSPROTO_H_
@@ -1010,6 +1010,17 @@ struct getresgid_args {
gid_t * egid; char egid_[PAD_(gid_t *)];
gid_t * sgid; char sgid_[PAD_(gid_t *)];
};
+struct kqueue_args {
+ register_t dummy;
+};
+struct kevent_args {
+ int fd; char fd_[PAD_(int)];
+ int nchanges; char nchanges_[PAD_(int)];
+ struct kevent ** changelist; char changelist_[PAD_(struct kevent **)];
+ int nevents; char nevents_[PAD_(int)];
+ struct kevent * eventlist; char eventlist_[PAD_(struct kevent *)];
+ struct timespec * timeout; char timeout_[PAD_(struct timespec *)];
+};
int nosys __P((struct proc *, struct nosys_args *));
void exit __P((struct proc *, struct rexit_args *)) __dead2;
int fork __P((struct proc *, struct fork_args *));
@@ -1239,6 +1250,8 @@ int extattr_delete_file __P((struct proc *, struct extattr_delete_file_args *));
int aio_waitcomplete __P((struct proc *, struct aio_waitcomplete_args *));
int getresuid __P((struct proc *, struct getresuid_args *));
int getresgid __P((struct proc *, struct getresgid_args *));
+int kqueue __P((struct proc *, struct kqueue_args *));
+int kevent __P((struct proc *, struct kevent_args *));
#ifdef COMPAT_43
diff --git a/sys/ufs/ufs/ufs_readwrite.c b/sys/ufs/ufs/ufs_readwrite.c
index 48088e9da7a1..df295f7faa82 100644
--- a/sys/ufs/ufs/ufs_readwrite.c
+++ b/sys/ufs/ufs/ufs_readwrite.c
@@ -47,7 +47,10 @@
#include <vm/vm_pager.h>
#include <vm/vm_map.h>
#include <vm/vnode_pager.h>
-#include <sys/poll.h>
+#include <sys/event.h>
+
+#define VN_KNOTE(vp, b) \
+ KNOTE((struct klist *)&vp->v_pollinfo.vpi_selinfo.si_note, (b))
/*
* Vnode op for reading.
@@ -513,6 +516,8 @@ WRITE(ap)
*/
if (resid > uio->uio_resid && ap->a_cred && ap->a_cred->cr_uid != 0)
ip->i_mode &= ~(ISUID | ISGID);
+ if (resid > uio->uio_resid)
+ VN_KNOTE(vp, NOTE_WRITE | (extended ? NOTE_EXTEND : 0));
if (error) {
if (ioflag & IO_UNIT) {
(void)UFS_TRUNCATE(vp, osize,
@@ -522,8 +527,6 @@ WRITE(ap)
}
} else if (resid > uio->uio_resid && (ioflag & IO_SYNC))
error = UFS_UPDATE(vp, 1);
- if (!error)
- VN_POLLEVENT(vp, POLLWRITE | (extended ? POLLEXTEND : 0));
if (object)
vm_object_vndeallocate(object);
diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c
index c3f60181b076..72c2a4ed664a 100644
--- a/sys/ufs/ufs/ufs_vnops.c
+++ b/sys/ufs/ufs/ufs_vnops.c
@@ -56,10 +56,9 @@
#include <sys/malloc.h>
#include <sys/dirent.h>
#include <sys/lockf.h>
-#include <sys/poll.h>
+#include <sys/event.h>
#include <sys/conf.h>
-#include <vm/vm_zone.h>
#include <vm/vm.h>
#include <vm/vm_extern.h>
@@ -119,6 +118,8 @@ union _qcvt {
tmp.val[_QUAD_LOWWORD] = (l); \
(q) = tmp.qcvt; \
}
+#define VN_KNOTE(vp, b) \
+ KNOTE(&vp->v_pollinfo.vpi_selinfo.si_note, (b))
/*
* A virgin directory (no blushing please).
@@ -185,7 +186,7 @@ ufs_create(ap)
ap->a_dvp, ap->a_vpp, ap->a_cnp);
if (error)
return (error);
- VN_POLLEVENT(ap->a_dvp, POLLWRITE);
+ VN_KNOTE(ap->a_dvp, NOTE_WRITE);
return (0);
}
@@ -211,7 +212,7 @@ ufs_mknod(ap)
ap->a_dvp, vpp, ap->a_cnp);
if (error)
return (error);
- VN_POLLEVENT(ap->a_dvp, POLLWRITE);
+ VN_KNOTE(ap->a_dvp, NOTE_WRITE);
ip = VTOI(*vpp);
ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
if (vap->va_rdev != VNOVAL) {
@@ -527,7 +528,7 @@ ufs_setattr(ap)
return (EROFS);
error = ufs_chmod(vp, (int)vap->va_mode, cred, p);
}
- VN_POLLEVENT(vp, POLLATTRIB);
+ VN_KNOTE(vp, NOTE_ATTRIB);
return (error);
}
@@ -705,8 +706,8 @@ ufs_remove(ap)
goto out;
}
error = ufs_dirremove(dvp, ip, ap->a_cnp->cn_flags, 0);
- VN_POLLEVENT(vp, POLLNLINK);
- VN_POLLEVENT(dvp, POLLWRITE);
+ VN_KNOTE(vp, NOTE_DELETE);
+ VN_KNOTE(dvp, NOTE_WRITE);
out:
return (error);
}
@@ -772,8 +773,8 @@ out1:
if (tdvp != vp)
VOP_UNLOCK(vp, 0, p);
out2:
- VN_POLLEVENT(vp, POLLNLINK);
- VN_POLLEVENT(tdvp, POLLWRITE);
+ VN_KNOTE(vp, NOTE_LINK);
+ VN_KNOTE(tdvp, NOTE_WRITE);
return (error);
}
@@ -994,7 +995,7 @@ abortit:
oldparent = dp->i_number;
doingdirectory = 1;
}
- VN_POLLEVENT(fdvp, POLLWRITE);
+ VN_KNOTE(fdvp, NOTE_WRITE); /* XXX right place? */
vrele(fdvp);
/*
@@ -1100,7 +1101,7 @@ abortit:
}
goto bad;
}
- VN_POLLEVENT(tdvp, POLLWRITE);
+ VN_KNOTE(tdvp, NOTE_WRITE);
vput(tdvp);
} else {
if (xp->i_dev != dp->i_dev || xp->i_dev != ip->i_dev)
@@ -1157,7 +1158,6 @@ abortit:
if (DOINGSOFTDEP(tvp))
softdep_change_linkcnt(xp);
}
- VN_POLLEVENT(tdvp, POLLWRITE);
if (doingdirectory && !DOINGSOFTDEP(tvp)) {
/*
* Truncate inode. The only stuff left in the directory
@@ -1181,8 +1181,9 @@ abortit:
tcnp->cn_cred, tcnp->cn_proc)) != 0)
goto bad;
}
+ VN_KNOTE(tdvp, NOTE_WRITE);
vput(tdvp);
- VN_POLLEVENT(tvp, POLLNLINK); /* XXX this right? */
+ VN_KNOTE(tvp, NOTE_DELETE);
vput(tvp);
xp = NULL;
}
@@ -1237,6 +1238,7 @@ abortit:
error = ufs_dirremove(fdvp, xp, fcnp->cn_flags, 0);
xp->i_flag &= ~IN_RENAME;
}
+ VN_KNOTE(fvp, NOTE_RENAME);
if (dp)
vput(fdvp);
if (xp)
@@ -1313,10 +1315,10 @@ ufs_mkdir(ap)
#ifdef QUOTA
struct ucred ucred, *ucp;
ucp = cnp->cn_cred;
-#endif I
+#endif
/*
* If we are hacking owners here, (only do this where told to)
- * and we are not giving it TOO root, (would subvert quotas)
+ * and we are not giving it TO root, (would subvert quotas)
* then go ahead and give it to the other user.
* The new directory also inherits the SUID bit.
* If user's UID and dir UID are the same,
@@ -1425,7 +1427,6 @@ ufs_mkdir(ap)
(void)VOP_BWRITE(bp->b_vp, bp);
goto bad;
}
- VN_POLLEVENT(dvp, POLLWRITE); /* XXX right place? */
/*
* Directory set up, now install its entry in the parent directory.
*
@@ -1446,6 +1447,7 @@ ufs_mkdir(ap)
bad:
if (error == 0) {
+ VN_KNOTE(dvp, NOTE_WRITE);
*ap->a_vpp = tvp;
} else {
dp->i_effnlink--;
@@ -1536,7 +1538,7 @@ ufs_rmdir(ap)
}
goto out;
}
- VN_POLLEVENT(dvp, POLLWRITE|POLLNLINK);
+ VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK);
cache_purge(dvp);
/*
* Truncate inode. The only stuff left in the directory is "." and
@@ -1556,7 +1558,7 @@ ufs_rmdir(ap)
}
cache_purge(vp);
out:
- VN_POLLEVENT(vp, POLLNLINK);
+ VN_KNOTE(vp, NOTE_DELETE);
return (error);
}
@@ -1581,7 +1583,7 @@ ufs_symlink(ap)
vpp, ap->a_cnp);
if (error)
return (error);
- VN_POLLEVENT(ap->a_dvp, POLLWRITE);
+ VN_KNOTE(ap->a_dvp, NOTE_WRITE);
vp = *vpp;
len = strlen(ap->a_target);
if (len < vp->v_mount->mnt_maxsymlinklen) {
@@ -2085,11 +2087,11 @@ ufs_makeinode(mode, dvp, vpp, cnp)
#ifdef QUOTA
struct ucred ucred, *ucp;
ucp = cnp->cn_cred;
-#endif I
+#endif
/*
* If we are not the owner of the directory,
* and we are hacking owners here, (only do this where told to)
- * and we are not giving it TOO root, (would subvert quotas)
+ * and we are not giving it TO root, (would subvert quotas)
* then go ahead and give it to the other user.
* Note that this drops off the execute bits for security.
*/
@@ -2300,5 +2302,3 @@ ufs_vnoperatespec(ap)
{
return (VOCALL(ufs_specop_p, ap->a_desc->vdesc_offset, ap));
}
-
-