blob: 32670840e34ed4698d4452fb8fde4cb676630511 [file] [log] [blame]
<!--
Documentation/_templates/layout.html
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership. The
ASF licenses this file to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance with the
License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
License for the specific language governing permissions and limitations
under the License.
-->
<!DOCTYPE html>
<html class="writer-html5" lang="en">
<head>
<meta charset="utf-8" /><meta name="generator" content="Docutils 0.18.1: http://docutils.sourceforge.net/" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>NXFFS &mdash; NuttX latest documentation</title>
<link rel="stylesheet" type="text/css" href="../../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../../_static/css/theme.css" />
<link rel="stylesheet" type="text/css" href="../../_static/copybutton.css" />
<link rel="stylesheet" type="text/css" href="../../_static/custom.css" />
<link rel="shortcut icon" href="../../_static/favicon.ico"/>
<script src="../../_static/jquery.js"></script>
<script src="../../_static/_sphinx_javascript_frameworks_compat.js"></script>
<script data-url_root="../../" id="documentation_options" src="../../_static/documentation_options.js"></script>
<script src="../../_static/doctools.js"></script>
<script src="../../_static/sphinx_highlight.js"></script>
<script src="../../_static/clipboard.min.js"></script>
<script src="../../_static/copybutton.js"></script>
<script src="../../_static/js/theme.js"></script>
<link rel="index" title="Index" href="../../genindex.html" />
<link rel="search" title="Search" href="../../search.html" />
<link rel="next" title="Partition Table" href="partition.html" />
<link rel="prev" title="NFS" href="nfs.html" />
</head>
<body class="wy-body-for-nav">
<div class="wy-grid-for-nav">
<nav data-toggle="wy-nav-shift" class="wy-nav-side">
<div class="wy-side-scroll">
<div class="wy-side-nav-search" >
<a href="../../index.html" class="icon icon-home"> NuttX
</a>
<!-- this version selector is quite ugly, should be probably replaced by something
more modern -->
<div class="version-selector">
<select onchange="javascript:location.href = this.value;">
<option value="../../../latest" selected="selected">latest</option>
<option value="../../../10.0.0" >10.0.0</option>
<option value="../../../10.0.1" >10.0.1</option>
<option value="../../../10.1.0" >10.1.0</option>
<option value="../../../10.2.0" >10.2.0</option>
<option value="../../../10.3.0" >10.3.0</option>
<option value="../../../11.0.0" >11.0.0</option>
<option value="../../../12.0.0" >12.0.0</option>
<option value="../../../12.1.0" >12.1.0</option>
<option value="../../../12.2.0" >12.2.0</option>
<option value="../../../12.2.1" >12.2.1</option>
<option value="../../../12.3.0" >12.3.0</option>
<option value="../../../12.4.0" >12.4.0</option>
<option value="../../../12.5.0" >12.5.0</option>
<option value="../../../12.5.1" >12.5.1</option>
<option value="../../../12.6.0" >12.6.0</option>
<option value="../../../12.7.0" >12.7.0</option>
<option value="../../../12.8.0" >12.8.0</option>
<option value="../../../12.9.0" >12.9.0</option>
<option value="../../../12.10.0" >12.10.0</option>
<option value="../../../12.11.0" >12.11.0</option>
</select>
</div>
<div role="search">
<form id="rtd-search-form" class="wy-form" action="../../search.html" method="get">
<input type="text" name="q" placeholder="Search docs" aria-label="Search docs" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
</div><div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="Navigation menu">
<p class="caption" role="heading"><span class="caption-text">Table of Contents</span></p>
<ul class="current">
<li class="toctree-l1"><a class="reference internal" href="../../index.html">Home</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../introduction/index.html">Introduction</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../quickstart/index.html">Getting Started</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../contributing/index.html">Contributing</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../introduction/inviolables.html">The Inviolable Principles of NuttX</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../platforms/index.html">Supported Platforms</a></li>
<li class="toctree-l1 current"><a class="reference internal" href="../index.html">OS Components</a><ul class="current">
<li class="toctree-l2"><a class="reference internal" href="../binfmt.html">Binary Loader</a></li>
<li class="toctree-l2"><a class="reference internal" href="../drivers/index.html">Device Drivers</a></li>
<li class="toctree-l2"><a class="reference internal" href="../nxflat.html">NXFLAT</a></li>
<li class="toctree-l2"><a class="reference internal" href="../nxgraphics/index.html">NX Graphics Subsystem</a></li>
<li class="toctree-l2"><a class="reference internal" href="../paging.html">On-Demand Paging</a></li>
<li class="toctree-l2"><a class="reference internal" href="../audio/index.html">Audio Subsystem</a></li>
<li class="toctree-l2 current"><a class="reference internal" href="index.html">NuttX File System</a><ul class="current">
<li class="toctree-l3"><a class="reference internal" href="index.html#virtual-file-system-vfs">Virtual File System (VFS)</a></li>
<li class="toctree-l3 current"><a class="reference internal" href="index.html#file-systems">File systems</a><ul class="current">
<li class="toctree-l4"><a class="reference internal" href="aio.html">Asynchronous I/O support</a></li>
<li class="toctree-l4"><a class="reference internal" href="binfs.html">BINFS</a></li>
<li class="toctree-l4"><a class="reference internal" href="cromfs.html">CROMFS</a></li>
<li class="toctree-l4"><a class="reference internal" href="fat.html">FAT</a></li>
<li class="toctree-l4"><a class="reference internal" href="hostfs.html">Host File System</a></li>
<li class="toctree-l4"><a class="reference internal" href="littlefs.html">LITTLEFS</a></li>
<li class="toctree-l4"><a class="reference internal" href="mmap.html">File mapping emulation (mmap)</a></li>
<li class="toctree-l4"><a class="reference internal" href="mnemofs.html">MNEMOFS</a></li>
<li class="toctree-l4"><a class="reference internal" href="nfs.html">NFS</a></li>
<li class="toctree-l4 current"><a class="current reference internal" href="#">NXFFS</a><ul>
<li class="toctree-l5"><a class="reference internal" href="#general-nxffs-organization">General NXFFS organization</a></li>
<li class="toctree-l5"><a class="reference internal" href="#general-operation">General operation</a></li>
<li class="toctree-l5"><a class="reference internal" href="#headers">Headers</a></li>
<li class="toctree-l5"><a class="reference internal" href="#nxffs-limitations">NXFFS Limitations</a></li>
<li class="toctree-l5"><a class="reference internal" href="#multiple-writers">Multiple Writers</a></li>
<li class="toctree-l5"><a class="reference internal" href="#ioctls">ioctls</a></li>
<li class="toctree-l5"><a class="reference internal" href="#things-to-do">Things to Do</a></li>
</ul>
</li>
<li class="toctree-l4"><a class="reference internal" href="partition.html">Partition Table</a></li>
<li class="toctree-l4"><a class="reference internal" href="procfs.html">PROCFS</a></li>
<li class="toctree-l4"><a class="reference internal" href="romfs.html">ROMFS</a></li>
<li class="toctree-l4"><a class="reference internal" href="rpmsgfs.html">RPMSG File System</a></li>
<li class="toctree-l4"><a class="reference internal" href="smartfs.html">SMARTFS</a></li>
<li class="toctree-l4"><a class="reference internal" href="shmfs.html">Shared Memory File System</a></li>
<li class="toctree-l4"><a class="reference internal" href="spiffs.html">SPIFFS</a></li>
<li class="toctree-l4"><a class="reference internal" href="tmpfs.html">TMPFS</a></li>
<li class="toctree-l4"><a class="reference internal" href="unionfs.html">Union File System</a></li>
<li class="toctree-l4"><a class="reference internal" href="userfs.html">User file system</a></li>
<li class="toctree-l4"><a class="reference internal" href="zipfs.html">ZipFS</a></li>
<li class="toctree-l4"><a class="reference internal" href="inotify.html">Inotify</a></li>
<li class="toctree-l4"><a class="reference internal" href="index.html#fs-categories">FS Categories</a></li>
</ul>
</li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="../libs/index.html">NuttX libraries</a></li>
<li class="toctree-l2"><a class="reference internal" href="../net/index.html">Network Support</a></li>
<li class="toctree-l2"><a class="reference internal" href="../mm/index.html">Memory Management</a></li>
<li class="toctree-l2"><a class="reference internal" href="../syscall.html">Syscall Layer</a></li>
<li class="toctree-l2"><a class="reference internal" href="../tools/index.html"><code class="docutils literal notranslate"><span class="pre">/tools</span></code> Host Tools</a></li>
<li class="toctree-l2"><a class="reference internal" href="../arch/index.html">Architecture-Specific Code</a></li>
<li class="toctree-l2"><a class="reference internal" href="../boards.html">Boards Support</a></li>
<li class="toctree-l2"><a class="reference internal" href="../cmake.html">CMake Support</a></li>
<li class="toctree-l2"><a class="reference internal" href="../openamp.html">OpenAMP Support</a></li>
<li class="toctree-l2"><a class="reference internal" href="../video.html">Video Subsystem</a></li>
<li class="toctree-l2"><a class="reference internal" href="../crypto.html">Crypto API Subsystem</a></li>
<li class="toctree-l2"><a class="reference internal" href="../wireless.html">Wireless Subsystem</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../../applications/index.html">Applications</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../implementation/index.html">Implementation Details</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../reference/index.html">API Reference</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../faq/index.html">FAQ</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../guides/index.html">Guides</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../glossary.html">Glossary</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../logos/index.html">NuttX Logos</a></li>
</ul>
</div>
</div>
</nav>
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap"><nav class="wy-nav-top" aria-label="Mobile navigation menu" >
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
<a href="../../index.html">NuttX</a>
</nav>
<div class="wy-nav-content">
<div class="rst-content">
<div role="navigation" aria-label="Page navigation">
<ul class="wy-breadcrumbs">
<li><a href="../../index.html" class="icon icon-home" aria-label="Home"></a></li>
<li class="breadcrumb-item"><a href="../index.html">OS Components</a></li>
<li class="breadcrumb-item"><a href="index.html">NuttX File System</a></li>
<li class="breadcrumb-item active">NXFFS</li>
<li class="wy-breadcrumbs-aside">
<a href="../../_sources/components/filesystem/nxffs.rst.txt" rel="nofollow"> View page source</a>
</li>
</ul>
<hr/>
</div>
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
<div itemprop="articleBody">
<section id="nxffs">
<h1>NXFFS<a class="headerlink" href="#nxffs" title="Permalink to this heading"></a></h1>
<p>This page contains information about the implementation of the NuttX
wear-leveling FLASH file system, NXFFS.</p>
<section id="general-nxffs-organization">
<h2>General NXFFS organization<a class="headerlink" href="#general-nxffs-organization" title="Permalink to this heading"></a></h2>
<p>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:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>ERASE LOGICAL Inodes begin with a inode header. inode may
BLOCK BLOCK CONTENTS be marked as &quot;deleted,&quot; pending re-packing.
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.
--+--------------+
</pre></div>
</div>
</section>
<section id="general-operation">
<h2>General operation<a class="headerlink" href="#general-operation" title="Permalink to this heading"></a></h2>
<p>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.</p>
<p>When the FLASH becomes full (no more space at the end of the FLASH), a
re-packing 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.</p>
</section>
<section id="headers">
<h2>Headers<a class="headerlink" href="#headers" title="Permalink to this heading"></a></h2>
<dl>
<dt><code class="docutils literal notranslate"><span class="pre">BLOCK</span> <span class="pre">HEADER</span></code></dt><dd><p>The block header is used to determine if the block has every been
formatted and also indicates bad blocks which should never be used.</p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">INODE</span> <span class="pre">HEADER</span></code></dt><dd><p>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.</p>
<p>At present, the only kind of inode support is a file. So for now, the
term file and inode are interchangeable.</p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">INODE</span> <span class="pre">DATA</span> <span class="pre">HEADER</span></code></dt><dd><p>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.</p>
</dd>
</dl>
</section>
<section id="nxffs-limitations">
<h2>NXFFS Limitations<a class="headerlink" href="#nxffs-limitations" title="Permalink to this heading"></a></h2>
<p>This implementation is very simple as, as a result, has several limitations
that you should be aware before opting to use NXFFS:</p>
<ol class="arabic simple">
<li><p>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.</p></li>
<li><p>Files may not be increased in size after they have been closed. The
O_APPEND open flag is not supported.</p></li>
<li><p>Files are always written sequential. Seeking within a file opened for
writing will not work.</p></li>
<li><p>There are no directories, however, ‘/’ may be used within a file name
string providing some illusion of directories.</p></li>
<li><p>Files may be opened for reading or for writing, but not both: The O_RDWR
open flag is not supported.</p></li>
<li><p>The re-packing 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.</p></li>
<li><p>Another limitation is that there can be only a single NXFFS volume
mounted at any time. This has to do with the fact that we bind to
an MTD driver (instead of a block driver) and bypass all of the normal
mount operations.</p></li>
</ol>
</section>
<section id="multiple-writers">
<h2>Multiple Writers<a class="headerlink" href="#multiple-writers" title="Permalink to this heading"></a></h2>
<p>As mentioned in the limitations above, there can be only one file opened
for writing at a time. If one thread has a file opened for writing and
another thread attempts to open a file for writing, then that second
thread will be blocked and will have to wait for the first thread to
close the file.</p>
<p>Such behavior may or may not be a problem for your application, depending
(1) how long the first thread keeps the file open for writing and (2) how
critical the behavior of the second thread is. Note that writing to FLASH
can always trigger a major FLASH reorganization and, hence, there is no
way to guarantee the first condition: The first thread may have the file
open for a long time even if it only intends to write a small amount.</p>
<p>Also note that a deadlock condition would occur if the SAME thread
attempted to open two files for writing. The thread would would be
blocked waiting for itself to close the first file.</p>
</section>
<section id="ioctls">
<h2>ioctls<a class="headerlink" href="#ioctls" title="Permalink to this heading"></a></h2>
<p>The file system supports to ioctls:</p>
<dl class="simple">
<dt><code class="docutils literal notranslate"><span class="pre">FIOC_REFORMAT</span></code></dt><dd><p>Will force the flash to be erased and a fresh, empty NXFFS file system to
be written on it.</p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">FIOC_OPTIMIZE</span></code></dt><dd><p>Will force immediate repacking of the file system. This will avoid the
delays to repack the file system in the emergency case when all of the
FLASH memory has been used. Instead, you can defer the garbage collection
to time when the system is not busy. Calling this function on a thrashing
file system will increase the amount of wear on the FLASH if you use this
frequently!</p>
</dd>
</dl>
</section>
<section id="things-to-do">
<h2>Things to Do<a class="headerlink" href="#things-to-do" title="Permalink to this heading"></a></h2>
<ul class="simple">
<li><p>The statfs() implementation is minimal. It should have some calculation
of the f_bfree, f_bavail, f_files, f_ffree return values.</p></li>
<li><p>There are too many allocs and frees. More structures may need to be
pre-allocated.</p></li>
<li><p>The file name is always extracted and held in allocated, variable-length
memory. The file name is not used during reading and eliminating the
file name in the entry structure would improve performance.</p></li>
<li><p>There is a big inefficiency in reading. On each read, the logic searches
for the read position from the beginning of the file each time. This
may be necessary whenever an lseek() is done, but not in general. Read
performance could be improved by keeping FLASH offset and read positional
information in the read open file structure.</p></li>
<li><p>Fault tolerance must be improved. We need to be absolutely certain that
any FLASH errors do not cause the file system to behavior incorrectly.</p></li>
<li><p>Wear leveling might be improved (?). Files are re-packed at the front
of FLASH as part of the clean-up operation. However, that means the files
that are not modified often become fixed in place at the beginning of
FLASH. This reduces the size of the pool moving files at the end of the
FLASH. As the file system becomes more filled with fixed files at the
front of the device, the level of wear on the blocks at the end of the
FLASH increases.</p></li>
<li><p>When the time comes to reorganization the FLASH, the system may be
unavailable for a long time. That is a bad behavior. What is needed,
I think, is a garbage collection task that runs periodically so that
when the big reorganization event occurs, most of the work is already
done. That garbage collection should search for valid blocks that no
longer contain valid data. It should pre-erase them, put them in
a good but empty state… all ready for file system re-organization.
NOTE: There is the FIOC_OPTIMIZE IOCTL command that can be used by an
application for force garbage collection when the system is not busy.
If used judiciously by the application, this can eliminate the problem.</p></li>
<li><p>And worse, when NXFSS reorganization the FLASH a power cycle can
damage the file system content if it happens at the wrong time.</p></li>
<li><p>The current design does not permit re-opening of files for write access
unless the file is truncated to zero length. This effectively prohibits
implementation of a proper truncate() method which should alter the
size of a previously written file. There is some fragmentary logic in
place but even this is conditioned out with __NO_TRUNCATE_SUPPORT__.</p></li>
</ul>
</section>
</section>
</div>
</div>
<footer><div class="rst-footer-buttons" role="navigation" aria-label="Footer">
<a href="nfs.html" class="btn btn-neutral float-left" title="NFS" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left" aria-hidden="true"></span> Previous</a>
<a href="partition.html" class="btn btn-neutral float-right" title="Partition Table" accesskey="n" rel="next">Next <span class="fa fa-arrow-circle-right" aria-hidden="true"></span></a>
</div>
<hr/>
<div role="contentinfo">
<p>&#169; Copyright 2023, The Apache Software Foundation.</p>
</div>
</footer>
</div>
</div>
</section>
</div>
<script>
jQuery(function () {
SphinxRtdTheme.Navigation.enable(true);
});
</script>
</body>
</html>