fifo.c 3.1 KB

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