1beacf11bSopenharmony_ci/**************************************************************************** 2beacf11bSopenharmony_ci * fs/mount/fs_mount.c 3beacf11bSopenharmony_ci * 4beacf11bSopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd. All rights reserved. 5beacf11bSopenharmony_ci * Based on NuttX originally from nuttx source (nuttx/fs/ and nuttx/drivers/) 6beacf11bSopenharmony_ci * 7beacf11bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 8beacf11bSopenharmony_ci * you may not use this file except in compliance with the License. 9beacf11bSopenharmony_ci * You may obtain a copy of the License at 10beacf11bSopenharmony_ci * 11beacf11bSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 12beacf11bSopenharmony_ci * 13beacf11bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 14beacf11bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 15beacf11bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16beacf11bSopenharmony_ci * See the License for the specific language governing permissions and 17beacf11bSopenharmony_ci * limitations under the License. 18beacf11bSopenharmony_ci * 19beacf11bSopenharmony_ci ****************************************************************************/ 20beacf11bSopenharmony_ci 21beacf11bSopenharmony_ci/**************************************************************************** 22beacf11bSopenharmony_ci * Included Files 23beacf11bSopenharmony_ci ****************************************************************************/ 24beacf11bSopenharmony_ci 25beacf11bSopenharmony_ci#include "vfs_config.h" 26beacf11bSopenharmony_ci 27beacf11bSopenharmony_ci#include "sys/mount.h" 28beacf11bSopenharmony_ci#include "string.h" 29beacf11bSopenharmony_ci#include "errno.h" 30beacf11bSopenharmony_ci#include "assert.h" 31beacf11bSopenharmony_ci#include "vnode.h" 32beacf11bSopenharmony_ci#include "stdlib.h" 33beacf11bSopenharmony_ci#ifdef LOSCFG_DRIVERS_MTD 34beacf11bSopenharmony_ci#include "mtd_partition.h" 35beacf11bSopenharmony_ci#endif 36beacf11bSopenharmony_ci#ifdef LOSCFG_FS_FAT_VIRTUAL_PARTITION 37beacf11bSopenharmony_ci#include "errcode_fat.h" 38beacf11bSopenharmony_ci#endif 39beacf11bSopenharmony_ci#include "los_tables.h" 40beacf11bSopenharmony_ci#ifdef LOSCFG_DRIVERS_RANDOM 41beacf11bSopenharmony_ci#include "hisoc/random.h" 42beacf11bSopenharmony_ci#else 43beacf11bSopenharmony_ci#include "stdlib.h" 44beacf11bSopenharmony_ci#endif 45beacf11bSopenharmony_ci#include "path_cache.h" 46beacf11bSopenharmony_ci#include "fs/mount.h" 47beacf11bSopenharmony_ci#include "fs/driver.h" 48beacf11bSopenharmony_ci#include "fs/fs.h" 49beacf11bSopenharmony_ci#ifdef LOSCFG_FS_ZPFS 50beacf11bSopenharmony_ci#include "zpfs.h" 51beacf11bSopenharmony_ci#endif 52beacf11bSopenharmony_ci#ifdef LOSCFG_MNT_CONTAINER 53beacf11bSopenharmony_ci#include "los_mnt_container_pri.h" 54beacf11bSopenharmony_ci#endif 55beacf11bSopenharmony_ci 56beacf11bSopenharmony_ci/* At least one filesystem must be defined, or this file will not compile. 57beacf11bSopenharmony_ci * It may be desire-able to make filesystems dynamically registered at 58beacf11bSopenharmony_ci * some time in the future, but at present, this file needs to know about 59beacf11bSopenharmony_ci * every configured filesystem. 60beacf11bSopenharmony_ci */ 61beacf11bSopenharmony_ci 62beacf11bSopenharmony_ci#ifdef CONFIG_FS_READABLE 63beacf11bSopenharmony_ci 64beacf11bSopenharmony_ci/**************************************************************************** 65beacf11bSopenharmony_ci * Pre-processor Definitions 66beacf11bSopenharmony_ci ****************************************************************************/ 67beacf11bSopenharmony_ci/* Configuration ************************************************************/ 68beacf11bSopenharmony_ci/* In the canonical case, a file system is bound to a block driver. However, 69beacf11bSopenharmony_ci * some less typical cases a block driver is not required. Examples are 70beacf11bSopenharmony_ci * pseudo file systems (like BINFS or PROCFS) and MTD file systems (like NXFFS). 71beacf11bSopenharmony_ci * 72beacf11bSopenharmony_ci * These file systems all require block drivers: 73beacf11bSopenharmony_ci */ 74beacf11bSopenharmony_ci 75beacf11bSopenharmony_ci#define BLKDRVR_NOT_MOUNTED 2 76beacf11bSopenharmony_ci 77beacf11bSopenharmony_ciextern struct fsmap_t g_fsmap[]; 78beacf11bSopenharmony_ciLOS_HAL_TABLE_BEGIN(g_fsmap, fsmap); 79beacf11bSopenharmony_ci 80beacf11bSopenharmony_ciextern struct fsmap_t g_fsmap_end; 81beacf11bSopenharmony_ciLOS_HAL_TABLE_END(g_fsmap_end, fsmap); 82beacf11bSopenharmony_ci 83beacf11bSopenharmony_ci/**************************************************************************** 84beacf11bSopenharmony_ci * Public Data 85beacf11bSopenharmony_ci ****************************************************************************/ 86beacf11bSopenharmony_ci 87beacf11bSopenharmony_ci/**************************************************************************** 88beacf11bSopenharmony_ci * Private Functions 89beacf11bSopenharmony_ci ****************************************************************************/ 90beacf11bSopenharmony_ci 91beacf11bSopenharmony_ci/**************************************************************************** 92beacf11bSopenharmony_ci * Name: mount_findfs 93beacf11bSopenharmony_ci * 94beacf11bSopenharmony_ci * Description: 95beacf11bSopenharmony_ci * find the specified filesystem 96beacf11bSopenharmony_ci * 97beacf11bSopenharmony_ci ****************************************************************************/ 98beacf11bSopenharmony_ci 99beacf11bSopenharmony_cistatic const struct fsmap_t *mount_findfs(const char *filesystemtype) 100beacf11bSopenharmony_ci{ 101beacf11bSopenharmony_ci struct fsmap_t *m = NULL; 102beacf11bSopenharmony_ci 103beacf11bSopenharmony_ci for (m = &g_fsmap[0]; m != &g_fsmap_end; ++m) 104beacf11bSopenharmony_ci { 105beacf11bSopenharmony_ci if (m->fs_filesystemtype && 106beacf11bSopenharmony_ci strcmp(filesystemtype, m->fs_filesystemtype) == 0) 107beacf11bSopenharmony_ci { 108beacf11bSopenharmony_ci return m; 109beacf11bSopenharmony_ci } 110beacf11bSopenharmony_ci } 111beacf11bSopenharmony_ci 112beacf11bSopenharmony_ci return (const struct fsmap_t *)NULL; 113beacf11bSopenharmony_ci} 114beacf11bSopenharmony_ci 115beacf11bSopenharmony_ci 116beacf11bSopenharmony_ci/**************************************************************************** 117beacf11bSopenharmony_ci * Public Functions 118beacf11bSopenharmony_ci ****************************************************************************/ 119beacf11bSopenharmony_ci 120beacf11bSopenharmony_ci/**************************************************************************** 121beacf11bSopenharmony_ci * Name: mount 122beacf11bSopenharmony_ci * 123beacf11bSopenharmony_ci * Description: 124beacf11bSopenharmony_ci * mount() attaches the filesystem specified by the 'source' block device 125beacf11bSopenharmony_ci * name into the root file system at the path specified by 'target.' 126beacf11bSopenharmony_ci * 127beacf11bSopenharmony_ci * Return: 128beacf11bSopenharmony_ci * Zero is returned on success; -1 is returned on an error and errno is 129beacf11bSopenharmony_ci * set appropriately: 130beacf11bSopenharmony_ci * 131beacf11bSopenharmony_ci * EACCES A component of a path was not searchable or mounting a read-only 132beacf11bSopenharmony_ci * filesystem was attempted without giving the MS_RDONLY flag. 133beacf11bSopenharmony_ci * EBUSY 'source' is already mounted. 134beacf11bSopenharmony_ci * EFAULT One of the pointer arguments points outside the user address 135beacf11bSopenharmony_ci * space. 136beacf11bSopenharmony_ci * EINVAL 'source' had an invalid superblock. 137beacf11bSopenharmony_ci * ENODEV 'filesystemtype' not configured 138beacf11bSopenharmony_ci * ENOENT A pathname was empty or had a nonexistent component. 139beacf11bSopenharmony_ci * ENOMEM Could not allocate a memory to copy filenames or data into. 140beacf11bSopenharmony_ci * ENOTBLK 'source' is not a block device 141beacf11bSopenharmony_ci * 142beacf11bSopenharmony_ci ****************************************************************************/ 143beacf11bSopenharmony_ci 144beacf11bSopenharmony_ciint mount(const char *source, const char *target, 145beacf11bSopenharmony_ci const char *filesystemtype, unsigned long mountflags, 146beacf11bSopenharmony_ci const void *data) 147beacf11bSopenharmony_ci{ 148beacf11bSopenharmony_ci int ret; 149beacf11bSopenharmony_ci int errcode = 0; 150beacf11bSopenharmony_ci struct Mount* mnt = NULL; 151beacf11bSopenharmony_ci struct Vnode *device = NULL; 152beacf11bSopenharmony_ci struct Vnode *mountpt_vnode = NULL; 153beacf11bSopenharmony_ci const struct fsmap_t *fsmap = NULL; 154beacf11bSopenharmony_ci const struct MountOps *mops = NULL; 155beacf11bSopenharmony_ci LIST_HEAD *mount_list = NULL; 156beacf11bSopenharmony_ci#ifdef LOSCFG_DRIVERS_MTD 157beacf11bSopenharmony_ci mtd_partition *partition = NULL; 158beacf11bSopenharmony_ci#endif 159beacf11bSopenharmony_ci 160beacf11bSopenharmony_ci if (filesystemtype == NULL) 161beacf11bSopenharmony_ci { 162beacf11bSopenharmony_ci errcode = -EINVAL; 163beacf11bSopenharmony_ci goto errout; 164beacf11bSopenharmony_ci } 165beacf11bSopenharmony_ci 166beacf11bSopenharmony_ci /* Verify required pointer arguments */ 167beacf11bSopenharmony_ci 168beacf11bSopenharmony_ci DEBUGASSERT(target && filesystemtype); 169beacf11bSopenharmony_ci 170beacf11bSopenharmony_ci /* Find the specified filesystem. Try the block driver file systems first */ 171beacf11bSopenharmony_ci 172beacf11bSopenharmony_ci if ((fsmap = mount_findfs(filesystemtype)) == NULL || (fsmap->is_bdfs && !source)) 173beacf11bSopenharmony_ci { 174beacf11bSopenharmony_ci PRINT_ERR("Failed to find file system %s\n", filesystemtype); 175beacf11bSopenharmony_ci errcode = -ENODEV; 176beacf11bSopenharmony_ci goto errout; 177beacf11bSopenharmony_ci } 178beacf11bSopenharmony_ci 179beacf11bSopenharmony_ci mops = fsmap->fs_mops; 180beacf11bSopenharmony_ci 181beacf11bSopenharmony_ci if (fsmap->is_bdfs && source) 182beacf11bSopenharmony_ci { 183beacf11bSopenharmony_ci /* Make sure that a block driver argument was provided */ 184beacf11bSopenharmony_ci 185beacf11bSopenharmony_ci DEBUGASSERT(source); 186beacf11bSopenharmony_ci 187beacf11bSopenharmony_ci /* Find the block driver */ 188beacf11bSopenharmony_ci 189beacf11bSopenharmony_ci ret = find_blockdriver(source, mountflags, &device); 190beacf11bSopenharmony_ci if (ret < 0) 191beacf11bSopenharmony_ci { 192beacf11bSopenharmony_ci PRINT_ERR("Failed to find block driver %s\n", source); 193beacf11bSopenharmony_ci errcode = ret; 194beacf11bSopenharmony_ci goto errout; 195beacf11bSopenharmony_ci } 196beacf11bSopenharmony_ci } 197beacf11bSopenharmony_ci 198beacf11bSopenharmony_ci VnodeHold(); 199beacf11bSopenharmony_ci ret = VnodeLookup(target, &mountpt_vnode, 0); 200beacf11bSopenharmony_ci 201beacf11bSopenharmony_ci /* The mount point must be an existed vnode. */ 202beacf11bSopenharmony_ci 203beacf11bSopenharmony_ci if (ret != OK) 204beacf11bSopenharmony_ci { 205beacf11bSopenharmony_ci PRINT_ERR("Failed to find valid mountpoint %s\n", target); 206beacf11bSopenharmony_ci errcode = -EINVAL; 207beacf11bSopenharmony_ci goto errout_with_lock; 208beacf11bSopenharmony_ci } 209beacf11bSopenharmony_ci if (mountpt_vnode->flag & VNODE_FLAG_MOUNT_NEW) 210beacf11bSopenharmony_ci { 211beacf11bSopenharmony_ci#ifdef LOSCFG_MNT_CONTAINER 212beacf11bSopenharmony_ci struct Mount *tMnt = NULL; 213beacf11bSopenharmony_ci LOS_DL_LIST_FOR_EACH_ENTRY(tMnt, GetMountList(), struct Mount, mountList) 214beacf11bSopenharmony_ci { 215beacf11bSopenharmony_ci if (tMnt->vnodeCovered == mountpt_vnode) 216beacf11bSopenharmony_ci { 217beacf11bSopenharmony_ci PRINT_ERR("can't mount to %s, already mounted.\n", target); 218beacf11bSopenharmony_ci errcode = -EINVAL; 219beacf11bSopenharmony_ci goto errout_with_lock; 220beacf11bSopenharmony_ci } 221beacf11bSopenharmony_ci } 222beacf11bSopenharmony_ci#else 223beacf11bSopenharmony_ci PRINT_ERR("can't mount to %s, already mounted.\n", target); 224beacf11bSopenharmony_ci errcode = -EINVAL; 225beacf11bSopenharmony_ci goto errout_with_lock; 226beacf11bSopenharmony_ci#endif 227beacf11bSopenharmony_ci } 228beacf11bSopenharmony_ci 229beacf11bSopenharmony_ci#ifdef LOSCFG_MNT_CONTAINER 230beacf11bSopenharmony_ci struct Mount *cacheMnt = NULL; 231beacf11bSopenharmony_ci if (source != NULL) 232beacf11bSopenharmony_ci { 233beacf11bSopenharmony_ci LOS_DL_LIST_FOR_EACH_ENTRY(cacheMnt, GetMountCache(), struct Mount, mountList) 234beacf11bSopenharmony_ci { 235beacf11bSopenharmony_ci if (strcmp(cacheMnt->devName, source) == 0) 236beacf11bSopenharmony_ci { 237beacf11bSopenharmony_ci struct Mount *newMnt = (struct Mount *)zalloc(sizeof(struct Mount)); 238beacf11bSopenharmony_ci if (newMnt == NULL) 239beacf11bSopenharmony_ci { 240beacf11bSopenharmony_ci PRINT_ERR("New mount alloc failed no memory!\n"); 241beacf11bSopenharmony_ci errcode = -EINVAL; 242beacf11bSopenharmony_ci goto errout; 243beacf11bSopenharmony_ci } 244beacf11bSopenharmony_ci *newMnt = *cacheMnt; 245beacf11bSopenharmony_ci LOS_ListTailInsert(GetMountList(), &(newMnt->mountList)); 246beacf11bSopenharmony_ci cacheMnt->vnodeCovered->mntCount++; 247beacf11bSopenharmony_ci VnodeDrop(); 248beacf11bSopenharmony_ci return OK; 249beacf11bSopenharmony_ci } 250beacf11bSopenharmony_ci } 251beacf11bSopenharmony_ci } 252beacf11bSopenharmony_ci#endif 253beacf11bSopenharmony_ci /* Bind the block driver to an instance of the file system. The file 254beacf11bSopenharmony_ci * system returns a reference to some opaque, fs-dependent structure 255beacf11bSopenharmony_ci * that encapsulates this binding. 256beacf11bSopenharmony_ci */ 257beacf11bSopenharmony_ci 258beacf11bSopenharmony_ci if (mops->Mount == NULL) 259beacf11bSopenharmony_ci { 260beacf11bSopenharmony_ci /* The filesystem does not support the bind operation ??? */ 261beacf11bSopenharmony_ci 262beacf11bSopenharmony_ci PRINTK("ERROR: Filesystem does not support bind\n"); 263beacf11bSopenharmony_ci errcode = -ENOSYS; 264beacf11bSopenharmony_ci goto errout_with_lock; 265beacf11bSopenharmony_ci } 266beacf11bSopenharmony_ci 267beacf11bSopenharmony_ci /* Increment reference count for the reference we pass to the file system */ 268beacf11bSopenharmony_ci#ifdef LOSCFG_DRIVERS_MTD 269beacf11bSopenharmony_ci if (fsmap->is_mtd_support && (device != NULL)) 270beacf11bSopenharmony_ci { 271beacf11bSopenharmony_ci partition = (mtd_partition *)((struct drv_data *)device->data)->priv; 272beacf11bSopenharmony_ci partition->mountpoint_name = (char *)zalloc(strlen(target) + 1); 273beacf11bSopenharmony_ci if (partition->mountpoint_name == NULL) 274beacf11bSopenharmony_ci { 275beacf11bSopenharmony_ci errcode = -ENOMEM; 276beacf11bSopenharmony_ci goto errout_with_lock; 277beacf11bSopenharmony_ci } 278beacf11bSopenharmony_ci (void)strncpy_s(partition->mountpoint_name, strlen(target) + 1, target, strlen(target)); 279beacf11bSopenharmony_ci partition->mountpoint_name[strlen(target)] = '\0'; 280beacf11bSopenharmony_ci } 281beacf11bSopenharmony_ci#endif 282beacf11bSopenharmony_ci 283beacf11bSopenharmony_ci mnt = MountAlloc(mountpt_vnode, (struct MountOps*)mops); 284beacf11bSopenharmony_ci 285beacf11bSopenharmony_ci#ifdef LOSCFG_FS_ZPFS 286beacf11bSopenharmony_ci if (strcmp(filesystemtype, ZPFS_NAME) == 0) 287beacf11bSopenharmony_ci { 288beacf11bSopenharmony_ci ret = ZpfsPrepare(source, target, mnt); 289beacf11bSopenharmony_ci if (ret < 0) 290beacf11bSopenharmony_ci { 291beacf11bSopenharmony_ci errcode = ret; 292beacf11bSopenharmony_ci goto errout_with_mountpt; 293beacf11bSopenharmony_ci } 294beacf11bSopenharmony_ci } 295beacf11bSopenharmony_ci#endif 296beacf11bSopenharmony_ci 297beacf11bSopenharmony_ci mnt->mountFlags = mountflags; 298beacf11bSopenharmony_ci 299beacf11bSopenharmony_ci mountpt_vnode->useCount++; 300beacf11bSopenharmony_ci ret = mops->Mount(mnt, device, data); 301beacf11bSopenharmony_ci mountpt_vnode->useCount--; 302beacf11bSopenharmony_ci if (ret != 0) 303beacf11bSopenharmony_ci { 304beacf11bSopenharmony_ci /* The vnode is unhappy with the blkdrvr for some reason. Back out 305beacf11bSopenharmony_ci * the count for the reference we failed to pass and exit with an 306beacf11bSopenharmony_ci * error. 307beacf11bSopenharmony_ci */ 308beacf11bSopenharmony_ci 309beacf11bSopenharmony_ci PRINT_ERR("Bind method failed: %d\n", ret); 310beacf11bSopenharmony_ci errcode = ret; 311beacf11bSopenharmony_ci#ifdef LOSCFG_DRIVERS_MTD 312beacf11bSopenharmony_ci if (fsmap->is_mtd_support && (device != NULL) && (partition != NULL)) 313beacf11bSopenharmony_ci { 314beacf11bSopenharmony_ci free(partition->mountpoint_name); 315beacf11bSopenharmony_ci partition->mountpoint_name = NULL; 316beacf11bSopenharmony_ci } 317beacf11bSopenharmony_ci#endif 318beacf11bSopenharmony_ci goto errout_with_mountpt; 319beacf11bSopenharmony_ci } 320beacf11bSopenharmony_ci mnt->vnodeBeCovered->flag |= VNODE_FLAG_MOUNT_ORIGIN; 321beacf11bSopenharmony_ci mnt->vnodeCovered->flag |= VNODE_FLAG_MOUNT_NEW; 322beacf11bSopenharmony_ci mnt->vnodeCovered->filePath = strdup(mountpt_vnode->filePath); 323beacf11bSopenharmony_ci mnt->vnodeDev = device; 324beacf11bSopenharmony_ci mnt->ops = mops; 325beacf11bSopenharmony_ci if (target && (strlen(target) != 0)) 326beacf11bSopenharmony_ci { 327beacf11bSopenharmony_ci ret = strcpy_s(mnt->pathName, PATH_MAX, target); 328beacf11bSopenharmony_ci if (ret != EOK) 329beacf11bSopenharmony_ci { 330beacf11bSopenharmony_ci PRINT_ERR("Failed to copy mount point pathname, errno %d\n", ret); 331beacf11bSopenharmony_ci } 332beacf11bSopenharmony_ci } 333beacf11bSopenharmony_ci 334beacf11bSopenharmony_ci if (source && (strlen(source) != 0)) 335beacf11bSopenharmony_ci { 336beacf11bSopenharmony_ci ret = strcpy_s(mnt->devName, PATH_MAX, source); 337beacf11bSopenharmony_ci if (ret != EOK) 338beacf11bSopenharmony_ci { 339beacf11bSopenharmony_ci PRINT_ERR("Failed to copy dev name, errno %d\n", ret); 340beacf11bSopenharmony_ci } 341beacf11bSopenharmony_ci } 342beacf11bSopenharmony_ci 343beacf11bSopenharmony_ci //* We have it, now populate it with driver specific information. */ 344beacf11bSopenharmony_ci 345beacf11bSopenharmony_ci mount_list = GetMountList(); 346beacf11bSopenharmony_ci LOS_ListAdd(mount_list, &mnt->mountList); 347beacf11bSopenharmony_ci 348beacf11bSopenharmony_ci#ifdef LOSCFG_MNT_CONTAINER 349beacf11bSopenharmony_ci if (source != NULL) 350beacf11bSopenharmony_ci { 351beacf11bSopenharmony_ci struct Mount *newMnt = (struct Mount *)zalloc(sizeof(struct Mount)); 352beacf11bSopenharmony_ci if (newMnt == NULL) 353beacf11bSopenharmony_ci { 354beacf11bSopenharmony_ci PRINT_ERR("New mount alloc failed no memory!\n"); 355beacf11bSopenharmony_ci errcode = -EINVAL; 356beacf11bSopenharmony_ci goto errout; 357beacf11bSopenharmony_ci } 358beacf11bSopenharmony_ci *newMnt = *mnt; 359beacf11bSopenharmony_ci LOS_ListTailInsert(GetMountCache(), &(newMnt->mountList)); 360beacf11bSopenharmony_ci } 361beacf11bSopenharmony_ci#endif 362beacf11bSopenharmony_ci 363beacf11bSopenharmony_ci if (!strcmp("/", target)) 364beacf11bSopenharmony_ci { 365beacf11bSopenharmony_ci ChangeRoot(mnt->vnodeCovered); 366beacf11bSopenharmony_ci } 367beacf11bSopenharmony_ci 368beacf11bSopenharmony_ci VnodeDrop(); 369beacf11bSopenharmony_ci 370beacf11bSopenharmony_ci /* We can release our reference to the blkdrver_vnode, if the filesystem 371beacf11bSopenharmony_ci * wants to retain the blockdriver vnode (which it should), then it must 372beacf11bSopenharmony_ci * have called vnode_addref(). There is one reference on mountpt_vnode 373beacf11bSopenharmony_ci * that will persist until umount() is called. 374beacf11bSopenharmony_ci */ 375beacf11bSopenharmony_ci 376beacf11bSopenharmony_ci return OK; 377beacf11bSopenharmony_ci 378beacf11bSopenharmony_ci /* A lot of goto's! But they make the error handling much simpler */ 379beacf11bSopenharmony_ci 380beacf11bSopenharmony_cierrout_with_mountpt: 381beacf11bSopenharmony_ci if (mnt) 382beacf11bSopenharmony_ci { 383beacf11bSopenharmony_ci free(mnt); 384beacf11bSopenharmony_ci } 385beacf11bSopenharmony_cierrout_with_lock: 386beacf11bSopenharmony_ci VnodeDrop(); 387beacf11bSopenharmony_cierrout: 388beacf11bSopenharmony_ci set_errno(-errcode); 389beacf11bSopenharmony_ci return VFS_ERROR; 390beacf11bSopenharmony_ci} 391beacf11bSopenharmony_ci#endif /* CONFIG_FS_READABLE */ 392