vfs_force_umount.c 11.0 KB
Newer Older
M
mucor 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
/*
 * Copyright (c) 2021-2021 Huawei Device Co., Ltd. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this list of
 *    conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
 *    of conditions and the following disclaimer in the documentation and/or other materials
 *    provided with the distribution.
 *
 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
 *    to endorse or promote products derived from this software without specific prior written
 *    permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "fs/mount.h"
#include "fs/dirent_fs.h"
#include "fs/file.h"
#include "vnode.h"
#include "path_cache.h"

/* vnode operations returns EIO */
X
x_xiny 已提交
38
static int ErrorVopCreate(struct Vnode *parent, const char *name, int mode, struct Vnode **vnode)
M
mucor 已提交
39
{
X
x_xiny 已提交
40 41 42 43
    (void)parent;
    (void)name;
    (void)mode;
    (void)vnode;
M
mucor 已提交
44 45 46
    return -EIO;
}

X
x_xiny 已提交
47
static int ErrorVopLookup(struct Vnode *parent, const char *name, int len, struct Vnode **vnode)
M
mucor 已提交
48
{
X
x_xiny 已提交
49 50 51 52
    (void)parent;
    (void)name;
    (void)len;
    (void)vnode;
M
mucor 已提交
53 54 55
    return -EIO;
}

X
x_xiny 已提交
56
static int ErrorVopOpen(struct Vnode *vnode, int fd, int mode, int flags)
M
mucor 已提交
57
{
X
x_xiny 已提交
58 59 60 61
    (void)vnode;
    (void)fd;
    (void)mode;
    (void)flags;
M
mucor 已提交
62 63 64
    return -EIO;
}

X
x_xiny 已提交
65
static int ErrorVopClose(struct Vnode *vnode)
M
mucor 已提交
66
{
X
x_xiny 已提交
67
    (void)vnode;
M
mucor 已提交
68 69 70 71
    /* already closed at force umount, do nothing here */
    return OK;
}

X
x_xiny 已提交
72
static int ErrorVopReclaim(struct Vnode *vnode)
M
mucor 已提交
73
{
X
x_xiny 已提交
74
    (void)vnode;
M
mucor 已提交
75 76 77
    return -EIO;
}

X
x_xiny 已提交
78
static int ErrorVopUnlink(struct Vnode *parent, struct Vnode *vnode, const char *fileName)
M
mucor 已提交
79
{
X
x_xiny 已提交
80 81 82
    (void)parent;
    (void)vnode;
    (void)fileName;
M
mucor 已提交
83 84 85
    return -EIO;
}

X
x_xiny 已提交
86
static int ErrorVopRmdir(struct Vnode *parent, struct Vnode *vnode, const char *dirName)
M
mucor 已提交
87
{
X
x_xiny 已提交
88 89 90
    (void)parent;
    (void)vnode;
    (void)dirName;
M
mucor 已提交
91 92 93
    return -EIO;
}

X
x_xiny 已提交
94
static int ErrorVopMkdir(struct Vnode *parent, const char *dirName, mode_t mode, struct Vnode **vnode)
M
mucor 已提交
95
{
X
x_xiny 已提交
96 97 98 99
    (void)parent;
    (void)dirName;
    (void)mode;
    (void)vnode;
M
mucor 已提交
100 101 102
    return -EIO;
}

X
x_xiny 已提交
103
static int ErrorVopReaddir(struct Vnode *vnode, struct fs_dirent_s *dir)
M
mucor 已提交
104
{
X
x_xiny 已提交
105 106
    (void)vnode;
    (void)dir;
M
mucor 已提交
107 108 109
    return -EIO;
}

X
x_xiny 已提交
110
static int ErrorVopOpendir(struct Vnode *vnode, struct fs_dirent_s *dir)
M
mucor 已提交
111
{
X
x_xiny 已提交
112 113
    (void)vnode;
    (void)dir;
M
mucor 已提交
114 115 116
    return -EIO;
}

X
x_xiny 已提交
117
static int ErrorVopRewinddir(struct Vnode *vnode, struct fs_dirent_s *dir)
M
mucor 已提交
118
{
X
x_xiny 已提交
119 120
    (void)vnode;
    (void)dir;
M
mucor 已提交
121 122 123
    return -EIO;
}

X
x_xiny 已提交
124
static int ErrorVopClosedir(struct Vnode *vnode, struct fs_dirent_s *dir)
M
mucor 已提交
125
{
X
x_xiny 已提交
126 127
    (void)vnode;
    (void)dir;
M
mucor 已提交
128 129 130 131
    /* already closed at force umount, do nothing here */
    return OK;
}

