1 /****************************************************************************
2 * fs/mount/fs_umount.c
3 *
4 * Copyright (C) 2007-2009, 2015 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 /****************************************************************************
37 * Included Files
38 ****************************************************************************/
39
40 #include "vfs_config.h"
41
42 #include "sys/mount.h"
43 #include "errno.h"
44 #include "vnode.h"
45 #include "stdlib.h"
46 #include "unistd.h"
47 #include "string.h"
48 #include "disk.h"
49 #include "fs/mount.h"
50 #ifdef LOSCFG_MNT_CONTAINER
51 #include "los_mnt_container_pri.h"
52 #endif
53
54 /****************************************************************************
55 * Public Functions
56 ****************************************************************************/
57
58 /****************************************************************************
59 * Name: umount
60 *
61 * Description:
62 * umount() detaches the filesystem mounted at the path specified by
63 * 'target.'
64 *
65 * Return:
66 * Zero is returned on success; -1 is returned on an error and errno is
67 * set appropriately:
68 *
69 * EACCES A component of a path was not searchable or mounting a read-only
70 * filesystem was attempted without giving the MS_RDONLY flag.
71 * EBUSY The target could not be unmounted because it is busy.
72 * EFAULT The pointer argument points outside the user address space.
73 *
74 ****************************************************************************/
75
fs_in_use(struct Mount * mnt,const char * target)76 BOOL fs_in_use(struct Mount *mnt, const char *target)
77 {
78 char cwd[PATH_MAX];
79 char *pret = getcwd(cwd, PATH_MAX);
80 if (pret != NULL)
81 {
82 if (!strncmp(target, cwd, strlen(target)))
83 {
84 return TRUE;
85 }
86 }
87 return VnodeInUseIter(mnt);
88 }
89
umount(const char * target)90 int umount(const char *target)
91 {
92 struct Vnode *mountpt_vnode = NULL;
93 struct Vnode *blkdrvr_vnode = NULL;
94 struct Vnode *covered_vnode = NULL;
95 struct Mount *mnt = NULL;
96 int ret;
97
98 /* Verify required pointer arguments */
99
100 if (target == NULL)
101 {
102 ret = -EFAULT;
103 goto errout;
104 }
105
106 /* Find the mountpt */
107 VnodeHold();
108 ret = VnodeLookup(target, &mountpt_vnode, 0);
109 if (ret != OK || !mountpt_vnode)
110 {
111 goto errout;
112 }
113 /* Verify that the vnode is a mountpoint */
114 if (!mountpt_vnode || !(mountpt_vnode->flag & VNODE_FLAG_MOUNT_NEW))
115 {
116 ret = -EINVAL;
117 goto errout;
118 }
119
120 #ifdef LOSCFG_MNT_CONTAINER
121 /* Verify that the vnode is a mountpoint */
122 struct Mount *tMnt = NULL;
123 bool found = false;
124 LOS_DL_LIST_FOR_EACH_ENTRY(tMnt, GetMountList(), struct Mount, mountList)
125 {
126 if (tMnt->vnodeCovered == mountpt_vnode)
127 {
128 found = true;
129 break;
130 }
131 }
132
133 if (!found)
134 {
135 ret = -EINVAL;
136 goto errout;
137 }
138
139 if (tMnt->vnodeCovered->mntCount > 0)
140 {
141 tMnt->vnodeCovered->mntCount--;
142 LOS_ListDelete(&tMnt->mountList);
143 free(tMnt);
144 VnodeDrop();
145 return OK;
146 }
147 #endif
148
149 /* Get mount point covered vnode and mount structure */
150 mnt = mountpt_vnode->originMount;
151 if (!mnt)
152 {
153 ret = -EINVAL;
154 goto errout;
155 }
156 covered_vnode = mnt->vnodeBeCovered;
157 if (!covered_vnode || !(covered_vnode->flag & VNODE_FLAG_MOUNT_ORIGIN))
158 {
159 ret = -EINVAL;
160 goto errout;
161 }
162
163 /* Unbind the block driver from the file system (destroying any fs
164 * private data.
165 */
166
167 if (mnt->ops == NULL || mnt->ops->Unmount == NULL)
168 {
169 /* The filesystem does not support the unbind operation ??? */
170
171 ret = -EINVAL;
172 goto errout;
173 }
174
175 /* Release the vnode under the mount point */
176 if (fs_in_use(mnt, target))
177 {
178 ret = -EBUSY;
179 goto errout;
180 }
181
182 ret = VnodeFreeAll(mnt);
183 if (ret != OK)
184 {
185 goto errout;
186 }
187 /* Umount the filesystem */
188 ret = mnt->ops->Unmount(mnt, &blkdrvr_vnode);
189 if (ret != OK)
190 {
191 goto errout;
192 }
193 #ifdef LOSCFG_MNT_CONTAINER
194 struct Mount *tCacheMnt = NULL;
195 LOS_DL_LIST_FOR_EACH_ENTRY(tCacheMnt, GetMountCache(), struct Mount, mountList)
196 {
197 if (tCacheMnt->vnodeCovered == mountpt_vnode)
198 {
199 LOS_ListDelete(&tCacheMnt->mountList);
200 free(tCacheMnt);
201 break;
202 }
203 }
204 #endif
205 VnodeFree(mountpt_vnode);
206 LOS_ListDelete(&mnt->mountList);
207
208 free(mnt);
209
210 /* Did the unbind method return a contained block driver */
211 if (blkdrvr_vnode)
212 {
213 ; /* block driver operations after umount */
214 }
215
216 covered_vnode->newMount = NULL;
217 #ifdef LOSCFG_MNT_CONTAINER
218 tCacheMnt = NULL;
219 found = false;
220 LOS_DL_LIST_FOR_EACH_ENTRY(tCacheMnt, GetMountCache(), struct Mount, mountList)
221 {
222 if (tCacheMnt->vnodeBeCovered == covered_vnode)
223 {
224 found = true;
225 break;
226 }
227 }
228 if (!found)
229 {
230 covered_vnode->flag &= ~(VNODE_FLAG_MOUNT_ORIGIN);
231 }
232 #else
233 covered_vnode->flag &= ~(VNODE_FLAG_MOUNT_ORIGIN);
234 #endif
235 VnodeDrop();
236
237 return OK;
238
239 /* A lot of goto's! But they make the error handling much simpler */
240 errout:
241 VnodeDrop();
242 set_errno(-ret);
243 return VFS_ERROR;
244 }
245
umount2(const char * __target,int __flags)246 int umount2(const char* __target, int __flags)
247 {
248 /* TODO: __flags need to be support */
249 if (__flags) {
250 set_errno(ENOSYS);
251 return VFS_ERROR;
252 }
253 return umount(__target);
254 }
255