NXFFS: more NAND-Releated changes; don't fail if a block read fails. That might just be a NAND uncorrectable bit error. Make scanning of the device on startup optional. This might have introduced some NXFFS issure -- To be determined

This commit is contained in:
Gregory Nutt 2013-12-02 17:19:22 -06:00
parent 006db0be7c
commit b3d3f59363
10 changed files with 304 additions and 114 deletions

View file

@ -14,6 +14,36 @@ config FS_NXFFS
if FS_NXFFS
config NXFFS_SCAN_VOLUME
bool "Scan volume"
default n
---help---
Scan the media for bad blocks on start-up. If too many bad or
unformatted blocks are found, then re-format the volume. Otherwise,
the volume will be reformatted only if no NXFFS file system is
found.
Why might you want to do this? If too many bad blocks accumulate
over time, then attempting to reformat my be the only way to
recover. And what if you power down the device while formatting
the FLASH so that you have only a partially formatted device?
Scanning the volume can get you out of these situations.
The down side is that scanning the volume can adversely affect
your start-up time. An option is to just erase the FLASH and
reboot in these cases. That can be done with
apps/system/flash_eraseall.
config NXFFS_REFORMAT_THRESH
int "Reformat percentage"
default 20
range 0 100
depends on NXFFS_SCAN_VOLUME
---help---
This defines the threshold for re-formatting. Is less than this
percentage of good blocks are found, then the volume is re-
formatted.
config NXFFS_PREALLOCATED
bool "Single, preallocated volume"
default y

View file

