diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2011-05-03 16:46:57 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2011-05-03 16:46:57 +0000 |
commit | c2064f636a8abfd8cb890e344fc86b360702cb5f (patch) | |
tree | c2fef7df0098e30547c6f32b63c929bfcd4f5fe1 | |
parent | 77ddf4fe79c737c9005b879298dbb5c96fca56e2 (diff) | |
download | nuttx-c2064f636a8abfd8cb890e344fc86b360702cb5f.tar.gz nuttx-c2064f636a8abfd8cb890e344fc86b360702cb5f.tar.bz2 nuttx-c2064f636a8abfd8cb890e344fc86b360702cb5f.zip |
Progress on NXFFS packing logic
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3555 42af7a65-404d-4744-a932-0658087f49c3
-rw-r--r-- | nuttx/fs/nxffs/nxffs.h | 69 | ||||
-rw-r--r-- | nuttx/fs/nxffs/nxffs_block.c | 2 | ||||
-rw-r--r-- | nuttx/fs/nxffs/nxffs_pack.c | 333 | ||||
-rw-r--r-- | nuttx/fs/nxffs/nxffs_read.c | 139 | ||||
-rw-r--r-- | nuttx/fs/nxffs/nxffs_write.c | 4 |
5 files changed, 410 insertions, 137 deletions
diff --git a/nuttx/fs/nxffs/nxffs.h b/nuttx/fs/nxffs/nxffs.h index 756a740e0..36a981868 100644 --- a/nuttx/fs/nxffs/nxffs.h +++ b/nuttx/fs/nxffs/nxffs.h @@ -783,28 +783,6 @@ extern FAR struct nxffs_ofile_s *nxffs_findofile(FAR struct nxffs_volume_s *volu extern int nxffs_wrreserve(FAR struct nxffs_volume_s *volume, size_t size); /**************************************************************************** - * Name: nxffs_nextblock - * - * Description: - * Search for the next valid data block starting at the provided - * FLASH offset. - * - * Input Parameters: - * volume - Describes the NXFFS volume. - * datlen - A memory location to return the data block length. - * - * Returned Value: - * Zero is returned on success. Otherwise, a negated errno is returned - * that indicates the nature of the failure. - * - * Defined in nxffs_read.c - * - ****************************************************************************/ - -extern int nxffs_nextblock(FAR struct nxffs_volume_s *volume, off_t offset, - FAR struct nxffs_blkentry_s *blkentry); - -/**************************************************************************** * Name: nxffs_wrverify * * Description: @@ -870,7 +848,52 @@ extern int nxffs_wrverify(FAR struct nxffs_volume_s *volume, size_t size); extern int nxffs_wrblkhdr(FAR struct nxffs_volume_s *volume, FAR struct nxffs_wrfile_s *wrfile); - + +/**************************************************************************** + * Name: nxffs_nextblock + * + * Description: + * Search for the next valid data block starting at the provided + * FLASH offset. + * + * Input Parameters: + * volume - Describes the NXFFS volume. + * datlen - A memory location to return the data block length. + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno is returned + * that indicates the nature of the failure. + * + * Defined in nxffs_read.c + * + ****************************************************************************/ + +extern int nxffs_nextblock(FAR struct nxffs_volume_s *volume, off_t offset, + FAR struct nxffs_blkentry_s *blkentry); + +/**************************************************************************** + * Name: nxffs_rdblkhdr + * + * Description: + * Read and verify the data block header at the specified offset. + * + * Input Parameters: + * volume - Describes the current volume. + * offset - The byte offset from the beginning of FLASH where the data block + * header is expected. + * datlen - A memory location to return the data block length. + * + * Returned Value: + * Zero on success. Otherwise, a negated errno value is returned + * indicating the nature of the failure. + * + * Defined in nxffs_read.c + * + ****************************************************************************/ + +extern int nxffs_rdblkhdr(FAR struct nxffs_volume_s *volume, off_t offset, + FAR uint16_t *datlen); + /**************************************************************************** * Name: nxffs_rminode * diff --git a/nuttx/fs/nxffs/nxffs_block.c b/nuttx/fs/nxffs/nxffs_block.c index 27f3249e3..4f3f89f6f 100644 --- a/nuttx/fs/nxffs/nxffs_block.c +++ b/nuttx/fs/nxffs/nxffs_block.c @@ -109,7 +109,7 @@ int nxffs_verifyblock(FAR struct nxffs_volume_s *volume, off_t block) */ blkhdr = (FAR struct nxffs_block_s *)volume->cache; - if (memcmp(blkhdr->magic, g_blockmagic, 4) == 0 && + if (memcmp(blkhdr->magic, g_blockmagic, NXFFS_MAGICSIZE) == 0 && blkhdr->state == BLOCK_STATE_GOOD) { /* The block is valid */ diff --git a/nuttx/fs/nxffs/nxffs_pack.c b/nuttx/fs/nxffs/nxffs_pack.c index b44a15736..7eca76746 100644 --- a/nuttx/fs/nxffs/nxffs_pack.c +++ b/nuttx/fs/nxffs/nxffs_pack.c @@ -70,8 +70,18 @@ struct nxffs_packstream_s struct nxffs_pack_s { - struct nxffs_packstream_s src; /* Describes the src stream */ - struct nxffs_packstream_s dest; /* Describes the destination stream */ + /* These describe the source and destination streams */ + + struct nxffs_packstream_s src; + struct nxffs_packstream_s dest; + + /* These describe the state of the current contents of the (destination) + * volume->pack buffer. + */ + + FAR uint8_t *iobuffer; /* I/O block start position */ + off_t ioblock; /* I/O block number */ + uint16_t iooffset; /* I/O block offset */ }; /**************************************************************************** @@ -83,32 +93,76 @@ struct nxffs_pack_s ****************************************************************************/ /**************************************************************************** - * Name: nxffs_startblock + * Name: nxffs_packseek * * 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. + * Seek to the destination offset in the pack buffer * * Input Parameters: * volume - The volume to be packed. + * pack - The volume packing state structure. + * offset - The desired offset * * Returned Values: - * Zero on success; Otherwise, a negated errno value is returned to - * indicate the nature of the failure. + * None * ****************************************************************************/ -static int nxffs_startblock(FAR struct nxffs_volume_s *volume, - FAR struct nxffs_pack_s *pack) +static void nxffs_packseek(FAR struct nxffs_volume_s *volume, + FAR struct nxffs_pack_s *pack, off_t offset) { - struct nxffs_blkentry_s blkentry; - off_t wasted; - off_t offset; - off_t nbytes; - int ret; + pack->ioblock = offset / volume->geo.blocksize; + pack->iooffset = offset - pack->ioblock * volume->geo.blocksize; +} + +/**************************************************************************** + * Name: nxffs_packvalid + * + * Description: + * Check if the current destination block is valid. + * + * Input Parameters: + * pack - The volume packing state structure. + * + * Returned Values: + * None + * + ****************************************************************************/ + +static inline bool nxffs_packvalid(FAR struct nxffs_pack_s *pack) +{ + FAR struct nxffs_block_s *blkhdr; + + blkhdr = (FAR struct nxffs_block_s *)pack->iobuffer; + return (memcmp(blkhdr->magic, g_blockmagic, NXFFS_MAGICSIZE) == 0 && + blkhdr->state == BLOCK_STATE_GOOD); +} + +/**************************************************************************** + * Name: nxffs_mediacheck + * + * Description: + * Verify that there is at least one valid block and at least one valid + * inode header on the media. On successful return, the volume packing + * structure is initialized and contains the offset to the first valid + * inode header is returned. + * + * Input Parameters: + * volume - The volume to be packed. + * pack - The volume packing state structure. + * + * Returned Values: + * The offset to the data area on the first valid block. Zero is return + * if there are no valid blocks or if there are no valid inode headers + * after the first valid block. + * + ****************************************************************************/ - memset(pack, 0, sizeof(struct nxffs_pack_s)); +static inline off_t nxffs_mediacheck(FAR struct nxffs_volume_s *volume, + FAR struct nxffs_pack_s *pack) +{ + off_t froffset; + int ret; /* Find the FLASH offset to the first valid block */ @@ -116,13 +170,62 @@ static int nxffs_startblock(FAR struct nxffs_volume_s *volume, ret = nxffs_validblock(volume, &volume->ioblock); if (ret < 0) { - /* No valid blocks? */ + /* No valid blocks? Return offset zero. */ - return nxffs_reformat(volume); + return 0; } + /* The offset to the free location to pack is then just after the block + * header in this block. + */ + volume->iooffset = SIZEOF_NXFFS_BLOCK_HDR; - offset = nxffs_iotell(volume); + froffset = nxffs_iotell(volume); + + /* Get the offset to the first valid inode entry after this free offset */ + + ret = nxffs_nextentry(volume, froffset, &pack->src.entry); + if (ret < 0) + { + /* No valid entries on the media -- Return offset zero */ + + return -ENOSPC; + } + + /* Okay.. the start block and first entry have been found */ + + return froffset; +} + +/**************************************************************************** + * 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. On entry, the volume packing structure should be as it + * was initialized by nxffx_mediacheck. on successful return, the volume + * packing state structure will be updated to begin the packing operation. + * + * 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. + * + * Returned Values: + * Zero on success; Otherwise, a negated errno value is returned to + * indicate the nature of the failure. + * + ****************************************************************************/ + +static inline int nxffs_startblock(FAR struct nxffs_volume_s *volume, + FAR struct nxffs_pack_s *pack, + off_t offset) +{ + struct nxffs_blkentry_s blkentry; + off_t wasted; + off_t nbytes; + int ret; /* Loop until we find a gap of unused FLASH large enough to warrant the * compression. @@ -130,16 +233,6 @@ static int nxffs_startblock(FAR struct nxffs_volume_s *volume, 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 @@ -195,13 +288,15 @@ static int nxffs_startblock(FAR struct nxffs_volume_s *volume, nxffs_ioseek(volume, offset); if (volume->iooffset + SIZEOF_NXFFS_INODE_HDR > volume->geo.blocksize) { - /* Find the next valid block */ + /* No.. not enough space here. 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 */ + /* No valid blocks? Then there is nothing we can do. Return + * the end-of-flash indication. + */ return -ENOSPC; } @@ -209,6 +304,18 @@ static int nxffs_startblock(FAR struct nxffs_volume_s *volume, volume->iooffset = SIZEOF_NXFFS_BLOCK_HDR; offset = nxffs_iotell(volume); } + + /* Get the offset to the next valid inode entry */ + + ret = nxffs_nextentry(volume, offset, &pack->src.entry); + if (ret < 0) + { + /* No more valid inode entries. Just return an end-of-flash error + * indication. + */ + + return -ENOSPC; + } } /* We won't get here */ @@ -217,6 +324,67 @@ static int nxffs_startblock(FAR struct nxffs_volume_s *volume, } /**************************************************************************** + * Name: nxffs_packblock + * + * Description: + * Resume packing from the source stream into the newly identified + * destination block. + * + * Input Parameters: + * volume - The volume to be packed + * pack - The volume packing state structure. + * + * Returned Values: + * Zero on success; Otherwise, a negated errno value is returned to + * indicate the nature of the failure. + * + ****************************************************************************/ + +static inline int nxffs_packblock(FAR struct nxffs_volume_s *volume, + FAR struct nxffs_pack_s *pack) +{ + int ret; + + /* Are we currently processing a block from the source stream? */ + + if (pack->src.blkoffset) + { + /* No, start with the first data block */ + + pack->src.blkoffset = pack->src.entry.doffset; + pack->src.fpos = 0; + pack->src.blkpos = 0; + + /* Seek to the data block header, read and verify the block header */ + + ret = nxffs_rdblkhdr(volume, pack->src.blkoffset, &pack->src.blklen); + if (ret < 0) + { + fdbg("Failed to verify the data block header: %d\n", -ret); + return ret; + } + } + + /* Loop, transferring data from the source block to the destination pack + * buffer until either (1) the source stream is exhausted, (2) the destination + * block is full, or (3) an error occurs. + */ + + for (;;) + { + /* Determine how much data is available in the dest pack buffer */ + + /* Dermined how much data is available in the src data block */ + + /* Transfer the data */ +#warning "Missing logic" + return -ENOSYS; + } + + return -ENOSYS; +} + +/**************************************************************************** * Public Functions ****************************************************************************/ @@ -239,28 +407,109 @@ static int nxffs_startblock(FAR struct nxffs_volume_s *volume, int nxffs_pack(FAR struct nxffs_volume_s *volume) { struct nxffs_pack_s pack; + off_t iooffset; + off_t eblock; + off_t block0; + off_t block; + int i; int ret; /* Get the offset to the first valid inode entry */ - ret = nxffs_startblock(volume, &pack); - if (ret < 0) + iooffset = nxffs_mediacheck(volume, &pack); + if (iooffset == 0) { - fdbg("Failed to find a start block: %d\n", -ret); - return ret; + /* Offset zero is only returned if no valid blocks were found on the + * FLASH media or if there are no valid inode entries on the FLASH after + * the first valid block. In this case, the media needs to be re- + * formatted. + */ + + return nxffs_reformat(volume); } - /* A special case is where the entire FLASH needs to be reformatted. In - * this case, the source and destination offsets will both be zero. + /* There is a valid format and valid inodes on the media.. setup up to + * begin the packing operation. */ - if (pack.src.entry.hoffset == 0 && pack.dest.entry.hoffset == 0) + ret = nxffs_startblock(volume, &pack, iooffset); + if (ret < 0) { - return OK; + /* This is a normal situation if the volume is full */ + + if (ret == -ENOSPC) + { + return OK; + } + else + { + fvdbg("Failed to find a packing position: %d\n", -ret); + return ret; + } } - /* Otherwise, begin pack at this src/dest block combination */ + /* Otherwise, begin pack at this src/dest block combination. Get the erase + * block associated with the destination header offset. + */ + + nxffs_packseek(volume, &pack, pack.dest.entry.hoffset); -# warning "Missing logic" - return -ENOSYS; + for (eblock = pack.ioblock / volume->blkper; + eblock < volume->geo.neraseblocks; + eblock++) + { + /* Read the erase block into the pack buffer. */ + + block0 = eblock * volume->blkper; + ret = MTD_BREAD(volume->mtd, block0, volume->blkper, volume->pack); + if (ret < 0) + { + fdbg("Failed to read erase block %d: %d\n", eblock, -ret); + goto errout_with_pack; + } + + /* Pack each I/O block */ + + for (i = 0, block = block0, pack.iobuffer = volume->pack; + i < volume->blkper; + i++, block++, pack.iobuffer += volume->geo.blocksize) + { + /* The first time here, the ioblock may point to an offset into + * the erase block. We just need to skip over those cases. + */ + + if (block >= pack.ioblock) + { + pack.ioblock = block; + + /* Check if this is a valid block */ + + if (nxffs_packvalid(&pack)) + { + /* Yes.. pack data into this block */ + + ret = nxffs_packblock(volume, &pack); + if (ret < 0) + { + fdbg("Failed to pack into block %d: %d\n", block, ret); + goto errout_with_pack; + } + } + } + } + + /* Write the packed I/O block to FLASH */ + + ret = MTD_BWRITE(volume->mtd, block0, volume->blkper, volume->pack); + if (ret < 0) + { + fdbg("Failed to write erase block %d: %d\n", eblock, -ret); + goto errout_with_pack; + } + } + +errout_with_pack: + nxffs_freeentry(&pack.src.entry); + nxffs_freeentry(&pack.dest.entry); + return ret; } diff --git a/nuttx/fs/nxffs/nxffs_read.c b/nuttx/fs/nxffs/nxffs_read.c index 30fcd09aa..0c2768c6a 100644 --- a/nuttx/fs/nxffs/nxffs_read.c +++ b/nuttx/fs/nxffs/nxffs_read.c @@ -70,75 +70,6 @@ ****************************************************************************/ /**************************************************************************** - * Name: nxffs_rdblkhdr - * - * Description: - * Read the dataa block header at this offset. Called only from nxffs_nextblock(). - * - * Input Parameters: - * volume - Describes the current volume. - * offset - The byte offset from the beginning of FLASH where the data block - * header is expected. - * datlen - A memory location to return the data block length. - * - * Returned Value: - * Zero on success. Otherwise, a negater errno value is returned - * indicating the nature of the failure. - * - ****************************************************************************/ - -static int nxffs_rdblkhdr(FAR struct nxffs_volume_s *volume, off_t offset, - FAR uint16_t *datlen) -{ - struct nxffs_data_s blkhdr; - uint32_t ecrc; - uint32_t crc; - uint16_t doffset; - uint16_t dlen; - - /* Read the header at the FLASH offset */ - - nxffs_ioseek(volume, offset); - doffset = volume->iooffset; - memcpy(&blkhdr, &volume->cache[doffset], SIZEOF_NXFFS_DATA_HDR); - - /* Extract the data length */ - - dlen = nxffs_rdle16(blkhdr.datlen); - - /* Get the offset to the beginning of the data */ - - doffset += SIZEOF_NXFFS_DATA_HDR; - - /* Make sure that all of the data fits within the block */ - - if ((uint32_t)doffset + (uint32_t)dlen > (uint32_t)volume->geo.blocksize) - { - fdbg("Data length=%d is unreasonable at offset=%d\n", dlen, doffset); - return -EIO; - } - - /* Extract the expected CRC and calculate the CRC of the data block */ - - ecrc = nxffs_rdle32(blkhdr.crc); - - nxffs_wrle32(blkhdr.crc, 0); - crc = crc32((FAR const uint8_t *)&blkhdr, SIZEOF_NXFFS_DATA_HDR); - crc = crc32part(&volume->cache[doffset], dlen, crc); - - if (crc != ecrc) - { - fdbg("CRC failure\n"); - return -EIO; - } - - /* Looks good! Return the data length and success */ - - *datlen = dlen; - return OK; -} - -/**************************************************************************** * Name: nxffs_rdseek * * Description: @@ -437,4 +368,74 @@ int nxffs_nextblock(FAR struct nxffs_volume_s *volume, off_t offset, return -ENOENT; } +/**************************************************************************** + * Name: nxffs_rdblkhdr + * + * Description: + * Read and verify the data block header at the specified offset. + * + * Input Parameters: + * volume - Describes the current volume. + * offset - The byte offset from the beginning of FLASH where the data block + * header is expected. + * datlen - A memory location to return the data block length. + * + * Returned Value: + * Zero on success. Otherwise, a negated errno value is returned + * indicating the nature of the failure. + * + ****************************************************************************/ + +int nxffs_rdblkhdr(FAR struct nxffs_volume_s *volume, off_t offset, + FAR uint16_t *datlen) +{ + struct nxffs_data_s blkhdr; + uint32_t ecrc; + uint32_t crc; + uint16_t doffset; + uint16_t dlen; + + /* Read the header at the FLASH offset */ + + nxffs_ioseek(volume, offset); + doffset = volume->iooffset; + memcpy(&blkhdr, &volume->cache[doffset], SIZEOF_NXFFS_DATA_HDR); + + /* Extract the data length */ + + dlen = nxffs_rdle16(blkhdr.datlen); + + /* Get the offset to the beginning of the data */ + + doffset += SIZEOF_NXFFS_DATA_HDR; + + /* Make sure that all of the data fits within the block */ + + if ((uint32_t)doffset + (uint32_t)dlen > (uint32_t)volume->geo.blocksize) + { + fdbg("Data length=%d is unreasonable at offset=%d\n", dlen, doffset); + return -EIO; + } + + /* Extract the expected CRC and calculate the CRC of the data block */ + + ecrc = nxffs_rdle32(blkhdr.crc); + + nxffs_wrle32(blkhdr.crc, 0); + crc = crc32((FAR const uint8_t *)&blkhdr, SIZEOF_NXFFS_DATA_HDR); + crc = crc32part(&volume->cache[doffset], dlen, crc); + + if (crc != ecrc) + { + fdbg("CRC failure\n"); + return -EIO; + } + + /* Looks good! Return the data length and success */ + + *datlen = dlen; + return OK; +} + + diff --git a/nuttx/fs/nxffs/nxffs_write.c b/nuttx/fs/nxffs/nxffs_write.c index e3dd84931..a15592655 100644 --- a/nuttx/fs/nxffs/nxffs_write.c +++ b/nuttx/fs/nxffs/nxffs_write.c @@ -715,7 +715,7 @@ int nxffs_wrverify(FAR struct nxffs_volume_s *volume, size_t size) iooffset = volume->iooffset; nerased = 0; - for (i = volume->iooffset; i <= volume->geo.blocksize - size; i++) + for (i = volume->iooffset; i < volume->geo.blocksize; i++) { /* Is this byte erased? */ @@ -745,7 +745,7 @@ int nxffs_wrverify(FAR struct nxffs_volume_s *volume, size_t size) else { nerased = 0; - iooffset = volume->iooffset + 1; + iooffset = i + 1; } } |