From f24821c3fad49b29783d8e7227417826647d1db7 Mon Sep 17 00:00:00 2001 From: patacongo Date: Mon, 2 May 2011 01:30:30 +0000 Subject: [PATCH] More NXFFS bugfixes git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3550 42af7a65-404d-4744-a932-0658087f49c3 --- TODO | 2 + configs/sim/nxffs/defconfig | 2 +- fs/nxffs/nxffs_dump.c | 6 +-- fs/nxffs/nxffs_open.c | 69 ++++++++++++++++++--------- fs/nxffs/nxffs_read.c | 93 ++++++++++++++++++++++++------------- fs/nxffs/nxffs_write.c | 20 ++++---- 6 files changed, 126 insertions(+), 66 deletions(-) diff --git a/TODO b/TODO index 24666fc926..23e9c72004 100644 --- a/TODO +++ b/TODO @@ -392,6 +392,8 @@ o Libraries (lib/) o File system / Generic drivers (fs/, drivers/) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + NOTE: The NXFFS file system has its own TODO list at nuttx/fs/nxffs/README.txt + Description: Implement chmod(), truncate(). Status: Open Priority: Low diff --git a/configs/sim/nxffs/defconfig b/configs/sim/nxffs/defconfig index c3edcfc155..acedc357da 100644 --- a/configs/sim/nxffs/defconfig +++ b/configs/sim/nxffs/defconfig @@ -116,7 +116,7 @@ CONFIG_ARCH_BOARD_SIM=y # #CONFIG_APPS_DIR= CONFIG_DEBUG=y -CONFIG_DEBUG_VERBOSE=y +CONFIG_DEBUG_VERBOSE=n CONFIG_DEBUG_SYMBOLS=y CONFIG_DEBUG_FS=y CONFIG_MM_REGIONS=1 diff --git a/fs/nxffs/nxffs_dump.c b/fs/nxffs/nxffs_dump.c index ccbaf320e6..5534af7495 100644 --- a/fs/nxffs/nxffs_dump.c +++ b/fs/nxffs/nxffs_dump.c @@ -193,12 +193,12 @@ static inline ssize_t nxffs_analyzeinode(FAR struct nxffs_blkinfo_s *blkinfo, /* If must be a good header */ - if (state = INODE_STATE_FILE) + if (state == INODE_STATE_FILE) { fdbg(" Block %d:%d: Verified FILE inode, datlen: %d\n", blkinfo->block, offset, datlen); } - else if (state = INODE_STATE_DELETED) + else if (state == INODE_STATE_DELETED) { fdbg(" Block %d:%d: Verified DELETED inode, datlen: %d\n", blkinfo->block, offset, datlen); @@ -249,7 +249,7 @@ static inline ssize_t nxffs_analyzedata(FAR struct nxffs_blkinfo_s *blkinfo, nxffs_wrle32(dathdr.crc, 0); crc = crc32((FAR const uint8_t *)&dathdr, SIZEOF_NXFFS_DATA_HDR); - crc = crc32part(&blkinfo->buffer[blkinfo->offset + SIZEOF_NXFFS_DATA_HDR], datlen, crc); + crc = crc32part(&blkinfo->buffer[offset + SIZEOF_NXFFS_DATA_HDR], datlen, crc); if (crc != ecrc) { diff --git a/fs/nxffs/nxffs_open.c b/fs/nxffs/nxffs_open.c index 604d1a0f42..0c101b78e0 100644 --- a/fs/nxffs/nxffs_open.c +++ b/fs/nxffs/nxffs_open.c @@ -702,15 +702,15 @@ errout: } /**************************************************************************** - * Name: nxffs_freeofile + * Name: nxffs_remofile * * Description: - * Free resources held by an open file. + * Remove an entry from the open file list. * ****************************************************************************/ -static inline void nxffs_freeofile(FAR struct nxffs_volume_s *volume, - FAR struct nxffs_ofile_s *ofile) +static inline void nxffs_remofile(FAR struct nxffs_volume_s *volume, + FAR struct nxffs_ofile_s *ofile) { FAR struct nxffs_ofile_s *prev; FAR struct nxffs_ofile_s *curr; @@ -735,21 +735,6 @@ static inline void nxffs_freeofile(FAR struct nxffs_volume_s *volume, { volume->ofiles = ofile->flink; } - - /* Release the open file entry */ - - nxffs_freeentry(&ofile->entry); - - /* Then free the open file container (unless this the pre-alloated - * write-only open file container) - */ - -#ifdef CONFIG_NXFSS_PREALLOCATED - if ((FAR struct nxffs_wrfile_s*)ofile != &g_wrfile) -#endif - { - kfree(ofile); - } } else { @@ -757,6 +742,33 @@ static inline void nxffs_freeofile(FAR struct nxffs_volume_s *volume, } } +/**************************************************************************** + * Name: nxffs_freeofile + * + * Description: + * Free resources held by an open file. + * + ****************************************************************************/ + +static inline void nxffs_freeofile(FAR struct nxffs_volume_s *volume, + FAR struct nxffs_ofile_s *ofile) +{ + /* Release the open file entry */ + + nxffs_freeentry(&ofile->entry); + + /* Then free the open file container (unless this the pre-alloated + * write-only open file container) + */ + +#ifdef CONFIG_NXFSS_PREALLOCATED + if ((FAR struct nxffs_wrfile_s*)ofile != &g_wrfile) +#endif + { + kfree(ofile); + } +} + /**************************************************************************** * Name: nxffs_wrclose * @@ -797,6 +809,13 @@ static int nxffs_wrclose(FAR struct nxffs_volume_s *volume, } } + /* Truncation is implemented by writing the new file, then deleting the + * older version of the file. Note that we removed the entry from the + * open file list earlier in the close sequence; this will prevent the + * open file check from failing when we remove the old version of the + * file. + */ + if (wrfile->truncate && wrfile->ofile.entry.name) { fvdbg("Removing old file: %s\n", wrfile->ofile.entry.name); @@ -1059,16 +1078,22 @@ int nxffs_close(FAR struct file *filep) ret = OK; if (ofile->crefs == 1) { - /* Decrementing the reference count would take it zero. Handle - * finalization of the write operation. + /* Decrementing the reference count would take it zero. + * + * Remove the entry from the open file list. We do this early + * to avoid some chick-and-egg problems with file truncation. */ + nxffs_remofile(volume, ofile); + + /* Handle special finalization of the write operation. */ + if (ofile->mode == O_WROK) { ret = nxffs_wrclose(volume, (FAR struct nxffs_wrfile_s *)ofile); } - /* Delete the open file state structure */ + /* Release all resouces held by the open file */ nxffs_freeofile(volume, ofile); } diff --git a/fs/nxffs/nxffs_read.c b/fs/nxffs/nxffs_read.c index 91bff39566..bfc4270b40 100644 --- a/fs/nxffs/nxffs_read.c +++ b/fs/nxffs/nxffs_read.c @@ -65,6 +65,7 @@ struct nxffs_blkentry_s { off_t hoffset; /* Offset to the block data header */ uint16_t datlen; /* Length of data following the header */ + uint16_t foffset; /* Offset to start of data */ }; /**************************************************************************** @@ -273,17 +274,18 @@ int nxffs_nextblock(FAR struct nxffs_volume_s *volume, off_t offset, * data headers. * * Input Parameters: - * volume - Describes the current volume - * entry - Describes the open inode - * fpos - The desired file position + * volume - Describes the current volume + * entry - Describes the open inode + * fpos - The desired file position + * blkentry - Describes the block entry that we are positioned in * ****************************************************************************/ static ssize_t nxffs_rdseek(FAR struct nxffs_volume_s *volume, FAR struct nxffs_entry_s *entry, - off_t fpos) + off_t fpos, + FAR struct nxffs_blkentry_s *blkentry) { - struct nxffs_blkentry_s blkentry; size_t datstart; size_t datend; off_t offset; @@ -302,7 +304,7 @@ static ssize_t nxffs_rdseek(FAR struct nxffs_volume_s *volume, { /* Check if the next data block contains the sought after file position */ - ret = nxffs_nextblock(volume, offset, &blkentry); + ret = nxffs_nextblock(volume, offset, blkentry); if (ret < 0) { fdbg("nxffs_nextblock failed: %d\n", -ret); @@ -312,17 +314,18 @@ static ssize_t nxffs_rdseek(FAR struct nxffs_volume_s *volume, /* Get the range of data offsets for this data block */ datstart = datend; - datend += blkentry.datlen; + datend += blkentry->datlen; /* Offset to search for the the next data block */ - offset = blkentry.hoffset + SIZEOF_NXFFS_DATA_HDR + blkentry.datlen; + offset = blkentry->hoffset + SIZEOF_NXFFS_DATA_HDR + blkentry->datlen; } while (datend <= fpos); /* Return the offset to the data within the current data block */ - nxffs_ioseek(volume, blkentry.hoffset + SIZEOF_NXFFS_DATA_HDR + fpos - datstart); + blkentry->foffset = fpos - datstart; + nxffs_ioseek(volume, blkentry->hoffset + SIZEOF_NXFFS_DATA_HDR + blkentry->foffset); return OK; } @@ -342,7 +345,12 @@ ssize_t nxffs_read(FAR struct file *filep, FAR char *buffer, size_t buflen) { FAR struct nxffs_volume_s *volume; FAR struct nxffs_ofile_s *ofile; - ssize_t ret; + struct nxffs_blkentry_s blkentry; + ssize_t total; + size_t available; + size_t readsize; + ssize_t nread; + int ret; fvdbg("Read %d bytes from offset %d\n", buflen, filep->f_pos); @@ -380,40 +388,63 @@ ssize_t nxffs_read(FAR struct file *filep, FAR char *buffer, size_t buflen) goto errout_with_semaphore; } - /* Don't seek past the end of the file */ + /* Loop until all bytes have been read */ - if (filep->f_pos >= ofile->entry.datlen) + for (total = 0; total < buflen; ) { - /* Return end-of-file */ + /* Don't seek past the end of the file */ - filep->f_pos = ofile->entry.datlen; - ret = 0; - goto errout_with_semaphore; - } + if (filep->f_pos >= ofile->entry.datlen) + { + /* Return the partial read */ - /* Seek to the current file offset */ + filep->f_pos = ofile->entry.datlen; + break; + } - ret = nxffs_rdseek(volume, &ofile->entry, filep->f_pos); - if (ret < 0) - { - fdbg("nxffs_rdseek failed: %d\n", -ret); - ret = -EACCES; - goto errout_with_semaphore; - } + /* Seek to the current file offset */ - /* Read data from that file offset */ + ret = nxffs_rdseek(volume, &ofile->entry, filep->f_pos, &blkentry); + if (ret < 0) + { + fdbg("nxffs_rdseek failed: %d\n", -ret); + ret = -EACCES; + goto errout_with_semaphore; + } + + /* How many bytes are available at this offset */ + + available = blkentry.datlen - blkentry.foffset; + + /* Don't read more than we need to */ + + readsize = buflen - total; + if (readsize > available) + { + readsize = available; + } + + /* Read data from that file offset */ + + nread = nxffs_rddata(volume, (FAR uint8_t *)&buffer[total], readsize); + if (nread < 0) + { + ret = nread; + goto errout_with_semaphore; + } - ret = nxffs_rddata(volume, (FAR uint8_t *)buffer, buflen); - if (ret > 0) - { /* Update the file offset */ - filep->f_pos += ret; + filep->f_pos += nread; + total += nread; } + sem_post(&volume->exclsem); + return total; + errout_with_semaphore: sem_post(&volume->exclsem); errout: - return ret; + return (ssize_t)ret; } diff --git a/fs/nxffs/nxffs_write.c b/fs/nxffs/nxffs_write.c index 8e91d2a7ed..2dcd916547 100644 --- a/fs/nxffs/nxffs_write.c +++ b/fs/nxffs/nxffs_write.c @@ -448,8 +448,9 @@ ssize_t nxffs_write(FAR struct file *filep, FAR const char *buffer, size_t bufle { FAR struct nxffs_volume_s *volume; FAR struct nxffs_wrfile_s *wrfile; - ssize_t nbytesleft; - ssize_t nbyteswritten; + ssize_t remaining; + ssize_t nwritten; + ssize_t total; int ret; fvdbg("Write %d bytes to offset %d\n", buflen, filep->f_pos); @@ -492,9 +493,10 @@ ssize_t nxffs_write(FAR struct file *filep, FAR const char *buffer, size_t bufle * error occurs) */ - nbytesleft = buflen; - while (nbytesleft > 0) + for (total = 0; total < buflen; ) { + remaining = buflen- total; + /* Have we already allocated the data block? */ if (wrfile->doffset == 0) @@ -502,7 +504,7 @@ ssize_t nxffs_write(FAR struct file *filep, FAR const char *buffer, size_t bufle /* No, allocate the data block now */ wrfile->datlen = 0; - ret = nxffs_wralloc(volume, wrfile, nbytesleft); + ret = nxffs_wralloc(volume, wrfile, remaining); if (ret < 0) { fdbg("Failed to allocate a data block: %d\n", -ret); @@ -527,8 +529,8 @@ ssize_t nxffs_write(FAR struct file *filep, FAR const char *buffer, size_t bufle * block to flash. */ - nbyteswritten = nxffs_wrappend(volume, wrfile, buffer, nbytesleft); - if (nbyteswritten < 0) + nwritten = nxffs_wrappend(volume, wrfile, &buffer[total], remaining); + if (nwritten < 0) { fdbg("Failed to append to FLASH to a data block: %d\n", -ret); goto errout_with_semaphore; @@ -536,12 +538,12 @@ ssize_t nxffs_write(FAR struct file *filep, FAR const char *buffer, size_t bufle /* Decrement the number of bytes remaining to be written */ - nbytesleft -= nbyteswritten; + total += nwritten; } /* Success.. return the number of bytes written */ - ret = buflen; + ret = total; filep->f_pos = wrfile->datlen; errout_with_semaphore: