| <!-- |
| 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 — 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 "deleted," 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>© Copyright 2023, The Apache Software Foundation.</p> |
| </div> |
| |
| |
| |
| </footer> |
| </div> |
| </div> |
| </section> |
| </div> |
| <script> |
| jQuery(function () { |
| SphinxRtdTheme.Navigation.enable(true); |
| }); |
| </script> |
| |
| </body> |
| </html> |