9
0
Fork 0

Finish logic to update open writer after packing

git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@3568 7fd9a85b-ad96-42d3-883c-3090e2eb8679
This commit is contained in:
patacongo 2011-05-05 23:31:44 +00:00
parent 75bbfc1095
commit 5cb1f29723
3 changed files with 367 additions and 130 deletions

View File

@ -108,7 +108,7 @@ int nxffs_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
goto errout;
}
/* Only a reformat command is supported */
/* Only a reformat and optimize commands are supported */
if (cmd == FIOC_REFORMAT)
{
@ -126,12 +126,22 @@ int nxffs_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
/* Re-format the volume -- all is lost */
ret = nxffs_reformat(volume);
goto errout_with_semaphore;
}
else if (cmd == FIOC_OPTIMIZE)
{
fvdbg("Optimize command\n");
/* Pack the volume */
ret = nxffs_pack(volume);
}
else
{
/* No other commands supported */
ret = -ENOTTY;
}
errout_with_semaphore:
sem_post(&volume->exclsem);

View File

@ -726,6 +726,8 @@ static void nxffs_wrdathdr(FAR struct nxffs_volume_s *volume,
uint16_t iooffset;
uint32_t crc;
if (pack->dest.blklen > 0)
{
/* Get the offset in the block corresponding to the location of the data
* block header. NOTE: This must lie in the same block as we currently have
* buffered.
@ -746,6 +748,7 @@ static void nxffs_wrdathdr(FAR struct nxffs_volume_s *volume,
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 */
@ -754,6 +757,95 @@ static void nxffs_wrdathdr(FAR struct nxffs_volume_s *volume,
pack->dest.blkpos = 0;
}
/****************************************************************************
* Name: nxffs_packtransfer
*
* Description:
* Transfer data from the source to the destination buffer.
*
* Input Parameters:
* volume - The volume to be packed
* pack - The volume packing state structure.
*
* Returned Values:
* None.
*
****************************************************************************/
static void nxffs_packtransfer(FAR struct nxffs_volume_s *volume,
FAR struct nxffs_pack_s *pack)
{
/* Determine how much data is available in the dest pack buffer */
uint16_t destlen = volume->geo.blocksize - pack->iooffset;
/* Dermined how much data is available in the src data block */
uint16_t srclen = pack->src.blklen - pack->src.blkpos;
/* Transfer the smaller of the two amounts data */
uint16_t xfrlen = MIN(srclen, destlen);
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 */
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 */
}
}
/****************************************************************************
* Name: nxffs_endsrcblock
*
* Description:
* The end of a source data block has been encountered. Locate the next
* source block and setup to continue the transfer.
*
* 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 int nxffs_endsrcblock(FAR struct nxffs_volume_s *volume,
FAR struct nxffs_pack_s *pack)
{
struct nxffs_blkentry_s blkentry;
off_t offset;
int ret;
/* Yes.. find the next data block in the source input stream. */
offset = pack->src.blkoffset + SIZEOF_NXFFS_DATA_HDR + pack->src.blklen;
ret = nxffs_nextblock(volume, offset, &blkentry);
if (ret < 0)
{
fdbg("Failed to find next data block: %d\n", -ret);
return ret;
}
/* Set up the source stream */
pack->src.blkoffset = blkentry.hoffset;
pack->src.blklen = blkentry.datlen;
pack->src.blkpos = 0;
return OK;
}
/****************************************************************************
* Name: nxffs_packblock
*
@ -801,9 +893,9 @@ static inline int nxffs_packblock(FAR struct nxffs_volume_s *volume,
ret = nxffs_destsetup(volume, pack);
if (ret < 0)
{
/* -ENOSPC is a special return value which simply means that all of the
* has been used up to the end. We need to return OK in this case and
* resume at the next block.
/* -ENOSPC is a special return value which simply means that all of
* the FLASH has been used up to the end of the current. We need to
* return OK in this case and resume at the next block.
*/
if (ret == -ENOSPC)
@ -824,33 +916,9 @@ static inline int nxffs_packblock(FAR struct nxffs_volume_s *volume,
for (;;)
{
/* Determine how much data is available in the dest pack buffer */
/* Transfer data from the source buffer to the destination buffer */
uint16_t destlen = volume->geo.blocksize - pack->iooffset;
/* Dermined how much data is available in the src data block */
uint16_t srclen = pack->src.blklen - pack->src.blkpos;
/* Transfer the smaller of the two amounts data */
uint16_t xfrlen = MIN(srclen, destlen);
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 */
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 */
}
nxffs_packtransfer(volume, pack);
/* Now, either the (1) src block has been fully transferred, (2) all
* of the source data has been transferred, or (3) the the destination
@ -940,23 +1008,11 @@ static inline int nxffs_packblock(FAR struct nxffs_volume_s *volume,
else if (pack->src.blkpos >= pack->src.blklen)
{
struct nxffs_blkentry_s blkentry;
/* Yes.. find the next data block in the source input stream. */
offset = pack->src.blkoffset + SIZEOF_NXFFS_DATA_HDR + pack->src.blklen;
ret = nxffs_nextblock(volume, offset, &blkentry);
ret = nxffs_endsrcblock(volume, pack);
if (ret < 0)
{
fdbg("Failed to find next data block: %d\n", -ret);
return ret;
}
/* Set up the source stream */
pack->src.blkoffset = blkentry.hoffset;
pack->src.blklen = blkentry.datlen;
pack->src.blkpos = 0;
}
/* Check if the destination block is full */
@ -973,6 +1029,70 @@ static inline int nxffs_packblock(FAR struct nxffs_volume_s *volume,
return -ENOSYS;
}
/****************************************************************************
* Name: nxffs_setupwriter
*
* Description:
* Writing is performed at the end of the free FLASH region. When we
* finish packing the other inodes, we still need to pack the partially
* written file at the end of FLASH. This function performs the setup
* necessary to perform that packing phase.
*
* Input Parameters:
* volume - The volume to be packed
* pack - The volume packing state structure.
*
* Returned Values:
* If there is an active writer of the volume, its open file instance is
* returned. NULL is returned otherwise.
*
****************************************************************************/
static FAR struct nxffs_wrfile_s *
nxffs_setupwriter(FAR struct nxffs_volume_s *volume,
FAR struct nxffs_pack_s *pack)
{
FAR struct nxffs_wrfile_s *wrfile;
/* Is there a writer? */
wrfile = nxffs_findwriter(volume);
if (wrfile)
{
/* Yes... It is the activity of this write that probably initiated
* this packing activity. The writer may have failed in one of several
* different stages:
*
* hoffset == 0: The write failed early before even FLASH for the inode
* header was set aside.
* noffset == 0: The write failed after the inode header was set aside,
* but before the inode name was written.
* doffset == 0: The write failed after writing the inode name, bue
* before any data blocks were written to FLASH.
*
* If no FLASH has been set aside for the write, then we don't need to
* do anything here.
*/
if (wrfile->ofile.entry.hoffset > 0)
{
/* Initialize for the packing operation. */
memset(&pack->dest, 0, sizeof(struct nxffs_packstream_s));
pack->dest.entry.name = strdup(wrfile->ofile.entry.name);
pack->dest.entry.utc = wrfile->ofile.entry.utc;
pack->dest.entry.datlen = wrfile->ofile.entry.datlen;
memset(&pack->src, 0, sizeof(struct nxffs_packstream_s));
memcpy(&pack->src.entry, &wrfile->ofile.entry, sizeof(struct nxffs_entry_s));
pack->src.entry.name = NULL;
return wrfile;
}
}
return NULL;
}
/****************************************************************************
* Name: nxffs_packwriter
*
@ -1000,9 +1120,113 @@ static inline int nxffs_packwriter(FAR struct nxffs_volume_s *volume,
FAR struct nxffs_pack_s *pack,
FAR struct nxffs_wrfile_s *wrfile)
{
#warning "Missing logic"
int ret;
/* Are we currently processing a block from the source stream? */
if (pack->src.blkoffset == 0)
{
/* No.. setup the source stream */
ret = nxffs_srcsetup(volume, pack, pack->src.entry.doffset);
if (ret < 0)
{
fdbg("Failed to configure the src stream: %d\n", -ret);
return ret;
}
}
/* We enter here on a new block every time, so we always have to setup
* the dest data stream. There should never be data block allocated at
* this point in time.
*/
DEBUGASSERT(pack->dest.blkoffset == 0 && pack->dest.blkpos == 0);
ret = nxffs_destsetup(volume, pack);
if (ret < 0)
{
/* -ENOSPC is a special return value which simply means that all of the
* has been used up to the end. We need to return OK in this case and
* resume at the next block.
*/
if (ret == -ENOSPC)
{
return OK;
}
else
{
fdbg("Failed to configure the dest stream: %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 (;;)
{
/* Transfer data from the source buffer to the destination buffer */
nxffs_packtransfer(volume, pack);
/* Now, either the (1) src block has been fully transferred, (2) all
* of the source data has been transferred, or (3) the the destination
* block is full, .. or all three.
*
* Check if all of the bytes in the source inode have been transferred.
*/
if (pack->src.fpos >= pack->src.entry.datlen)
{
/* Write the final destination data block header and inode
* headers.
*/
nxffs_wrdathdr(volume, pack);
/* Set the new offsets in the open file instance. */
wrfile->ofile.entry.hoffset = pack->dest.entry.hoffset;
wrfile->ofile.entry.noffset = pack->dest.entry.noffset;
wrfile->ofile.entry.doffset = pack->dest.entry.doffset;
/* Return an end-of-flash error to indicate that all of the write
* data has been transferred.
*/
return -ENOSPC;
}
/* Not at the end of the source data stream. Check if we are at the
* end of the current source data block.
*/
else if (pack->src.blkpos >= pack->src.blklen)
{
ret = nxffs_endsrcblock(volume, pack);
if (ret < 0)
{
return ret;
}
}
/* Check if the destination block is full */
if (pack->iooffset >= volume->geo.blocksize)
{
/* Yes.. Write the destination data block header and return success */
nxffs_wrdathdr(volume, pack);
return OK;
}
}
return -ENOSYS;
}
/****************************************************************************
* Public Functions
@ -1084,7 +1308,7 @@ int nxffs_pack(FAR struct nxffs_volume_s *volume)
* the partially written file at the end of FLASH.
*/
wrfile = nxffs_findwriter(volume);
wrfile = nxffs_setupwriter(volume, &pack);
}
/* Otherwise return OK.. meaning that there is nothing more we can
@ -1190,7 +1414,7 @@ int nxffs_pack(FAR struct nxffs_volume_s *volume)
* and so will not be found by nxffs_packblock().
*/
wrfile = nxffs_findwriter(volume);
wrfile = nxffs_setupwriter(volume, &pack);
}
else
{

View File

@ -97,6 +97,9 @@
#define FIOC_REFORMAT _FIOC(0x0002) /* IN: None
* OUT: None
*/
#define FIOC_OPTIMIZE _FIOC(0x0003) /* IN: None
* OUT: None
*/
/* NuttX file system ioctl definitions */