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