@ -374,7 +374,7 @@ extern struct nxffs_volume_s g_volume;
*
****************************************************************************/
extern int nxffs_limits(FAR struct nxffs_volume_s *volume);
int nxffs_limits(FAR struct nxffs_volume_s *volume);
/****************************************************************************
* Name: nxffs_rdle16
@ -392,7 +392,7 @@ extern int nxffs_limits(FAR struct nxffs_volume_s *volume);
*
****************************************************************************/
extern uint16_t nxffs_rdle16(FAR const uint8_t *val);
uint16_t nxffs_rdle16(FAR const uint8_t *val);
/****************************************************************************
* Name: nxffs_wrle16
@ -411,7 +411,7 @@ extern uint16_t nxffs_rdle16(FAR const uint8_t *val);
*
****************************************************************************/
extern void nxffs_wrle16(uint8_t *dest, uint16_t val);
void nxffs_wrle16(uint8_t *dest, uint16_t val);
/****************************************************************************
* Name: nxffs_rdle32
@ -429,7 +429,7 @@ extern void nxffs_wrle16(uint8_t *dest, uint16_t val);
*
****************************************************************************/
extern uint32_t nxffs_rdle32(FAR const uint8_t *val);
uint32_t nxffs_rdle32(FAR const uint8_t *val);
/****************************************************************************
* Name: nxffs_wrle32
@ -448,7 +448,7 @@ extern uint32_t nxffs_rdle32(FAR const uint8_t *val);
*
****************************************************************************/
extern void nxffs_wrle32(uint8_t *dest, uint32_t val);
void nxffs_wrle32(uint8_t *dest, uint32_t val);
/****************************************************************************
* Name: nxffs_erased
@ -467,7 +467,7 @@ extern void nxffs_wrle32(uint8_t *dest, uint32_t val);
*
****************************************************************************/
extern size_t nxffs_erased(FAR const uint8_t *buffer, size_t buflen);
size_t nxffs_erased(FAR const uint8_t *buffer, size_t buflen);
/****************************************************************************
* Name: nxffs_rdcache
@ -487,7 +487,7 @@ extern size_t nxffs_erased(FAR const uint8_t *buffer, size_t buflen);
*
****************************************************************************/
extern int nxffs_rdcache(FAR struct nxffs_volume_s *volume, off_t block);
int nxffs_rdcache(FAR struct nxffs_volume_s *volume, off_t block);
/****************************************************************************
* Name: nxffs_wrcache
@ -505,7 +505,7 @@ extern int nxffs_rdcache(FAR struct nxffs_volume_s *volume, off_t block);
*
****************************************************************************/
extern int nxffs_wrcache(FAR struct nxffs_volume_s *volume);
int nxffs_wrcache(FAR struct nxffs_volume_s *volume);
/****************************************************************************
* Name: nxffs_ioseek
@ -524,7 +524,7 @@ extern int nxffs_wrcache(FAR struct nxffs_volume_s *volume);
*
****************************************************************************/
extern void nxffs_ioseek(FAR struct nxffs_volume_s *volume, off_t offset);
void nxffs_ioseek(FAR struct nxffs_volume_s *volume, off_t offset);
/****************************************************************************
* Name: nxffs_iotell
@ -542,7 +542,7 @@ extern void nxffs_ioseek(FAR struct nxffs_volume_s *volume, off_t offset);
*
****************************************************************************/
extern off_t nxffs_iotell(FAR struct nxffs_volume_s *volume);
off_t nxffs_iotell(FAR struct nxffs_volume_s *volume);
/****************************************************************************
* Name: nxffs_getc
@ -566,7 +566,7 @@ extern off_t nxffs_iotell(FAR struct nxffs_volume_s *volume);
*
****************************************************************************/
extern int nxffs_getc(FAR struct nxffs_volume_s *volume, uint16_t reserve);
int nxffs_getc(FAR struct nxffs_volume_s *volume, uint16_t reserve);
/****************************************************************************
* Name: nxffs_freeentry
@ -590,7 +590,7 @@ extern int nxffs_getc(FAR struct nxffs_volume_s *volume, uint16_t reserve);
*
****************************************************************************/
extern void nxffs_freeentry(FAR struct nxffs_entry_s *entry);
void nxffs_freeentry(FAR struct nxffs_entry_s *entry);
/****************************************************************************
* Name: nxffs_nextentry
@ -612,8 +612,8 @@ extern void nxffs_freeentry(FAR struct nxffs_entry_s *entry);
*
****************************************************************************/
extern int nxffs_nextentry(FAR struct nxffs_volume_s *volume, off_t offset,
FAR struct nxffs_entry_s *entry);
int nxffs_nextentry(FAR struct nxffs_volume_s *volume, off_t offset,
FAR struct nxffs_entry_s *entry);
/****************************************************************************
* Name: nxffs_findinode
@ -636,9 +636,8 @@ extern int nxffs_nextentry(FAR struct nxffs_volume_s *volume, off_t offset,
*
****************************************************************************/
extern int nxffs_findinode(FAR struct nxffs_volume_s *volume,
FAR const char *name,
FAR struct nxffs_entry_s *entry);
int nxffs_findinode(FAR struct nxffs_volume_s *volume, FAR const char *name,
FAR struct nxffs_entry_s *entry);
/****************************************************************************
* Name: nxffs_inodeend
@ -664,8 +663,8 @@ extern int nxffs_findinode(FAR struct nxffs_volume_s *volume,
*
****************************************************************************/
extern off_t nxffs_inodeend(FAR struct nxffs_volume_s *volume,
FAR struct nxffs_entry_s *entry);
off_t nxffs_inodeend(FAR struct nxffs_volume_s *volume,
FAR struct nxffs_entry_s *entry);
/****************************************************************************
* Name: nxffs_verifyblock
@ -680,14 +679,19 @@ extern off_t nxffs_inodeend(FAR struct nxffs_volume_s *volume,
* block - The (logical) block number to load and verify.
*
* Returned Values:
* Zero is returned on success. Otherwise, a negated errno value is
* returned indicating the nature of the failure.
* OK (zero( is returned on success. Otherwise, a negated errno value is
* returned indicating the nature of the failure:
*
* -EIO is returned if we failed to read the block. If we are using
* NAND memory, then this probably means that the block has
* uncorrectable bit errors.
* -ENOENT is returned if the block is a bad block.
*
* Defined in nxffs_block.c
*
****************************************************************************/
extern int nxffs_verifyblock(FAR struct nxffs_volume_s *volume, off_t block);
int nxffs_verifyblock(FAR struct nxffs_volume_s *volume, off_t block);
/****************************************************************************
* Name: nxffs_validblock
@ -709,7 +713,7 @@ extern int nxffs_verifyblock(FAR struct nxffs_volume_s *volume, off_t block);
*
****************************************************************************/
extern int nxffs_validblock(struct nxffs_volume_s *volume, off_t *block);
int nxffs_validblock(struct nxffs_volume_s *volume, off_t *block);
/****************************************************************************
* Name: nxffs_blockstats
@ -732,8 +736,8 @@ extern int nxffs_validblock(struct nxffs_volume_s *volume, off_t *block);
*
****************************************************************************/
extern int nxffs_blockstats(FAR struct nxffs_volume_s *volume,
FAR struct nxffs_blkstats_s *stats);
int nxffs_blockstats(FAR struct nxffs_volume_s *volume,
FAR struct nxffs_blkstats_s *stats);
/****************************************************************************
* Name: nxffs_reformat
@ -754,7 +758,27 @@ extern int nxffs_blockstats(FAR struct nxffs_volume_s *volume,
*
****************************************************************************/
extern int nxffs_reformat(FAR struct nxffs_volume_s *volume);
int nxffs_reformat(FAR struct nxffs_volume_s *volume);
/****************************************************************************
* Name: nxffs_blkinit
*
* Description:
* Initialize an NXFFS block to the erased state with the specified block
* status.
*
* Input Parameters:
* volume - Describes the NXFFS volume (needed for the blocksize).
* blkptr - Pointer to the logic block to initialize.
* state - Either BLOCK_STATE_GOOD or BLOCK_STATE_BAD.
*
* Returned Value:
* None.
*
****************************************************************************/
void nxffs_blkinit(FAR struct nxffs_volume_s *volume, FAR uint8_t *blkptr,
uint8_t state);
/****************************************************************************
* Name: nxffs_findofile
@ -776,8 +800,8 @@ extern int nxffs_reformat(FAR struct nxffs_volume_s *volume);
*
****************************************************************************/
extern FAR struct nxffs_ofile_s *nxffs_findofile(FAR struct nxffs_volume_s *volume,
FAR const char *name);
FAR struct nxffs_ofile_s *nxffs_findofile(FAR struct nxffs_volume_s *volume,
FAR const char *name);
/****************************************************************************
* Name: nxffs_findwriter
@ -797,7 +821,7 @@ extern FAR struct nxffs_ofile_s *nxffs_findofile(FAR struct nxffs_volume_s *volu
*
****************************************************************************/
extern FAR struct nxffs_wrfile_s *nxffs_findwriter(FAR struct nxffs_volume_s *volume);
FAR struct nxffs_wrfile_s *nxffs_findwriter(FAR struct nxffs_volume_s *volume);
/****************************************************************************
* Name: nxffs_wrinode
@ -823,8 +847,8 @@ extern FAR struct nxffs_wrfile_s *nxffs_findwriter(FAR struct nxffs_volume_s *vo
*
****************************************************************************/
extern int nxffs_wrinode(FAR struct nxffs_volume_s *volume,
FAR struct nxffs_entry_s *entry);
int nxffs_wrinode(FAR struct nxffs_volume_s *volume,
FAR struct nxffs_entry_s *entry);
/****************************************************************************
* Name: nxffs_updateinode
@ -843,8 +867,8 @@ extern int nxffs_wrinode(FAR struct nxffs_volume_s *volume,
*
****************************************************************************/
extern int nxffs_updateinode(FAR struct nxffs_volume_s *volume,
FAR struct nxffs_entry_s *entry);
int nxffs_updateinode(FAR struct nxffs_volume_s *volume,
FAR struct nxffs_entry_s *entry);
/****************************************************************************
* Name: nxffs_wrreserve
@ -884,7 +908,7 @@ extern int nxffs_updateinode(FAR struct nxffs_volume_s *volume,
*
****************************************************************************/
extern int nxffs_wrreserve(FAR struct nxffs_volume_s *volume, size_t size);
int nxffs_wrreserve(FAR struct nxffs_volume_s *volume, size_t size);
/****************************************************************************
* Name: nxffs_wrverify
@ -928,7 +952,7 @@ extern int nxffs_wrreserve(FAR struct nxffs_volume_s *volume, size_t size);
*
****************************************************************************/
extern int nxffs_wrverify(FAR struct nxffs_volume_s *volume, size_t size);
int nxffs_wrverify(FAR struct nxffs_volume_s *volume, size_t size);
/****************************************************************************
* Name: nxffs_wrblkhdr
@ -950,8 +974,8 @@ 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);
int nxffs_wrblkhdr(FAR struct nxffs_volume_s *volume,
FAR struct nxffs_wrfile_s *wrfile);
/****************************************************************************
* Name: nxffs_nextblock
@ -972,8 +996,8 @@ extern int nxffs_wrblkhdr(FAR struct nxffs_volume_s *volume,
*
****************************************************************************/
extern int nxffs_nextblock(FAR struct nxffs_volume_s *volume, off_t offset,
FAR struct nxffs_blkentry_s *blkentry);
int nxffs_nextblock(FAR struct nxffs_volume_s *volume, off_t offset,
FAR struct nxffs_blkentry_s *blkentry);
/****************************************************************************
* Name: nxffs_rdblkhdr
@ -995,8 +1019,8 @@ extern int nxffs_nextblock(FAR struct nxffs_volume_s *volume, off_t offset,
*
****************************************************************************/
extern int nxffs_rdblkhdr(FAR struct nxffs_volume_s *volume, off_t offset,
FAR uint16_t *datlen);
int nxffs_rdblkhdr(FAR struct nxffs_volume_s *volume, off_t offset,
FAR uint16_t *datlen);
/****************************************************************************
* Name: nxffs_rminode
@ -1015,7 +1039,7 @@ extern int nxffs_rdblkhdr(FAR struct nxffs_volume_s *volume, off_t offset,
*
****************************************************************************/
extern int nxffs_rminode(FAR struct nxffs_volume_s *volume, FAR const char *name);
int nxffs_rminode(FAR struct nxffs_volume_s *volume, FAR const char *name);
/****************************************************************************
* Name: nxffs_pack
@ -1033,7 +1057,7 @@ extern int nxffs_rminode(FAR struct nxffs_volume_s *volume, FAR const char *name
*
****************************************************************************/
extern int nxffs_pack(FAR struct nxffs_volume_s *volume);
int nxffs_pack(FAR struct nxffs_volume_s *volume);
/****************************************************************************
* Standard mountpoint operation methods

View file

@ -83,9 +83,13 @@
* block - The (logical) block number to load and verify.
*
* Returned Values:
* Zero is returned on success. Otherwise, a negated errno value is
* returned indicating the nature of the failure. -ENOENT is returned
* if the block is a bad block.
* OK (zero( is returned on success. Otherwise, a negated errno value is
* returned indicating the nature of the failure:
*
* -EIO is returned if we failed to read the block. If we are using
* NAND memory, then this probably means that the block has
* uncorrectable bit errors.
* -ENOENT is returned if the block is a bad block.
*
****************************************************************************/
@ -102,7 +106,7 @@ int nxffs_verifyblock(FAR struct nxffs_volume_s *volume, off_t block)
/* Perhaps we are at the end of the media */
fdbg("ERROR: Failed to read data into cache: %d\n", ret);
return ret;
return -EIO;
}
/* Check if the block has a magic number (meaning that it is not

View file

@ -246,8 +246,13 @@ int nxffs_getc(FAR struct nxffs_volume_s *volume, uint16_t reserve)
ret = nxffs_verifyblock(volume, volume->ioblock);
if (ret < 0 && ret != -ENOENT)
{
/* A read error occurred. This probably means that we are
* using NAND memory this block has an uncorrectable bit error.
* Ignore the error (after complaining) and try the next
* block.
*/
fdbg("ERROR: Failed to read valid data into cache: %d\n", ret);
return ret;
}
}
while (ret != OK);

