diff --git a/drivers/bch/Make.defs b/drivers/bch/Make.defs index d22d5a2dce0eb19f216bb50a09876c8f44d96c62..efbfbe2bc4113a29703a8b0df3f9db31c117083d 100644 --- a/drivers/bch/Make.defs +++ b/drivers/bch/Make.defs @@ -35,6 +35,6 @@ BCH_ASRCS = BCH_CSRCS = bchlib_setup.c bchlib_teardown.c bchlib_read.c bchlib_write.c \ - bchlib_cache.c bchlib_refs.c bchlib_sem.c bchdev_register.c \ - bchdev_unregister.c bchdev_driver.c + bchlib_cache.c bchlib_sem.c bchdev_register.c bchdev_unregister.c \ + bchdev_driver.c diff --git a/drivers/bch/bch_internal.h b/drivers/bch/bch_internal.h index 5e1e6d0aba462e828c05a0e42bdd7a3868a96f11..cef8a49b80f9ad399fc219bbacbf41dd1869dbbb 100644 --- a/drivers/bch/bch_internal.h +++ b/drivers/bch/bch_internal.h @@ -88,8 +88,6 @@ EXTERN struct file_operations bch_fops; ****************************************************************************/ EXTERN void bchlib_semtake(FAR struct bchlib_s *bch); -EXTERN int bchlib_incref(FAR struct bchlib_s *bch); -EXTERN int bchlib_decref(FAR struct bchlib_s *bch); EXTERN int bchlib_flushsector(FAR struct bchlib_s *bch); EXTERN int bchlib_readsector(FAR struct bchlib_s *bch, size_t sector); diff --git a/drivers/bch/bchdev_driver.c b/drivers/bch/bchdev_driver.c index 33e26032fc9577f924e0a2360d3e31372168684d..9f579bbab416882b57977a494a1d6a7bd5506b24 100644 --- a/drivers/bch/bchdev_driver.c +++ b/drivers/bch/bchdev_driver.c @@ -102,9 +102,26 @@ struct file_operations bch_fops = static int bch_open(FAR struct file *filp) { FAR struct inode *inode = filp->f_inode; + FAR struct bchlib_s *bch; + int ret; DEBUGASSERT(inode && inode->i_private); - return bchlib_incref((FAR struct bchlib_s *)inode->i_private); + bch = (FAR struct bchlib_s *)inode->i_private; + + /* Increment the reference count */ + + bchlib_semtake(bch); + if (bch->refs == MAX_OPENCNT) + { + return -EMFILE; + } + else + { + bch->refs++; + } + bchlib_semgive(bch); + + return ret; } /**************************************************************************** @@ -117,9 +134,32 @@ static int bch_open(FAR struct file *filp) static int bch_close(FAR struct file *filp) { FAR struct inode *inode = filp->f_inode; + FAR struct bchlib_s *bch; + int ret; DEBUGASSERT(inode && inode->i_private); - return bchlib_decref((FAR struct bchlib_s *)inode->i_private); + bch = (FAR struct bchlib_s *)inode->i_private; + + /* Flush any dirty pages remaining in the cache */ + + bchlib_semtake(bch); + (void)bchlib_flushsector(bch); + + /* Decrement the reference count (I don't use bchlib_decref() because I + * want the entire close operation to be atomic wrt other driver operations. + */ + + if (bch->refs == 0) + { + ret = -EIO; + } + else + { + bch->refs--; + } + bchlib_semgive(bch); + + return ret; } /**************************************************************************** @@ -192,15 +232,17 @@ static int bch_ioctl(FAR struct file *filp, int cmd, unsigned long arg) { FAR struct bchlib_s **bchr = (FAR struct bchlib_s **)arg; - if (!bchr) + bchlib_semtake(bch); + if (!bchr && bch->refs < 255) { ret = -EINVAL; } else { - ret = bchlib_incref(bch); + bch->refs++; *bchr = bch; } + bchlib_semgive(bch); } return ret; diff --git a/drivers/bch/bchdev_unregister.c b/drivers/bch/bchdev_unregister.c index b71dfd385f63cd2db4669db4ec3b62086d123dba..7008824a7019b7b9b9b66b7343b7afb60c05eaa6 100644 --- a/drivers/bch/bchdev_unregister.c +++ b/drivers/bch/bchdev_unregister.c @@ -111,7 +111,9 @@ int bchdev_unregister(const char *chardev) return ret; } - /* Get a reference to the internal data structure */ + /* Get a reference to the internal data structure. On success, we + * will hold a reference count on the state structure. + */ ret = ioctl(fd, DIOC_GETPRIV, (unsigned long)&bch); (void)close(fd); @@ -122,11 +124,14 @@ int bchdev_unregister(const char *chardev) return -errno; } - /* Lock out context switches */ + /* Lock out context switches. If there are no other references + * and no context switches, then we can assume that we can safely + * teardown the driver. + */ sched_lock(); - /* Check if the internal structure is non-busy (we hold one reference) */ + /* Check if the internal structure is non-busy (we hold one reference). */ if (bch->refs > 1) { @@ -134,7 +139,10 @@ int bchdev_unregister(const char *chardev) goto errout_with_lock; } - /* Unregister the driver (this cannot suspend) */ + /* Unregister the driver (this cannot suspend or we lose our non-preemptive + * state!). Once the driver is successfully unregistered, we can assume + * we have exclusive access to the state instance. + */ ret = unregister_driver(chardev); if (ret < 0) @@ -149,7 +157,7 @@ int bchdev_unregister(const char *chardev) return bchlib_teardown(bch); errout_with_lock: + bch->refs--; sched_unlock(); - bchlib_decref(bch); return ret; } diff --git a/drivers/bch/bchlib_cache.c b/drivers/bch/bchlib_cache.c index 48b3c80f19df3e50d05566770fd2852d5991d837..e7ad5e70ebada5d0e24647938724fc10faf272f6 100644 --- a/drivers/bch/bchlib_cache.c +++ b/drivers/bch/bchlib_cache.c @@ -79,6 +79,9 @@ * Description: * Flush the current contents of the sector buffer (if dirty) * + * Assumptions: + * Caller must assume mutual exclusion + * ****************************************************************************/ int bchlib_flushsector(FAR struct bchlib_s *bch) @@ -105,6 +108,9 @@ int bchlib_flushsector(FAR struct bchlib_s *bch) * Description: * Flush the current contents of the sector buffer (if dirty) * + * Assumptions: + * Caller must assume mutual exclusion + * ****************************************************************************/ int bchlib_readsector(FAR struct bchlib_s *bch, size_t sector) diff --git a/drivers/bch/bchlib_refs.c b/drivers/bch/bchlib_refs.c deleted file mode 100644 index 43ecf061adc3915dd3ac44e4d390314a33d81a5d..0000000000000000000000000000000000000000 --- a/drivers/bch/bchlib_refs.c +++ /dev/null @@ -1,123 +0,0 @@ -/**************************************************************************** - * drivers/bch/bchlib_refs.c - * - * Copyright (C) 2008 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt <spudmonkey@racsa.co.cr> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name NuttX nor the names of its contributors may be - * used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************/ - -/**************************************************************************** - * Compilation Switches - ****************************************************************************/ - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include <nuttx/config.h> - -#include <sys/types.h> -#if 0 -#include <sys/stat.h> -#include <sys/ioctl.h> - -#include <unistd.h> -#include <string.h> -#include <fcntl.h> -#include <sched.h> - -#include <nuttx/fs.h> -#include <nuttx/ioctl.h> -#endif - -#include <semaphore.h> -#include <errno.h> -#include <assert.h> -#include <debug.h> - -#include "bch_internal.h" - -/**************************************************************************** - * Definitions - ****************************************************************************/ - -/**************************************************************************** - * Private Function Prototypes - ****************************************************************************/ - -/**************************************************************************** - * Public Data - ****************************************************************************/ - -/**************************************************************************** - * Private Functions - ****************************************************************************/ - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: bchlib_incref - ****************************************************************************/ - -int bchlib_incref(FAR struct bchlib_s *bch) -{ - bchlib_semtake(bch); - if (bch->refs == MAX_OPENCNT) - { - return -EMFILE; - } - else - { - bch->refs++; - } - bchlib_semgive(bch); - return OK; -} - -/**************************************************************************** - * Name: bchlib_decref - ****************************************************************************/ - -int bchlib_decref(FAR struct bchlib_s *bch) -{ - bchlib_semtake(bch); - if (bch->refs == 0) - { - return -EIO; - } - else - { - bch->refs--; - } - bchlib_semgive(bch); - return OK; -} diff --git a/include/nuttx/fs.h b/include/nuttx/fs.h index ad979c5849daa4c89f9fa94033eefc1aec653a78..946c605895905e72e4eba390ee43f971e25dba25 100644 --- a/include/nuttx/fs.h +++ b/include/nuttx/fs.h @@ -392,7 +392,9 @@ EXTERN int loteardown(const char *devname); EXTERN int bchdev_register(const char *blkdev, const char *chardev, boolean readonly); EXTERN int bchdev_unregister(const char *chardev); -/* Low level, direct access: */ +/* Low level, direct access. NOTE: low-level access and character driver access + * are incompatible. One and only one access method should be implemented. + */ EXTERN int bchlib_setup(const char *blkdev, boolean readonly, FAR void **handle); EXTERN int bchlib_teardown(FAR void *handle);