More NXFFS logic

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3538 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo 2011-04-28 22:24:10 +00:00
parent 73308cef13
commit 90aaaebeae
7 changed files with 440 additions and 7 deletions

View file

@ -35,9 +35,9 @@
ifeq ($(CONFIG_FS_NXFFS),y)
ASRCS +=
CSRCS += nxffs_block.c nxffs_blockstats.c nxffs_cache.c \
nxffs_initialize.c nxffs_inode.c nxffs_open.c nxffs_reformat.c \
nxffs_stat.c nxffs_unlink.c nxffs_util.c
CSRCS += nxffs_block.c nxffs_blockstats.c nxffs_cache.c nxffs_dirent.c \
nxffs_initialize.c nxffs_inode.c nxffs_ioctl.c nxffs_open.c \
nxffs_reformat.c nxffs_stat.c nxffs_unlink.c nxffs_util.c
# Argument for dependency checking

94
fs/nxffs/README.txt Executable file
View file

@ -0,0 +1,94 @@
General NXFFS organization
==========================
The following example assumes 4 logical blocks per FLASH erase block. The
actual relationship is determined by the FLASH geometry reported by the MTD
driver.
ERASE LOGICAL Inodes begin with a inode header. inode may
BLOCK BLOCK CONTENTS be marked as "deleted," pending clean-up.
n 4*n --+--------------+
|BBBBBBBBBBBBBB| Logic block header
|IIIIIIIIIIIIII| Inodes begin with a inode header
|DDDDDDDDDDDDDD| Data block containing inode data block
| (Inode Data) |
4*n+1 --+--------------+
|BBBBBBBBBBBBBB| Logic block header
|DDDDDDDDDDDDDD| Inodes may consist of multiple data blocks
| (Inode Data) |
|IIIIIIIIIIIIII| Next inode header
| | Possibly a few unused bytes at the end of a block
4*n+2 --+--------------+
|BBBBBBBBBBBBBB| Logic block header
|DDDDDDDDDDDDDD|
| (Inode Data) |
4*n+3 --+--------------+
|BBBBBBBBBBBBBB| Logic block header
|IIIIIIIIIIIIII| Next inode header
|DDDDDDDDDDDDDD|
| (Inode Data) |
n+1 4*(n+1) --+--------------+
|BBBBBBBBBBBBBB| Logic block header
| | All FLASH is unused after the end of the final
| | inode.
--+--------------+
General operation
=================
Inodes are written starting at the beginning of FLASH. As inodes are
deleted, they are marked as deleted but not removed. As new inodes are
written, allocations proceed to toward the end of the FLASH -- thus,
supporting wear leveling by using all FLASH blocks equally.
When the FLASH becomes full (no more space at the end of the FLASH), a
clean-up operation must be performed: All inodes marked deleted are
finally removed and the remaining inodes are packed at the beginning of
the FLASH. Allocations then continue at the freed FLASH memory at the
end of the FLASH.
Headers
=======
BLOCK HEADER:
The block header is used to determine if the block has every been
formatted and also indicates bad blocks which should never be used.
INODE HEADER:
Each inode begins with an inode header that contains, among other things,
the name of the inode, the offset to the first data block, and the
length of the inode data.
At present, the only kind of inode support is a file. So for now, the
term file and inode are interchangeable.
INODE DATA HEADER:
Inode data is enclosed in a data header. For a given inode, there
is at most one inode data block per logical block. If the inode data
spans more than one logical block, then the inode data may be enclosed
in multiple data blocks, one per logical block.
NXFFS Limitations
=================
This implementation is very simple as, as a result, has several limitations
that you should be aware before opting to use NXFFS:
1. Since the files are contiguous in FLASH and since allocations always
proceed toward the end of the FLASH, there can only be one file opened
for writing at a time. Multiple files may be opened for reading.
2. Files may not be increased in size after they have been closed. The
O_APPEND open flag is not supported.
3. Files are always written sequential. Seeking within a file opened for
writing will not work.
4. There are no directories, however, '/' may be used within a file name
string providing some illusion of directories.
5. Files may be opened for reading or for writing, but not both: The O_RDWR
open flag is not supported.
6. The clean-up process occurs only during a write when the free FLASH
memory at the end of the FLASH is exhausted. Thus, occasionally, file
writing may take a long time.

View file

