linux-bk/fs/fifo.c
<<
>>
Prefs
   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/smp_lock.h>
  15#include <linux/fs.h>
  16
  17static void wait_for_partner(struct inode* inode, unsigned int* cnt)
  18{
  19        int cur = *cnt; 
  20        while(cur == *cnt) {
  21                pipe_wait(inode);
  22                if(signal_pending(current))
  23                        break;
  24        }
  25}
  26
  27static void wake_up_partner(struct inode* inode)
  28{
  29        wake_up_interruptible(PIPE_WAIT(*inode));
  30}
  31
  32static int fifo_open(struct inode *inode, struct file *filp)
  33{
  34        int ret;
  35
  36        ret = -ERESTARTSYS;
  37        lock_kernel();
  38        if (down_interruptible(PIPE_SEM(*inode)))
  39                goto err_nolock_nocleanup;
  40
  41        if (!inode->i_pipe) {
  42                ret = -ENOMEM;
  43                if(!pipe_new(inode))
  44                        goto err_nocleanup;
  45        }
  46        filp->f_version = 0;
  47
  48        switch (filp->f_mode) {
  49        case 1:
  50        /*
  51         *  O_RDONLY
  52         *  POSIX.1 says that O_NONBLOCK means return with the FIFO
  53         *  opened, even when there is no process writing the FIFO.
  54         */
  55                filp->f_op = &read_fifo_fops;
  56                PIPE_RCOUNTER(*inode)++;
  57                if (PIPE_READERS(*inode)++ == 0)
  58                        wake_up_partner(inode);
  59
  60                if (!PIPE_WRITERS(*inode)) {
  61                        if ((filp->f_flags & O_NONBLOCK)) {
  62                                /* suppress POLLHUP until we have
  63                                 * seen a writer */
  64                                filp->f_version = PIPE_WCOUNTER(*inode);
  65                        } else 
  66                        {
  67                                wait_for_partner(inode, &PIPE_WCOUNTER(*inode));
  68                                if(signal_pending(current))
  69                                        goto err_rd;
  70                        }
  71                }
  72                break;
  73        
  74        case 2:
  75        /*
  76         *  O_WRONLY
  77         *  POSIX.1 says that O_NONBLOCK means return -1 with
  78         *  errno=ENXIO when there is no process reading the FIFO.
  79         */
  80                ret = -ENXIO;
  81                if ((filp->f_flags & O_NONBLOCK) && !PIPE_READERS(*inode))
  82                        goto err;
  83
  84                filp->f_op = &write_fifo_fops;
  85                PIPE_WCOUNTER(*inode)++;
  86                if (!PIPE_WRITERS(*inode)++)
  87                        wake_up_partner(inode);
  88
  89                if (!PIPE_READERS(*inode)) {
  90                        wait_for_partner(inode, &PIPE_RCOUNTER(*inode));
  91                        if (signal_pending(current))
  92                                goto err_wr;
  93                }
  94                break;
  95        
  96        case 3:
  97        /*
  98         *  O_RDWR
  99         *  POSIX.1 leaves this case "undefined" when O_NONBLOCK is set.
 100         *  This implementation will NEVER block on a O_RDWR open, since
 101         *  the process can at least talk to itself.
 102         */
 103                filp->f_op = &rdwr_fifo_fops;
 104
 105                PIPE_READERS(*inode)++;
 106                PIPE_WRITERS(*inode)++;
 107                PIPE_RCOUNTER(*inode)++;
 108                PIPE_WCOUNTER(*inode)++;
 109                if (PIPE_READERS(*inode) == 1 || PIPE_WRITERS(*inode) == 1)
 110                        wake_up_partner(inode);
 111                break;
 112
 113        default:
 114                ret = -EINVAL;
 115                goto err;
 116        }
 117
 118        /* Ok! */
 119        up(PIPE_SEM(*inode));
 120        unlock_kernel();
 121        return 0;
 122
 123err_rd:
 124        if (!--PIPE_READERS(*inode))
 125                wake_up_interruptible(PIPE_WAIT(*inode));
 126        ret = -ERESTARTSYS;
 127        goto err;
 128
 129err_wr:
 130        if (!--PIPE_WRITERS(*inode))
 131                wake_up_interruptible(PIPE_WAIT(*inode));
 132        ret = -ERESTARTSYS;
 133        goto err;
 134
 135err:
 136        if (!PIPE_READERS(*inode) && !PIPE_WRITERS(*inode)) {
 137                struct pipe_inode_info *info = inode->i_pipe;
 138                inode->i_pipe = NULL;
 139                free_page((unsigned long)info->base);
 140                kfree(info);
 141        }
 142
 143err_nocleanup:
 144        up(PIPE_SEM(*inode));
 145
 146err_nolock_nocleanup:
 147        unlock_kernel();
 148        return ret;
 149}
 150
 151/*
 152 * Dummy default file-operations: the only thing this does
 153 * is contain the open that then fills in the correct operations
 154 * depending on the access mode of the file...
 155 */
 156struct file_operations def_fifo_fops = {
 157        .open           = fifo_open,    /* will set read or write pipe_fops */
 158};
 159
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.