X
x_xiny 已提交
132
static int ErrorVopGetattr(struct Vnode *vnode, struct stat *st)
M
mucor 已提交
133
{
X
x_xiny 已提交
134 135
    (void)vnode;
    (void)st;
M
mucor 已提交
136 137 138
    return -EIO;
}

X
x_xiny 已提交
139
static int ErrorVopSetattr(struct Vnode *vnode, struct stat *st)
M
mucor 已提交
140
{
X
x_xiny 已提交
141 142
    (void)vnode;
    (void)st;
M
mucor 已提交
143 144 145
    return -EIO;
}

X
x_xiny 已提交
146
static int ErrorVopChattr(struct Vnode *vnode, struct IATTR *attr)
M
mucor 已提交
147
{
X
x_xiny 已提交
148 149
    (void)vnode;
    (void)attr;
M
mucor 已提交
150 151 152
    return -EIO;
}

X
x_xiny 已提交
153
static int ErrorVopRename(struct Vnode *src, struct Vnode *dstParent, const char *srcName, const char *dstName)
M
mucor 已提交
154
{
X
x_xiny 已提交
155 156 157 158
    (void)src;
    (void)dstParent;
    (void)srcName;
    (void)dstName;
M
mucor 已提交
159 160 161
    return -EIO;
}

X
x_xiny 已提交
162
static int ErrorVopTruncate(struct Vnode *vnode, off_t len)
M
mucor 已提交
163
{
X
x_xiny 已提交
164 165
    (void)vnode;
    (void)len;
M
mucor 已提交
166 167 168
    return -EIO;
}

X
x_xiny 已提交
169
static int ErrorVopTruncate64(struct Vnode *vnode, off64_t len)
M
mucor 已提交
170
{
X
x_xiny 已提交
171 172
    (void)vnode;
    (void)len;
M
mucor 已提交
173 174 175
    return -EIO;
}

X
x_xiny 已提交
176
static int ErrorVopFscheck(struct Vnode *vnode, struct fs_dirent_s *dir)
M
mucor 已提交
177
{
X
x_xiny 已提交
178 179
    (void)vnode;
    (void)dir;
M
mucor 已提交
180 181 182
    return -EIO;
}

X
x_xiny 已提交
183
static int ErrorVopLink(struct Vnode *src, struct Vnode *dstParent, struct Vnode **dst, const char *dstName)
M
mucor 已提交
184
{
X
x_xiny 已提交
185 186 187 188
    (void)src;
    (void)dstParent;
    (void)dst;
    (void)dstName;
M
mucor 已提交
189 190 191
    return -EIO;
}

X
x_xiny 已提交
192
static int ErrorVopSymlink(struct Vnode *parentVnode, struct Vnode **newVnode, const char *path, const char *target)
M
mucor 已提交
193
{
X
x_xiny 已提交
194 195 196 197
    (void)parentVnode;
    (void)newVnode;
    (void)path;
    (void)target;
M
mucor 已提交
198 199 200
    return -EIO;
}

X
x_xiny 已提交
201
static ssize_t ErrorVopReadlink(struct Vnode *vnode, char *buffer, size_t bufLen)
M
mucor 已提交
202
{
X
x_xiny 已提交
203 204 205
    (void)vnode;
    (void)buffer;
    (void)bufLen;
M
mucor 已提交
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234
    return -EIO;
}

static struct VnodeOps g_errorVnodeOps = {
    .Create = ErrorVopCreate,
    .Lookup = ErrorVopLookup,
    .Open = ErrorVopOpen,
    .Close = ErrorVopClose,
    .Reclaim = ErrorVopReclaim,
    .Unlink = ErrorVopUnlink,
    .Rmdir = ErrorVopRmdir,
    .Mkdir = ErrorVopMkdir,
    .Readdir = ErrorVopReaddir,
    .Opendir = ErrorVopOpendir,
    .Rewinddir = ErrorVopRewinddir,
    .Closedir = ErrorVopClosedir,
    .Getattr = ErrorVopGetattr,
    .Setattr = ErrorVopSetattr,
    .Chattr = ErrorVopChattr,
    .Rename = ErrorVopRename,
    .Truncate = ErrorVopTruncate,
    .Truncate64 = ErrorVopTruncate64,
    .Fscheck = ErrorVopFscheck,
    .Link = ErrorVopLink,
    .Symlink = ErrorVopSymlink,
    .Readlink = ErrorVopReadlink,
};

