1 /****************************************************************************
2 * drivers/bch/bchdev_unregister.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 #include <sys/stat.h>
25 #include <unistd.h>
26 #include <fcntl.h>
27 #include <sched.h>
28 #include <errno.h>
29 #include <assert.h>
30 #include <sys/ioctl.h>
31 #include "bch.h"
32 #include "fs/driver.h"
33
34 #define _err PRINTK
35
36 /****************************************************************************
37 * Public Functions
38 ****************************************************************************/
39
40 /****************************************************************************
41 * Name: bchdev_unregister
42 *
43 * Description:
44 * Unregister character driver access to a block device that was created
45 * by a previous call to bchdev_register().
46 *
47 ****************************************************************************/
48
bchdev_unregister(const char * chardev)49 int bchdev_unregister(const char *chardev)
50 {
51 struct bchlib_s *bch;
52 int fd;
53 int ret;
54
55 /* Sanity check */
56
57 if (!chardev)
58 {
59 return -EINVAL;
60 }
61
62 /* Open the character driver associated with chardev */
63
64 fd = open(chardev, O_RDONLY);
65 if (fd < 0)
66 {
67 _err("ERROR: Failed to open %s: %d\n", chardev, errno);
68 return -errno;
69 }
70
71 /* Get a reference to the internal data structure. On success, we
72 * will hold a reference count on the state structure.
73 */
74
75 ret = ioctl(fd, DIOC_GETPRIV, (unsigned long)((uintptr_t)&bch));
76 (void)close(fd);
77
78 if (ret < 0)
79 {
80 _err("ERROR: ioctl failed: %d\n", errno);
81 return -errno;
82 }
83
84 /* Lock out context switches. If there are no other references
85 * and no context switches, then we can assume that we can safely
86 * teardown the driver.
87 */
88
89 LOS_TaskLock();
90
91 /* Check if the internal structure is non-busy (we hold one reference). */
92
93 if (bch->refs > 1)
94 {
95 ret = -EBUSY;
96 goto errout_with_lock;
97 }
98
99 /* Unregister the driver (this cannot suspend or we lose our non-preemptive
100 * state!). Once the driver is successfully unregistered, we can assume
101 * we have exclusive access to the state instance.
102 */
103
104 ret = unregister_driver(chardev);
105 if (ret < 0)
106 {
107 goto errout_with_lock;
108 }
109
110 LOS_TaskUnlock();
111
112 /* Release the internal structure */
113
114 bch->refs = 0;
115 return bchlib_teardown(bch);
116
117 errout_with_lock:
118 bch->refs--;
119 LOS_TaskUnlock();
120 return ret;
121 }
122