View file

@ -157,7 +157,9 @@ int nxffs_initialize(FAR struct mtd_dev_s *mtd)
{
FAR struct nxffs_volume_s *volume;
struct nxffs_blkstats_s stats;
#ifdef CONFIG_NXFFS_SCAN_VOLUME
off_t threshold;
#endif
int ret;
/* If CONFIG_NXFFS_PREALLOCATED is defined, then this is the single, pre-
@ -230,6 +232,7 @@ int nxffs_initialize(FAR struct mtd_dev_s *mtd)
volume->nblocks = volume->geo.neraseblocks * volume->blkper;
DEBUGASSERT((off_t)volume->blkper * volume->geo.blocksize == volume->geo.erasesize);
#ifdef CONFIG_NXFFS_SCAN_VOLUME
/* Check if there is a valid NXFFS file system on the flash */
ret = nxffs_blockstats(volume, &stats);
@ -243,7 +246,7 @@ int nxffs_initialize(FAR struct mtd_dev_s *mtd)
* blocks is high, then reformat the FLASH.
*/
threshold = stats.nblocks / 5;
threshold = (stats.nblocks * CONFIG_NXFFS_REFORMAT_THRESH) / 100;
if (stats.ngood < threshold || stats.nunformat > threshold)
{
/* Reformat the volume */
@ -266,6 +269,7 @@ int nxffs_initialize(FAR struct mtd_dev_s *mtd)
}
#endif
}
#endif /* CONFIG_NXFFS_SCAN_VOLUME */
/* Get the file system limits */
@ -275,6 +279,37 @@ int nxffs_initialize(FAR struct mtd_dev_s *mtd)
return OK;
}
/* We may need to format the volume. Try that before giving up. */
fdbg("WARNING: Failed to calculate file system limits: %d\n", -ret);
ret = nxffs_reformat(volume);
if (ret < 0)
{
fdbg("ERROR: Failed to reformat the volume: %d\n", -ret);
goto errout_with_buffer;
}
/* Get statistics on the re-formatted volume */
#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_FS)
ret = nxffs_blockstats(volume, &stats);
if (ret < 0)
{
fdbg("ERROR: Failed to collect block statistics: %d\n", -ret);
goto errout_with_buffer;
}
#endif
/* Now try to get the file system limits again */
ret = nxffs_limits(volume);
if (ret == OK)
{
return OK;
}
/* Now give up */
fdbg("ERROR: Failed to calculate file system limits: %d\n", -ret);
errout_with_buffer:
@ -382,6 +417,7 @@ int nxffs_limits(FAR struct nxffs_volume_s *volume)
offset = nxffs_inodeend(volume, &entry);
nxffs_freeentry(&entry);
}
fvdbg("Last inode before offset %d\n", offset);
}
@ -412,6 +448,7 @@ int nxffs_limits(FAR struct nxffs_volume_s *volume)
volume->inoffset = volume->froffset;
fvdbg("No inodes, inoffset: %d\n", volume->inoffset);
}
return OK;
}
@ -444,6 +481,7 @@ int nxffs_limits(FAR struct nxffs_volume_s *volume)
volume->inoffset = offset;
fvdbg("First inode at offset %d\n", volume->inoffset);
}
return OK;
}
}

