Root/fs/fifo.c

1/*
2 * linux/fs/fifo.c
3 *
4 * written by Paul H. Hargrove
5 *
6 * Fixes:
7 * 10-06-1999, AV: fixed OOM handling in fifo_open(), moved
8 * initialization there, switched to external
9 * allocation of pipe_inode_info.
10 */
11
12#include <linux/mm.h>
13#include <linux/slab.h>
14#include <linux/fs.h>
15#include <linux/sched.h>
16#include <linux/pipe_fs_i.h>
17
18static void wait_for_partner(struct inode* inode, unsigned int *cnt)
19{
20    int cur = *cnt;
21
22    while (cur == *cnt) {
23        pipe_wait(inode->i_pipe);
24        if (signal_pending(current))
25            break;
26    }
27}
28
29static void wake_up_partner(struct inode* inode)
30{
31    wake_up_interruptible(&inode->i_pipe->wait);
32}
33
34static int fifo_open(struct inode *inode, struct file *filp)
35{
36    struct pipe_inode_info *pipe;
37    int ret;
38
39    mutex_lock(&inode->i_mutex);
40    pipe = inode->i_pipe;
41    if (!pipe) {
42        ret = -ENOMEM;
43        pipe = alloc_pipe_info(inode);
44        if (!pipe)
45            goto err_nocleanup;
46        inode->i_pipe = pipe;
47    }
48    filp->f_version = 0;
49
50    /* We can only do regular read/write on fifos */
51    filp->f_mode &= (FMODE_READ | FMODE_WRITE);
52
53    switch (filp->f_mode) {
54    case FMODE_READ:
55    /*
56     * O_RDONLY
57     * POSIX.1 says that O_NONBLOCK means return with the FIFO
58     * opened, even when there is no process writing the FIFO.
59     */
60        filp->f_op = &read_pipefifo_fops;
61        pipe->r_counter++;
62        if (pipe->readers++ == 0)
63            wake_up_partner(inode);
64
65        if (!pipe->writers) {
66            if ((filp->f_flags & O_NONBLOCK)) {
67                /* suppress POLLHUP until we have
68                 * seen a writer */
69                filp->f_version = pipe->w_counter;
70            } else
71            {
72                wait_for_partner(inode, &pipe->w_counter);
73                if(signal_pending(current))
74                    goto err_rd;
75            }
76        }
77        break;
78    
79    case FMODE_WRITE:
80    /*
81     * O_WRONLY
82     * POSIX.1 says that O_NONBLOCK means return -1 with
83     * errno=ENXIO when there is no process reading the FIFO.
84     */
85        ret = -ENXIO;
86        if ((filp->f_flags & O_NONBLOCK) && !pipe->readers)
87            goto err;
88
89        filp->f_op = &write_pipefifo_fops;
90        pipe->w_counter++;
91        if (!pipe->writers++)
92            wake_up_partner(inode);
93
94        if (!pipe->readers) {
95            wait_for_partner(inode, &pipe->r_counter);
96            if (signal_pending(current))
97                goto err_wr;
98        }
99        break;
100    
101    case FMODE_READ | FMODE_WRITE:
102    /*
103     * O_RDWR
104     * POSIX.1 leaves this case "undefined" when O_NONBLOCK is set.
105     * This implementation will NEVER block on a O_RDWR open, since
106     * the process can at least talk to itself.
107     */
108        filp->f_op = &rdwr_pipefifo_fops;
109
110        pipe->readers++;
111        pipe->writers++;
112        pipe->r_counter++;
113        pipe->w_counter++;
114        if (pipe->readers == 1 || pipe->writers == 1)
115            wake_up_partner(inode);
116        break;
117
118    default:
119        ret = -EINVAL;
120        goto err;
121    }
122
123    /* Ok! */
124    mutex_unlock(&inode->i_mutex);
125    return 0;
126
127err_rd:
128    if (!--pipe->readers)
129        wake_up_interruptible(&pipe->wait);
130    ret = -ERESTARTSYS;
131    goto err;
132
133err_wr:
134    if (!--pipe->writers)
135        wake_up_interruptible(&pipe->wait);
136    ret = -ERESTARTSYS;
137    goto err;
138
139err:
140    if (!pipe->readers && !pipe->writers)
141        free_pipe_info(inode);
142
143err_nocleanup:
144    mutex_unlock(&inode->i_mutex);
145    return ret;
146}
147
148/*
149 * Dummy default file-operations: the only thing this does
150 * is contain the open that then fills in the correct operations
151 * depending on the access mode of the file...
152 */
153const struct file_operations def_fifo_fops = {
154    .open = fifo_open, /* will set read_ or write_pipefifo_fops */
155};
156

Archive Download this file



interactive