@ -73,14 +73,14 @@
* n 4*n --+--------------+
* |BBBBBBBBBBBBBB| Logic block header
* |IIIIIIIIIIIIII| Inodes begin with a inode header
* |DDDDDDDDDDDDD| Data block containing inode data block
* |DDDDDDDDDDDDDD| Data block containing inode data block
* | (Inode Data) |
* 4*n+1 --+--------------+
* |BBBBBBBBBBBBBB| Logic block header
* |DDDDDDDDDDDDDD| Inodes may consist of multiple data blocks
* | (Inode Data) |
* |IIIIIIIIIIIIII| Next inode header
* | | Possibly a few unused bytes at the end of a block
* | | Possibly a few unused bytes at the end of a block
* 4*n+2 --+--------------+
* |BBBBBBBBBBBBBB| Logic block header
* |DDDDDDDDDDDDDD|
@ -141,7 +141,6 @@
* 6. The clean-up process occurs only during a write when the free FLASH
* memory at the end of the FLASH is exhausted. Thus, occasionally, file
* writing may take a long time.
*
*/
/* Values for logical block state. Basically, there are only two, perhaps
@ -703,7 +702,7 @@ extern int nxffs_rminode(FAR struct nxffs_volume_s *volume, FAR const char *name
* - nxffs_open() and nxffs_close() are defined in nxffs_open.c
* - nxffs_ioctl() is defined in nxffs_ioctl.c
* - nxffs_opendir(), nxffs_readdir(), and nxffs_rewindir() are defined in
* nxffs_dir.c
* nxffs_dirent.c
* - nxffs_stat() and nxffs_statfs() are defined in nxffs_stat.c
* - nxffs_unlink() is defined nxffs_unlink.c
*

222
fs/nxffs/nxffs_dirent.c Normal file
View file

@ -0,0 +1,222 @@
/****************************************************************************
* fs/nxffs/nxffs_dirent.c
*
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
*
* References: Linux/Documentation/filesystems/romfs.txt
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <string.h>
#include <dirent.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/fs.h>
#include <nuttx/mtd.h>
#include <nuttx/dirent.h>
#include "nxffs.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Public Types
****************************************************************************/
/****************************************************************************
* Public Variables
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: nxffs_opendir
*
* Description:
* Open a directory for read access
*
****************************************************************************/
int nxffs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
FAR struct fs_dirent_s *dir)
{
struct nxffs_volume_s *volume;
int ret;
fvdbg("relpath: \"%s\"\n", relpath ? relpath : "NULL");
/* Sanity checks */
DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL);
/* Recover the file system state from the NuttX inode instance */
volume = mountpt->i_private;
ret = sem_wait(&volume->exclsem);
if (ret != OK)
{
goto errout;
}
/* The requested directory must be the volume-relative "root" directory */
if (relpath && relpath[0] != '\0')
{
ret = -ENOENT;
goto errout_with_semaphore;
}
/* Set the offset to the offset to the first valid inode */
dir->u.nxffs.nx_offset = volume->inoffset;
ret = OK;
errout_with_semaphore:
sem_post(&volume->exclsem);
errout:
return ret;
}
/****************************************************************************
* Name: nxffs_readdir
*
* Description: Read the next directory entry
*
****************************************************************************/
int nxffs_readdir(FAR struct inode *mountpt, FAR struct fs_dirent_s *dir)
{
FAR struct nxffs_volume_s *volume;
FAR struct nxffs_entry_s entry;
off_t offset;
int ret;
/* Sanity checks */
DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL);
/* Recover the file system state from the NuttX inode instance */
volume = mountpt->i_private;
ret = sem_wait(&volume->exclsem);
if (ret != OK)
{
goto errout;
}
/* Read the next inode header from the offset */
offset = dir->u.nxffs.nx_offset;
ret = nxffs_nextentry(volume, offset, &entry);
/* If the read was successful, then handle the reported inode. Note
* that when the last inode has been reported, the value -ENOENT will
* be returned.. which is correct for the readdir() method.
*/
if (ret == OK)
{
/* Return the filename and file type */
fvdbg("Offset %d: \"%s\"\n", entry.hoffset, entry.name);
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;
nxffs_freeentry(&entry);
ret = OK;
}
sem_post(&volume->exclsem);
errout:
return ret;
}
/****************************************************************************
* Name: nxffs_rewindir
*
* Description:
* Reset directory read to the first entry
*
****************************************************************************/
int nxffs_rewinddir(FAR struct inode *mountpt, FAR struct fs_dirent_s *dir)
{
FAR struct nxffs_volume_s *volume;
int ret;
fvdbg("Entry\n");
/* Sanity checks */
DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL);
/* Recover the file system state from the NuttX inode instance */
volume = mountpt->i_private;
ret = sem_wait(&volume->exclsem);
if (ret != OK)
{
goto errout;
}
/* Reset the offset to the FLASH offset to the first valid inode */
dir->u.nxffs.nx_offset = volume->inoffset;
ret = OK;
sem_post(&volume->exclsem);
errout:
return ret;
}

100
fs/nxffs/nxffs_ioctl.c Normal file
View file

@ -0,0 +1,100 @@
/****************************************************************************
* fs/nxffs/nxffs_ioctl.c
*
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
*
* References: Linux/Documentation/filesystems/romfs.txt
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/fs.h>
#include <nuttx/mtd.h>
#include "nxffs.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Public Types
****************************************************************************/
/****************************************************************************
* Public Variables
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: nxffs_ioctl
*
* Description:
* Standard mountpoint ioctl method.
*
****************************************************************************/
int nxffs_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
{
FAR struct nxffs_volume_s *volume;
fvdbg("cmd: %d arg: %08lx\n", cmd, arg);
/* Sanity checks */
DEBUGASSERT(filep->f_priv != NULL && filep->f_inode != NULL);
/* Recover the file system state from the open file */
volume = filep->f_inode->i_private;
DEBUGASSERT(volume != NULL);
/* No ioctl commands yet supported */
return -ENOTTY;
}

View file

@ -289,6 +289,10 @@ static inline int nxffs_rdopen(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_ofile_s *ofile)

View file

@ -105,6 +105,17 @@ struct fs_binfsdir_s
unsigned int fb_index; /* Index to the next named entry point */
};
#endif
#ifdef CONFIG_FS_NXFFS
/* NXFFS is the tiny NuttX wear-leveling FLASH file system. The state value is
* the offset in FLASH memory to the next inode entry.
*/
struct fs_nxffsdir_s
{
off_t nx_offset; /* Offset to the next inode */
};
#endif
#endif /* CONFIG_DISABLE_MOUNTPOINT */
struct fs_dirent_s
@ -153,7 +164,10 @@ struct fs_dirent_s
#ifdef CONFIG_APPS_BINDIR
struct fs_binfsdir_s binfs;
#endif
#ifdef CONFIG_FS_NXFFS
struct fs_nxffsdir_s nxffs;
#endif
#endif /* !CONFIG_DISABLE_MOUNTPOINT */
} u;
/* In any event, this the actual struct dirent that is returned by readdir */