Misc NXFFS bugfixes

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3559 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo
2011-05-04 14:20:52 +00:00
parent a6a3a9b484
commit 4e23151cdd
5 changed files with 149 additions and 121 deletions
+4 -2
View File
@@ -754,12 +754,14 @@ extern FAR struct nxffs_ofile_s *nxffs_findofile(FAR struct nxffs_volume_s *volu
* Name: nxffs_wrinode * Name: nxffs_wrinode
* *
* Description: * Description:
* Write the inode header and inode file name to FLASH. This is done in * Write the inode header (only to FLASH. This is done in two contexts:
* two contexts:
* *
* 1. When an inode is closed, or * 1. When an inode is closed, or
* 2. As part of the file system packing logic when an inode is moved. * 2. As part of the file system packing logic when an inode is moved.
* *
* Note that in either case, the inode name has already been written to
* FLASH.
*
* Input parameters * Input parameters
* volume - Describes the NXFFS volume * volume - Describes the NXFFS volume
* entry - Describes the indoe header to write * entry - Describes the indoe header to write
+11 -9
View File
@@ -81,7 +81,6 @@ struct nxffs_blkinfo_s
static const char g_hdrformat[] = " BLOCK:OFFS TYPE STATE LENGTH\n"; static const char g_hdrformat[] = " BLOCK:OFFS TYPE STATE LENGTH\n";
static const char g_format[] = " %5d:%-5d %s %s %5d\n"; static const char g_format[] = " %5d:%-5d %s %s %5d\n";
static const char g_blkformat[] = "--%5d:%-5d %s %s %5d\n";
/**************************************************************************** /****************************************************************************
* Private Functions * Private Functions
@@ -292,7 +291,7 @@ static inline void nxffs_analyze(FAR struct nxffs_blkinfo_s *blkinfo)
blkhdr = (FAR struct nxffs_block_s *)blkinfo->buffer; blkhdr = (FAR struct nxffs_block_s *)blkinfo->buffer;
if (memcmp(blkhdr->magic, g_blockmagic, NXFFS_MAGICSIZE) != 0) if (memcmp(blkhdr->magic, g_blockmagic, NXFFS_MAGICSIZE) != 0)
{ {
fdbg(g_blkformat, blkinfo->block, 0, "BLOCK", "NO FRMT", fdbg(g_format, blkinfo->block, 0, "BLOCK", "NO FRMT",
blkinfo->geo.blocksize); blkinfo->geo.blocksize);
} }
else if (blkhdr->state == BLOCK_STATE_GOOD) else if (blkhdr->state == BLOCK_STATE_GOOD)
@@ -301,24 +300,26 @@ static inline void nxffs_analyze(FAR struct nxffs_blkinfo_s *blkinfo)
size_t nerased = nxffs_erased(blkinfo->buffer + SIZEOF_NXFFS_BLOCK_HDR, datsize); size_t nerased = nxffs_erased(blkinfo->buffer + SIZEOF_NXFFS_BLOCK_HDR, datsize);
if (nerased == datsize) if (nerased == datsize)
{ {
fdbg(g_blkformat, blkinfo->block, 0, "BLOCK", "ERASED ", fdbg(g_format, blkinfo->block, 0, "BLOCK", "ERASED ",
blkinfo->geo.blocksize); blkinfo->geo.blocksize);
return; return;
} }
#if 0 /* Too much output, to little information */
else else
{ {
fdbg(g_blkformat, blkinfo->block, 0, "BLOCK", "IN USE ", fdbg(g_format, blkinfo->block, 0, "BLOCK", "IN USE ",
blkinfo->geo.blocksize); blkinfo->geo.blocksize);
} }
#endif
} }
else if (blkhdr->state == BLOCK_STATE_BAD) else if (blkhdr->state == BLOCK_STATE_BAD)
{ {
fdbg(g_blkformat, blkinfo->block, 0, "BLOCK", "BAD ", fdbg(g_format, blkinfo->block, 0, "BLOCK", "BAD ",
blkinfo->geo.blocksize); blkinfo->geo.blocksize);
} }
else else
{ {
fdbg(g_blkformat, blkinfo->block, 0, "BLOCK", "CORRUPT", fdbg(g_format, blkinfo->block, 0, "BLOCK", "CORRUPT",
blkinfo->geo.blocksize); blkinfo->geo.blocksize);
} }
@@ -342,8 +343,9 @@ static inline void nxffs_analyze(FAR struct nxffs_blkinfo_s *blkinfo)
nbytes = nxffs_analyzeinode(blkinfo, hdrndx); nbytes = nxffs_analyzeinode(blkinfo, hdrndx);
if (nbytes > 0) if (nbytes > 0)
{ {
i = hdrndx + nbytes; i = hdrndx + nbytes - 1;
} }
inndx = 0;
} }
} }
else if (ch == g_datamagic[datndx]) else if (ch == g_datamagic[datndx])
@@ -355,11 +357,11 @@ static inline void nxffs_analyze(FAR struct nxffs_blkinfo_s *blkinfo)
{ {
hdrndx = i - NXFFS_MAGICSIZE + 1; hdrndx = i - NXFFS_MAGICSIZE + 1;
nbytes = nxffs_analyzedata(blkinfo, hdrndx); nbytes = nxffs_analyzedata(blkinfo, hdrndx);
nbytes = nxffs_analyzeinode(blkinfo, hdrndx);
if (nbytes > 0) if (nbytes > 0)
{ {
i = hdrndx + nbytes; i = hdrndx + nbytes - 1;
} }
datndx = 0;
} }
} }
} }
+86 -56
View File
@@ -111,7 +111,7 @@ static struct nxffs_wrfile_s g_wrfile;
* *
* On successful return the following are also valid: * On successful return the following are also valid:
* *
* wrfile->ofile.entry.hoffset - Flash offset to candidate header position * wrfile->ofile.entry.hoffset - FLASH offset to candidate header position
* volume->ioblock - Read/write block number of the block containing the * volume->ioblock - Read/write block number of the block containing the
* header position * header position
* volume->iooffset - The offset in the block to the candidate header * volume->iooffset - The offset in the block to the candidate header
@@ -165,7 +165,7 @@ static inline int nxffs_hdrpos(FAR struct nxffs_volume_s *volume,
* *
* On successful return the following are also valid: * On successful return the following are also valid:
* *
* wrfile->ofile.entry.noffset - Flash offset to candidate name position * wrfile->ofile.entry.noffset - FLASH offset to candidate name position
* volume->ioblock - Read/write block number of the block containing the * volume->ioblock - Read/write block number of the block containing the
* name position * name position
* volume->iooffset - The offset in the block to the candidate name * volume->iooffset - The offset in the block to the candidate name
@@ -227,7 +227,7 @@ static inline int nxffs_nampos(FAR struct nxffs_volume_s *volume,
* *
* On successful return the following are also valid: * On successful return the following are also valid:
* *
* wrfile->ofile.entry.hoffset - Flash offset to candidate header position * wrfile->ofile.entry.hoffset - FLASH offset to candidate header position
* volume->ioblock - Read/write block number of the block containing the * volume->ioblock - Read/write block number of the block containing the
* header position * header position
* volume->iooffset - The offset in the block to the candidate header * volume->iooffset - The offset in the block to the candidate header
@@ -288,7 +288,7 @@ static inline int nxffs_hdrerased(FAR struct nxffs_volume_s *volume,
* *
* On successful return the following are also valid: * On successful return the following are also valid:
* *
* wrfile->ofile.entry.noffset - Flash offset to candidate name position * wrfile->ofile.entry.noffset - FLASH offset to candidate name position
* volume->ioblock - Read/write block number of the block containing the * volume->ioblock - Read/write block number of the block containing the
* name position * name position
* volume->iooffset - The offset in the block to the candidate name * volume->iooffset - The offset in the block to the candidate name
@@ -315,6 +315,63 @@ static inline int nxffs_namerased(FAR struct nxffs_volume_s *volume,
return ret; return ret;
} }
/****************************************************************************
* Name: nxffs_wrname
*
* Description:
* Write the inode name to cache at the position verified by
* nxffs_namerased().
*
* On entry it assumes:
*
* entry->noffset - FLASH offset to final name position
* volume->ioblock - Read/write block number of the block containing the
* name position
* volume->iooffset - The offset in the block to the candidate name
* position.
*
* Input Parameters:
* volume - Describes the NXFFS volume
* entry - Describes the entry to be written.
*
* Returned Value:
* Zero is returned on success. Otherwise, a negated errno value is
* returned indicating the nature of the failure.
*
****************************************************************************/
static inline int nxffs_wrname(FAR struct nxffs_volume_s *volume,
FAR struct nxffs_entry_s *entry,
int namlen)
{
int ret;
/* Seek to the inode name position and assure that it is in the volume
* cache.
*/
nxffs_ioseek(volume, entry->noffset);
ret = nxffs_rdcache(volume, volume->ioblock);
if (ret < 0)
{
fdbg("Failed to read inode name block %d: %d\n",
volume->ioblock, -ret);
return ret;
}
/* Copy the inode name to the volume cache and write the inode name block */
memcpy(&volume->cache[volume->iooffset], entry->name, namlen);
ret = nxffs_wrcache(volume);
if (ret < 0)
{
fdbg("Failed to write inode header block %d: %d\n",
volume->ioblock, -ret);
}
return ret;
}
/**************************************************************************** /****************************************************************************
* Name: nxffs_wropen * Name: nxffs_wropen
* *
@@ -517,8 +574,7 @@ static inline int nxffs_wropen(FAR struct nxffs_volume_s *volume,
} }
/* Loop until the inode name is configured or until a failure occurs. /* Loop until the inode name is configured or until a failure occurs.
* Note that nothing is written to FLASH. The inode name is not * Note that nothing is written to FLASH.
* written until the file is closed.
*/ */
for (;;) for (;;)
@@ -535,8 +591,20 @@ static inline int nxffs_wropen(FAR struct nxffs_volume_s *volume,
ret = nxffs_namerased(volume, wrfile, namlen); ret = nxffs_namerased(volume, wrfile, namlen);
if (ret == OK) if (ret == OK)
{ {
/* Valid memory for the inode header was found. Break out of /* Valid memory for the inode header was found. Write the
* the loop. * inode name to this location.
*/
ret = nxffs_wrname(volume, &wrfile->ofile.entry, namlen);
if (ret < 0)
{
fdbg("Failed to write the inode name: %d\n", -ret);
goto errout_with_name;
}
/* Then just break out of the loop reporting success. Note
* that the alllocated inode name string is retained; it
* will be needed later to calculate the inode CRC.
*/ */
break; break;
@@ -1028,12 +1096,14 @@ errout:
* Name: nxffs_wrinode * Name: nxffs_wrinode
* *
* Description: * Description:
* Write the inode header and inode file name to FLASH. This is done in * Write the inode header (only to FLASH. This is done in two contexts:
* two contexts:
* *
* 1. When an inode is closed, or * 1. When an inode is closed, or
* 2. As part of the file system packing logic when an inode is moved. * 2. As part of the file system packing logic when an inode is moved.
* *
* Note that in either case, the inode name has already been written to
* FLASH.
*
* Input parameters * Input parameters
* volume - Describes the NXFFS volume * volume - Describes the NXFFS volume
* entry - Describes the indoe header to write * entry - Describes the indoe header to write
@@ -1044,25 +1114,16 @@ errout:
* *
****************************************************************************/ ****************************************************************************/
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)
{ {
FAR struct nxffs_inode_s *inode; FAR struct nxffs_inode_s *inode;
off_t namblock;
uint16_t namoffset;
uint32_t crc; uint32_t crc;
int namlen; int namlen;
int ret; int ret;
/* Write the inode header to FLASH. First get the block where we will /* Seek to the inode header position and assure that it is in the volume
* write the file name. * cache.
*/
nxffs_ioseek(volume, entry->noffset);
namblock = volume->ioblock;
namoffset = volume->iooffset;
/* Now seek to the inode header position and assure that it is in the
* volume cache.
*/ */
nxffs_ioseek(volume, entry->hoffset); nxffs_ioseek(volume, entry->hoffset);
@@ -1103,46 +1164,15 @@ int nxffs_wrinode(FAR struct nxffs_volume_s *volume, FAR struct nxffs_entry_s *e
inode->state = INODE_STATE_FILE; inode->state = INODE_STATE_FILE;
nxffs_wrle32(inode->crc, crc); nxffs_wrle32(inode->crc, crc);
/* Are the inode header and the inode name in the same block? Normally, /* Write the block with the inode header */
* they will be in the same block. However, they could potentially be
* far apart due to intervening bad blocks.
*/
if (volume->ioblock != namblock)
{
/* Write the block with the inode header */
ret = nxffs_wrcache(volume);
if (ret < 0)
{
fdbg("Failed to write inode header block %d: %d\n",
volume->ioblock, -ret);
goto errout;
}
/* Make sure the that block containing the inode name is in the cache */
volume->ioblock = namblock;
volume->iooffset = namoffset;
ret = nxffs_rdcache(volume, volume->ioblock);
if (ret < 0)
{
fdbg("Failed to read inode name block %d: %d\n",
volume->ioblock, -ret);
goto errout;
}
}
/* Finally, copy the inode name to the cache and write the inode name block */
memcpy(&volume->cache[namoffset], entry->name, namlen);
ret = nxffs_wrcache(volume); ret = nxffs_wrcache(volume);
if (ret < 0) if (ret < 0)
{ {
fdbg("Failed to write inode header block %d: %d\n", fdbg("Failed to write inode header block %d: %d\n",
volume->ioblock, -ret); volume->ioblock, -ret);
} }
/* The volume is now available for other writers */ /* The volume is now available for other writers */
errout: errout:
+43 -52
View File
@@ -475,7 +475,14 @@ static int nxffs_destsetup(FAR struct nxffs_volume_s *volume,
return -ENOSPC; return -ENOSPC;
} }
/* Yes.. reserve space for the inode name (but don't write it yet) */ /* Yes.. Write the inode name to the volume packing buffer now, but do
* not free the name string memory yet; it will be needed later to\
* calculate the header CRC.
*/
memcpy(&volume->pack[pack->iooffset], pack->dest.entry.name, namlen);
/* Reserve space for the inode name */
pack->dest.entry.noffset = nxffs_packtell(volume, pack); pack->dest.entry.noffset = nxffs_packtell(volume, pack);
pack->iooffset += namlen; pack->iooffset += namlen;
@@ -548,7 +555,9 @@ static int nxffs_destsetup(FAR struct nxffs_volume_s *volume,
* Name: nxffs_wrinodehdr * Name: nxffs_wrinodehdr
* *
* Description: * Description:
* Write the destination inode header to FLASH. * Write the destination inode header (only) to FLASH. Note that the inode
* name has already been written to FLASH (thus greatly simplifying the
* the complexity of this operation).
* *
* Input Parameters: * Input Parameters:
* volume - The volume to be packed * volume - The volume to be packed
@@ -565,64 +574,38 @@ static int nxffs_wrinodehdr(FAR struct nxffs_volume_s *volume,
{ {
FAR struct nxffs_inode_s *inode; FAR struct nxffs_inode_s *inode;
off_t ioblock; off_t ioblock;
off_t namblock;
uint16_t iooffset; uint16_t iooffset;
uint16_t namoffset;
uint32_t crc; uint32_t crc;
int namlen; int namlen;
int ret;
/* Get positions corresponding to the inode header and inode name positions */ /* Get seek positions corresponding to the inode header location */
ioblock = nxffs_getblock(volume, pack->dest.entry.hoffset); ioblock = nxffs_getblock(volume, pack->dest.entry.hoffset);
iooffset = nxffs_getoffset(volume, pack->dest.entry.hoffset, ioblock); iooffset = nxffs_getoffset(volume, pack->dest.entry.hoffset, ioblock);
namblock = nxffs_getblock(volume, pack->dest.entry.noffset);
namoffset = nxffs_getoffset(volume, pack->dest.entry.noffset, namblock);
/* The inode header is not written until all of the inode data has been /* The inode header is not written until all of the inode data has been
* packed into its new location. As a result, there are three possibilities: * packed into its new location. As a result, there are two possibilities:
* *
* 1. The inode header lies in the current, unwritten erase block, * 1. The inode header lies in the current, unwritten erase block,
* 2. The inode header resides in an earlier erase block and has already * 2. The inode header resides in an earlier erase block and has already
* been written to FLASH, but the inode name resides within the erase * been written to FLASH.
* block and has not been written to FLASH, or
* 3. The inode header resides in an earlier erase block and has already
* been written to FLASH (most likely case for files larger than an
* erase block).
* *
* Case 2 & 3: Does the inode header reside in a block before the beginning * Recall that the inode name has already been written to FLASH. If that
* were not the case, then there would be other complex possibilities.
*
* Case 2: Does the inode header reside in a block before the beginning
* of the current erase block? * of the current erase block?
*/ */
if (ioblock < pack->block0) if (ioblock < pack->block0)
{ {
/* Does the inode name also reside in a block before the beginning of /* Case 2: The inode header lies in an earlier erase block that has
* the current erase block? * already been written to FLASH. In this case, if we are very
* careful, we can just use the standard routine to write the inode
* header that is called during the normal file close operation:
*/ */
if (namblock < pack->block0) return nxffs_wrinode(volume, &pack->dest.entry);
{
/* Yes.. this is case 3: Both the inode block header and the inode
* name lie in an earlier erase block that has already been written
* to FLASH. In this case, if we are very careful, we can just use
* the standard routine to write the inode header that is called
* during the normal file close operation:
*/
ret = nxffs_wrinode(volume, &pack->dest.entry);
return ret;
}
else
{
/* Case 2: The inode header lies in an earlier erase block that
* has been written to FLASH but the inode name is in the cache and
* still unwritten.
*/
#warning "Missing logic"
return -ENOSYS;
}
} }
/* Cases 1: Both the inode header and name are in the unwritten cache memory. */ /* Cases 1: Both the inode header and name are in the unwritten cache memory. */
@@ -656,11 +639,6 @@ return -ENOSYS;
inode->state = INODE_STATE_FILE; inode->state = INODE_STATE_FILE;
nxffs_wrle32(inode->crc, crc); nxffs_wrle32(inode->crc, crc);
/* Write the inode name */
namoffset += (namblock - pack->block0) * volume->geo.blocksize;
memcpy(&volume->pack[namoffset], pack->dest.entry.name, namlen);
/* Reset the dest inode information */ /* Reset the dest inode information */
nxffs_freeentry(&pack->dest.entry); nxffs_freeentry(&pack->dest.entry);
@@ -692,14 +670,14 @@ static void nxffs_wrdathdr(FAR struct nxffs_volume_s *volume,
uint16_t iooffset; uint16_t iooffset;
uint32_t crc; uint32_t crc;
/* Get the offset in the block corresponding to the location of the inode /* Get the offset in the block corresponding to the location of the data
* header. NOTE: This must lie in the same block as we currently have * block header. NOTE: This must lie in the same block as we currently have
* buffered. * buffered.
*/ */
ioblock = nxffs_getblock(volume, pack->dest.entry.hoffset); ioblock = nxffs_getblock(volume, pack->dest.blkoffset);
iooffset = nxffs_getoffset(volume, pack->dest.entry.hoffset, ioblock); iooffset = nxffs_getoffset(volume, pack->dest.blkoffset, ioblock);
DEBUGASSERT(ioblock == pack->ioblock); DEBUGASSERT(pack->dest.blkoffset && ioblock == pack->ioblock);
/* Write the data block header to memory */ /* Write the data block header to memory */
@@ -915,7 +893,7 @@ static inline int nxffs_packblock(FAR struct nxffs_volume_s *volume,
/* Yes.. find the next data block in the source input stream. */ /* Yes.. find the next data block in the source input stream. */
offset = pack->src.blkoffset + pack->src.blklen; offset = pack->src.blkoffset + SIZEOF_NXFFS_BLOCK_HDR + pack->src.blklen;
ret = nxffs_nextblock(volume, offset, &blkentry); ret = nxffs_nextblock(volume, offset, &blkentry);
if (ret < 0) if (ret < 0)
{ {
@@ -1082,12 +1060,25 @@ int nxffs_pack(FAR struct nxffs_volume_s *volume)
} }
} }
/* We now have an in-memory image of how we want this erase block to
* appear. Now it is safe to erase the block.
*/
ret = MTD_ERASE(volume->mtd, eblock, 1);
if (ret < 0)
{
fdbg("Failed to erase block %d [%d]: %d\n",
eblock, pack.block0, -ret);
goto errout_with_pack;
}
/* Write the packed I/O block to FLASH */ /* Write the packed I/O block to FLASH */
ret = MTD_BWRITE(volume->mtd, pack.block0, volume->blkper, volume->pack); ret = MTD_BWRITE(volume->mtd, pack.block0, volume->blkper, volume->pack);
if (ret < 0) if (ret < 0)
{ {
fdbg("Failed to write erase block %d: %d\n", eblock, -ret); fdbg("Failed to write erase block %d [%]: %d\n",
eblock, pack.block0, -ret);
goto errout_with_pack; goto errout_with_pack;
} }
} }
+5 -2
View File
@@ -344,7 +344,7 @@ int nxffs_nextblock(FAR struct nxffs_volume_s *volume, off_t offset,
* FLASH seek location. * FLASH seek location.
*/ */
blkentry->hoffset = nxffs_iotell(volume) - 4; blkentry->hoffset = nxffs_iotell(volume) - NXFFS_MAGICSIZE;
/* Read the block header and verify the block at that address */ /* Read the block header and verify the block at that address */
@@ -356,8 +356,11 @@ int nxffs_nextblock(FAR struct nxffs_volume_s *volume, off_t offset,
return OK; return OK;
} }
/* False alarm.. keep looking */ /* False alarm.. Restore the volume cache position (that was
* destroyed by nxfs_rdblkhdr()) and keep looking.
*/
nxffs_ioseek(volume, blkentry->hoffset + NXFFS_MAGICSIZE);
nmagic = 0; nmagic = 0;
} }
} }