1beacf11bSopenharmony_ci/****************************************************************************
2beacf11bSopenharmony_ci * fs/driver/fs_openblockdriver.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#include "errno.h"
27beacf11bSopenharmony_ci#include "fs/driver.h"
28beacf11bSopenharmony_ci#include "vnode.h"
29beacf11bSopenharmony_ci#include "disk.h"
30beacf11bSopenharmony_ci#include <linux/kernel.h>
31beacf11bSopenharmony_ci
32beacf11bSopenharmony_ci/****************************************************************************
33beacf11bSopenharmony_ci * Public Functions
34beacf11bSopenharmony_ci ****************************************************************************/
35beacf11bSopenharmony_ci
36beacf11bSopenharmony_ci/****************************************************************************
37beacf11bSopenharmony_ci * Name: open_blockdriver
38beacf11bSopenharmony_ci *
39beacf11bSopenharmony_ci * Description:
40beacf11bSopenharmony_ci *   Return the vnode of the block driver specified by 'pathname'
41beacf11bSopenharmony_ci *
42beacf11bSopenharmony_ci * Input Parameters:
43beacf11bSopenharmony_ci *   pathname - the full path to the block driver to be opened
44beacf11bSopenharmony_ci *   mountflags - if MS_RDONLY is not set, then driver must support write
45beacf11bSopenharmony_ci *     operations (see include/sys/mount.h)
46beacf11bSopenharmony_ci *   ppvnode - address of the location to return the vnode reference
47beacf11bSopenharmony_ci *
48beacf11bSopenharmony_ci * Returned Value:
49beacf11bSopenharmony_ci *   Returns zero on success or a negated errno on failure:
50beacf11bSopenharmony_ci *
51beacf11bSopenharmony_ci *   EINVAL  - pathname or pvnode is NULL
52beacf11bSopenharmony_ci *   ENOENT  - No block driver of this name is registered
53beacf11bSopenharmony_ci *   ENOTBLK - The vnode associated with the pathname is not a block driver
54beacf11bSopenharmony_ci *   EACCESS - The MS_RDONLY option was not set but this driver does not
55beacf11bSopenharmony_ci *     support write access
56beacf11bSopenharmony_ci *
57beacf11bSopenharmony_ci ****************************************************************************/
58beacf11bSopenharmony_ci
59beacf11bSopenharmony_ci
60beacf11bSopenharmony_ciextern int find_blockdriver(const char *pathname, int mountflags, struct Vnode **vpp);
61beacf11bSopenharmony_ci
62beacf11bSopenharmony_ciint open_blockdriver(const char *pathname, int mountflags,
63beacf11bSopenharmony_ci                     struct Vnode **ppvnode)
64beacf11bSopenharmony_ci{
65beacf11bSopenharmony_ci  struct Vnode *vnode_ptr = NULL;
66beacf11bSopenharmony_ci  los_part *part = NULL;
67beacf11bSopenharmony_ci  los_disk *disk = NULL;
68beacf11bSopenharmony_ci  int ret;
69beacf11bSopenharmony_ci
70beacf11bSopenharmony_ci  /* Minimal sanity checks */
71beacf11bSopenharmony_ci
72beacf11bSopenharmony_ci#ifdef CONFIG_DEBUG
73beacf11bSopenharmony_ci  if (ppvnode == NULL)
74beacf11bSopenharmony_ci    {
75beacf11bSopenharmony_ci      ret = -EINVAL;
76beacf11bSopenharmony_ci      goto errout;
77beacf11bSopenharmony_ci    }
78beacf11bSopenharmony_ci#endif
79beacf11bSopenharmony_ci
80beacf11bSopenharmony_ci  /* Find the vnode associated with this block driver name.  find_blockdriver
81beacf11bSopenharmony_ci   * will perform all additional error checking.
82beacf11bSopenharmony_ci   */
83beacf11bSopenharmony_ci
84beacf11bSopenharmony_ci  ret = find_blockdriver(pathname, mountflags, &vnode_ptr);
85beacf11bSopenharmony_ci  if (ret < 0)
86beacf11bSopenharmony_ci    {
87beacf11bSopenharmony_ci      PRINT_DEBUG("Failed to file %s block driver\n", pathname);
88beacf11bSopenharmony_ci      goto errout;
89beacf11bSopenharmony_ci    }
90beacf11bSopenharmony_ci
91beacf11bSopenharmony_ci  /* Open the block driver.  Note that no mutually exclusive access
92beacf11bSopenharmony_ci   * to the driver is enforced here.  That must be done in the driver
93beacf11bSopenharmony_ci   * if needed.
94beacf11bSopenharmony_ci   */
95beacf11bSopenharmony_ci
96beacf11bSopenharmony_ci  struct drv_data* drv = (struct drv_data*)vnode_ptr->data;
97beacf11bSopenharmony_ci  struct block_operations *ops = (struct block_operations *)drv->ops;
98beacf11bSopenharmony_ci
99beacf11bSopenharmony_ci  part = los_part_find(vnode_ptr);
100beacf11bSopenharmony_ci  if (part != NULL)
101beacf11bSopenharmony_ci    {
102beacf11bSopenharmony_ci      disk = get_disk(part->disk_id);
103beacf11bSopenharmony_ci      if (disk == NULL)
104beacf11bSopenharmony_ci        {
105beacf11bSopenharmony_ci          ret = -EINVAL;
106beacf11bSopenharmony_ci          goto errout_with_vnode;
107beacf11bSopenharmony_ci        }
108beacf11bSopenharmony_ci
109beacf11bSopenharmony_ci      if (pthread_mutex_lock(&disk->disk_mutex) != ENOERR)
110beacf11bSopenharmony_ci        {
111beacf11bSopenharmony_ci          PRINT_ERR("%s %d, mutex lock fail!\n", __FUNCTION__, __LINE__);
112beacf11bSopenharmony_ci          return -1;
113beacf11bSopenharmony_ci        }
114beacf11bSopenharmony_ci      if (disk->disk_status == STAT_INUSED)
115beacf11bSopenharmony_ci        {
116beacf11bSopenharmony_ci
117beacf11bSopenharmony_ci          if (ops->open != NULL)
118beacf11bSopenharmony_ci            {
119beacf11bSopenharmony_ci              ret = ops->open(vnode_ptr);
120beacf11bSopenharmony_ci              if (ret < 0)
121beacf11bSopenharmony_ci                {
122beacf11bSopenharmony_ci                  PRINT_DEBUG("%s driver open failed\n", pathname);
123beacf11bSopenharmony_ci                  (void)pthread_mutex_unlock(&disk->disk_mutex);
124beacf11bSopenharmony_ci                  goto errout_with_vnode;
125beacf11bSopenharmony_ci                }
126beacf11bSopenharmony_ci            }
127beacf11bSopenharmony_ci         }
128beacf11bSopenharmony_ci
129beacf11bSopenharmony_ci      if (pthread_mutex_unlock(&disk->disk_mutex) != ENOERR)
130beacf11bSopenharmony_ci        {
131beacf11bSopenharmony_ci          PRINT_ERR("%s %d, mutex unlock fail!\n", __FUNCTION__, __LINE__);
132beacf11bSopenharmony_ci          return -1;
133beacf11bSopenharmony_ci        }
134beacf11bSopenharmony_ci
135beacf11bSopenharmony_ci    }
136beacf11bSopenharmony_ci  else
137beacf11bSopenharmony_ci    {
138beacf11bSopenharmony_ci      if (ops->open != NULL)
139beacf11bSopenharmony_ci        {
140beacf11bSopenharmony_ci          ret = ops->open(vnode_ptr);
141beacf11bSopenharmony_ci          if (ret < 0)
142beacf11bSopenharmony_ci            {
143beacf11bSopenharmony_ci              PRINT_DEBUG("%s driver open failed\n", pathname);
144beacf11bSopenharmony_ci              goto errout_with_vnode;
145beacf11bSopenharmony_ci            }
146beacf11bSopenharmony_ci        }
147beacf11bSopenharmony_ci    }
148beacf11bSopenharmony_ci
149beacf11bSopenharmony_ci  *ppvnode = vnode_ptr;
150beacf11bSopenharmony_ci  return OK;
151beacf11bSopenharmony_ci
152beacf11bSopenharmony_cierrout_with_vnode:
153beacf11bSopenharmony_cierrout:
154beacf11bSopenharmony_ci  return ret;
155beacf11bSopenharmony_ci}
156