fifo.c 3.2 KB

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