NXFFS is basically functional -- more testing needed

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3565 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo 2011-05-05 18:21:44 +00:00
parent 8865c298c6
commit 4aa6da9344
6 changed files with 193 additions and 102 deletions

View File

@ -177,7 +177,6 @@
#define NXFFS_MINDATA 16
/* Internal definitions *****************************************************/
/* If we encounter this number of erased bytes, we assume that all of the
* flash beyond this point is erased.
@ -640,6 +639,33 @@ extern int nxffs_findinode(FAR struct nxffs_volume_s *volume,
FAR const char *name,
FAR struct nxffs_entry_s *entry);
/****************************************************************************
* Name: nxffs_inodeend
*
* Description:
* Return an *approximiate* FLASH offset to end of the inode data. The
* returned value is guaranteed to be be less then or equal to the offset
* of the thing-of-interest in FLASH. Parsing for interesting things
* can begin at that point.
*
* Assumption: The inode header has been verified by the caller and is
* known to contain valid data.
*
* Input Parameters:
* volume - Describes the NXFFS volume
* entry - Describes the inode.
*
* Returned Value:
* A FLASH offset to the (approximate) end of the inode data. No errors
* are detected.
*
* Defined in nxffs_inode.c
*
****************************************************************************/
extern off_t nxffs_inodeend(FAR struct nxffs_volume_s *volume,
FAR struct nxffs_entry_s *entry);
/****************************************************************************
* Name: nxffs_verifyblock
*

View File

@ -166,14 +166,9 @@ int nxffs_readdir(FAR struct inode *mountpt, FAR struct fs_dirent_s *dir)
dir->fd_dir.d_type = DTYPE_FILE;
strncpy(dir->fd_dir.d_name, entry.name, NAME_MAX+1);
/* Discard this entry and set the next offset using the rw data
* length as the offset increment. This is, of course, not accurate
* because it does not account for the data headers that enclose the
* data. But it is guaranteed to be less than or equal to the
* correct offset and, hence, better then searching byte-for-byte.
*/
/* Discard this entry and set the next offset. */
dir->u.nxffs.nx_offset = entry.doffset + entry.datlen;
dir->u.nxffs.nx_offset = nxffs_inodeend(volume, &entry);
nxffs_freeentry(&entry);
ret = OK;
}

View File

