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
51 /****************************************************************************
52 * Public Functions
53 ****************************************************************************/
54
55 /****************************************************************************
56 * Name: umount
57 *
58 * Description:
59 * umount() detaches the filesystem mounted at the path specified by
60 * 'target.'
61 *
62 * Return:
63 * Zero is returned on success; -1 is returned on an error and errno is
64 * set appropriately:
65 *
66 * EACCES A component of a path was not searchable or mounting a read-only
67 * filesystem was attempted without giving the MS_RDONLY flag.
68 * EBUSY The target could not be unmounted because it is busy.
69 * EFAULT The pointer argument points outside the user address space.
70 *
71 ****************************************************************************/
72
fs_in_use(struct Mount * mnt,const char * target)73 BOOL fs_in_use(struct Mount *mnt, const char *target)
74 {
75 char cwd[PATH_MAX];
76 char *pret = getcwd(cwd, PATH_MAX);
77 if (pret != NULL)
78 {
79 if (!strncmp(target, cwd, strlen(target)))
80 {
81 return TRUE;
82 }
83 }
84 return VnodeInUseIter(mnt);
85 }
86
umount(const char * target)87 int umount(const char *target)
88 {
89 struct Vnode *mountpt_vnode = NULL;
90 struct Vnode *blkdrvr_vnode = NULL;
91 struct Vnode *covered_vnode = NULL;
92 struct Mount *mnt = NULL;
93 int ret;
94
95 /* Verify required pointer arguments */
96
97 if (target == NULL)
98 {
99 ret = -EFAULT;
100 goto errout;
101 }
102
103 /* Find the mountpt */
104 VnodeHold();
105 ret = VnodeLookup(target, &mountpt_vnode, 0);
106 if (ret != OK || !mountpt_vnode)
107 {
108 goto errout;
109 }
110 /* Verify that the vnode is a mountpoint */
111 if (!mountpt_vnode || !(mountpt_vnode->flag & VNODE_FLAG_MOUNT_NEW))
112 {
113 ret = -EINVAL;
114 goto errout;
115 }
116
117 /* Get mount point covered vnode and mount structure */
118 mnt = mountpt_vnode->originMount;
119 if (!mnt)
120 {
121 ret = -EINVAL;
122 goto errout;
123 }
124 covered_vnode = mnt->vnodeBeCovered;
125 if (!covered_vnode || !(covered_vnode->flag & VNODE_FLAG_MOUNT_ORIGIN))
126 {
127 ret = -EINVAL;
128 goto errout;
129 }
130
131 /* Unbind the block driver from the file system (destroying any fs
132 * private data.
133 */
134
135 if (mnt->ops == NULL || mnt->ops->Unmount == NULL)
136 {
137 /* The filesystem does not support the unbind operation ??? */
138
139 ret = -EINVAL;
140 goto errout;
141 }
142
143 /* Release the vnode under the mount point */
144 if (fs_in_use(mnt, target))
145 {
146 ret = -EBUSY;
147 goto errout;
148 }
149
150 ret = VnodeFreeAll(mnt);
151 if (ret != OK)
152 {
153 goto errout;
154 }
155 /* Umount the filesystem */
156 ret = mnt->ops->Unmount(mnt, &blkdrvr_vnode);
157 if (ret != OK)
158 {
159 goto errout;
160 }
161
162 VnodeFree(mountpt_vnode);
163 LOS_ListDelete(&mnt->mountList);
164 free(mnt);
165
166 /* Did the unbind method return a contained block driver */
167 if (blkdrvr_vnode)
168 {
169 ; /* block driver operations after umount */
170 }
171
172 covered_vnode->newMount = NULL;
173 covered_vnode->flag &= ~(VNODE_FLAG_MOUNT_ORIGIN);
174 VnodeDrop();
175
176 return OK;
177
178 /* A lot of goto's! But they make the error handling much simpler */
179 errout:
180 VnodeDrop();
181 set_errno(-ret);
182 return VFS_ERROR;
183 }
184
umount2(const char * __target,int __flags)185 int umount2(const char* __target, int __flags)
186 {
187 /* TODO: __flags need to be support */
188 if (__flags) {
189 set_errno(ENOSYS);
190 return VFS_ERROR;
191 }
192 return umount(__target);
193 }
194