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:
parent
73308cef13
commit
90aaaebeae
7 changed files with 440 additions and 7 deletions
|
|
@ -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
94
fs/nxffs/README.txt
Executable 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.
|
||||
|
|
@ -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
222
fs/nxffs/nxffs_dirent.c
Normal 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
100
fs/nxffs/nxffs_ioctl.c
Normal 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;
|
||||
}
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue