aio_fsync.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. /****************************************************************************
  2. * fs/aio/aio_fsync.c
  3. *
  4. * Copyright (C) 2014 Gregory Nutt. All rights reserved.
  5. * Author: Gregory Nutt <gnutt@nuttx.org>
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in
  15. * the documentation and/or other materials provided with the
  16. * distribution.
  17. * 3. Neither the name NuttX nor the names of its contributors may be
  18. * used to endorse or promote products derived from this software
  19. * without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  24. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  25. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  26. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  27. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  28. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  29. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  31. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  32. * POSSIBILITY OF SUCH DAMAGE.
  33. *
  34. ****************************************************************************/
  35. /****************************************************************************
  36. * Included Files
  37. ****************************************************************************/
  38. #include <nuttx/config.h>
  39. #include <unistd.h>
  40. #include <fcntl.h>
  41. #include <aio.h>
  42. #include <assert.h>
  43. #include <errno.h>
  44. #include <debug.h>
  45. #include <nuttx/fs/fs.h>
  46. #include "aio/aio.h"
  47. #ifdef CONFIG_FS_AIO
  48. /****************************************************************************
  49. * Private Functions
  50. ****************************************************************************/
  51. /****************************************************************************
  52. * Name: aio_fsync_worker
  53. *
  54. * Description:
  55. * This function executes on the worker thread and performs the
  56. * asynchronous I/O operation.
  57. *
  58. * Input Parameters:
  59. * arg - Worker argument. In this case, a pointer to an instance of
  60. * struct aiocb cast to void *.
  61. *
  62. * Returned Value:
  63. * None
  64. *
  65. ****************************************************************************/
  66. static void aio_fsync_worker(FAR void *arg)
  67. {
  68. FAR struct aio_container_s *aioc = (FAR struct aio_container_s *)arg;
  69. FAR struct aiocb *aiocbp;
  70. pid_t pid;
  71. #ifdef CONFIG_PRIORITY_INHERITANCE
  72. uint8_t prio;
  73. #endif
  74. int ret;
  75. /* Get the information from the container, decant the AIO control block,
  76. * and free the container before starting any I/O. That will minimize
  77. * the delays by any other threads waiting for a pre-allocated container.
  78. */
  79. DEBUGASSERT(aioc && aioc->aioc_aiocbp);
  80. pid = aioc->aioc_pid;
  81. #ifdef CONFIG_PRIORITY_INHERITANCE
  82. prio = aioc->aioc_prio;
  83. #endif
  84. aiocbp = aioc_decant(aioc);
  85. /* Perform the fsync using u.aioc_filep */
  86. ret = file_fsync(aioc->u.aioc_filep);
  87. if (ret < 0)
  88. {
  89. ferr("ERROR: file_fsync failed: %d\n", ret);
  90. aiocbp->aio_result = ret;
  91. }
  92. else
  93. {
  94. aiocbp->aio_result = OK;
  95. }
  96. /* Signal the client */
  97. aio_signal(pid, aiocbp);
  98. #ifdef CONFIG_PRIORITY_INHERITANCE
  99. /* Restore the low priority worker thread default priority */
  100. lpwork_restorepriority(prio);
  101. #endif
  102. }
  103. /****************************************************************************
  104. * Public Functions
  105. ****************************************************************************/
  106. /****************************************************************************
  107. * Name: aio_fsync
  108. *
  109. * Description:
  110. * The aio_fsync() function asynchronously forces all I/O operations
  111. * associated with the file indicated by the file descriptor aio_fildes
  112. * member of the aiocb structure referenced by the aiocbp argument and
  113. * queued at the time of the call to aio_fsync() to the synchronized
  114. * I/O completion state. The function call will return when the
  115. * synchronization request has been initiated or queued to the file or
  116. * device (even when the data cannot be synchronized immediately).
  117. *
  118. * If op is O_DSYNC, all currently queued I/O operations will be
  119. * completed as if by a call to fdatasync(); that is, as defined for
  120. * synchronized I/O data integrity completion. If op is O_SYNC, all
  121. * currently queued I/O operations will be completed as if by a call to
  122. * fsync(); that is, as defined for synchronized I/O file integrity
  123. * completion. If the aio_fsync() function fails, or if the operation
  124. * queued by aio_fsync() fails, then, as for fsync() and fdatasync(),
  125. * outstanding I/O operations are not guaranteed to have been completed.
  126. * [See "POSIX Compliance" below]
  127. *
  128. * If aio_fsync() succeeds, then it is only the I/O that was queued at
  129. * the time of the call to aio_fsync() that is guaranteed to be forced
  130. * to the relevant completion state. The completion of subsequent I/O
  131. * on the file descriptor is not guaranteed to be completed in a
  132. * synchronized fashion.
  133. *
  134. * The aiocbp argument refers to an asynchronous I/O control block. The
  135. * aiocbp value may be used as an argument to aio_error() and aio_return()
  136. * in order to determine the error status and return status, respectively,
  137. * of the asynchronous operation while it is proceeding. When the request
  138. * is queued, the error status for the operation is [EINPROGRESS]. When
  139. * all data has been successfully transferred, the error status will be
  140. * reset to reflect the success or failure of the operation. If the
  141. * operation does not complete successfully, the error status for the
  142. * operation will be set to indicate the error. The aio_sigevent member
  143. * determines the asynchronous notification to occur when all operations
  144. * have achieved synchronized I/O completion. All other members of the
  145. * structure referenced by aiocbp are ignored. If the control block
  146. * referenced by aiocbp becomes an illegal address prior to asynchronous
  147. * I/O completion, then the behavior is undefined.
  148. *
  149. * If the aio_fsync() function fails or aiocbp indicates an error
  150. * condition, data is not guaranteed to have been successfully transferred.
  151. *
  152. * Input Parameters:
  153. * op - Should be either O_SYNC or O_DSYNC. Ignored in this
  154. * implementation.
  155. * aiocbp - A pointer to an instance of struct aiocb
  156. *
  157. * Returned Value:
  158. * The aio_fsync() function will return the value 0 if the I/O operation is
  159. * successfully queued; otherwise, the function will return the value -1
  160. * and set errno to indicate the error.
  161. *
  162. * The aio_fsync() function will fail if:
  163. *
  164. * EAGAIN - The requested asynchronous operation was not queued due to
  165. * temporary resource limitations.
  166. * EBADF - The aio_fildes member of the aiocb structure referenced by
  167. * the aiocbp argument is not a valid file descriptor open for writing.
  168. * EINVAL - This implementation does not support synchronized I/O for
  169. * this file.
  170. * EINVAL - A value of op other than O_DSYNC or O_SYNC was specified.
  171. *
  172. * In the event that any of the queued I/O operations fail, aio_fsync()
  173. * will return the error condition defined for read() and write(). The
  174. * error is returned in the error status for the asynchronous fsync()
  175. * operation, which can be retrieved using aio_error().
  176. *
  177. * POSIX Compliance
  178. * - NuttX does not currently make any distinction between O_DYSNC and
  179. * O_SYNC. Hence, the 'op' argument is ignored altogether.
  180. * - Most errors required in the standard are not detected at this point.
  181. * There are no pre-queuing checks for the validity of the operation.
  182. *
  183. ****************************************************************************/
  184. int aio_fsync(int op, FAR struct aiocb *aiocbp)
  185. {
  186. FAR struct aio_container_s *aioc;
  187. int ret;
  188. DEBUGASSERT(op == O_SYNC); /* || op == O_DSYNC */
  189. DEBUGASSERT(aiocbp);
  190. /* The result -EINPROGRESS means that the transfer has not yet completed */
  191. sigwork_init(&aiocbp->aio_sigwork);
  192. aiocbp->aio_result = -EINPROGRESS;
  193. aiocbp->aio_priv = NULL;
  194. /* Create a container for the AIO control block. This may cause us to
  195. * block if there are insufficient resources to satisfy the request.
  196. */
  197. aioc = aio_contain(aiocbp);
  198. if (!aioc)
  199. {
  200. /* The errno has already been set (probably EBADF) */
  201. aiocbp->aio_result = -get_errno();
  202. return ERROR;
  203. }
  204. /* Defer the work to the worker thread */
  205. ret = aio_queue(aioc, aio_fsync_worker);
  206. if (ret < 0)
  207. {
  208. /* The result and the errno have already been set */
  209. aioc_decant(aioc);
  210. return ERROR;
  211. }
  212. return OK;
  213. }
  214. #endif /* CONFIG_FS_AIO */