/* * linux/fs/fifo.c * * written by Paul H. Hargrove */ #include <errno.h> #include <linux/fcntl.h> #include <linux/sched.h> #include <linux/kernel.h> extern struct file_operations read_pipe_fops; extern struct file_operations write_pipe_fops; extern struct file_operations rdwr_pipe_fops; static int fifo_open(struct inode * inode,struct file * filp) { int retval = 0; unsigned long page; switch( filp->f_mode ) { case 1: /* * O_RDONLY * POSIX.1 says that O_NONBLOCK means return with the FIFO * opened, even when there is no process writing the FIFO. */ filp->f_op = &read_pipe_fops; PIPE_READERS(*inode)++; if (!(filp->f_flags & O_NONBLOCK)) while (!PIPE_WRITERS(*inode)) { if (PIPE_HEAD(*inode) != PIPE_TAIL(*inode)) break; if (current->signal & ~current->blocked) { retval = -ERESTARTSYS; break; } interruptible_sleep_on(&PIPE_READ_WAIT(*inode)); } if (retval) PIPE_READERS(*inode)--; break; case 2: /* * O_WRONLY * 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; } filp->f_op = &write_pipe_fops; PIPE_WRITERS(*inode)++; while (!PIPE_READERS(*inode)) { if (current->signal & ~current->blocked) { retval = -ERESTARTSYS; break; } interruptible_sleep_on(&PIPE_WRITE_WAIT(*inode)); } if (retval) PIPE_WRITERS(*inode)--; break; case 3: /* * O_RDWR * POSIX.1 leaves this case "undefined" when O_NONBLOCK is set. * This implementation will NEVER block on a O_RDWR open, since * the process can at least talk to itself. */ filp->f_op = &rdwr_pipe_fops; PIPE_WRITERS(*inode) += 1; PIPE_READERS(*inode) += 1; break; default: retval = -EINVAL; } if (PIPE_WRITERS(*inode)) wake_up(&PIPE_READ_WAIT(*inode)); if (PIPE_READERS(*inode)) wake_up(&PIPE_WRITE_WAIT(*inode)); if (retval || inode->i_size) return retval; page = get_free_page(); if (inode->i_size) { free_page(page); return 0; } if (!page) return -ENOMEM; inode->i_size = page; return 0; } /* * Dummy default file-operations: the only thing this does * is contain the open that then fills in the correct operations * depending on the access mode of the file... */ struct file_operations def_fifo_fops = { NULL, NULL, NULL, NULL, NULL, NULL, fifo_open, /* will set read or write pipe_fops */ NULL };