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)
This commit is contained in:
parent
cd613b6351
commit
f950879e16
@ -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 *);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user