summaryrefslogtreecommitdiff
path: root/nuttx/drivers
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2015-02-01 07:24:16 -0600
committerGregory Nutt <gnutt@nuttx.org>2015-02-01 07:24:16 -0600
commit55d5b35fffeba4221eafe5e161319088b92e12e1 (patch)
tree60a002fe1a1412a21c20119d70e1e3516ef71952 /nuttx/drivers
parent9dd15e33285b1d81984d346223ad7483c246a7a9 (diff)
downloadpx4-nuttx-55d5b35fffeba4221eafe5e161319088b92e12e1.tar.gz
px4-nuttx-55d5b35fffeba4221eafe5e161319088b92e12e1.tar.bz2
px4-nuttx-55d5b35fffeba4221eafe5e161319088b92e12e1.zip
drivers/ramdisk.c and include/nuttx/fs/ramdisk.h: Add logic to dispose of the drvier and RAM buffer when the RAM disk has been unlinked and all open references to the RAM disk have been closed. Add new parameters to romdisk() to specify what should be done with the RAM/ROM buffer -- Should it be freed or not? Changed all calls to ramdisk() to use these new parameters.
Diffstat (limited to 'nuttx/drivers')
-rw-r--r--nuttx/drivers/ramdisk.c183
1 files changed, 151 insertions, 32 deletions
diff --git a/nuttx/drivers/ramdisk.c b/nuttx/drivers/ramdisk.c
index ee45aaf05..4c9a1405d 100644
--- a/nuttx/drivers/ramdisk.c
+++ b/nuttx/drivers/ramdisk.c
@@ -54,22 +54,37 @@
#include <nuttx/fs/ramdisk.h>
/****************************************************************************
- * Private Definitions
+ * Pre-processor Definitions
****************************************************************************/
+/* Helpers for rdflags */
+
+/* User input flags */
+
+#define RDFLAG_USER (RDFLAG_WRENABLED | RDFLAG_FUNLINK)
+
+#define RDFLAG_IS_WRENABLED(f) (((f) & RDFLAG_WRENABLED) != 0)
+#define RDFLAG_IS_FUNLINK(f) (((f) & RDFLAG_WRENABLED) != 0)
+
+/* Flag set when the RAM disk block driver is unlink */
+
+#define RDFLAG_UNLINK(f) do { (f) |= RDFLAG_UNLINKED; } while (0)
+#define RDFLAG_IS_UNLINKED(f) (((f) & RDFLAG_UNLINKED) != 0)
+
/****************************************************************************
* Private Types
****************************************************************************/
struct rd_struct_s
{
- uint32_t rd_nsectors; /* Number of sectors on device */
- uint16_t rd_sectsize; /* The size of one sector */
+ uint32_t rd_nsectors; /* Number of sectors on device */
+ uint16_t rd_sectsize; /* The size of one sector */
+ uint8_t rd_crefs; /* Open reference count */
+ uint8_t rd_flags; /* See RDFLAG_* definitions */
#ifdef CONFIG_FS_WRITABLE
- bool rd_writeenabled; /* true: can write to ram disk */
- uint8_t *rd_buffer; /* RAM disk backup memory */
+ FAR uint8_t *rd_buffer; /* RAM disk backup memory */
#else
- const uint8_t *rd_buffer; /* ROM disk backup memory */
+ FAR const uint8_t *rd_buffer; /* ROM disk backup memory */
#endif
};
@@ -77,16 +92,22 @@ struct rd_struct_s
* Private Function Prototypes
****************************************************************************/
+static void rd_destroy(FAR struct rd_struct_s *dev);
+
static int rd_open(FAR struct inode *inode);
static int rd_close(FAR struct inode *inode);
-static ssize_t rd_read(FAR struct inode *inode, unsigned char *buffer,
- size_t start_sector, unsigned int nsectors);
+static ssize_t rd_read(FAR struct inode *inode, FAR unsigned char *buffer,
+ size_t start_sector, unsigned int nsectors);
#ifdef CONFIG_FS_WRITABLE
-static ssize_t rd_write(FAR struct inode *inode, const unsigned char *buffer,
- size_t start_sector, unsigned int nsectors);
+static ssize_t rd_write(FAR struct inode *inode,
+ FAR const unsigned char *buffer, size_t start_sector,
+ unsigned int nsectors);
#endif
-static int rd_geometry(FAR struct inode *inode, struct geometry *geometry);
-static int rd_ioctl(FAR struct inode *inode, int cmd, unsigned long arg);
+static int rd_geometry(FAR struct inode *inode,
+ FAR struct geometry *geometry);
+static int rd_ioctl(FAR struct inode *inode, int cmd,
+ unsigned long arg);
+static int rd_unlink(FAR struct inode *inode);
/****************************************************************************
* Private Data
@@ -103,7 +124,8 @@ static const struct block_operations g_bops =
NULL, /* write */
#endif
rd_geometry, /* geometry */
- rd_ioctl /* ioctl */
+ rd_ioctl, /* ioctl */
+ rd_unlink /* unlink */
};
/****************************************************************************
@@ -111,6 +133,25 @@ static const struct block_operations g_bops =
****************************************************************************/
/****************************************************************************
+ * Name: rd_destroy
+ *
+ * Description:
+ * Free all resources used by the RAM disk
+ *
+ ****************************************************************************/
+
+static void rd_destroy(FAR struct rd_struct_s *dev)
+{
+ /* And free the dev structure.
+ * REVISIT: This is not very helpful. What we really need to know
+ * is if we can free the RAM disk memory; that is the major resource
+ * consumed by this driver. But we do not know if we can or should.
+ */
+
+ kmm_free(dev);
+}
+
+/****************************************************************************
* Name: rd_open
*
* Description: Open the block device
@@ -119,12 +160,22 @@ static const struct block_operations g_bops =
static int rd_open(FAR struct inode *inode)
{
- fvdbg("Entry\n");
+ FAR struct rd_struct_s *dev;
+
+ DEBUGASSERT(inode && inode->i_private);
+ dev = (FAR struct rd_struct_s *)inode->i_private;
+
+ /* Increment the open reference count */
+
+ dev->rd_crefs++;
+ DEBUGASSERT(dev->rd_crefs > 0);
+
+ fvdbg("rd_crefs: %d\n", dev->rd_crefs);
return OK;
}
/****************************************************************************
- * Name: rd_closel
+ * Name: rd_close
*
* Description: close the block device
*
@@ -132,7 +183,31 @@ static int rd_open(FAR struct inode *inode)
static int rd_close(FAR struct inode *inode)
{
- fvdbg("Entry\n");
+ FAR struct rd_struct_s *dev;
+
+ DEBUGASSERT(inode && inode->i_private);
+ dev = (FAR struct rd_struct_s *)inode->i_private;
+
+ /* Increment the open reference count */
+
+ DEBUGASSERT(dev->rd_crefs > 0);
+ dev->rd_crefs--;
+ fvdbg("rd_crefs: %d\n", dev->rd_crefs);
+
+ /* Was that the last open reference to the RAM disk? */
+
+ if (dev->rd_crefs == 0)
+ {
+ /* Yes.. Have we been unlinked? */
+
+ if (RDFLAG_IS_UNLINKED(dev->rd_flags))
+ {
+ /* Yes.. Release all of the RAM disk resources */
+
+ rd_destroy(dev);
+ }
+ }
+
return OK;
}
@@ -146,10 +221,10 @@ static int rd_close(FAR struct inode *inode)
static ssize_t rd_read(FAR struct inode *inode, unsigned char *buffer,
size_t start_sector, unsigned int nsectors)
{
- struct rd_struct_s *dev;
+ FAR struct rd_struct_s *dev;
DEBUGASSERT(inode && inode->i_private);
- dev = (struct rd_struct_s *)inode->i_private;
+ dev = (FAR struct rd_struct_s *)inode->i_private;
fvdbg("sector: %d nsectors: %d sectorsize: %d\n",
start_sector, dev->rd_sectsize, nsectors);
@@ -189,7 +264,7 @@ static ssize_t rd_write(FAR struct inode *inode, const unsigned char *buffer,
fvdbg("sector: %d nsectors: %d sectorsize: %d\n",
start_sector, dev->rd_sectsize, nsectors);
- if (!dev->rd_writeenabled)
+ if (!RDFLAG_IS_WRENABLED(dev->rd_flags))
{
return -EACCES;
}
@@ -230,7 +305,7 @@ static int rd_geometry(FAR struct inode *inode, struct geometry *geometry)
geometry->geo_available = true;
geometry->geo_mediachanged = false;
#ifdef CONFIG_FS_WRITABLE
- geometry->geo_writeenabled = dev->rd_writeenabled;
+ geometry->geo_writeenabled = RDFLAG_IS_WRENABLED(dev->rd_flags);
#else
geometry->geo_writeenabled = false;
#endif
@@ -251,14 +326,15 @@ static int rd_geometry(FAR struct inode *inode, struct geometry *geometry)
/****************************************************************************
* Name: rd_ioctl
*
- * Description: Return device geometry
+ * Description:
+ * Return device geometry
*
****************************************************************************/
static int rd_ioctl(FAR struct inode *inode, int cmd, unsigned long arg)
{
- struct rd_struct_s *dev ;
- void **ppv = (void**)((uintptr_t)arg);
+ FAR struct rd_struct_s *dev;
+ FAR void **ppv = (void**)((uintptr_t)arg);
fvdbg("Entry\n");
@@ -267,8 +343,8 @@ static int rd_ioctl(FAR struct inode *inode, int cmd, unsigned long arg)
DEBUGASSERT(inode && inode->i_private);
if (cmd == BIOC_XIPBASE && ppv)
{
- dev = (struct rd_struct_s *)inode->i_private;
- *ppv = (void*)dev->rd_buffer;
+ dev = (FAR struct rd_struct_s *)inode->i_private;
+ *ppv = (FAR void *)dev->rd_buffer;
fvdbg("ppv: %p\n", *ppv);
return OK;
@@ -278,19 +354,61 @@ static int rd_ioctl(FAR struct inode *inode, int cmd, unsigned long arg)
}
/****************************************************************************
+ * Name: rd_unlink
+ *
+ * Description:
+ * The block driver has been unlinked.
+ *
+ ****************************************************************************/
+
+static int rd_unlink(FAR struct inode *inode)
+{
+ FAR struct rd_struct_s *dev;
+
+ DEBUGASSERT(inode && inode->i_private);
+ dev = (FAR struct rd_struct_s *)inode->i_private;
+
+ /* Mark the pipe unlinked */
+
+ RDFLAG_UNLINK(dev->rd_flags);
+
+ /* Are the any open references to the driver? */
+
+ if (dev->rd_crefs == 0)
+ {
+ /* No... release all resources held by the block driver */
+
+ rd_destroy(dev);
+ }
+
+ return OK;
+}
+
+/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
- * Name: ramdisk_register
+ * Name: ramdisk_register or romdisk_register
+ *
+ * Description:
+ * Non-standard function to register a ramdisk or a romdisk
+ *
+ * Input Parmeters:
+ * minor: Selects suffix of device named /dev/ramN, N={1,2,3...}
+ * nsectors: Number of sectors on device
+ * sectize: The size of one sector
+ * rdflags: See RDFLAG_* definitions
+ * buffer: RAM disk backup memory
+ *
+ * Returned Valued:
+ * Zero on success; a negated errno value on failure.
*
- * Description: Register the a ramdisk
-
****************************************************************************/
#ifdef CONFIG_FS_WRITABLE
int ramdisk_register(int minor, uint8_t *buffer, uint32_t nsectors,
- uint16_t sectsize, bool writeenabled)
+ uint16_t sectsize, uint8_t rdflags)
#else
int romdisk_register(int minor, uint8_t *buffer, uint32_t nsectors,
uint16_t sectsize)
@@ -313,17 +431,18 @@ int romdisk_register(int minor, uint8_t *buffer, uint32_t nsectors,
/* Allocate a ramdisk device structure */
- dev = (struct rd_struct_s *)kmm_malloc(sizeof(struct rd_struct_s));
+ dev = (struct rd_struct_s *)kmm_zalloc(sizeof(struct rd_struct_s));
if (dev)
{
/* Initialize the ramdisk device structure */
dev->rd_nsectors = nsectors; /* Number of sectors on device */
dev->rd_sectsize = sectsize; /* The size of one sector */
+ dev->rd_buffer = buffer; /* RAM disk backup memory */
+
#ifdef CONFIG_FS_WRITABLE
- dev->rd_writeenabled = writeenabled; /* true: can write to ram disk */
+ dev->rd_flags = rdflags & RDFLAG_USER;
#endif
- dev->rd_buffer = buffer; /* RAM disk backup memory */
/* Create a ramdisk device name */