diff --git a/arch/sim/src/up_blockdevice.c b/arch/sim/src/up_blockdevice.c index 5173d9b0bfd..dc473075fed 100644 --- a/arch/sim/src/up_blockdevice.c +++ b/arch/sim/src/up_blockdevice.c @@ -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 * * 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); } diff --git a/arch/sim/src/up_deviceimage.c b/arch/sim/src/up_deviceimage.c index 346adb3a24e..715782f8e84 100644 --- a/arch/sim/src/up_deviceimage.c +++ b/arch/sim/src/up_deviceimage.c @@ -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 * * 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; } /**************************************************************************** diff --git a/binfmt/pcode.c b/binfmt/pcode.c index b2cac588065..a4423c6900d 100644 --- a/binfmt/pcode.c +++ b/binfmt/pcode.c @@ -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 * * Redistribution and use in source and binary forms, with or without diff --git a/configs/ea3131/src/up_usbmsc.c b/configs/ea3131/src/up_usbmsc.c index b80ea35be3e..ec74fa49222 100644 --- a/configs/ea3131/src/up_usbmsc.c +++ b/configs/ea3131/src/up_usbmsc.c @@ -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 * * 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, diff --git a/configs/ea3152/src/up_usbmsc.c b/configs/ea3152/src/up_usbmsc.c index 55bd3440c74..cec8dc63bca 100644 --- a/configs/ea3152/src/up_usbmsc.c +++ b/configs/ea3152/src/up_usbmsc.c @@ -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 * * 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", diff --git a/drivers/ramdisk.c b/drivers/ramdisk.c index ee45aaf05fc..4c9a1405d57 100644 --- a/drivers/ramdisk.c +++ b/drivers/ramdisk.c @@ -54,22 +54,37 @@ #include /**************************************************************************** - * 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); diff --git a/include/nuttx/fs/ramdisk.h b/include/nuttx/fs/ramdisk.h index d00a0e2d528..8721839775f 100644 --- a/include/nuttx/fs/ramdisk.h +++ b/include/nuttx/fs/ramdisk.h @@ -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 * * 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