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 */ 38static int ErrorVopCreate(struct Vnode *parent, const char *name, int mode, struct Vnode **vnode) 39{ 40 (void)parent; 41 (void)name; 42 (void)mode; 43 (void)vnode; 44 return -EIO; 45} 46 47static int ErrorVopLookup(struct Vnode *parent, const char *name, int len, struct Vnode **vnode) 48{ 49 (void)parent; 50 (void)name; 51 (void)len; 52 (void)vnode; 53 return -EIO; 54} 55 56static int ErrorVopOpen(struct Vnode *vnode, int fd, int mode, int flags) 57{ 58 (void)vnode; 59 (void)fd; 60 (void)mode; 61 (void)flags; 62 return -EIO; 63} 64 65static int ErrorVopClose(struct Vnode *vnode) 66{ 67 (void)vnode; 68 /* already closed at force umount, do nothing here */ 69 return OK; 70} 71 72static int ErrorVopReclaim(struct Vnode *vnode) 73{ 74 (void)vnode; 75 return -EIO; 76} 77 78static int ErrorVopUnlink(struct Vnode *parent, struct Vnode *vnode, const char *fileName) 79{ 80 (void)parent; 81 (void)vnode; 82 (void)fileName; 83 return -EIO; 84} 85 86static int ErrorVopRmdir(struct Vnode *parent, struct Vnode *vnode, const char *dirName) 87{ 88 (void)parent; 89 (void)vnode; 90 (void)dirName; 91 return -EIO; 92} 93 94static int ErrorVopMkdir(struct Vnode *parent, const char *dirName, mode_t mode, struct Vnode **vnode) 95{ 96 (void)parent; 97 (void)dirName; 98 (void)mode; 99 (void)vnode; 100 return -EIO; 101} 102 103static int ErrorVopReaddir(struct Vnode *vnode, struct fs_dirent_s *dir) 104{ 105 (void)vnode; 106 (void)dir; 107 return -EIO; 108} 109 110static int ErrorVopOpendir(struct Vnode *vnode, struct fs_dirent_s *dir) 111{ 112 (void)vnode; 113 (void)dir; 114 return -EIO; 115} 116 117static int ErrorVopRewinddir(struct Vnode *vnode, struct fs_dirent_s *dir) 118{ 119 (void)vnode; 120 (void)dir; 121 return -EIO; 122} 123 124static int ErrorVopClosedir(struct Vnode *vnode, struct fs_dirent_s *dir) 125{ 126 (void)vnode; 127 (void)dir; 128 /* already closed at force umount, do nothing here */ 129 return OK; 130} 131 132static int ErrorVopGetattr(struct Vnode *vnode, struct stat *st) 133{ 134 (void)vnode; 135 (void)st; 136 return -EIO; 137} 138 139static int ErrorVopSetattr(struct Vnode *vnode, struct stat *st) 140{ 141 (void)vnode; 142 (void)st; 143 return -EIO; 144} 145 146static int ErrorVopChattr(struct Vnode *vnode, struct IATTR *attr) 147{ 148 (void)vnode; 149 (void)attr; 150 return -EIO; 151} 152 153static int ErrorVopRename(struct Vnode *src, struct Vnode *dstParent, const char *srcName, const char *dstName) 154{ 155 (void)src; 156 (void)dstParent; 157 (void)srcName; 158 (void)dstName; 159 return -EIO; 160} 161 162static int ErrorVopTruncate(struct Vnode *vnode, off_t len) 163{ 164 (void)vnode; 165 (void)len; 166 return -EIO; 167} 168 169static int ErrorVopTruncate64(struct Vnode *vnode, off64_t len) 170{ 171 (void)vnode; 172 (void)len; 173 return -EIO; 174} 175 176static int ErrorVopFscheck(struct Vnode *vnode, struct fs_dirent_s *dir) 177{ 178 (void)vnode; 179 (void)dir; 180 return -EIO; 181} 182 183static int ErrorVopLink(struct Vnode *src, struct Vnode *dstParent, struct Vnode **dst, const char *dstName) 184{ 185 (void)src; 186 (void)dstParent; 187 (void)dst; 188 (void)dstName; 189 return -EIO; 190} 191 192static int ErrorVopSymlink(struct Vnode *parentVnode, struct Vnode **newVnode, const char *path, const char *target) 193{ 194 (void)parentVnode; 195 (void)newVnode; 196 (void)path; 197 (void)target; 198 return -EIO; 199} 200 201static ssize_t ErrorVopReadlink(struct Vnode *vnode, char *buffer, size_t bufLen) 202{ 203 (void)vnode; 204 (void)buffer; 205 (void)bufLen; 206 return -EIO; 207} 208 209static struct VnodeOps g_errorVnodeOps = { 210 .Create = ErrorVopCreate, 211 .Lookup = ErrorVopLookup, 212 .Open = ErrorVopOpen, 213 .Close = ErrorVopClose, 214 .Reclaim = ErrorVopReclaim, 215 .Unlink = ErrorVopUnlink, 216 .Rmdir = ErrorVopRmdir, 217 .Mkdir = ErrorVopMkdir, 218 .Readdir = ErrorVopReaddir, 219 .Opendir = ErrorVopOpendir, 220 .Rewinddir = ErrorVopRewinddir, 221 .Closedir = ErrorVopClosedir, 222 .Getattr = ErrorVopGetattr, 223 .Setattr = ErrorVopSetattr, 224 .Chattr = ErrorVopChattr, 225 .Rename = ErrorVopRename, 226 .Truncate = ErrorVopTruncate, 227 .Truncate64 = ErrorVopTruncate64, 228 .Fscheck = ErrorVopFscheck, 229 .Link = ErrorVopLink, 230 .Symlink = ErrorVopSymlink, 231 .Readlink = ErrorVopReadlink, 232}; 233 234/* file operations returns EIO */ 235static int ErrorFopOpen(struct file *filep) 236{ 237 (void)filep; 238 return -EIO; 239} 240 241static int ErrorFopClose(struct file *filep) 242{ 243 (void)filep; 244 /* already closed at force umount, do nothing here */ 245 return OK; 246} 247 248static ssize_t ErrorFopRead(struct file *filep, char *buffer, size_t buflen) 249{ 250 (void)filep; 251 (void)buffer; 252 (void)buflen; 253 return -EIO; 254} 255 256static ssize_t ErrorFopWrite(struct file *filep, const char *buffer, size_t buflen) 257{ 258 (void)filep; 259 (void)buffer; 260 (void)buflen; 261 return -EIO; 262} 263 264static off_t ErrorFopSeek(struct file *filep, off_t offset, int whence) 265{ 266 (void)filep; 267 (void)offset; 268 (void)whence; 269 return -EIO; 270} 271 272static int ErrorFopIoctl(struct file *filep, int cmd, unsigned long arg) 273{ 274 (void)filep; 275 (void)cmd; 276 (void)arg; 277 return -EIO; 278} 279 280static int ErrorFopMmap(struct file* filep, struct VmMapRegion *region) 281{ 282 (void)filep; 283 (void)region; 284 return -EIO; 285} 286 287static int ErrorFopPoll(struct file *filep, poll_table *fds) 288{ 289 (void)filep; 290 (void)fds; 291 return -EIO; 292} 293 294static int ErrorFopStat(struct file *filep, struct stat* st) 295{ 296 (void)filep; 297 (void)st; 298 return -EIO; 299} 300 301static int ErrorFopFallocate(struct file* filep, int mode, off_t offset, off_t len) 302{ 303 (void)filep; 304 (void)mode; 305 (void)offset; 306 (void)len; 307 return -EIO; 308} 309 310static int ErrorFopFallocate64(struct file *filep, int mode, off64_t offset, off64_t len) 311{ 312 (void)filep; 313 (void)mode; 314 (void)offset; 315 (void)len; 316 return -EIO; 317} 318 319static int ErrorFopFsync(struct file *filep) 320{ 321 (void)filep; 322 return -EIO; 323} 324 325static ssize_t ErrorFopReadpage(struct file *filep, char *buffer, size_t buflen) 326{ 327 (void)filep; 328 (void)buffer; 329 (void)buflen; 330 return -EIO; 331} 332 333static int ErrorFopUnlink(struct Vnode *vnode) 334{ 335 (void)vnode; 336 return -EIO; 337} 338 339static struct file_operations_vfs g_errorFileOps = { 340 .open = ErrorFopOpen, 341 .close = ErrorFopClose, 342 .read = ErrorFopRead, 343 .write = ErrorFopWrite, 344 .seek = ErrorFopSeek, 345 .ioctl = ErrorFopIoctl, 346 .mmap = ErrorFopMmap, 347 .poll = ErrorFopPoll, 348 .stat = ErrorFopStat, 349 .fallocate = ErrorFopFallocate, 350 .fallocate64 = ErrorFopFallocate64, 351 .fsync = ErrorFopFsync, 352 .readpage = ErrorFopReadpage, 353 .unlink = ErrorFopUnlink, 354}; 355 356static struct Mount* GetDevMountPoint(const struct Vnode *dev) 357{ 358 struct Mount *mnt = NULL; 359 LIST_HEAD *mntList = GetMountList(); 360 if (mntList == NULL) { 361 return NULL; 362 } 363 364 LOS_DL_LIST_FOR_EACH_ENTRY(mnt, mntList, struct Mount, mountList) { 365 if (mnt->vnodeDev == dev) { 366 return mnt; 367 } 368 } 369 return NULL; 370} 371 372static void DirPreClose(struct fs_dirent_s *dirp) 373{ 374 struct Vnode *node = NULL; 375 if (dirp == NULL || dirp->fd_root == NULL) { 376 return; 377 } 378 379 node = dirp->fd_root; 380 if (node->vop && node->vop->Closedir) { 381 node->vop->Closedir(node, dirp); 382 } 383} 384 385static void FilePreClose(struct file *filep, const struct file_operations_vfs *ops) 386{ 387 if (filep->f_oflags & O_DIRECTORY) { 388 DirPreClose(filep->f_dir); 389 return; 390 } 391 392 if (ops && ops->close) { 393 ops->close(filep); 394 } 395} 396 397static void FileDisableAndClean(const struct Mount *mnt) 398{ 399 struct filelist *flist = &tg_filelist; 400 struct file *filep = NULL; 401 const struct file_operations_vfs *originOps = NULL; 402 403 for (int i = 3; i < CONFIG_NFILE_DESCRIPTORS; i++) { 404 if (!get_bit(i)) { 405 continue; 406 } 407 filep = &flist->fl_files[i]; 408 if (filep == NULL || filep->f_vnode == NULL) { 409 continue; 410 } 411 if (filep->f_vnode->originMount != mnt) { 412 continue; 413 } 414 originOps = filep->ops; 415 filep->ops = &g_errorFileOps; 416 FilePreClose(filep, originOps); 417 } 418} 419 420static void VnodeTryFree(struct Vnode *vnode) 421{ 422 if (vnode->useCount == 0) { 423 VnodeFree(vnode); 424 return; 425 } 426 427 VnodePathCacheFree(vnode); 428 LOS_ListDelete(&(vnode->hashEntry)); 429 LOS_ListDelete(&vnode->actFreeEntry); 430 431 if (vnode->vop->Reclaim) { 432 vnode->vop->Reclaim(vnode); 433 } 434 vnode->vop = &g_errorVnodeOps; 435 vnode->fop = &g_errorFileOps; 436} 437 438static void VnodeTryFreeAll(const struct Mount *mount) 439{ 440 struct Vnode *vnode = NULL; 441 struct Vnode *nextVnode = NULL; 442 443 LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(vnode, nextVnode, GetVnodeActiveList(), struct Vnode, actFreeEntry) { 444 if ((vnode->originMount != mount) || (vnode->flag & VNODE_FLAG_MOUNT_NEW)) { 445 continue; 446 } 447 VnodeTryFree(vnode); 448 } 449} 450 451int ForceUmountDev(struct Vnode *dev) 452{ 453 int ret; 454 struct Vnode *origin = NULL; 455 struct filelist *flist = &tg_filelist; 456 if (dev == NULL) { 457 return -EINVAL; 458 } 459 460 (void)sem_wait(&flist->fl_sem); 461 VnodeHold(); 462 463 struct Mount *mnt = GetDevMountPoint(dev); 464 if (mnt == NULL) { 465 VnodeDrop(); 466 (void)sem_post(&flist->fl_sem); 467 return -ENXIO; 468 } 469 origin = mnt->vnodeBeCovered; 470 471 FileDisableAndClean(mnt); 472 VnodeTryFreeAll(mnt); 473 ret = mnt->ops->Unmount(mnt, &dev); 474 if (ret != OK) { 475 PRINT_ERR("unmount in fs failed, ret = %d, errno = %d\n", ret, errno); 476 } 477 478 LOS_ListDelete(&mnt->mountList); 479 free(mnt); 480 origin->newMount = NULL; 481 origin->flag &= ~(VNODE_FLAG_MOUNT_ORIGIN); 482 483 VnodeDrop(); 484 (void)sem_post(&flist->fl_sem); 485 486 return OK; 487} 488