diff options
author | kib <kib@FreeBSD.org> | 2012-03-07 07:31:50 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2012-03-07 07:31:50 +0000 |
commit | 9d4d411642d8ae4323ed9b0a43cc35dcd602a654 (patch) | |
tree | 962288acaad3ba101c032ff509e596c7e1619d71 /sys | |
parent | 1ead29e7154b634bb94ffd418424a2000e42c68c (diff) | |
download | FreeBSD-src-9d4d411642d8ae4323ed9b0a43cc35dcd602a654.zip FreeBSD-src-9d4d411642d8ae4323ed9b0a43cc35dcd602a654.tar.gz |
The pipe_poll() performs lockless access to the vnode to test
fifo_iseof() condition, allowing the v_fifoinfo to be reset and freed
by fifo_cleanup().
Precalculate EOF at the places were fo_wgen is changed, and cache the
state in a new pipe state flag PIPE_SAMEWGEN.
Reported and tested by: bf
Submitted by: gianni
MFC after: 1 week (a backport)
Diffstat (limited to 'sys')
-rw-r--r-- | sys/fs/fifofs/fifo.h | 1 | ||||
-rw-r--r-- | sys/fs/fifofs/fifo_vnops.c | 25 | ||||
-rw-r--r-- | sys/kern/sys_pipe.c | 2 | ||||
-rw-r--r-- | sys/sys/pipe.h | 1 |
4 files changed, 14 insertions, 15 deletions
diff --git a/sys/fs/fifofs/fifo.h b/sys/fs/fifofs/fifo.h index 94bccc6..da85ae2 100644 --- a/sys/fs/fifofs/fifo.h +++ b/sys/fs/fifofs/fifo.h @@ -33,7 +33,6 @@ /* * Prototypes for fifo operations on vnodes. */ -int fifo_iseof(struct file *); int fifo_vnoperate(struct vop_generic_args *); int fifo_printinfo(struct vnode *); diff --git a/sys/fs/fifofs/fifo_vnops.c b/sys/fs/fifofs/fifo_vnops.c index 1cc17cf..65c44ae 100644 --- a/sys/fs/fifofs/fifo_vnops.c +++ b/sys/fs/fifofs/fifo_vnops.c @@ -67,8 +67,16 @@ struct fifoinfo { long fi_readers; long fi_writers; int fi_wgen; + int fi_seqcount; }; +#define FIFO_UPDWGEN(fip, pip) do { \ + if ((fip)->fi_wgen == (fip)->fi_seqcount) \ + (pip)->pipe_state |= PIPE_SAMEWGEN; \ + else \ + (pip)->pipe_state &= ~PIPE_SAMEWGEN; \ +} while (0) + static vop_print_t fifo_print; static vop_open_t fifo_open; static vop_close_t fifo_close; @@ -174,7 +182,8 @@ fifo_open(ap) if (fip->fi_writers > 0) wakeup(&fip->fi_writers); } - fp->f_seqcount = fip->fi_wgen - fip->fi_writers; + fip->fi_seqcount = fip->fi_wgen - fip->fi_writers; + FIFO_UPDWGEN(fip, fpipe); } if (ap->a_mode & FWRITE) { if ((ap->a_mode & O_NONBLOCK) && fip->fi_readers == 0) { @@ -228,6 +237,7 @@ fifo_open(ap) if (fpipe->pipe_state & PIPE_WANTR) wakeup(fpipe); fip->fi_wgen++; + FIFO_UPDWGEN(fip, fpipe); PIPE_UNLOCK(fpipe); fifo_cleanup(vp); } @@ -287,6 +297,7 @@ fifo_close(ap) if (cpipe->pipe_state & PIPE_WANTR) wakeup(cpipe); fip->fi_wgen++; + FIFO_UPDWGEN(fip, cpipe); PIPE_UNLOCK(cpipe); } } @@ -373,15 +384,3 @@ fifo_advlock(ap) return (ap->a_flags & F_FLOCK ? EOPNOTSUPP : EINVAL); } -int -fifo_iseof(struct file *fp) -{ - struct fifoinfo *fip; - - KASSERT(fp->f_vnode != NULL, ("fifo_iseof: no vnode info")); - KASSERT(fp->f_vnode->v_fifoinfo != NULL, ("fifo_iseof: no fifoinfo")); - fip = fp->f_vnode->v_fifoinfo; - PIPE_LOCK_ASSERT(fip->fi_pipe, MA_OWNED); - return (fp->f_seqcount == fip->fi_wgen); -} - diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c index 89b9589..e973c22 100644 --- a/sys/kern/sys_pipe.c +++ b/sys/kern/sys_pipe.c @@ -1430,7 +1430,7 @@ pipe_poll(fp, events, active_cred, td) levents = events & (POLLIN | POLLINIGNEOF | POLLPRI | POLLRDNORM | POLLRDBAND); if (rpipe->pipe_state & PIPE_NAMED && fp->f_flag & FREAD && levents && - fifo_iseof(fp)) + rpipe->pipe_state & PIPE_SAMEWGEN) events |= POLLINIGNEOF; if ((events & POLLINIGNEOF) == 0) { diff --git a/sys/sys/pipe.h b/sys/sys/pipe.h index 36e3021..d60185a 100644 --- a/sys/sys/pipe.h +++ b/sys/sys/pipe.h @@ -96,6 +96,7 @@ struct pipemapping { #define PIPE_DIRECTW 0x400 /* Pipe direct write active. */ #define PIPE_DIRECTOK 0x800 /* Direct mode ok. */ #define PIPE_NAMED 0x1000 /* Is a named pipe. */ +#define PIPE_SAMEWGEN 0x2000 /* same write generation for named pipes. */ /* * Per-pipe data structure. |