fs_umount2.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. /****************************************************************************
  2. * fs/mount/fs_umount2.c
  3. *
  4. * Licensed to the Apache Software Foundation (ASF) under one or more
  5. * contributor license agreements. See the NOTICE file distributed with
  6. * this work for additional information regarding copyright ownership. The
  7. * ASF licenses this file to you under the Apache License, Version 2.0 (the
  8. * "License"); you may not use this file except in compliance with the
  9. * License. You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  15. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  16. * License for the specific language governing permissions and limitations
  17. * under the License.
  18. *
  19. ****************************************************************************/
  20. /****************************************************************************
  21. * Included Files
  22. ****************************************************************************/
  23. #include <nuttx/config.h>
  24. #include <sys/mount.h>
  25. #include <stdbool.h>
  26. #include <errno.h>
  27. #include <assert.h>
  28. #include <nuttx/fs/fs.h>
  29. #include "inode/inode.h"
  30. /****************************************************************************
  31. * Public Functions
  32. ****************************************************************************/
  33. /****************************************************************************
  34. * Name: nx_umount2
  35. *
  36. * Description:
  37. * nx_umount2() is similar to the standard 'umount2' interface except that
  38. * is not a cancellation point and it does not modify the errno variable.
  39. *
  40. * nx_umount2() is an internal NuttX interface and should not be called
  41. * from applications.
  42. *
  43. * Returned Value:
  44. * Zero is returned on success; a negated value is returned on any failure.
  45. *
  46. ****************************************************************************/
  47. int nx_umount2(FAR const char *target, unsigned int flags)
  48. {
  49. FAR struct inode *mountpt_inode;
  50. FAR struct inode *blkdrvr_inode = NULL;
  51. struct inode_search_s desc;
  52. int ret;
  53. /* Verify required pointer arguments */
  54. if (!target)
  55. {
  56. ret = -EFAULT;
  57. goto errout;
  58. }
  59. /* Find the mountpt */
  60. SETUP_SEARCH(&desc, target, false);
  61. ret = inode_find(&desc);
  62. if (ret < 0)
  63. {
  64. goto errout_with_search;
  65. }
  66. /* Get the search results */
  67. mountpt_inode = desc.node;
  68. DEBUGASSERT(mountpt_inode != NULL);
  69. /* Verify that the inode is a mountpoint */
  70. if (!INODE_IS_MOUNTPT(mountpt_inode))
  71. {
  72. ret = -EINVAL;
  73. goto errout_with_mountpt;
  74. }
  75. /* Unbind the block driver from the file system (destroying any fs
  76. * private data.
  77. */
  78. if (!mountpt_inode->u.i_mops->unbind)
  79. {
  80. /* The filesystem does not support the unbind operation ??? */
  81. ret = -EINVAL;
  82. goto errout_with_mountpt;
  83. }
  84. /* The unbind method returns the number of references to the
  85. * filesystem (i.e., open files), zero if the unbind was
  86. * performed, or a negated error code on a failure.
  87. */
  88. /* Hold the semaphore through the unbind logic */
  89. ret = inode_semtake();
  90. if (ret < 0)
  91. {
  92. goto errout_with_mountpt;
  93. }
  94. ret = mountpt_inode->u.i_mops->unbind(mountpt_inode->i_private,
  95. &blkdrvr_inode, flags);
  96. if (ret < 0)
  97. {
  98. /* The inode is unhappy with the blkdrvr for some reason */
  99. goto errout_with_semaphore;
  100. }
  101. else if (ret > 0)
  102. {
  103. ret = -EBUSY;
  104. goto errout_with_semaphore;
  105. }
  106. /* Successfully unbound. Convert the mountpoint inode to regular
  107. * pseudo-file inode.
  108. */
  109. mountpt_inode->i_flags &= ~FSNODEFLAG_TYPE_MASK;
  110. mountpt_inode->i_private = NULL;
  111. mountpt_inode->u.i_mops = NULL;
  112. #ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
  113. /* If the node has children, then do not delete it. */
  114. if (mountpt_inode->i_child != NULL)
  115. {
  116. /* Just decrement the reference count (without deleting it) */
  117. DEBUGASSERT(mountpt_inode->i_crefs > 0);
  118. mountpt_inode->i_crefs--;
  119. }
  120. else
  121. #endif
  122. {
  123. /* Remove the mountpoint inode from the inode tree. The inode will
  124. * not be deleted yet because there is still at least reference on
  125. * it (from the mount)
  126. */
  127. ret = inode_remove(target);
  128. inode_semgive();
  129. /* The return value of -EBUSY is normal (in fact, it should
  130. * not be OK)
  131. */
  132. if (ret != OK && ret != -EBUSY)
  133. {
  134. goto errout_with_mountpt;
  135. }
  136. /* Release the mountpoint inode and any block driver inode
  137. * returned by the file system unbind above. This should cause
  138. * the inode to be deleted (unless there are other references)
  139. */
  140. inode_release(mountpt_inode);
  141. }
  142. /* Did the unbind method return a contained block driver */
  143. if (blkdrvr_inode)
  144. {
  145. inode_release(blkdrvr_inode);
  146. }
  147. RELEASE_SEARCH(&desc);
  148. return OK;
  149. /* A lot of goto's! But they make the error handling much simpler */
  150. errout_with_semaphore:
  151. inode_semgive();
  152. errout_with_mountpt:
  153. inode_release(mountpt_inode);
  154. if (blkdrvr_inode)
  155. {
  156. inode_release(blkdrvr_inode);
  157. }
  158. errout_with_search:
  159. RELEASE_SEARCH(&desc);
  160. errout:
  161. return ret;
  162. }
  163. /****************************************************************************
  164. * Name: umount2
  165. *
  166. * Description:
  167. * umount() detaches the filesystem mounted at the path specified by
  168. * 'target.'
  169. *
  170. * Returned Value:
  171. * Zero is returned on success; -1 is returned on an error and errno is
  172. * set appropriately:
  173. *
  174. * EACCES A component of a path was not searchable or mounting a read-only
  175. * filesystem was attempted without giving the MS_RDONLY flag.
  176. * EBUSY The target could not be unmounted because it is busy.
  177. * EFAULT The pointer argument points outside the user address space.
  178. *
  179. ****************************************************************************/
  180. int umount2(FAR const char *target, unsigned int flags)
  181. {
  182. int ret;
  183. ret = nx_umount2(target, flags);
  184. if (ret < 0)
  185. {
  186. set_errno(-ret);
  187. ret = ERROR;
  188. }
  189. return ret;
  190. }