diff --git a/drivers/mtd/rammtd.c b/drivers/mtd/rammtd.c index 6a2e1f4c206b8af0425cbab5c1bcf675bd9876f6..a7adf4b99f1a83917d37ddeeb9a9b01146cf4bfd 100644 --- a/drivers/mtd/rammtd.c +++ b/drivers/mtd/rammtd.c @@ -127,13 +127,6 @@ static int ram_erase(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks DEBUGASSERT(dev); - /* Convert the erase block to a logical block and the number of blocks - * in logical block numbers - */ - - startblock *= CONFIG_RAMMTD_BLKPER; - nblocks *= CONFIG_RAMMTD_BLKPER; - /* Don't let the erase exceed the size of the ram buffer */ if (startblock >= priv->nblocks) @@ -141,11 +134,18 @@ static int ram_erase(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks return 0; } - if (startblock + nblocks >= priv->nblocks) + if (startblock + nblocks > priv->nblocks) { - nblocks = priv->nblocks - nblocks; + nblocks = priv->nblocks - startblock; } + /* Convert the erase block to a logical block and the number of blocks + * in logical block numbers + */ + + startblock *= CONFIG_RAMMTD_BLKPER; + nblocks *= CONFIG_RAMMTD_BLKPER; + /* Get the offset corresponding to the first block and the size * corresponding to the number of blocks. */ diff --git a/fs/nxffs/README.txt b/fs/nxffs/README.txt index 47a7d7f971bc6d050f78fbfb40c404d099e1b06b..8da14bf58cce137c0e596fae7c4c7bfe27b1670a 100755 --- a/fs/nxffs/README.txt +++ b/fs/nxffs/README.txt @@ -151,3 +151,6 @@ Things to Do may be necessary whenever an lseek() is done, but not in general. Read performance could be improved by keeping FLASH offset and read positional 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. + diff --git a/fs/nxffs/nxffs_dump.c b/fs/nxffs/nxffs_dump.c index fbd3807d35dab4615136936097f6ac16e576273a..889f10b528357ae484cee55799e4ba4734ef64f7 100644 --- a/fs/nxffs/nxffs_dump.c +++ b/fs/nxffs/nxffs_dump.c @@ -194,7 +194,7 @@ static inline ssize_t nxffs_analyzeinode(FAR struct nxffs_blkinfo_s *blkinfo, if (crc != ecrc) { - fdbg(g_format, blkinfo->block, offset, "INODE", "CRC ", datlen); + fdbg(g_format, blkinfo->block, offset, "INODE", "CRC BAD", datlen); return ERROR; } @@ -212,7 +212,10 @@ static inline ssize_t nxffs_analyzeinode(FAR struct nxffs_blkinfo_s *blkinfo, { fdbg(g_format, blkinfo->block, offset, "INODE", "CORRUPT", datlen); } - return noffs + inode.namlen - offset; + + /* Return the block-relative offset to the next byte after the inode name */ + + return noffs + inode.namlen - offset - blkinfo->offset; } #endif @@ -257,7 +260,7 @@ static inline ssize_t nxffs_analyzedata(FAR struct nxffs_blkinfo_s *blkinfo, if (crc != ecrc) { - fdbg(g_format, blkinfo->block, offset, "DATA ", "CRC ", datlen); + fdbg(g_format, blkinfo->block, offset, "DATA ", "CRC BAD", datlen); return ERROR; } diff --git a/fs/nxffs/nxffs_pack.c b/fs/nxffs/nxffs_pack.c index 9a80b41a9c5d7ac5387a9bf733078ec3c18b0766..b4dc10ccabcdcb7f495039d72b9c756d4276562e 100644 --- a/fs/nxffs/nxffs_pack.c +++ b/fs/nxffs/nxffs_pack.c @@ -450,6 +450,8 @@ static int nxffs_destsetup(FAR struct nxffs_volume_s *volume, { DEBUGASSERT(pack->iooffset + SIZEOF_NXFFS_INODE_HDR <= volume->geo.blocksize); pack->dest.entry.hoffset = nxffs_packtell(volume, pack); + memset(&pack->iobuffer[pack->iooffset], CONFIG_NXFFS_ERASEDSTATE, + SIZEOF_NXFFS_INODE_HDR); pack->iooffset += SIZEOF_NXFFS_INODE_HDR; } @@ -480,7 +482,7 @@ static int nxffs_destsetup(FAR struct nxffs_volume_s *volume, * calculate the header CRC. */ - memcpy(&volume->pack[pack->iooffset], pack->dest.entry.name, namlen); + memcpy(&pack->iobuffer[pack->iooffset], pack->dest.entry.name, namlen); /* Reserve space for the inode name */ @@ -688,7 +690,7 @@ static void nxffs_wrdathdr(FAR struct nxffs_volume_s *volume, /* Update the entire data block CRC (including the header) */ - crc = crc32(&volume->cache[volume->iooffset], pack->dest.blklen + SIZEOF_NXFFS_DATA_HDR); + crc = crc32(&pack->iobuffer[iooffset], pack->dest.blklen + SIZEOF_NXFFS_DATA_HDR); nxffs_wrle32(dathdr->crc, crc); /* Setup state to allocate the next data block */ @@ -788,6 +790,7 @@ static inline int nxffs_packblock(FAR struct nxffs_volume_s *volume, pack->src.blkpos += xfrlen; pack->dest.fpos += xfrlen; /* Destination data offsets */ pack->dest.blkpos += xfrlen; + pack->dest.blklen += xfrlen; /* Destination data block size */ volume->iooffset += xfrlen; /* Source I/O block offset */ pack->iooffset += xfrlen; /* Destination I/O block offset */ @@ -948,6 +951,7 @@ int nxffs_pack(FAR struct nxffs_volume_s *volume) off_t iooffset; off_t eblock; off_t block; + bool packed; int i; int ret; @@ -1002,11 +1006,15 @@ int nxffs_pack(FAR struct nxffs_volume_s *volume) * the ioblock and through the final erase block on the FLASH. */ + packed = false; for (eblock = pack.ioblock / volume->blkper; eblock < volume->geo.neraseblocks; eblock++) { - /* Read the erase block into the pack buffer. */ + /* 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. + */ pack.block0 = eblock * volume->blkper; ret = MTD_BREAD(volume->mtd, pack.block0, volume->blkper, volume->pack); @@ -1030,28 +1038,57 @@ int nxffs_pack(FAR struct nxffs_volume_s *volume) { /* Set the I/O position. Note on the first time we get * pack.iooffset will hold the offset in the first I/O block - * to the first inode header. + * to the first inode header. After that, it will always + * refer to the first byte after the block header. */ pack.ioblock = block; - /* Check if this is a valid block (it will be valid for the - * first block. + /* If this is not a valid block or if we have already + * finished packing the valid inode entries, then just fall + * through, reset the FLASH memory to the erase state, and + * write the reset values to FLASH. (The first block that + * we want to process will always be valid -- we have + * already verified that). */ - if (nxffs_packvalid(&pack)) + if (!packed && 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; + /* The error -ENOSPC is a special value that simply + * means that there is nothing further to be packed. + */ + + if (ret == -ENOSPC) + { + packed = true; + } + else + { + /* Otherwise, something really bad happened */ + + fdbg("Failed to pack into block %d: %d\n", + block, ret); + goto errout_with_pack; + } } } + /* Set any unused portion at the end of the block to the + * erased state. + */ + + if (pack.iooffset < volume->geo.blocksize) + { + memset(&pack.iobuffer[pack.iooffset], + CONFIG_NXFFS_ERASEDSTATE, + volume->geo.blocksize - pack.iooffset); + } + /* Next time we get here, pack.iooffset will point to the * first byte after the block header. */