9
0
Fork 0

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.

This commit is contained in:
Gregory Nutt 2015-02-01 07:24:16 -06:00
parent 9dd15e3328
commit 55d5b35fff
9 changed files with 269 additions and 135 deletions

View File

@ -1,7 +1,7 @@
/****************************************************************************
* examples/mount/ramdisk.c
*
* Copyright (C) 2008-2009 Gregory Nutt. All rights reserved.
* Copyright (C) 2008-2009, 2015 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -116,7 +116,7 @@ int create_ramdisk(void)
(FAR uint8_t *)pbuffer,
CONFIG_EXAMPLES_MOUNT_NSECTORS,
CONFIG_EXAMPLES_MOUNT_SECTORSIZE,
true);
RDFLAG_WRENABLED | RDFLAG_FUNLINK);
if (ret < 0)
{
printf("create_ramdisk: Failed to register ramdisk at %s: %d\n",

View File

@ -1250,7 +1250,8 @@ int cmd_mkrd(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
/* Then register the ramdisk */
ret = ramdisk_register(minor, buffer, nsectors, sectsize, true);
ret = ramdisk_register(minor, buffer, nsectors, sectsize,
RDFLAG_WRENABLED | RDFLAG_FUNLINK);
if (ret < 0)
{
nsh_output(vtbl, g_fmtcmdfailed, argv[0], "ramdisk_register", NSH_ERRNO_OF(-ret));

View File

@ -1,7 +1,7 @@
/****************************************************************************
* arch/sim/src/up_blockdevice.c
*
* Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2009, 2015 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -84,5 +84,6 @@
void up_registerblockdevice(void)
{
ramdisk_register(0, (uint8_t*)up_deviceimage(), NSECTORS, LOGICAL_SECTOR_SIZE, true);
ramdisk_register(0, (uint8_t*)up_deviceimage(), NSECTORS,
LOGICAL_SECTOR_SIZE, RDFLAG_WRENABLED | RDFLAG_FUNLINK);
}

View File

@ -1,7 +1,7 @@
/****************************************************************************
* arch/sim/src/up_deviceimage.c
*
* Copyright (C) 2007, 2009, 2014 Gregory Nutt. All rights reserved.
* Copyright (C) 2007, 2009, 2014-2015 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -207,107 +207,111 @@ static const unsigned char g_vfatdata[] =
char *up_deviceimage(void)
{
char *pbuffer;
int bufsize = 1024*1024;
int offset = 0;
z_stream strm;
int ret;
char *pbuffer;
int bufsize = 1024*1024;
int offset = 0;
z_stream strm;
int ret;
/* Ininitilize inflate state */
/* Initialize inflate state */
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.avail_in = 0;
strm.next_in = Z_NULL;
ret = inflateInit(&strm);
if (ret != Z_OK)
{
sdbg("inflateInit FAILED: ret=%d msg=\"%s\"\n", ret, strm.msg ? strm.msg : "No message" );
return NULL;
}
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.avail_in = 0;
strm.next_in = Z_NULL;
ret = inflateInit(&strm);
if (ret != Z_OK)
{
sdbg("inflateInit FAILED: ret=%d msg=\"%s\"\n",
ret, strm.msg ? strm.msg : "No message" );
return NULL;
}
/* Allocate a buffer to hold the decompressed buffer. We may have
* to reallocate this a few times to get the size right.
*/
/* Allocate a buffer to hold the decompressed buffer. We may have to
* reallocate this a few times to get the size right.
*/
pbuffer = (char*)kmm_malloc(bufsize);
pbuffer = (char*)kmm_malloc(bufsize);
/* Set up the input buffer */
/* Set up the input buffer */
strm.avail_in = sizeof(g_vfatdata);
strm.next_in = (Bytef*)g_vfatdata;
strm.avail_in = sizeof(g_vfatdata);
strm.next_in = (Bytef*)g_vfatdata;
/* Run inflate() on input until output buffer not full */
/* Run inflate() on input until output buffer not full */
do {
/* Set up to catch the next output chunk in the output buffer */
do
{
/* Set up to catch the next output chunk in the output buffer */
strm.avail_out = bufsize - offset;
strm.next_out = (Bytef*)&pbuffer[offset];
strm.avail_out = bufsize - offset;
strm.next_out = (Bytef*)&pbuffer[offset];
/* inflate */
/* inflate */
ret = inflate(&strm, Z_NO_FLUSH);
ret = inflate(&strm, Z_NO_FLUSH);
/* Handle inflate() error return values */
/* Handle inflate() error return values */
switch (ret)
{
case Z_NEED_DICT:
case Z_DATA_ERROR:
case Z_MEM_ERROR:
case Z_STREAM_ERROR:
sdbg("inflate FAILED: ret=%d msg=\"%s\"\n", ret, strm.msg ? strm.msg : "No message" );
(void)inflateEnd(&strm);
kmm_free(pbuffer);
return NULL;
}
switch (ret)
{
case Z_NEED_DICT:
case Z_DATA_ERROR:
case Z_MEM_ERROR:
case Z_STREAM_ERROR:
sdbg("inflate FAILED: ret=%d msg=\"%s\"\n",
ret, strm.msg ? strm.msg : "No message" );
(void)inflateEnd(&strm);
kmm_free(pbuffer);
return NULL;
}
/* If avail_out is zero, then inflate() returned only
* because it is out of buffer space. In this case, we
* will have to reallocate the buffer and try again.
*/
/* If avail_out is zero, then inflate() returned only because it is
* out of buffer space. In this case, we will have to reallocate
* the buffer and try again.
*/
if (strm.avail_out == 0)
{
int newbufsize = bufsize + 128*1024;
char *newbuffer = kmm_realloc(pbuffer, newbufsize);
if (!newbuffer)
{
kmm_free(pbuffer);
return NULL;
}
else
{
pbuffer = newbuffer;
offset = bufsize;
bufsize = newbufsize;
}
}
else
{
/* There are unused bytes in the buffer, reallocate to
* correct size.
*/
if (strm.avail_out == 0)
{
int newbufsize = bufsize + 128*1024;
char *newbuffer = kmm_realloc(pbuffer, newbufsize);
if (!newbuffer)
{
kmm_free(pbuffer);
return NULL;
}
else
{
pbuffer = newbuffer;
offset = bufsize;
bufsize = newbufsize;
}
}
else
{
/* There are unused bytes in the buffer, reallocate to
* correct size.
*/
int newbufsize = bufsize - strm.avail_out;
char *newbuffer = kmm_realloc(pbuffer, newbufsize);
if (!newbuffer)
{
kmm_free(pbuffer);
return NULL;
}
else
{
pbuffer = newbuffer;
bufsize = newbufsize;
}
}
} while (strm.avail_out == 0 && ret != Z_STREAM_END);
int newbufsize = bufsize - strm.avail_out;
char *newbuffer = kmm_realloc(pbuffer, newbufsize);
if (!newbuffer)
{
kmm_free(pbuffer);
return NULL;
}
else
{
pbuffer = newbuffer;
bufsize = newbufsize;
}
}
}
while (strm.avail_out == 0 && ret != Z_STREAM_END);
(void)inflateEnd(&strm);
return pbuffer;
(void)inflateEnd(&strm);
return pbuffer;
}
/****************************************************************************

View File

@ -1,7 +1,7 @@
/****************************************************************************
* binfmt/pcode.c
*
* Copyright (C) 2014 Gregory Nutt. All rights reserved.
* Copyright (C) 2014-2015 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without

View File

@ -1,7 +1,7 @@
/****************************************************************************
* configs/ea3131/src/up_usbmsc.c
*
* Copyright (C) 2010, 2013 Gregory Nutt. All rights reserved.
* Copyright (C) 2010, 2013, 2015 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Configure and register the SAM3U MMC/SD SDIO block driver.
@ -103,7 +103,7 @@ int usbmsc_archinitialize(void)
pbuffer,
USBMSC_NSECTORS,
USBMSC_SECTORSIZE,
true);
RDFLAG_WRENABLED | RDFLAG_FUNLINK);
if (ret < 0)
{
syslog(LOG_ERR,

View File

@ -1,7 +1,7 @@
/****************************************************************************
* configs/ea3152/src/up_usbmsc.c
*
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
* Copyright (C) 2011, 2015 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Configure and register the SAM3U MMC/SD SDIO block driver.
@ -103,7 +103,7 @@ int usbmsc_archinitialize(void)
pbuffer,
USBMSC_NSECTORS,
USBMSC_SECTORSIZE,
true);
RDFLAG_WRENABLED | RDFLAG_FUNLINK);
if (ret < 0)
{
printf("create_ramdisk: Failed to register ramdisk at %s: %d\n",

View File

@ -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,13 +124,33 @@ static const struct block_operations g_bops =
NULL, /* write */
#endif
rd_geometry, /* geometry */
rd_ioctl /* ioctl */
rd_ioctl, /* ioctl */
rd_unlink /* unlink */
};
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* 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
*
@ -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;
@ -277,20 +353,62 @@ static int rd_ioctl(FAR struct inode *inode, int cmd, unsigned long arg)
return -ENOTTY;
}
/****************************************************************************
* 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,18 +431,19 @@ 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 */
#ifdef CONFIG_FS_WRITABLE
dev->rd_writeenabled = writeenabled; /* true: can write to ram disk */
#endif
dev->rd_buffer = buffer; /* RAM disk backup memory */
#ifdef CONFIG_FS_WRITABLE
dev->rd_flags = rdflags & RDFLAG_USER;
#endif
/* Create a ramdisk device name */
snprintf(devname, 16, "/dev/ram%d", minor);

