diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1999-10-09 00:00:47 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1999-10-09 00:00:47 +0000 |
commit | d6434e1042f3b0a6dfe1b1f615af369486f9b1fa (patch) | |
tree | e2be02f33984c48ec019c654051d27964e42c441 /fs/fifo.c | |
parent | 609d1e803baf519487233b765eb487f9ec227a18 (diff) |
Merge with 2.3.19.
Diffstat (limited to 'fs/fifo.c')
-rw-r--r-- | fs/fifo.c | 178 |
1 files changed, 89 insertions, 89 deletions
@@ -12,38 +12,38 @@ #include <linux/mm.h> #include <linux/malloc.h> -static int fifo_open(struct inode * inode,struct file * filp) +static int fifo_open(struct inode *inode, struct file *filp) { - int retval = 0; - unsigned long page = 0; - struct pipe_inode_info *info, *tmp = NULL; - - if (inode->i_pipe) - goto got_it; - tmp = kmalloc(sizeof(struct pipe_inode_info),GFP_KERNEL); - if (inode->i_pipe) - goto got_it; - if (!tmp) - goto oom; - page = __get_free_page(GFP_KERNEL); - if (inode->i_pipe) - goto got_it; - if (!page) - goto oom; - inode->i_pipe = tmp; - PIPE_LOCK(*inode) = 0; - PIPE_START(*inode) = PIPE_LEN(*inode) = 0; - PIPE_BASE(*inode) = (char *) page; - PIPE_RD_OPENERS(*inode) = PIPE_WR_OPENERS(*inode) = 0; - PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 0; - init_waitqueue_head(&PIPE_WAIT(*inode)); - tmp = NULL; /* no need to free it */ - page = 0; - -got_it: - - switch( filp->f_mode ) { + int ret; + ret = -ERESTARTSYS; + if (down_interruptible(PIPE_SEM(*inode))) + goto err_nolock_nocleanup; + + if (! inode->i_pipe) { + unsigned long page; + struct pipe_inode_info *info; + + info = kmalloc(sizeof(struct pipe_inode_info),GFP_KERNEL); + + ret = -ENOMEM; + if (!info) + goto err_nocleanup; + page = __get_free_page(GFP_KERNEL); + if (!page) { + kfree(info); + goto err_nocleanup; + } + + inode->i_pipe = info; + + init_waitqueue_head(PIPE_WAIT(*inode)); + PIPE_BASE(*inode) = (char *) page; + PIPE_START(*inode) = PIPE_LEN(*inode) = 0; + PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 0; + } + + switch (filp->f_mode) { case 1: /* * O_RDONLY @@ -51,26 +51,26 @@ got_it: * opened, even when there is no process writing the FIFO. */ filp->f_op = &connecting_fifo_fops; - if (!PIPE_READERS(*inode)++) - wake_up_interruptible(&PIPE_WAIT(*inode)); - if (!(filp->f_flags & O_NONBLOCK) && !PIPE_WRITERS(*inode)) { - PIPE_RD_OPENERS(*inode)++; + if (PIPE_READERS(*inode)++ == 0) + wake_up_interruptible(PIPE_WAIT(*inode)); + + if (!(filp->f_flags & O_NONBLOCK)) { while (!PIPE_WRITERS(*inode)) { - if (signal_pending(current)) { - retval = -ERESTARTSYS; - break; - } - interruptible_sleep_on(&PIPE_WAIT(*inode)); + if (signal_pending(current)) + goto err_rd; + up(PIPE_SEM(*inode)); + interruptible_sleep_on(PIPE_WAIT(*inode)); + + /* Note that using down_interruptible here + and similar places below is pointless, + since we have to acquire the lock to clean + up properly. */ + down(PIPE_SEM(*inode)); } - if (!--PIPE_RD_OPENERS(*inode)) - wake_up_interruptible(&PIPE_WAIT(*inode)); } - while (PIPE_WR_OPENERS(*inode)) - interruptible_sleep_on(&PIPE_WAIT(*inode)); + if (PIPE_WRITERS(*inode)) filp->f_op = &read_fifo_fops; - if (retval && !--PIPE_READERS(*inode)) - wake_up_interruptible(&PIPE_WAIT(*inode)); break; case 2: @@ -79,29 +79,21 @@ got_it: * POSIX.1 says that O_NONBLOCK means return -1 with * errno=ENXIO when there is no process reading the FIFO. */ - if ((filp->f_flags & O_NONBLOCK) && !PIPE_READERS(*inode)) { - retval = -ENXIO; - break; - } + ret = -ENXIO; + if ((filp->f_flags & O_NONBLOCK) && !PIPE_READERS(*inode)) + goto err; + filp->f_op = &write_fifo_fops; if (!PIPE_WRITERS(*inode)++) - wake_up_interruptible(&PIPE_WAIT(*inode)); - if (!PIPE_READERS(*inode)) { - PIPE_WR_OPENERS(*inode)++; - while (!PIPE_READERS(*inode)) { - if (signal_pending(current)) { - retval = -ERESTARTSYS; - break; - } - interruptible_sleep_on(&PIPE_WAIT(*inode)); - } - if (!--PIPE_WR_OPENERS(*inode)) - wake_up_interruptible(&PIPE_WAIT(*inode)); + wake_up_interruptible(PIPE_WAIT(*inode)); + + while (!PIPE_READERS(*inode)) { + if (signal_pending(current)) + goto err_wr; + up(PIPE_SEM(*inode)); + interruptible_sleep_on(PIPE_WAIT(*inode)); + down(PIPE_SEM(*inode)); } - while (PIPE_RD_OPENERS(*inode)) - interruptible_sleep_on(&PIPE_WAIT(*inode)); - if (retval && !--PIPE_WRITERS(*inode)) - wake_up_interruptible(&PIPE_WAIT(*inode)); break; case 3: @@ -112,39 +104,47 @@ got_it: * the process can at least talk to itself. */ filp->f_op = &rdwr_fifo_fops; - if (!PIPE_READERS(*inode)++) - wake_up_interruptible(&PIPE_WAIT(*inode)); - while (PIPE_WR_OPENERS(*inode)) - interruptible_sleep_on(&PIPE_WAIT(*inode)); - if (!PIPE_WRITERS(*inode)++) - wake_up_interruptible(&PIPE_WAIT(*inode)); - while (PIPE_RD_OPENERS(*inode)) - interruptible_sleep_on(&PIPE_WAIT(*inode)); + + PIPE_READERS(*inode)++; + PIPE_WRITERS(*inode)++; + if (PIPE_READERS(*inode) == 1 || PIPE_WRITERS(*inode) == 1) + wake_up_interruptible(PIPE_WAIT(*inode)); break; default: - retval = -EINVAL; + ret = -EINVAL; + goto err; } - if (retval) - goto cleanup; -out: - if (tmp) - kfree(tmp); - if (page) - free_page(page); - return retval; - -cleanup: + + /* Ok! */ + up(PIPE_SEM(*inode)); + return 0; + +err_rd: + if (!--PIPE_READERS(*inode)) + wake_up_interruptible(PIPE_WAIT(*inode)); + ret = -ERESTARTSYS; + goto err; + +err_wr: + if (!--PIPE_WRITERS(*inode)) + wake_up_interruptible(PIPE_WAIT(*inode)); + ret = -ERESTARTSYS; + goto err; + +err: if (!PIPE_READERS(*inode) && !PIPE_WRITERS(*inode)) { - info = inode->i_pipe; + struct pipe_inode_info *info = inode->i_pipe; inode->i_pipe = NULL; free_page((unsigned long)info->base); kfree(info); } - goto out; -oom: - retval = -ENOMEM; - goto out; + +err_nocleanup: + up(PIPE_SEM(*inode)); + +err_nolock_nocleanup: + return ret; } /* |