/* file operations returns EIO */
X
x_xiny 已提交
235
static int ErrorFopOpen(struct file *filep)
M
mucor 已提交
236
{
X
x_xiny 已提交
237
    (void)filep;
M
mucor 已提交
238 239 240
    return -EIO;
}

X
x_xiny 已提交
241
static int ErrorFopClose(struct file *filep)
M
mucor 已提交
242
{
X
x_xiny 已提交
243
    (void)filep;
M
mucor 已提交
244 245 246 247
    /* already closed at force umount, do nothing here */
    return OK;
}

X
x_xiny 已提交
248
static ssize_t ErrorFopRead(struct file *filep, char *buffer, size_t buflen)
M
mucor 已提交
249
{
X
x_xiny 已提交
250 251 252
    (void)filep;
    (void)buffer;
    (void)buflen;
M
mucor 已提交
253 254 255
    return -EIO;
}

X
x_xiny 已提交
256
static ssize_t ErrorFopWrite(struct file *filep, const char *buffer, size_t buflen)
M
mucor 已提交
257
{
X
x_xiny 已提交
258 259 260
    (void)filep;
    (void)buffer;
    (void)buflen;
M
mucor 已提交
261 262 263
    return -EIO;
}

X
x_xiny 已提交
264
static off_t ErrorFopSeek(struct file *filep, off_t offset, int whence)
M
mucor 已提交
265
{
X
x_xiny 已提交
266 267 268
    (void)filep;
    (void)offset;
    (void)whence;
M
mucor 已提交
269 270 271
    return -EIO;
}

X
x_xiny 已提交
272
static int ErrorFopIoctl(struct file *filep, int cmd, unsigned long arg)
M
mucor 已提交
273
{
X
x_xiny 已提交
274 275 276
    (void)filep;
    (void)cmd;
    (void)arg;
M
mucor 已提交
277 278 279
    return -EIO;
}

X
x_xiny 已提交
280
static int ErrorFopMmap(struct file* filep, struct VmMapRegion *region)
M
mucor 已提交
281
{
X
x_xiny 已提交
282 283
    (void)filep;
    (void)region;
M
mucor 已提交
284 285 286
    return -EIO;
}

X
x_xiny 已提交
287
static int ErrorFopPoll(struct file *filep, poll_table *fds)
M
mucor 已提交
288
{
X
x_xiny 已提交
289 290
    (void)filep;
    (void)fds;
M
mucor 已提交
291 292 293
    return -EIO;
}

X
x_xiny 已提交
294
static int ErrorFopStat(struct file *filep, struct stat* st)
M
mucor 已提交
295
{
X
x_xiny 已提交
296 297
    (void)filep;
    (void)st;
M
mucor 已提交
298 299 300
    return -EIO;
}

X
x_xiny 已提交
301
static int ErrorFopFallocate(struct file* filep, int mode, off_t offset, off_t len)
M
mucor 已提交
302
{
X
x_xiny 已提交
303 304 305 306
    (void)filep;
    (void)mode;
    (void)offset;
    (void)len;
M
mucor 已提交
307 308 309
    return -EIO;
}

X
x_xiny 已提交
310
static int ErrorFopFallocate64(struct file *filep, int mode, off64_t offset, off64_t len)
M
mucor 已提交
311
{
X
x_xiny 已提交
312 313 314 315
    (void)filep;
    (void)mode;
    (void)offset;
    (void)len;
M
mucor 已提交
316 317 318
    return -EIO;
}

X
x_xiny 已提交
319
static int ErrorFopFsync(struct file *filep)
M
mucor 已提交
320
{
X
x_xiny 已提交
321
    (void)filep;
M
mucor 已提交
322 323 324
    return -EIO;
}

X
x_xiny 已提交
325
static ssize_t ErrorFopReadpage(struct file *filep, char *buffer, size_t buflen)
M
mucor 已提交
326
{
X
x_xiny 已提交
327 328 329
    (void)filep;
    (void)buffer;
    (void)buflen;
M
mucor 已提交
330 331 332
    return -EIO;
}

X
x_xiny 已提交
333
static int ErrorFopUnlink(struct Vnode *vnode)
M
mucor 已提交
334
{
X
x_xiny 已提交
335
    (void)vnode;
M
mucor 已提交
336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359
    return -EIO;
}