View File

@ -1,7 +1,7 @@
/****************************************************************************
* include/nuttx/fs/ramdisk.h
*
* Copyright (C) 2008-2009, 2012-2013 Gregory Nutt. All rights reserved.
* Copyright (C) 2008-2009, 2012-2013, 2015 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -48,6 +48,14 @@
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Values for rdflags */
#define RDFLAG_WRENABLED (1 << 0) /* Bit 0: 1=Can write to RAM disk */
#define RDFLAG_FUNLINK (1 << 1) /* Bit 1: 1=Free memory when unlinked */
/* For internal use by the driver only */
#define RDFLAG_UNLINKED (1 << 2) /* Bit 2: 1=Driver has been unlinked */
/****************************************************************************
* Type Definitions
@ -59,7 +67,8 @@
#ifdef __cplusplus
#define EXTERN extern "C"
extern "C" {
extern "C"
{
#else
#define EXTERN extern
#endif
@ -74,7 +83,7 @@ extern "C" {
* minor: Selects suffix of device named /dev/ramN, N={1,2,3...}
* nsectors: Number of sectors on device
* sectize: The size of one sector
* writeenabled: true: can write to ram disk
* rdflags: See RDFLAG_* definitions
* buffer: RAM disk backup memory
*
* Returned Valued:
@ -83,12 +92,12 @@ extern "C" {
****************************************************************************/
#ifdef CONFIG_FS_WRITABLE
EXTERN int ramdisk_register(int minor, FAR uint8_t *buffer, uint32_t nsectors,
uint16_t sectize, bool writeenabled);
int ramdisk_register(int minor, FAR uint8_t *buffer, uint32_t nsectors,
uint16_t sectize, uint8_t rdflags);
#define romdisk_register(m,b,n,s) ramdisk_register(m,b,n,s,0)
#else
EXTERN int romdisk_register(int minor, FAR uint8_t *buffer, uint32_t nsectors,
uint16_t sectize);
int romdisk_register(int minor, FAR uint8_t *buffer, uint32_t nsectors,
uint16_t sectize);
#endif
#undef EXTERN