summaryrefslogtreecommitdiffstats
path: root/sys/fs
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2015-09-27 01:06:45 +0000
committerkib <kib@FreeBSD.org>2015-09-27 01:06:45 +0000
commitd059c10283c1b9c979f237d20f8944465a2e3f62 (patch)
treefecb18b1e05de65123c48de02c9b429c91550efd /sys/fs
parent80ccd15a369de97ea8f395ca1bcbda7d54541731 (diff)
downloadFreeBSD-src-d059c10283c1b9c979f237d20f8944465a2e3f62.zip
FreeBSD-src-d059c10283c1b9c979f237d20f8944465a2e3f62.tar.gz
MFC r288044:
Ensure that when a blockable open of fifo returns success, a valid file descriptor opened for complimentary access exists as well.
Diffstat (limited to 'sys/fs')
-rw-r--r--sys/fs/fifofs/fifo_vnops.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/sys/fs/fifofs/fifo_vnops.c b/sys/fs/fifofs/fifo_vnops.c
index e544bba..716faa3 100644
--- a/sys/fs/fifofs/fifo_vnops.c
+++ b/sys/fs/fifofs/fifo_vnops.c
@@ -64,6 +64,8 @@ struct fifoinfo {
struct pipe *fi_pipe;
long fi_readers;
long fi_writers;
+ u_int fi_rgen;
+ u_int fi_wgen;
};
static vop_print_t fifo_print;
@@ -137,6 +139,7 @@ fifo_open(ap)
struct thread *td;
struct fifoinfo *fip;
struct pipe *fpipe;
+ u_int gen;
int error, stops_deferred;
vp = ap->a_vp;
@@ -164,6 +167,7 @@ fifo_open(ap)
PIPE_LOCK(fpipe);
if (ap->a_mode & FREAD) {
fip->fi_readers++;
+ fip->fi_rgen++;
if (fip->fi_readers == 1) {
fpipe->pipe_state &= ~PIPE_EOF;
if (fip->fi_writers > 0)
@@ -179,6 +183,7 @@ fifo_open(ap)
return (ENXIO);
}
fip->fi_writers++;
+ fip->fi_wgen++;
if (fip->fi_writers == 1) {
fpipe->pipe_state &= ~PIPE_EOF;
if (fip->fi_readers > 0)
@@ -187,6 +192,7 @@ fifo_open(ap)
}
if ((ap->a_mode & O_NONBLOCK) == 0) {
if ((ap->a_mode & FREAD) && fip->fi_writers == 0) {
+ gen = fip->fi_wgen;
VOP_UNLOCK(vp, 0);
stops_deferred = sigallowstop();
error = msleep(&fip->fi_readers, PIPE_MTX(fpipe),
@@ -194,7 +200,7 @@ fifo_open(ap)
if (stops_deferred)
sigdeferstop();
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
- if (error) {
+ if (error != 0 && gen == fip->fi_wgen) {
fip->fi_readers--;
if (fip->fi_readers == 0) {
PIPE_LOCK(fpipe);
@@ -214,6 +220,7 @@ fifo_open(ap)
*/
}
if ((ap->a_mode & FWRITE) && fip->fi_readers == 0) {
+ gen = fip->fi_rgen;
VOP_UNLOCK(vp, 0);
stops_deferred = sigallowstop();
error = msleep(&fip->fi_writers, PIPE_MTX(fpipe),
@@ -221,7 +228,7 @@ fifo_open(ap)
if (stops_deferred)
sigdeferstop();
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
- if (error) {
+ if (error != 0 && gen == fip->fi_rgen) {
fip->fi_writers--;
if (fip->fi_writers == 0) {
PIPE_LOCK(fpipe);
OpenPOWER on IntegriCloud