1 /****************************************************************************
2 * fs/driver/fs_closeblockdriver.c
3 *
4 * Licensed to the Apache Software Foundation (ASF) under one or more
5 * contributor license agreements. See the NOTICE file distributed with
6 * this work for additional information regarding copyright ownership. The
7 * ASF licenses this file to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance with the
9 * License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16 * License for the specific language governing permissions and limitations
17 * under the License.
18 *
19 ****************************************************************************/
20
21 /****************************************************************************
22 * Included Files
23 ****************************************************************************/
24
25 #include "fs/driver.h"
26 #include "vfs_config.h"
27 #include "errno.h"
28 #include "vnode.h"
29 #include "disk.h"
30
31 /****************************************************************************
32 * Public Functions
33 ****************************************************************************/
34
35 /****************************************************************************
36 * Name: close_blockdriver
37 *
38 * Description:
39 * Call the close method and release the vnode
40 *
41 * Input Parameters:
42 * vnode - reference to the vnode of a block driver opened by open_blockdriver
43 *
44 * Returned Value:
45 * Returns zero on success or a negated errno on failure:
46 *
47 * EINVAL - vnode is NULL
48 * ENOTBLK - The vnode is not a block driver
49 *
50 ****************************************************************************/
51
close_blockdriver(struct Vnode * vnode_ptr)52 int close_blockdriver(struct Vnode *vnode_ptr)
53 {
54 int ret = 0; /* Assume success */
55 los_part *part = NULL;
56 los_disk *disk = NULL;
57 struct block_operations *bop = NULL;
58
59 /* Sanity checks */
60
61 if (vnode_ptr == NULL || vnode_ptr->data == NULL)
62 {
63 ret = -EINVAL;
64 goto errout;
65 }
66
67 bop = (struct block_operations*)(((struct drv_data*)vnode_ptr->data)->ops);
68
69 if (bop == NULL) {
70 PRINT_ERR("vnode ops is null, not a valid block driver\n");
71 ret = -EINVAL;
72 goto errout;
73 }
74
75 /* Verify that the vnode is a block driver. */
76
77 if (vnode_ptr->type != VNODE_TYPE_BLK)
78 {
79 PRINT_ERR("vnode is not a block driver\n");
80 ret = -ENOTBLK;
81 goto errout;
82 }
83
84
85 part = los_part_find(vnode_ptr);
86 if (part != NULL)
87 {
88 disk = get_disk(part->disk_id);
89 if (disk == NULL)
90 {
91 ret = -EINVAL;
92 goto errout;
93 }
94
95 if (pthread_mutex_lock(&disk->disk_mutex) != ENOERR)
96 {
97 PRINT_ERR("%s %d, mutex lock fail!\n", __FUNCTION__, __LINE__);
98 return -EAGAIN;
99 }
100
101 if (disk->disk_status == STAT_INUSED)
102 {
103 /* Close the block driver. Not that no mutually exclusive access
104 * to the driver is enforced here. That must be done in the driver
105 * if needed.
106 */
107
108 if (bop->close != NULL)
109 {
110 ret = bop->close(vnode_ptr);
111 }
112 }
113
114 if (pthread_mutex_unlock(&disk->disk_mutex) != ENOERR)
115 {
116 PRINT_ERR("%s %d, mutex unlock fail!\n", __FUNCTION__, __LINE__);
117 }
118
119 }
120 else
121 {
122 if (bop->close != NULL)
123 {
124 ret = bop->close(vnode_ptr);
125 }
126 }
127
128 errout:
129 return ret;
130 }
131