diff options
author | patacongo <patacongo@7fd9a85b-ad96-42d3-883c-3090e2eb8679> | 2011-05-05 18:21:44 +0000 |
---|---|---|
committer | patacongo <patacongo@7fd9a85b-ad96-42d3-883c-3090e2eb8679> | 2011-05-05 18:21:44 +0000 |
commit | fd627dc2b8f485236fad8f3d08375282fdddd025 (patch) | |
tree | 4aac5e15a1f92756064fb8cbc477ea761457b536 | |
parent | 33b2bc77ba6f841b3fa50bf5cc49dc449010729f (diff) |
NXFFS is basically functional -- more testing needed
git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@3565 7fd9a85b-ad96-42d3-883c-3090e2eb8679
-rw-r--r-- | apps/examples/nxffs/nxffs_main.c | 45 | ||||
-rw-r--r-- | nuttx/fs/nxffs/nxffs.h | 28 | ||||
-rw-r--r-- | nuttx/fs/nxffs/nxffs_dirent.c | 11 | ||||
-rw-r--r-- | nuttx/fs/nxffs/nxffs_initialize.c | 13 | ||||
-rw-r--r-- | nuttx/fs/nxffs/nxffs_inode.c | 64 | ||||
-rw-r--r-- | nuttx/fs/nxffs/nxffs_pack.c | 169 | ||||
-rw-r--r-- | nuttx/fs/nxffs/nxffs_read.c | 6 |
7 files changed, 224 insertions, 112 deletions
diff --git a/apps/examples/nxffs/nxffs_main.c b/apps/examples/nxffs/nxffs_main.c index 12383071a7..b2a6846c09 100644 --- a/apps/examples/nxffs/nxffs_main.c +++ b/apps/examples/nxffs/nxffs_main.c @@ -251,9 +251,16 @@ static inline int nxffs_wrfile(FAR struct nxffs_filedesc_s *file) fd = open(file->name, O_WRONLY | O_CREAT | O_EXCL, 0666); if (fd < 0) { - message("ERROR: Failed to open file for writing: %d\n", errno); - message(" File name: %s\n", file->name); - message(" File size: %d\n", file->len); + /* If it failed because there is no space on the device, then don't + * complain. + */ + + if (errno != ENOSPC) + { + message("ERROR: Failed to open file for writing: %d\n", errno); + message(" File name: %s\n", file->name); + message(" File size: %d\n", file->len); + } nxffs_freefile(file); return ERROR; } @@ -274,11 +281,21 @@ static inline int nxffs_wrfile(FAR struct nxffs_filedesc_s *file) nbyteswritten = write(fd, &g_fileimage[offset], nbytestowrite); if (nbyteswritten < 0) { - message("ERROR: Failed to write file: %d\n", errno); - message(" File name: %s\n", file->name); - message(" File size: %d\n", file->len); - message(" Write offset: %d\n", offset); - message(" Write size: %d\n", nbytestowrite); + int err = errno; + + /* If the write failed because there is no space on the device, + * then don't complain. + */ + + if (err != ENOSPC) + { + message("ERROR: Failed to write file: %d\n", err); + message(" File name: %s\n", file->name); + message(" File size: %d\n", file->len); + message(" Write offset: %d\n", offset); + message(" Write size: %d\n", nbytestowrite); + ret = ERROR; + } close(fd); /* Remove any garbage file that might have been left behind */ @@ -286,11 +303,13 @@ static inline int nxffs_wrfile(FAR struct nxffs_filedesc_s *file) ret = unlink(file->name); if (ret < 0) { - message(" Failed to remove corrupted file\n"); + message(" Failed to remove partial file\n"); } else { - message(" Successfully removed corrupted file\n"); +#if CONFIG_EXAMPLES_NXFFS_VERBOSE != 0 + message(" Successfully removed partial file\n"); +#endif } nxffs_freefile(file); @@ -332,7 +351,9 @@ static int nxffs_fillfs(void) ret = nxffs_wrfile(file); if (ret < 0) { +#if CONFIG_EXAMPLES_NXFFS_VERBOSE != 0 message("ERROR: Failed to write file %d\n", i); +#endif return ERROR; } @@ -645,8 +666,8 @@ static int nxffs_directory(void) int user_start(int argc, char *argv[]) { FAR struct mtd_dev_s *mtd; + unsigned int i; int ret; - int i; /* Seed the random number generated */ @@ -688,7 +709,7 @@ int user_start(int argc, char *argv[]) */ #if CONFIG_EXAMPLES_NXFFS_NLOOPS == 0 - for (;;) + for (i = 0; ; i++) #else for (i = 1; i <= CONFIG_EXAMPLES_NXFFS_NLOOPS; i++) #endif diff --git a/nuttx/fs/nxffs/nxffs.h b/nuttx/fs/nxffs/nxffs.h index 735e4fc0aa..262c8577e8 100644 --- a/nuttx/fs/nxffs/nxffs.h +++ b/nuttx/fs/nxffs/nxffs.h @@ -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. @@ -641,6 +640,33 @@ extern int nxffs_findinode(FAR struct nxffs_volume_s *volume, 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 * * Description: diff --git a/nuttx/fs/nxffs/nxffs_dirent.c b/nuttx/fs/nxffs/nxffs_dirent.c index bd53ffe0ce..40ae8662f4 100644 --- a/nuttx/fs/nxffs/nxffs_dirent.c +++ b/nuttx/fs/nxffs/nxffs_dirent.c @@ -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. - */ - - dir->u.nxffs.nx_offset = entry.doffset + entry.datlen; + /* Discard this entry and set the next offset. */ + + dir->u.nxffs.nx_offset = nxffs_inodeend(volume, &entry); nxffs_freeentry(&entry); ret = OK; } diff --git a/nuttx/fs/nxffs/nxffs_initialize.c b/nuttx/fs/nxffs/nxffs_initialize.c index c040fa6499..7fd1d51fc5 100644 --- a/nuttx/fs/nxffs/nxffs_initialize.c +++ b/nuttx/fs/nxffs/nxffs_initialize.c @@ -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); diff --git a/nuttx/fs/nxffs/nxffs_inode.c b/nuttx/fs/nxffs/nxffs_inode.c index 361b5df7ee..121c1f6db4 100644 --- a/nuttx/fs/nxffs/nxffs_inode.c +++ b/nuttx/fs/nxffs/nxffs_inode.c @@ -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); +} + + diff --git a/nuttx/fs/nxffs/nxffs_pack.c b/nuttx/fs/nxffs/nxffs_pack.c index d4a7d5f39e..212d2b4293 100644 --- a/nuttx/fs/nxffs/nxffs_pack.c +++ b/nuttx/fs/nxffs/nxffs_pack.c @@ -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. + */ - /* Yes.. reserve space for the data block header */ + ret = -ENOSPC; + goto errout; + } - pack->dest.entry.doffset = nxffs_packtell(volume, pack); - pack->iooffset += SIZEOF_NXFFS_DATA_HDR; + /* Yes.. reserve space for the data block header */ - /* Initialize the output data stream to start with the first data block */ + pack->dest.entry.doffset = nxffs_packtell(volume, pack); + pack->iooffset += SIZEOF_NXFFS_DATA_HDR; - pack->dest.blkoffset = pack->dest.entry.doffset; - pack->dest.blklen = 0; - pack->dest.blkpos = 0; - } + /* Initialize the output data stream to start with the first data block */ - /* State 4: Starting a new block. Verify that there is space in the current - * block for another (minimal sized) block - */ + pack->dest.blkoffset = pack->dest.entry.doffset; + pack->dest.blklen = 0; + pack->dest.blkpos = 0; + } - 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 */ + /* 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; + 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); - - /* 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 */ + 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 */ + } /* 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) diff --git a/nuttx/fs/nxffs/nxffs_read.c b/nuttx/fs/nxffs/nxffs_read.c index f52e218598..cf9bf78e0a 100644 --- a/nuttx/fs/nxffs/nxffs_read.c +++ b/nuttx/fs/nxffs/nxffs_read.c @@ -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 */ |