View file

@ -1409,21 +1409,40 @@ start_pack:
eblock < volume->geo.neraseblocks;
eblock++)
{
/* Read the erase block into the pack buffer. We need to do this even
* if we are overwriting the entire block so that we skip over
* previously marked bad blocks.
*/
/* Get the starting block number of the erase block */
pack.block0 = eblock * volume->blkper;
ret = MTD_BREAD(volume->mtd, pack.block0, volume->blkper, volume->pack);
if (ret < 0)
{
fdbg("ERROR: Failed to read erase block %d: %d\n", eblock, -ret);
goto errout_with_pack;
}
/* Read the entire erase block into the pack buffer, one-block-at-a-
* time. We need to do this even if we are overwriting the entire
* block so that (1) we skip over previously marked bad blocks, and
* (2) we can handle individual block read failures.
*
* For most FLASH, a read failure indicates a fatal hardware failure.
* But for NAND FLASH, the read failure probably indicates a block
* with uncorrectable bit errors.
*/
/* Pack each I/O block */
for (i = 0, block = pack.block0, pack.iobuffer = volume->pack;
i < volume->blkper;
i++, block++, pack.iobuffer += volume->geo.blocksize)
{
/* Read the next block in the erase block */
ret = MTD_BREAD(volume->mtd, block, 1, pack.iobuffer);
if (ret < 0)
{
/* Force a the block to be an NXFFS bad block */
fdbg("ERROR: Failed to read block %d: %d\n", block, ret);
nxffs_blkinit(volume, pack.iobuffer, BLOCK_STATE_BAD);
}
}
/* Now ack each I/O block */
for (i = 0, block = pack.block0, pack.iobuffer = volume->pack;
i < volume->blkper;
i++, block++, pack.iobuffer += volume->geo.blocksize)

View file

@ -92,14 +92,11 @@ static int nxffs_format(FAR struct nxffs_volume_s *volume)
/* Create an image of one properly formatted erase sector */
memset(volume->pack, CONFIG_NXFFS_ERASEDSTATE, volume->geo.erasesize);
for (blkptr = volume->pack, i = 0;
i < volume->blkper;
blkptr += volume->geo.blocksize, i++)
{
FAR struct nxffs_block_s *blkhdr = (FAR struct nxffs_block_s*)blkptr;
memcpy(blkhdr->magic, g_blockmagic, NXFFS_MAGICSIZE);
blkhdr->state = BLOCK_STATE_GOOD;
nxffs_blkinit(volume, blkptr, BLOCK_STATE_GOOD);
}
/* Erase and format each erase block */
@ -149,7 +146,8 @@ static int nxffs_badblocks(FAR struct nxffs_volume_s *volume)
{
FAR uint8_t *blkptr; /* Pointer to next block data */
off_t eblock; /* Erase block number */
off_t lblock; /* Logical block number */
off_t lblock; /* Logical block number of the erase block */
off_t block; /* Working block number */
ssize_t nxfrd; /* Number of blocks transferred */
bool good; /* TRUE: block is good */
bool modified; /* TRUE: The erase block has been modified */
@ -159,31 +157,50 @@ static int nxffs_badblocks(FAR struct nxffs_volume_s *volume)
for (eblock = 0; eblock < volume->geo.neraseblocks; eblock++)
{
/* Read the entire erase block */
/* Get the logical block number of the erase block */
lblock = eblock * volume->blkper;
nxfrd = MTD_BREAD(volume->mtd, lblock, volume->blkper, volume->pack);
if (nxfrd != volume->blkper)
{
fdbg("ERROR: Read erase block %d failed: %d\n", lblock, nxfrd);
return -EIO;
}
/* Process each logical block */
/* Read the entire erase block into memory, processing each block one-
* at-a-time. We could read the entire erase block at once. That
* would be more efficient. However, for the case of NAND FLASH, each
* individual block can fail independently due to uncorrectable bit
* errors in that block.
*/
modified = false;
for (blkptr = volume->pack, i = 0;
for (i = 0, block = lblock, blkptr = volume->pack;
i < volume->blkper;
blkptr += volume->geo.blocksize, i++)
i++, block++, blkptr += volume->geo.blocksize)
{
FAR struct nxffs_block_s *blkhdr = (FAR struct nxffs_block_s*)blkptr;
/* Check block header */
/* Read the next block in the erase block */
good = true;
if (memcmp(blkhdr->magic, g_blockmagic, NXFFS_MAGICSIZE) != 0 ||
blkhdr->state != BLOCK_STATE_GOOD)
good = true;
nxfrd = MTD_BREAD(volume->mtd, block, i, blkptr);
if (nxfrd < 0)
{
/* Failed to read the block. This should never happen with
* most FLASH. However, for NAND this probably means that we
* read a block with uncorrectable bit errors.
*/
fdbg("ERROR: Failed to read block %d: %d\n",
block, (int)nxfrd);
good = false;
}
/* Check the block header */
else if (memcmp(blkhdr->magic, g_blockmagic, NXFFS_MAGICSIZE) != 0 ||
blkhdr->state != BLOCK_STATE_GOOD)
{
/* The block is not formated with the NXFFS magic bytes or else
* the block is specifically marked bad.
*/
good = false;
}
@ -196,15 +213,14 @@ static int nxffs_badblocks(FAR struct nxffs_volume_s *volume)
good = (blocksize == erasesize);
}
/* If the block is bad, attempt to re-write the block header indicating
* a bad block (of course, if the block has failed, this may not be
* possible, depending upon failure modes.
/* If the block is bad, attempt to re-write the block header
* indicating a bad block (of course, if the block has failed,
* this may not be possible, depending upon failure modes.
*/
if (!good)
{
memcpy(blkhdr->magic, g_blockmagic, NXFFS_MAGICSIZE);
blkhdr->state = BLOCK_STATE_BAD;
nxffs_blkinit(volume, blkptr, BLOCK_STATE_BAD);
modified = true;
}
}
@ -269,3 +285,30 @@ int nxffs_reformat(FAR struct nxffs_volume_s *volume)
return ret;
}
/****************************************************************************
* Name: nxffs_blkinit
*
* Description:
* Initialize an NXFFS block to the erased state with the specified block
* status.
*
* Input Parameters:
* volume - Describes the NXFFS volume (needed for the blocksize).
* blkptr - Pointer to the logic block to initialize.
* state - Either BLOCK_STATE_GOOD or BLOCK_STATE_BAD.
*
* Returned Value:
* None.
*
****************************************************************************/
void nxffs_blkinit(FAR struct nxffs_volume_s *volume, FAR uint8_t *blkptr,
uint8_t state)
{
FAR struct nxffs_block_s *blkhdr = (FAR struct nxffs_block_s*)blkptr;
memset(blkptr, CONFIG_NXFFS_ERASEDSTATE, volume->geo.blocksize);
memcpy(blkhdr->magic, g_blockmagic, NXFFS_MAGICSIZE);
blkhdr->state = state;
}

View file

@ -127,7 +127,8 @@ int nxffs_rminode(FAR struct nxffs_volume_s *volume, FAR const char *name)
ret = nxffs_rdcache(volume, volume->ioblock);
if (ret < 0)
{
fdbg("ERROR: Failed to read data into cache: %d\n", ret);
fdbg("ERROR: Failed to read block %d into cache: %d\n",
volume->ioblock, ret);
goto errout_with_entry;
}
@ -141,7 +142,8 @@ int nxffs_rminode(FAR struct nxffs_volume_s *volume, FAR const char *name)
ret = nxffs_wrcache(volume);
if (ret < 0)
{
fdbg("ERROR: Failed to read data into cache: %d\n", ret);
fdbg("ERROR: Failed to write block %d: %d\n",
volume->ioblock, ret);
}
errout_with_entry:

View file

@ -705,52 +705,64 @@ int nxffs_wrverify(FAR struct nxffs_volume_s *volume, size_t size)
ret = nxffs_rdcache(volume, volume->ioblock);
if (ret < 0)
{
fdbg("ERROR: Failed to read block %d: %d\n", volume->ioblock, -ret);
return ret;
/* Ignore the error... just skip to the next block. This should
* never happen with normal FLASH, but could occur with NAND if
* the block has uncorrectable bit errors.
*/
fdbg("ERROR: Failed to read block %d: %d\n",
volume->ioblock, -ret);
}
/* Search to the very end of this block if we have to */
iooffset = volume->iooffset;
nerased = 0;
for (i = volume->iooffset; i < volume->geo.blocksize; i++)
else
{
/* Is this byte erased? */
iooffset = volume->iooffset;
nerased = 0;
if (volume->cache[i] == CONFIG_NXFFS_ERASEDSTATE)
for (i = volume->iooffset; i < volume->geo.blocksize; i++)
{
/* Yes.. increment the count of contiguous, erased bytes */
/* Is this byte erased? */
nerased++;
/* Is the whole header memory erased? */
if (nerased >= size)
if (volume->cache[i] == CONFIG_NXFFS_ERASEDSTATE)
{
/* Yes.. this this is where we will put the object */
/* Yes.. increment the count of contiguous, erased bytes */
off_t offset = volume->ioblock * volume->geo.blocksize + iooffset;
nerased++;
/* Update the free flash offset and return success */
/* Is the whole header memory erased? */
volume->froffset = offset + size;
return OK;
if (nerased >= size)
{
/* Yes.. this this is where we will put the object */
off_t offset =
volume->ioblock * volume->geo.blocksize + iooffset;
/* Update the free flash offset and return success */
volume->froffset = offset + size;
return OK;
}
}
}
/* This byte is not erased! (It should be unless the block is bad) */
/* This byte is not erased! (It should be unless the block is
* bad)
*/
else
{
nerased = 0;
iooffset = i + 1;
else
{
nerased = 0;
iooffset = i + 1;
}
}
}
/* If we get here, then we have looked at every byte in the block
* and did not find any sequence of erased bytes long enough to hold
* the object. Skip to the next, valid block.
/* If we get here, then either (1) this block is not read-able, or
* (2) we have looked at every byte in the block and did not find
* any sequence of erased bytes long enough to hold the object.
* Skip to the next, valid block.
*/
volume->ioblock++;

View file

@ -1,7 +1,7 @@
/****************************************************************************
* include/nuttx/fs/nxffs.h
*
* Copyright (C) 2011-2012 Gregory Nutt. All rights reserved.
* Copyright (C) 2011-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -94,6 +94,19 @@
#undef CONFIG_NXFSS_PREALLOCATED
#define CONFIG_NXFSS_PREALLOCATED 1
/* If we were asked to scan the volume, then a re-formatting threshold must
* also be provided.
*/
#ifdef CONFIG_NXFFS_SCAN_VOLUME
# ifndef CONFIG_NXFFS_REFORMAT_THRESH
# define CONFIG_NXFFS_REFORMAT_THRESH 20
# endif
# if CONFIG_NXFFS_REFORMAT_THRESH < 0 || CONFIG_NXFFS_REFORMAT_THRESH > 100
# error CONFIG_NXFFS_REFORMAT_THRESH is not a valid percentage
# endif
#endif
/****************************************************************************
* Public Function Prototypes
****************************************************************************/