@ -361,14 +361,9 @@ int nxffs_limits(FAR struct nxffs_volume_s *volume)
volume->inoffset = entry.hoffset;
fvdbg("First inode at offset %d\n", volume->inoffset);
/* Discard this entry and set the next offset using the rw data
* length as the offset increment. This is, of course, not accurate
* because it does not account for the data headers that enclose the
* data. But it is guaranteed to be less than or equal to the
* correct offset and, hence, better then searching byte-for-byte.
*/
/* Discard this entry and set the next offset. */
offset = entry.doffset + entry.datlen;
offset = nxffs_inodeend(volume, &entry);
nxffs_freeentry(&entry);
}
@ -378,9 +373,9 @@ int nxffs_limits(FAR struct nxffs_volume_s *volume)
{
while ((ret = nxffs_nextentry(volume, offset, &entry)) == OK)
{
/* Discard the entry and guess the next offset (see comments above). */
/* Discard the entry and guess the next offset. */
offset = entry.doffset + entry.datlen;
offset = nxffs_inodeend(volume, &entry);
nxffs_freeentry(&entry);
}
fvdbg("Last inode before offset %d\n", offset);

View File

@ -181,11 +181,11 @@ static int nxffs_rdentry(FAR struct nxffs_volume_s *volume, off_t offset,
if (state != INODE_STATE_FILE)
{
/* It is a deleted file. But still, the data offset and the
* start size is good so we can use this information to advance
* start size are good so we can use this information to advance
* further in FLASH memory and reduce the search time.
*/
offset = entry->doffset + entry->datlen + SIZEOF_NXFFS_DATA_HDR;
offset = nxffs_inodeend(volume, entry);
nxffs_freeentry(entry);
ret = -ENOENT;
goto errout;
@ -432,7 +432,7 @@ int nxffs_findinode(FAR struct nxffs_volume_s *volume, FAR const char *name,
* byte-for-byte.
*/
offset = entry->doffset + entry->datlen;
offset = nxffs_inodeend(volume, entry);
nxffs_freeentry(entry);
}
@ -440,3 +440,61 @@ int nxffs_findinode(FAR struct nxffs_volume_s *volume, FAR const char *name,
return -ENOENT;
}
/****************************************************************************
* Name: nxffs_inodeend
*
* Description:
* Return an *approximiate* FLASH offset to end of the inode data. The
* returned value is guaranteed to be be less then or equal to the offset
* of the thing-of-interest in FLASH. Parsing for interesting things
* can begin at that point.
*
* Assumption: The inode header has been verified by the caller and is
* known to contain valid data.
*
* Input Parameters:
* volume - Describes the NXFFS volume
* entry - Describes the inode.
*
* Returned Value:
* A FLASH offset to the (approximate) end of the inode data. No errors
* are detected.
*
****************************************************************************/
off_t nxffs_inodeend(FAR struct nxffs_volume_s *volume,
FAR struct nxffs_entry_s *entry)
{
/* A zero length file will have no data blocks */
if (entry->doffset)
{
/* This is the maximum size of one data block */
uint16_t maxsize = volume->geo.blocksize - SIZEOF_NXFFS_DATA_HDR;
/* This is the minimum number of blocks require to span all of the
* inode data. One additional block could possibly be required -- we
* could make this accurate by looking at the size of the first, perhaps
* partial, data block.
*/
off_t minblocks = (entry->datlen + maxsize - 1) / maxsize;
/* And this is our best, simple guess at the end of the inode data */
return entry->doffset + entry->datlen + minblocks * SIZEOF_NXFFS_DATA_HDR;
}
/* Otherwise, return an offset that accounts only for the inode header and
* the inode name.
*/
/* All valid inodes will have a name associated with them */
DEBUGASSERT(entry->noffset);
return entry->noffset + strlen(entry->name);
}

View File

@ -399,7 +399,8 @@ static inline int nxffs_startpos(FAR struct nxffs_volume_s *volume,
* Input Parameters:
* volume - The volume to be packed
* pack - The volume packing state structure.
* offset - FLASH offset to the data block header
* offset - FLASH offset to the data block header (will be zero for zero-
* files.
*
* Returned Values:
* Zero on success; Otherwise, a negated errno value is returned to
@ -410,22 +411,27 @@ static inline int nxffs_startpos(FAR struct nxffs_volume_s *volume,
static int nxffs_srcsetup(FAR struct nxffs_volume_s *volume,
FAR struct nxffs_pack_s *pack, off_t offset)
{
int ret;
/* No, start with the first data block */
/* Start with the first data block */
pack->src.blkoffset = offset;
pack->src.blkpos = 0;
/* Seek to the data block header, read and verify the block header */
/* Zero-length files have no valid data block offset */
ret = nxffs_rdblkhdr(volume, offset, &pack->src.blklen);
if (ret < 0)
if (offset > 0)
{
fdbg("Failed to verify the data block header: %d\n", -ret);
/* Seek to the data block header, read and verify the block header */
int ret = nxffs_rdblkhdr(volume, offset, &pack->src.blklen);
if (ret < 0)
{
fdbg("Failed to verify the data block header: %d\n", -ret);
}
return ret;
}
return ret;
DEBUGASSERT(pack->src.entry.datlen == 0);
return OK;
}
/****************************************************************************
@ -449,6 +455,7 @@ static int nxffs_destsetup(FAR struct nxffs_volume_s *volume,
{
size_t mindata;
int namlen;
int ret;
/* The destination can be in one of three of states:
*
@ -516,66 +523,77 @@ static int nxffs_destsetup(FAR struct nxffs_volume_s *volume,
/* State 3: Inode header not-written, inode name written. Still need the position
* of the first data block.
*
* Deal with the special case where the source inode is a zero length file
* with no data blocks to be transferred.
*/
if (pack->dest.entry.doffset == 0)
if (pack->src.entry.doffset > 0)
{
/* Will the data block header plus a minimal amount of data fit in this
* block? (or the whole file if the file is very small).
*/
mindata = MIN(NXFFS_MINDATA, pack->dest.entry.datlen);
if (pack->iooffset + SIZEOF_NXFFS_DATA_HDR + mindata > volume->geo.blocksize)
if (pack->dest.entry.doffset == 0)
{
/* No.. return an indication that we are at the end of the block
* and try again later.
/* Will the data block header plus a minimal amount of data fit in this
* block? (or the whole file if the file is very small).
*/
return -ENOSPC;
mindata = MIN(NXFFS_MINDATA, pack->dest.entry.datlen);
if (pack->iooffset + SIZEOF_NXFFS_DATA_HDR + mindata > volume->geo.blocksize)
{
/* No.. return an indication that we are at the end of the block
* and try again later.
*/
ret = -ENOSPC;
goto errout;
}
/* Yes.. reserve space for the data block header */
pack->dest.entry.doffset = nxffs_packtell(volume, pack);
pack->iooffset += SIZEOF_NXFFS_DATA_HDR;
/* Initialize the output data stream to start with the first data block */
pack->dest.blkoffset = pack->dest.entry.doffset;
pack->dest.blklen = 0;
pack->dest.blkpos = 0;
}
/* Yes.. reserve space for the data block header */
pack->dest.entry.doffset = nxffs_packtell(volume, pack);
pack->iooffset += SIZEOF_NXFFS_DATA_HDR;
/* Initialize the output data stream to start with the first data block */
pack->dest.blkoffset = pack->dest.entry.doffset;
pack->dest.blklen = 0;
pack->dest.blkpos = 0;
}
/* State 4: Starting a new block. Verify that there is space in the current
* block for another (minimal sized) block
*/
if (pack->dest.blkoffset == 0)
{
/* Will the data block header plus a minimal amount of data fit in this
* block? (or the whole file if the file is very small).
/* State 4: Starting a new block. Verify that there is space in the current
* block for another (minimal sized) block
*/
mindata = MIN(NXFFS_MINDATA, pack->dest.entry.datlen);
if (pack->iooffset + SIZEOF_NXFFS_DATA_HDR + mindata > volume->geo.blocksize)
if (pack->dest.blkoffset == 0)
{
/* No.. return an indication that we are at the end of the block
* and try again later.
/* Will the data block header plus a minimal amount of data fit in this
* block? (or the whole file if the file is very small).
*/
return -ENOSPC;
mindata = MIN(NXFFS_MINDATA, pack->dest.entry.datlen);
if (pack->iooffset + SIZEOF_NXFFS_DATA_HDR + mindata > volume->geo.blocksize)
{
/* No.. return an indication that we are at the end of the block
* and try again later.
*/
ret = -ENOSPC;
goto errout;
}
/* Yes.. reserve space for the data block header */
pack->dest.blkoffset = nxffs_packtell(volume, pack);
pack->iooffset += SIZEOF_NXFFS_DATA_HDR;
pack->dest.blklen = 0;
pack->dest.blkpos = 0;
}
/* Yes.. reserve space for the data block header */
pack->dest.blkoffset = nxffs_packtell(volume, pack);
pack->iooffset += SIZEOF_NXFFS_DATA_HDR;
pack->dest.blklen = 0;
pack->dest.blkpos = 0;
}
ret = OK;
errout:
volume->froffset = nxffs_packtell(volume, pack);
return OK;
return ret;
}
/****************************************************************************
@ -806,19 +824,22 @@ static inline int nxffs_packblock(FAR struct nxffs_volume_s *volume,
/* Transfer the smaller of the two amounts data */
uint16_t xfrlen = MIN(srclen, destlen);
nxffs_ioseek(volume, pack->src.blkoffset + SIZEOF_NXFFS_DATA_HDR + pack->src.blkpos);
memcpy(&pack->iobuffer[pack->iooffset], &volume->cache[volume->iooffset], xfrlen);
if (xfrlen > 0)
{
nxffs_ioseek(volume, pack->src.blkoffset + SIZEOF_NXFFS_DATA_HDR + pack->src.blkpos);
memcpy(&pack->iobuffer[pack->iooffset], &volume->cache[volume->iooffset], xfrlen);
/* Increment counts and offset for this data transfer */
/* Increment counts and offset for this data transfer */
pack->src.fpos += xfrlen; /* Source data offsets */
pack->src.blkpos += xfrlen;
pack->dest.fpos += xfrlen; /* Destination data offsets */
pack->dest.blkpos += xfrlen;
pack->dest.blklen += xfrlen; /* Destination data block size */
pack->iooffset += xfrlen; /* Destination I/O block offset */
volume->iooffset += xfrlen; /* Source I/O block offset */
volume->froffset += xfrlen; /* Free FLASH offset */
pack->src.fpos += xfrlen; /* Source data offsets */
pack->src.blkpos += xfrlen;
pack->dest.fpos += xfrlen; /* Destination data offsets */
pack->dest.blkpos += xfrlen;
pack->dest.blklen += xfrlen; /* Destination data block size */
pack->iooffset += xfrlen; /* Destination I/O block offset */
volume->iooffset += xfrlen; /* Source I/O block offset */
volume->froffset += xfrlen; /* Free FLASH offset */
}
/* Now, either the (1) src block has been fully transferred, (2) all
* of the source data has been transferred, or (3) the the destination
@ -839,7 +860,9 @@ static inline int nxffs_packblock(FAR struct nxffs_volume_s *volume,
/* Find the next valid source inode */
offset = pack->src.blkoffset + pack->src.blklen;
ret = nxffs_nextentry(volume, offset, &pack->src.entry);
memset(&pack->src, 0, sizeof(struct nxffs_packstream_s));
ret = nxffs_nextentry(volume, offset, &pack->src.entry);
if (ret < 0)
{
/* No more valid inode entries. Just return an end-of-flash error
@ -859,16 +882,11 @@ static inline int nxffs_packblock(FAR struct nxffs_volume_s *volume,
/* Setup the dest stream */
pack->dest.entry.hoffset = 0;
pack->dest.entry.noffset = 0;
pack->dest.entry.doffset = 0;
pack->dest.entry.name = pack->src.entry.name;
pack->dest.entry.utc = pack->src.entry.utc;
pack->dest.entry.datlen = pack->src.entry.datlen;
pack->dest.blkoffset = 0;
pack->dest.blklen = 0;
pack->dest.blkpos = 0;
pack->src.entry.name = NULL;
memset(&pack->dest, 0, sizeof(struct nxffs_packstream_s));
pack->dest.entry.name = pack->src.entry.name;
pack->dest.entry.utc = pack->src.entry.utc;
pack->dest.entry.datlen = pack->src.entry.datlen;
pack->src.entry.name = NULL;
/* Is there sufficient space at the end of the I/O block to hold
* the inode header?
@ -883,14 +901,7 @@ static inline int nxffs_packblock(FAR struct nxffs_volume_s *volume,
return OK;
}
/* Set the current inode header off to the current position and reserve
* the memory.
*/
pack->dest.entry.hoffset = nxffs_packtell(volume, pack);
pack->iooffset += SIZEOF_NXFFS_INODE_HDR;
/* Then configure the destination stream */
/* Configure the destination stream */
ret = nxffs_destsetup(volume, pack);
if (ret < 0)

View File

@ -101,6 +101,12 @@ static ssize_t nxffs_rdseek(FAR struct nxffs_volume_s *volume,
*/
offset = entry->doffset;
if (offset == 0)
{
/* Zero length files will have no data blocks */
return -ENOSPC;
}
/* Loop until we read the data block containing the desired position */