• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /****************************************************************************
2  * fs/mount/fs_umount.c
3  *
4  * Copyright (c) 2023 Huawei Device Co., Ltd. All rights reserved.
5  * Based on NuttX originally written by Gregory Nutt
6  *
7  *   Copyright (C) 2007-2009, 2015 Gregory Nutt. All rights reserved.
8  *   Author: Gregory Nutt <gnutt@nuttx.org>
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  *
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in
18  *    the documentation and/or other materials provided with the
19  *    distribution.
20  * 3. Neither the name NuttX nor the names of its contributors may be
21  *    used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
31  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
32  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35  * POSSIBILITY OF SUCH DAMAGE.
36  *
37  ****************************************************************************/
38 
39 /****************************************************************************
40  * Included Files
41  ****************************************************************************/
42 
43 #include "vfs_config.h"
44 
45 #include "sys/mount.h"
46 #include "errno.h"
47 #include "vnode.h"
48 #include "stdlib.h"
49 #include "unistd.h"
50 #include "string.h"
51 #include "disk.h"
52 #include "fs/mount.h"
53 #ifdef LOSCFG_MNT_CONTAINER
54 #include "los_mnt_container_pri.h"
55 #endif
56 
57 /****************************************************************************
58  * Public Functions
59  ****************************************************************************/
60 
61 /****************************************************************************
62  * Name: umount
63  *
64  * Description:
65  *   umount() detaches the filesystem mounted at the path specified by
66  *  'target.'
67  *
68  * Return:
69  *   Zero is returned on success; -1 is returned on an error and errno is
70  *   set appropriately:
71  *
72  *   EACCES A component of a path was not searchable or mounting a read-only
73  *      filesystem was attempted without giving the MS_RDONLY flag.
74  *   EBUSY The target could not be unmounted because it is busy.
75  *   EFAULT The pointer argument points outside the user address space.
76  *
77  ****************************************************************************/
78 
fs_in_use(struct Mount * mnt,const char * target)79 BOOL fs_in_use(struct Mount *mnt, const char *target)
80 {
81   char cwd[PATH_MAX];
82   char *pret = getcwd(cwd, PATH_MAX);
83   if (pret != NULL)
84     {
85       if (!strncmp(target, cwd, strlen(target)))
86         {
87           return TRUE;
88         }
89     }
90     return VnodeInUseIter(mnt);
91 }
92 
umount(const char * target)93 int umount(const char *target)
94 {
95   struct Vnode *mountpt_vnode = NULL;
96   struct Vnode *blkdrvr_vnode = NULL;
97   struct Vnode *covered_vnode = NULL;
98   struct Mount *mnt = NULL;
99   int ret;
100 
101   /* Verify required pointer arguments */
102 
103   if (target == NULL)
104     {
105       ret = -EFAULT;
106       goto errout;
107     }
108 
109   /* Find the mountpt */
110   VnodeHold();
111   ret = VnodeLookup(target, &mountpt_vnode, 0);
112   if (ret != OK || !mountpt_vnode)
113     {
114       goto errout;
115     }
116   /* Verify that the vnode is a mountpoint */
117   if (!mountpt_vnode || !(mountpt_vnode->flag & VNODE_FLAG_MOUNT_NEW))
118     {
119       ret = -EINVAL;
120       goto errout;
121     }
122 
123 #ifdef LOSCFG_MNT_CONTAINER
124   /* Verify that the vnode is a mountpoint */
125   struct Mount *tMnt = NULL;
126   bool found = false;
127   LOS_DL_LIST_FOR_EACH_ENTRY(tMnt, GetMountList(), struct Mount, mountList)
128     {
129       if (tMnt->vnodeCovered == mountpt_vnode)
130         {
131           found = true;
132           break;
133         }
134     }
135 
136   if (!found)
137     {
138       ret = -EINVAL;
139       goto errout;
140     }
141 
142   if (tMnt->vnodeCovered->mntCount > 0)
143     {
144       tMnt->vnodeCovered->mntCount--;
145       LOS_ListDelete(&tMnt->mountList);
146       free(tMnt);
147       VnodeDrop();
148       return OK;
149     }
150 #endif
151 
152   /* Get mount point covered vnode and mount structure */
153   mnt = mountpt_vnode->originMount;
154   if (!mnt)
155     {
156       ret = -EINVAL;
157       goto errout;
158     }
159   covered_vnode = mnt->vnodeBeCovered;
160   if (!covered_vnode || !(covered_vnode->flag & VNODE_FLAG_MOUNT_ORIGIN))
161     {
162       ret = -EINVAL;
163       goto errout;
164     }
165 
166   /* Unbind the block driver from the file system (destroying any fs
167    * private data.
168    */
169 
170   if (mnt->ops == NULL || mnt->ops->Unmount == NULL)
171     {
172       /* The filesystem does not support the unbind operation ??? */
173 
174       ret = -EINVAL;
175       goto errout;
176     }
177 
178   /* Release the vnode under the mount point */
179   if (fs_in_use(mnt, target))
180     {
181       ret = -EBUSY;
182       goto errout;
183     }
184 
185   ret = VnodeFreeAll(mnt);
186   if (ret != OK)
187     {
188       goto errout;
189     }
190   /* Umount the filesystem */
191   ret = mnt->ops->Unmount(mnt, &blkdrvr_vnode);
192   if (ret != OK)
193     {
194       goto errout;
195     }
196 #ifdef LOSCFG_MNT_CONTAINER
197   struct Mount *tCacheMnt = NULL;
198   LOS_DL_LIST_FOR_EACH_ENTRY(tCacheMnt, GetMountCache(), struct Mount, mountList)
199     {
200       if (tCacheMnt->vnodeCovered == mountpt_vnode)
201         {
202           LOS_ListDelete(&tCacheMnt->mountList);
203           free(tCacheMnt);
204           break;
205         }
206     }
207 #endif
208   VnodeFree(mountpt_vnode);
209   LOS_ListDelete(&mnt->mountList);
210 
211   free(mnt);
212 
213   /* Did the unbind method return a contained block driver */
214   if (blkdrvr_vnode)
215     {
216       ; /* block driver operations after umount */
217     }
218 
219   covered_vnode->newMount = NULL;
220 #ifdef LOSCFG_MNT_CONTAINER
221   tCacheMnt = NULL;
222   found = false;
223   LOS_DL_LIST_FOR_EACH_ENTRY(tCacheMnt, GetMountCache(), struct Mount, mountList)
224     {
225       if (tCacheMnt->vnodeBeCovered == covered_vnode)
226         {
227           found = true;
228           break;
229         }
230     }
231   if (!found)
232     {
233       covered_vnode->flag &= ~(VNODE_FLAG_MOUNT_ORIGIN);
234     }
235 #else
236   covered_vnode->flag &= ~(VNODE_FLAG_MOUNT_ORIGIN);
237 #endif
238   VnodeDrop();
239 
240   return OK;
241 
242   /* A lot of goto's!  But they make the error handling much simpler */
243 errout:
244   VnodeDrop();
245   set_errno(-ret);
246   return VFS_ERROR;
247 }
248 
umount2(const char * __target,int __flags)249 int umount2(const char* __target, int __flags)
250 {
251     /* TODO: __flags need to be support */
252     if (__flags) {
253         set_errno(ENOSYS);
254         return VFS_ERROR;
255     }
256     return umount(__target);
257 }
258