diff options
author | Konstantin Belousov <kib@FreeBSD.org> | 2012-03-07 07:31:50 +0000 |
---|---|---|
committer | Konstantin Belousov <kib@FreeBSD.org> | 2012-03-07 07:31:50 +0000 |
commit | f950879e16c0a4c794beff0731a53494613e9c56 (patch) | |
tree | 962288acaad3ba101c032ff509e596c7e1619d71 /sys/fs | |
parent | cd613b635128f2737d31ce49fbadceb36636f9e0 (diff) | |
download | src-f950879e16c0a4c794beff0731a53494613e9c56.tar.gz src-f950879e16c0a4c794beff0731a53494613e9c56.zip |
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)
Notes
Notes:
svn path=/head/; revision=232641
Diffstat (limited to 'sys/fs')
-rw-r--r-- | sys/fs/fifofs/fifo.h | 1 | ||||
-rw-r--r-- | sys/fs/fifofs/fifo_vnops.c | 25 |
2 files changed, 12 insertions, 14 deletions
diff --git a/sys/fs/fifofs/fifo.h b/sys/fs/fifofs/fifo.h index 94bccc68466a..da85ae23d86b 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 1cc17cf9e6fd..65c44ae2cab8 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); -} - |