summaryrefslogtreecommitdiffstats
path: root/sys/fs
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2012-03-07 07:31:50 +0000
committerkib <kib@FreeBSD.org>2012-03-07 07:31:50 +0000
commit9d4d411642d8ae4323ed9b0a43cc35dcd602a654 (patch)
tree962288acaad3ba101c032ff509e596c7e1619d71 /sys/fs
parent1ead29e7154b634bb94ffd418424a2000e42c68c (diff)
downloadFreeBSD-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/fs')
-rw-r--r--sys/fs/fifofs/fifo.h1
-rw-r--r--sys/fs/fifofs/fifo_vnops.c25
2 files changed, 12 insertions, 14 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);
-}
-
OpenPOWER on IntegriCloud