summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2008-11-16 01:57:16 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2008-11-16 01:57:16 +0000
commit07d4b44782830707067d8955f8d8a4c69dccbd6f (patch)
tree6548d2d672b122aa2f308463a49f17184f9cdd15
parentfd8cf5088ad9d355baa5bfad15617b0f2459a7a9 (diff)
downloadnuttx-07d4b44782830707067d8955f8d8a4c69dccbd6f.tar.gz
nuttx-07d4b44782830707067d8955f8d8a4c69dccbd6f.tar.bz2
nuttx-07d4b44782830707067d8955f8d8a4c69dccbd6f.zip
Flush dirty cache on close
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@1250 42af7a65-404d-4744-a932-0658087f49c3
-rw-r--r--nuttx/drivers/bch/Make.defs4
-rw-r--r--nuttx/drivers/bch/bch_internal.h2
-rw-r--r--nuttx/drivers/bch/bchdev_driver.c50
-rw-r--r--nuttx/drivers/bch/bchdev_unregister.c18
-rw-r--r--nuttx/drivers/bch/bchlib_cache.c6
-rw-r--r--nuttx/drivers/bch/bchlib_refs.c123
-rw-r--r--nuttx/include/nuttx/fs.h4
7 files changed, 70 insertions, 137 deletions
diff --git a/nuttx/drivers/bch/Make.defs b/nuttx/drivers/bch/Make.defs
index d22d5a2dc..efbfbe2bc 100644
--- a/nuttx/drivers/bch/Make.defs
+++ b/nuttx/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/nuttx/drivers/bch/bch_internal.h b/nuttx/drivers/bch/bch_internal.h
index 5e1e6d0ab..cef8a49b8 100644
--- a/nuttx/drivers/bch/bch_internal.h
+++ b/nuttx/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/nuttx/drivers/bch/bchdev_driver.c b/nuttx/drivers/bch/bchdev_driver.c
index 33e26032f..9f579bbab 100644
--- a/nuttx/drivers/bch/bchdev_driver.c
+++ b/nuttx/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/nuttx/drivers/bch/bchdev_unregister.c b/nuttx/drivers/bch/bchdev_unregister.c
index b71dfd385..7008824a7 100644
--- a/nuttx/drivers/bch/bchdev_unregister.c
+++ b/nuttx/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/nuttx/drivers/bch/bchlib_cache.c b/nuttx/drivers/bch/bchlib_cache.c
index 48b3c80f1..e7ad5e70e 100644
--- a/nuttx/drivers/bch/bchlib_cache.c
+++ b/nuttx/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/nuttx/drivers/bch/bchlib_refs.c b/nuttx/drivers/bch/bchlib_refs.c
deleted file mode 100644
index 43ecf061a..000000000
--- a/nuttx/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/nuttx/include/nuttx/fs.h b/nuttx/include/nuttx/fs.h
index ad979c584..946c60589 100644
--- a/nuttx/include/nuttx/fs.h
+++ b/nuttx/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);