summaryrefslogtreecommitdiff
path: root/nuttx/fs/nxffs/nxffs_pack.c
diff options
context:
space:
mode:
Diffstat (limited to 'nuttx/fs/nxffs/nxffs_pack.c')
-rw-r--r--nuttx/fs/nxffs/nxffs_pack.c178
1 files changed, 178 insertions, 0 deletions
diff --git a/nuttx/fs/nxffs/nxffs_pack.c b/nuttx/fs/nxffs/nxffs_pack.c
index 476c5972b..b44a15736 100644
--- a/nuttx/fs/nxffs/nxffs_pack.c
+++ b/nuttx/fs/nxffs/nxffs_pack.c
@@ -41,7 +41,10 @@
#include <nuttx/config.h>
+#include <string.h>
#include <errno.h>
+#include <assert.h>
+#include <debug.h>
#include "nxffs.h"
@@ -52,6 +55,24 @@
/****************************************************************************
* Public Types
****************************************************************************/
+/* This structure supports access to one inode data stream */
+
+struct nxffs_packstream_s
+{
+ struct nxffs_entry_s entry; /* Described the inode header */
+ off_t fpos; /* Current file position */
+ off_t blkoffset; /* Offset to the current data block */
+ uint16_t blklen; /* Size of this block */
+ uint16_t blkpos; /* Position in block corresponding to fpos */
+};
+
+/* The structure supports the overall packing operation */
+
+struct nxffs_pack_s
+{
+ struct nxffs_packstream_s src; /* Describes the src stream */
+ struct nxffs_packstream_s dest; /* Describes the destination stream */
+};
/****************************************************************************
* Public Variables
@@ -62,6 +83,140 @@
****************************************************************************/
/****************************************************************************
+ * Name: nxffs_startblock
+ *
+ * Description:
+ * Find the position in FLASH memory where we should begin packing. That
+ * position is the place where there is a gap between the last and the next
+ * valid inode.
+ *
+ * Input Parameters:
+ * volume - The volume to be packed.
+ *
+ * Returned Values:
+ * Zero on success; Otherwise, a negated errno value is returned to
+ * indicate the nature of the failure.
+ *
+ ****************************************************************************/
+
+static int nxffs_startblock(FAR struct nxffs_volume_s *volume,
+ FAR struct nxffs_pack_s *pack)
+{
+ struct nxffs_blkentry_s blkentry;
+ off_t wasted;
+ off_t offset;
+ off_t nbytes;
+ int ret;
+
+ memset(pack, 0, sizeof(struct nxffs_pack_s));
+
+ /* Find the FLASH offset to the first valid block */
+
+ volume->ioblock = 0;
+ ret = nxffs_validblock(volume, &volume->ioblock);
+ if (ret < 0)
+ {
+ /* No valid blocks? */
+
+ return nxffs_reformat(volume);
+ }
+
+ volume->iooffset = SIZEOF_NXFFS_BLOCK_HDR;
+ offset = nxffs_iotell(volume);
+
+ /* Loop until we find a gap of unused FLASH large enough to warrant the
+ * compression.
+ */
+
+ for(;;)
+ {
+ /* Get the offset to the first valid inode entry */
+
+ ret = nxffs_nextentry(volume, offset, &pack->src.entry);
+ if (ret < 0)
+ {
+ /* No valid entries -- reformat the flash */
+
+ return nxffs_reformat(volume);
+ }
+
+ /* Is there wasted space between the offset where the we could have
+ * valid data and the offset to the beginning of the first valid
+ * inode header? NOTE: The threshold check is not accurate, there
+ * may or may not be intervening block headers making the separation
+ * seem larger than it is.
+ */
+
+ DEBUGASSERT(pack->src.entry.hoffset >= offset);
+ wasted = pack->src.entry.hoffset - offset;
+ if (wasted > CONFIG_NXFFS_PACKTHRESHOLD)
+ {
+ /* This is where we must begin packing */
+
+ memcpy(&pack->dest.entry, &pack->src.entry, sizeof(struct nxffs_entry_s));
+
+ pack->dest.entry.hoffset = offset;
+ pack->src.entry.name = NULL;
+ return OK;
+ }
+
+ /* Free the allocated memory in the entry */
+
+ nxffs_freeentry(&pack->src.entry);
+
+ /* Update the offset to the first byte at the end of the last data
+ * block.
+ */
+
+ nbytes = 0;
+ offset = pack->src.entry.doffset;
+
+ while (nbytes < pack->src.entry.datlen)
+ {
+ /* Read the next data block header */
+
+ ret = nxffs_nextblock(volume, offset, &blkentry);
+ if (ret < 0)
+ {
+ fdbg("Failed to find next data block: %d\n", -ret);
+ return ret;
+ }
+
+ /* Get the number of blocks and pointer to where the next
+ * data block might lie.
+ */
+
+ nbytes += blkentry.datlen;
+ offset = blkentry.hoffset + SIZEOF_NXFFS_DATA_HDR + blkentry.datlen;
+ }
+
+ /* Make sure there is space at this location for an inode header */
+
+ nxffs_ioseek(volume, offset);
+ if (volume->iooffset + SIZEOF_NXFFS_INODE_HDR > volume->geo.blocksize)
+ {
+ /* Find the next valid block */
+
+ volume->ioblock++;
+ ret = nxffs_validblock(volume, &volume->ioblock);
+ if (ret < 0)
+ {
+ /* No valid blocks? Then there is nothing we can do */
+
+ return -ENOSPC;
+ }
+
+ volume->iooffset = SIZEOF_NXFFS_BLOCK_HDR;
+ offset = nxffs_iotell(volume);
+ }
+ }
+
+ /* We won't get here */
+
+ return -ENOSYS;
+}
+
+/****************************************************************************
* Public Functions
****************************************************************************/
@@ -83,6 +238,29 @@
int nxffs_pack(FAR struct nxffs_volume_s *volume)
{
+ struct nxffs_pack_s pack;
+ int ret;
+
+ /* Get the offset to the first valid inode entry */
+
+ ret = nxffs_startblock(volume, &pack);
+ if (ret < 0)
+ {
+ fdbg("Failed to find a start block: %d\n", -ret);
+ return ret;
+ }
+
+ /* A special case is where the entire FLASH needs to be reformatted. In
+ * this case, the source and destination offsets will both be zero.
+ */
+
+ if (pack.src.entry.hoffset == 0 && pack.dest.entry.hoffset == 0)
+ {
+ return OK;
+ }
+
+ /* Otherwise, begin pack at this src/dest block combination */
+
# warning "Missing logic"
return -ENOSYS;
}