diff options
Diffstat (limited to 'nuttx')
-rwxr-xr-x | nuttx/fs/nxffs/README.txt | 10 | ||||
-rw-r--r-- | nuttx/fs/nxffs/nxffs_pack.c | 74 | ||||
-rw-r--r-- | nuttx/include/nuttx/nxffs.h | 18 |
3 files changed, 81 insertions, 21 deletions
diff --git a/nuttx/fs/nxffs/README.txt b/nuttx/fs/nxffs/README.txt index 8da14bf58..72da497a9 100755 --- a/nuttx/fs/nxffs/README.txt +++ b/nuttx/fs/nxffs/README.txt @@ -136,9 +136,6 @@ blocked waiting for itself to close the first file. Things to Do
============
-- The implementation is not yet finished. It needs at, a minimum,
- completion of the file system packing logic. It is not usuable without
- that feature.
- The statfs() implementation is minimal. It whould have some calcuation
of the f_bfree, f_bavail, f_files, f_ffree return values.
- There are too many allocs and frees. More structures may need to be
@@ -153,4 +150,11 @@ Things to Do information in the read open file structure.
- Fault tolerance must be improved. We need to be absolutely certain that
any FLASH errors do not cause the file system to behavior incorrectly.
+- Wear leveling could be improved as well. Files are re-packed at the front
+ of FLASH as part of the clean-up operation. However, that means the files
+ that are not modified often become fixed in place at the beginning of
+ FLASH. This reduces the size of the pool moving files at the end of the
+ FLASH. As the file system becomes more filled with fixed files at the
+ front of the device, the level of wear on the blocks at the end of the
+ FLASH increases.
diff --git a/nuttx/fs/nxffs/nxffs_pack.c b/nuttx/fs/nxffs/nxffs_pack.c index 57fa11e76..70ae506d4 100644 --- a/nuttx/fs/nxffs/nxffs_pack.c +++ b/nuttx/fs/nxffs/nxffs_pack.c @@ -258,19 +258,24 @@ static inline off_t nxffs_mediacheck(FAR struct nxffs_volume_s *volume, * Input Parameters: * volume - The volume to be packed * pack - The volume packing state structure. - * offset - location to return the pointer to first valid inode header. + * froffset - On input, this is the location where we should be searching + * for the location to begin packing. If -ENOSPC is returned -- meaning + * that the FLASH -- then no packing can be performed. In this case + * (only) , then the free flash offset is returned through this location. * * Returned Values: * Zero on success; Otherwise, a negated errno value is returned to - * indicate the nature of the failure. + * indicate the nature of the failure. If -ENOSPC is returned then the + * free FLASH offset is also returned. * ****************************************************************************/ static inline int nxffs_startpos(FAR struct nxffs_volume_s *volume, FAR struct nxffs_pack_s *pack, - off_t offset) + off_t *froffset) { struct nxffs_blkentry_s blkentry; + off_t offset = *froffset; off_t wasted; off_t nbytes; int ret; @@ -352,6 +357,7 @@ static inline int nxffs_startpos(FAR struct nxffs_volume_s *volume, * the end-of-flash indication. */ + *froffset = volume->froffset; return -ENOSPC; } @@ -365,9 +371,11 @@ static inline int nxffs_startpos(FAR struct nxffs_volume_s *volume, if (ret < 0) { /* No more valid inode entries. Just return an end-of-flash error - * indication. + * indication. However, there could be many deleted inodes; set + * volume->froffset to indicate the true free FLASH position. */ + *froffset = offset; return -ENOSPC; } } @@ -975,14 +983,43 @@ int nxffs_pack(FAR struct nxffs_volume_s *volume) * begin the packing operation. */ - ret = nxffs_startpos(volume, &pack, iooffset); + packed = false; + ret = nxffs_startpos(volume, &pack, &iooffset); if (ret < 0) { /* This is a normal situation if the volume is full */ if (ret == -ENOSPC) { - return OK; + /* In the case where the volume is full, nxffs_startpos() will + * recalculate the free FLASH offset and store in in iooffset. There + * may be deleted files at the end of FLASH. In this case, we don't + * have to pack any files, we simply have to erase FLASH at the end. + * But don't do this unless there is some particularly big FLASH + * savings (otherwise, we risk wearing out these final blocks). + */ + + if (iooffset + CONFIG_NXFFS_TAILTHRESHOLD < volume->froffset) + { + /* Yes... we can recover CONFIG_NXFFS_TAILTHRESHOLD bytes */ + + pack.ioblock = nxffs_getblock(volume, iooffset); + pack.iooffset = nxffs_getoffset(volume, iooffset, pack.ioblock); + volume->froffset = iooffset; + + /* Setting packed to true will supress all packing operations */ + + packed = true; + } + + /* Otherwise return OK.. meaning that there is nothing more we can + * do to recover FLASH space. + */ + + else + { + return OK; + } } else { @@ -990,26 +1027,27 @@ int nxffs_pack(FAR struct nxffs_volume_s *volume) return ret; } } + else + { + /* Otherwise, begin pack at this src/dest block combination. Initialize + * ioblock and iooffset with the position of the first inode header. + */ - /* Otherwise, begin pack at this src/dest block combination. Initialize - * ioblock and iooffset with the position of the first inode header. - */ - - pack.ioblock = nxffs_getblock(volume, pack.dest.entry.hoffset); - pack.iooffset = nxffs_getoffset(volume, pack.dest.entry.hoffset, pack.ioblock); + pack.ioblock = nxffs_getblock(volume, pack.dest.entry.hoffset); + pack.iooffset = nxffs_getoffset(volume, pack.dest.entry.hoffset, pack.ioblock); - /* Reserve space for the inode header. Note we are guaranteed by - * nxffs_startpos() that the inode header will fit at hoffset. - */ + /* Reserve space for the inode header. Note we are guaranteed by + * nxffs_startpos() that the inode header will fit at hoffset. + */ - pack.iooffset += SIZEOF_NXFFS_INODE_HDR; - volume->froffset = nxffs_packtell(volume, &pack); + pack.iooffset += SIZEOF_NXFFS_INODE_HDR; + volume->froffset = nxffs_packtell(volume, &pack); + } /* Then pack all erase blocks starting with the erase block that contains * the ioblock and through the final erase block on the FLASH. */ - packed = false; for (eblock = pack.ioblock / volume->blkper; eblock < volume->geo.neraseblocks; eblock++) diff --git a/nuttx/include/nuttx/nxffs.h b/nuttx/include/nuttx/nxffs.h index d601b4a41..4d1343676 100644 --- a/nuttx/include/nuttx/nxffs.h +++ b/nuttx/include/nuttx/nxffs.h @@ -59,14 +59,32 @@ # error "CONFIG_NXFFS_ERASEDSTATE must be either 0x00 or 0xff" #endif +/* Don't bother trying to pack things closer together than this. */ + #ifndef CONFIG_NXFFS_PACKTHRESHOLD # define CONFIG_NXFFS_PACKTHRESHOLD 32 #endif +/* This is how big an inode name is permitted to be. */ + #ifndef CONFIG_NXFFS_MAXNAMLEN # define CONFIG_NXFFS_MAXNAMLEN 255 #endif +/* Clean-up can either mean packing files together toward the end of the file + * or, if file are deleted at the end of the file, clean up can simply mean + * erasing the end of FLASH memory so that it can be re-used again. However, + * doing this can also harm the life of the FLASH part because it can mean + * that the tail end of the FLASH is re-used too often. + * + * This threshold determines if/when it is worth erased the tail end of FLASH + * and making it available for re-use (and possible over-wear). + */ + +#ifndef CONFIG_NXFFS_TAILTHRESHOLD +# define CONFIG_NXFFS_TAILTHRESHOLD (8*1024) +#endif + /* At present, only a single pre-allocated NXFFS volume is supported. This * is because here can be only a single NXFFS volume mounted at any time. * This has to do with the fact that we bind to an MTD driver (instead of a |