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 49int 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 117errout_with_lock: 118 bch->refs--; 119 LOS_TaskUnlock(); 120 return ret; 121} 122