• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2021 Huawei Device Co., Ltd. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without modification,
5  * are permitted provided that the following conditions are met:
6  *
7  * 1. Redistributions of source code must retain the above copyright notice, this list of
8  *    conditions and the following disclaimer.
9  *
10  * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11  *    of conditions and the following disclaimer in the documentation and/or other materials
12  *    provided with the distribution.
13  *
14  * 3. Neither the name of the copyright holder nor the names of its contributors may be used
15  *    to endorse or promote products derived from this software without specific prior written
16  *    permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
22  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include "fs/mount.h"
32 #include "fs/dirent_fs.h"
33 #include "fs/file.h"
34 #include "vnode.h"
35 #include "path_cache.h"
36 
37 /* vnode operations returns EIO */
ErrorVopCreate(struct Vnode * parent,const char * name,int mode,struct Vnode ** vnode)38 static int ErrorVopCreate (struct Vnode *parent, const char *name, int mode, struct Vnode **vnode)
39 {
40     return -EIO;
41 }
42 
ErrorVopLookup(struct Vnode * parent,const char * name,int len,struct Vnode ** vnode)43 static int ErrorVopLookup (struct Vnode *parent, const char *name, int len, struct Vnode **vnode)
44 {
45     return -EIO;
46 }
47 
ErrorVopOpen(struct Vnode * vnode,int fd,int mode,int flags)48 static int ErrorVopOpen (struct Vnode *vnode, int fd, int mode, int flags)
49 {
50     return -EIO;
51 }
52 
ErrorVopClose(struct Vnode * vnode)53 static int ErrorVopClose (struct Vnode *vnode)
54 {
55     /* already closed at force umount, do nothing here */
56     return OK;
57 }
58 
ErrorVopReclaim(struct Vnode * vnode)59 static int ErrorVopReclaim (struct Vnode *vnode)
60 {
61     return -EIO;
62 }
63 
ErrorVopUnlink(struct Vnode * parent,struct Vnode * vnode,const char * fileName)64 static int ErrorVopUnlink (struct Vnode *parent, struct Vnode *vnode, const char *fileName)
65 {
66     return -EIO;
67 }
68 
ErrorVopRmdir(struct Vnode * parent,struct Vnode * vnode,const char * dirName)69 static int ErrorVopRmdir (struct Vnode *parent, struct Vnode *vnode, const char *dirName)
70 {
71     return -EIO;
72 }
73 
ErrorVopMkdir(struct Vnode * parent,const char * dirName,mode_t mode,struct Vnode ** vnode)74 static int ErrorVopMkdir (struct Vnode *parent, const char *dirName, mode_t mode, struct Vnode **vnode)
75 {
76     return -EIO;
77 }
78 
ErrorVopReaddir(struct Vnode * vnode,struct fs_dirent_s * dir)79 static int ErrorVopReaddir (struct Vnode *vnode, struct fs_dirent_s *dir)
80 {
81     return -EIO;
82 }
83 
ErrorVopOpendir(struct Vnode * vnode,struct fs_dirent_s * dir)84 static int ErrorVopOpendir (struct Vnode *vnode, struct fs_dirent_s *dir)
85 {
86     return -EIO;
87 }
88 
ErrorVopRewinddir(struct Vnode * vnode,struct fs_dirent_s * dir)89 static int ErrorVopRewinddir (struct Vnode *vnode, struct fs_dirent_s *dir)
90 {
91     return -EIO;
92 }
93 
ErrorVopClosedir(struct Vnode * vnode,struct fs_dirent_s * dir)94 static int ErrorVopClosedir (struct Vnode *vnode, struct fs_dirent_s *dir)
95 {
96     /* already closed at force umount, do nothing here */
97     return OK;
98 }
99 
ErrorVopGetattr(struct Vnode * vnode,struct stat * st)100 static int ErrorVopGetattr (struct Vnode *vnode, struct stat *st)
101 {
102     return -EIO;
103 }
104 
ErrorVopSetattr(struct Vnode * vnode,struct stat * st)105 static int ErrorVopSetattr (struct Vnode *vnode, struct stat *st)
106 {
107     return -EIO;
108 }
109 
ErrorVopChattr(struct Vnode * vnode,struct IATTR * attr)110 static int ErrorVopChattr (struct Vnode *vnode, struct IATTR *attr)
111 {
112     return -EIO;
113 }
114 
ErrorVopRename(struct Vnode * src,struct Vnode * dstParent,const char * srcName,const char * dstName)115 static int ErrorVopRename (struct Vnode *src, struct Vnode *dstParent, const char *srcName, const char *dstName)
116 {
117     return -EIO;
118 }
119 
ErrorVopTruncate(struct Vnode * vnode,off_t len)120 static int ErrorVopTruncate (struct Vnode *vnode, off_t len)
121 {
122     return -EIO;
123 }
124 
ErrorVopTruncate64(struct Vnode * vnode,off64_t len)125 static int ErrorVopTruncate64 (struct Vnode *vnode, off64_t len)
126 {
127     return -EIO;
128 }
129 
ErrorVopFscheck(struct Vnode * vnode,struct fs_dirent_s * dir)130 static int ErrorVopFscheck (struct Vnode *vnode, struct fs_dirent_s *dir)
131 {
132     return -EIO;
133 }
134 
ErrorVopLink(struct Vnode * src,struct Vnode * dstParent,struct Vnode ** dst,const char * dstName)135 static int ErrorVopLink (struct Vnode *src, struct Vnode *dstParent, struct Vnode **dst, const char *dstName)
136 {
137     return -EIO;
138 }
139 
ErrorVopSymlink(struct Vnode * parentVnode,struct Vnode ** newVnode,const char * path,const char * target)140 static int ErrorVopSymlink (struct Vnode *parentVnode, struct Vnode **newVnode, const char *path, const char *target)
141 {
142     return -EIO;
143 }
144 
ErrorVopReadlink(struct Vnode * vnode,char * buffer,size_t bufLen)145 static ssize_t ErrorVopReadlink (struct Vnode *vnode, char *buffer, size_t bufLen)
146 {
147     return -EIO;
148 }
149 
150 static struct VnodeOps g_errorVnodeOps = {
151     .Create = ErrorVopCreate,
152     .Lookup = ErrorVopLookup,
153     .Open = ErrorVopOpen,
154     .Close = ErrorVopClose,
155     .Reclaim = ErrorVopReclaim,
156     .Unlink = ErrorVopUnlink,
157     .Rmdir = ErrorVopRmdir,
158     .Mkdir = ErrorVopMkdir,
159     .Readdir = ErrorVopReaddir,
160     .Opendir = ErrorVopOpendir,
161     .Rewinddir = ErrorVopRewinddir,
162     .Closedir = ErrorVopClosedir,
163     .Getattr = ErrorVopGetattr,
164     .Setattr = ErrorVopSetattr,
165     .Chattr = ErrorVopChattr,
166     .Rename = ErrorVopRename,
167     .Truncate = ErrorVopTruncate,
168     .Truncate64 = ErrorVopTruncate64,
169     .Fscheck = ErrorVopFscheck,
170     .Link = ErrorVopLink,
171     .Symlink = ErrorVopSymlink,
172     .Readlink = ErrorVopReadlink,
173 };
174 
175 /* file operations returns EIO */
ErrorFopOpen(struct file * filep)176 static int ErrorFopOpen (struct file *filep)
177 {
178     return -EIO;
179 }
180 
ErrorFopClose(struct file * filep)181 static int ErrorFopClose (struct file *filep)
182 {
183     /* already closed at force umount, do nothing here */
184     return OK;
185 }
186 
ErrorFopRead(struct file * filep,char * buffer,size_t buflen)187 static ssize_t ErrorFopRead (struct file *filep, char *buffer, size_t buflen)
188 {
189     return -EIO;
190 }
191 
ErrorFopWrite(struct file * filep,const char * buffer,size_t buflen)192 static ssize_t ErrorFopWrite (struct file *filep, const char *buffer, size_t buflen)
193 {
194     return -EIO;
195 }
196 
ErrorFopSeek(struct file * filep,off_t offset,int whence)197 static off_t ErrorFopSeek (struct file *filep, off_t offset, int whence)
198 {
199     return -EIO;
200 }
201 
ErrorFopIoctl(struct file * filep,int cmd,unsigned long arg)202 static int ErrorFopIoctl (struct file *filep, int cmd, unsigned long arg)
203 {
204     return -EIO;
205 }
206 
ErrorFopMmap(struct file * filep,struct VmMapRegion * region)207 static int ErrorFopMmap (struct file* filep, struct VmMapRegion *region)
208 {
209     return -EIO;
210 }
211 
ErrorFopPoll(struct file * filep,poll_table * fds)212 static int ErrorFopPoll (struct file *filep, poll_table *fds)
213 {
214     return -EIO;
215 }
216 
ErrorFopStat(struct file * filep,struct stat * st)217 static int ErrorFopStat (struct file *filep, struct stat* st)
218 {
219     return -EIO;
220 }
221 
ErrorFopFallocate(struct file * filep,int mode,off_t offset,off_t len)222 static int ErrorFopFallocate (struct file* filep, int mode, off_t offset, off_t len)
223 {
224     return -EIO;
225 }
226 
ErrorFopFallocate64(struct file * filep,int mode,off64_t offset,off64_t len)227 static int ErrorFopFallocate64 (struct file *filep, int mode, off64_t offset, off64_t len)
228 {
229     return -EIO;
230 }
231 
ErrorFopFsync(struct file * filep)232 static int ErrorFopFsync (struct file *filep)
233 {
234     return -EIO;
235 }
236 
ErrorFopReadpage(struct file * filep,char * buffer,size_t buflen)237 static ssize_t ErrorFopReadpage (struct file *filep, char *buffer, size_t buflen)
238 {
239     return -EIO;
240 }
241 
ErrorFopUnlink(struct Vnode * vnode)242 static int ErrorFopUnlink (struct Vnode *vnode)
243 {
244     return -EIO;
245 }
246 
247 static struct file_operations_vfs g_errorFileOps = {
248     .open = ErrorFopOpen,
249     .close = ErrorFopClose,
250     .read = ErrorFopRead,
251     .write = ErrorFopWrite,
252     .seek = ErrorFopSeek,
253     .ioctl = ErrorFopIoctl,
254     .mmap = ErrorFopMmap,
255     .poll = ErrorFopPoll,
256     .stat = ErrorFopStat,
257     .fallocate = ErrorFopFallocate,
258     .fallocate64 = ErrorFopFallocate64,
259     .fsync = ErrorFopFsync,
260     .readpage = ErrorFopReadpage,
261     .unlink = ErrorFopUnlink,
262 };
263 
GetDevMountPoint(struct Vnode * dev)264 static struct Mount* GetDevMountPoint(struct Vnode *dev)
265 {
266     struct Mount *mnt = NULL;
267     LIST_HEAD *mntList = GetMountList();
268     if (mntList == NULL) {
269         return NULL;
270     }
271 
272     LOS_DL_LIST_FOR_EACH_ENTRY(mnt, mntList, struct Mount, mountList) {
273         if (mnt->vnodeDev == dev) {
274             return mnt;
275         }
276     }
277     return NULL;
278 }
279 
DirPreClose(struct fs_dirent_s * dirp)280 static void DirPreClose(struct fs_dirent_s *dirp)
281 {
282     struct Vnode *node = NULL;
283     if (dirp == NULL || dirp->fd_root == NULL) {
284         return;
285     }
286 
287     node = dirp->fd_root;
288     if (node->vop && node->vop->Closedir) {
289         node->vop->Closedir(node, dirp);
290     }
291 }
292 
FilePreClose(struct file * filep,const struct file_operations_vfs * ops)293 static void FilePreClose(struct file *filep, const struct file_operations_vfs *ops)
294 {
295     if (filep->f_oflags & O_DIRECTORY) {
296         DirPreClose(filep->f_dir);
297         return;
298     }
299 
300     if (ops && ops->close) {
301         ops->close(filep);
302     }
303 }
304 
FileDisableAndClean(struct Mount * mnt)305 static void FileDisableAndClean(struct Mount *mnt)
306 {
307     struct filelist *flist = &tg_filelist;
308     struct file *filep = NULL;
309     const struct file_operations_vfs *originOps = NULL;
310 
311     for (int i = 3; i < CONFIG_NFILE_DESCRIPTORS; i++) {
312         if (!get_bit(i)) {
313             continue;
314         }
315         filep = &flist->fl_files[i];
316         if (filep == NULL || filep->f_vnode == NULL) {
317             continue;
318         }
319         if (filep->f_vnode->originMount != mnt) {
320             continue;
321         }
322         originOps = filep->ops;
323         filep->ops = &g_errorFileOps;
324         FilePreClose(filep, originOps);
325     }
326 }
327 
VnodeTryFree(struct Vnode * vnode)328 static void VnodeTryFree(struct Vnode *vnode)
329 {
330     if (vnode->useCount == 0) {
331         VnodeFree(vnode);
332         return;
333     }
334 
335     VnodePathCacheFree(vnode);
336     LOS_ListDelete(&(vnode->hashEntry));
337     LOS_ListDelete(&vnode->actFreeEntry);
338 
339     if (vnode->vop->Reclaim) {
340         vnode->vop->Reclaim(vnode);
341     }
342     vnode->vop = &g_errorVnodeOps;
343     vnode->fop = &g_errorFileOps;
344 }
345 
VnodeTryFreeAll(struct Mount * mount)346 static void VnodeTryFreeAll(struct Mount *mount)
347 {
348     struct Vnode *vnode = NULL;
349     struct Vnode *nextVnode = NULL;
350 
351     LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(vnode, nextVnode, GetVnodeActiveList(), struct Vnode, actFreeEntry) {
352         if ((vnode->originMount != mount) || (vnode->flag & VNODE_FLAG_MOUNT_NEW)) {
353             continue;
354         }
355         VnodeTryFree(vnode);
356     }
357 }
358 
ForceUmountDev(struct Vnode * dev)359 int ForceUmountDev(struct Vnode *dev)
360 {
361     int ret;
362     struct Vnode *origin = NULL;
363     struct filelist *flist = &tg_filelist;
364     if (dev == NULL) {
365         return -EINVAL;
366     }
367 
368     (void)sem_wait(&flist->fl_sem);
369     VnodeHold();
370 
371     struct Mount *mnt = GetDevMountPoint(dev);
372     if (mnt == NULL) {
373         VnodeDrop();
374         (void)sem_post(&flist->fl_sem);
375         return -ENXIO;
376     }
377     origin = mnt->vnodeBeCovered;
378 
379     FileDisableAndClean(mnt);
380     VnodeTryFreeAll(mnt);
381     ret = mnt->ops->Unmount(mnt, &dev);
382     if (ret != OK) {
383         PRINT_ERR("unmount in fs failed, ret = %d, errno = %d\n", ret, errno);
384     }
385 
386     LOS_ListDelete(&mnt->mountList);
387     free(mnt);
388     origin->newMount = NULL;
389     origin->flag &= ~(VNODE_FLAG_MOUNT_ORIGIN);
390 
391     VnodeDrop();
392     (void)sem_post(&flist->fl_sem);
393 
394     return OK;
395 }
396