static struct file_operations_vfs g_errorFileOps = {
    .open = ErrorFopOpen,
    .close = ErrorFopClose,
    .read = ErrorFopRead,
    .write = ErrorFopWrite,
    .seek = ErrorFopSeek,
    .ioctl = ErrorFopIoctl,
    .mmap = ErrorFopMmap,
    .poll = ErrorFopPoll,
    .stat = ErrorFopStat,
    .fallocate = ErrorFopFallocate,
    .fallocate64 = ErrorFopFallocate64,
    .fsync = ErrorFopFsync,
    .readpage = ErrorFopReadpage,
    .unlink = ErrorFopUnlink,
};

static struct Mount* GetDevMountPoint(struct Vnode *dev)
{
    struct Mount *mnt = NULL;
    LIST_HEAD *mntList = GetMountList();
W
wangchen 已提交
360 361 362 363
    if (mntList == NULL) {
        return NULL;
    }

M
mucor 已提交
364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400
    LOS_DL_LIST_FOR_EACH_ENTRY(mnt, mntList, struct Mount, mountList) {
        if (mnt->vnodeDev == dev) {
            return mnt;
        }
    }
    return NULL;
}

static void DirPreClose(struct fs_dirent_s *dirp)
{
    struct Vnode *node = NULL;
    if (dirp == NULL || dirp->fd_root == NULL) {
        return;
    }

    node = dirp->fd_root;
    if (node->vop && node->vop->Closedir) {
        node->vop->Closedir(node, dirp);
    }
}

static void FilePreClose(struct file *filep, const struct file_operations_vfs *ops)
{
    if (filep->f_oflags & O_DIRECTORY) {
        DirPreClose(filep->f_dir);
        return;
    }

    if (ops && ops->close) {
        ops->close(filep);
    }
}

static void FileDisableAndClean(struct Mount *mnt)
{
    struct filelist *flist = &tg_filelist;
    struct file *filep = NULL;
W
wangchen 已提交
401
    const struct file_operations_vfs *originOps = NULL;
M
mucor 已提交
402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453

    for (int i = 3; i < CONFIG_NFILE_DESCRIPTORS; i++) {
        if (!get_bit(i)) {
            continue;
        }
        filep = &flist->fl_files[i];
        if (filep == NULL || filep->f_vnode == NULL) {
            continue;
        }
        if (filep->f_vnode->originMount != mnt) {
            continue;
        }
        originOps = filep->ops;
        filep->ops = &g_errorFileOps;
        FilePreClose(filep, originOps);
    }
}

static void VnodeTryFree(struct Vnode *vnode)
{
    if (vnode->useCount == 0) {
        VnodeFree(vnode);
        return;
    }

    VnodePathCacheFree(vnode);
    LOS_ListDelete(&(vnode->hashEntry));
    LOS_ListDelete(&vnode->actFreeEntry);

    if (vnode->vop->Reclaim) {
        vnode->vop->Reclaim(vnode);
    }
    vnode->vop = &g_errorVnodeOps;
    vnode->fop = &g_errorFileOps;
}

static void VnodeTryFreeAll(struct Mount *mount)
{
    struct Vnode *vnode = NULL;
    struct Vnode *nextVnode = NULL;

    LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(vnode, nextVnode, GetVnodeActiveList(), struct Vnode, actFreeEntry) {
        if ((vnode->originMount != mount) || (vnode->flag & VNODE_FLAG_MOUNT_NEW)) {
            continue;
        }
        VnodeTryFree(vnode);
    }
}

int ForceUmountDev(struct Vnode *dev)
{
    int ret;
W
wangchen 已提交
454
    struct Vnode *origin = NULL;
M
mucor 已提交
455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487
    struct filelist *flist = &tg_filelist;
    if (dev == NULL) {
        return -EINVAL;
    }

    (void)sem_wait(&flist->fl_sem);
    VnodeHold();

    struct Mount *mnt = GetDevMountPoint(dev);
    if (mnt == NULL) {
        VnodeDrop();
        (void)sem_post(&flist->fl_sem);
        return -ENXIO;
    }
    origin = mnt->vnodeBeCovered;

    FileDisableAndClean(mnt);
    VnodeTryFreeAll(mnt);
    ret = mnt->ops->Unmount(mnt, &dev);
    if (ret != OK) {
        PRINT_ERR("unmount in fs failed, ret = %d, errno = %d\n", ret, errno);
    }

    LOS_ListDelete(&mnt->mountList);
    free(mnt);
    origin->newMount = NULL;
    origin->flag &= ~(VNODE_FLAG_MOUNT_ORIGIN);

    VnodeDrop();
    (void)sem_post(&flist->fl_sem);

    return OK;
}