FFS3 filesystem
The Flash FileSystem version 3 (FFS3) drivers implement a POSIX-like filesystem on NOR flash memory devices. This filesystem is unique to QNX OS.
The drivers are standalone executables that contain both the flash filesystem code and the flash device code. There are versions of FFS3 drivers for different embedded systems hardware as well as PCMCIA memory cards. The naming convention for the drivers is devf-system, where system describes the embedded system.
To find out what flash devices we currently support, refer to the following sources:
- the boards and mtd-flash directories under bsp_working_dir/src/hardware/flash
- in the QNX OS docs, the devf-* entries in the Utilities Reference
We provide the libraries and source code needed to build custom flash filesystem drivers for different embedded systems.
Organization
The FFS3 filesystem drivers support one or more logical flash drives. Each logical drive is called a socket, which consists of a contiguous and homogeneous region of flash memory. For example, consider a system containing two different types of flash device at different addresses, where one device is used for the boot image and the other for the flash filesystem. In this case, each flash device would appear in a different socket.
Each socket may be divided into one or more partitions. Two types of partitions are supported:
- Raw partitions
- A raw partition in the socket is any partition that doesn't contain a flash filesystem.
The driver doesn't recognize any filesystem types other than the flash filesystem.
A raw partition may contain an image filesystem or some application-specific data.
The filesystem will make accessible through a raw mountpoint (see below) any partitions on the flash that aren't flash filesystem partitions.
- Flash filesystem partitions
- A flash filesystem partition contains the POSIX-like flash filesystem,
which uses a proprietary format to store the filesystem data on the flash devices.
This format isn't compatible with either the Microsoft Flash File System 2 (FFS2) or the PCMCIA FTL specification.
The FFS3 filesystem allows files and directories to be freely created and deleted. It recovers space from deleted files using a reclaim mechanism similar to garbage collection.
When you start the flash filesystem driver, by default it will mount any partitions it finds in the socket. There can be only one instance of the driver per flash device, and the driver must be given the full size of the flash chip. You can specify the mountpoint (e.g., /flash) using mkefs or flashctl.
Mountpoint | Description |
---|---|
/dev/fsX | Raw mountpoint socket X |
/dev/fsXpY | Raw mountpoint socket X partition Y |
/fsXpY | Filesystem mountpoint socket X partition Y |
Features
The FFS3 filesystem supports many advanced features, such as POSIX compatibility, multiple threads, background reclaim, fault recovery, endian-awareness, wear-leveling, and error-handling.
- POSIX
- The filesystem supports the standard POSIX functionality (including long filenames, access privileges,
random writes, truncation, and symbolic links) with the following exceptions:
- You can't create hard links.
- Access times aren't supported (but file modification times and attribute change times are).
These design compromises allow this filesystem to remain small and simple, yet include most features normally found with block device filesystems.
- Storage efficiency
- The filesystem uses a fixed-size 32-byte extent header for each piece of
user data stored on the filesystem.
The filesystem has a 512-byte
append buffer
that's used to coalesce small appends to a file before flushing them out to disk. There's no other caching of user data in the filesystem (read or write). The maximum extent size is currently limited to 4096 bytes of data (plus the 32-byte header) for files which are created at runtime, although mkefs can create 16 KB extents. - Wear leveling
- Wear leveling is performed on blocks within a given partition.
If the flash is split into multiple partitions, then each partition has a
smaller pool to level across.
Blocks never migrate from one partition to another.
The most common type of reclaim in the filesystem (a foreground reclaim) always does a double-reclaim operation. The first reclaim always takes the block in the partition with the lowest erase count, and swaps it with the spare. Then the block that requires the reclaim is swapped with the spare. This has shown to result in near-perfect wear leveling when foreground reclaims are used.
- Background reclaim
- The FFS3 filesystem stores files and directories as a linked list of extents, which are marked for deletion as
they're deleted or updated.
Blocks to be reclaimed are chosen using a simple algorithm that finds the block with
the most space to be reclaimed, while keeping level the amount of wear of each individual block.
This wear-leveling increases the MTBF (mean time between failures) of the flash
devices, thus increasing their longevity.
The background reclaim process is performed when there isn't enough free space. The reclaim process first copies the contents of the reclaim block to an empty spare block, which then replaces the reclaim block. The reclaim block is then erased. Unlike rotating media with a mechanical head, proximity of data isn't a factor with a flash filesystem, so data can be scattered on the media without loss of performance.
- Fault recovery
- The filesystem has been designed to minimize corruption due to accidental loss-of-power faults.
Updates to extent headers and erase block headers are always executed in carefully scheduled sequences.
These sequences allow the recovery of the filesystem's integrity in the case of data corruption.
Note that properly designed flash hardware is essential for effective fault-recovery systems. In particular, special reset circuitry must be in place to hold the system in
reset
before power levels drop below critical. Otherwise, spurious or random bus activity can form write/erase commands and corrupt the flash beyond recovery.Rename operations are guaranteed atomic, even through loss-of-power faults. This means, for example, that if you lost power while giving an image or executable a new name, you would still be able to access the file via its old name upon recovery.
When the FFS3 filesystem driver is started, it scans the state of every extent header on the media (in order to validate its integrity) and takes appropriate action, ranging from a simple block reclamation to the erasure of dangling extent links. This process is merged with the filesystem's normal mount procedure in order to achieve optimal bootstrap timings.
- Flash errors
- As flash hardware wears out, its write state-machine may
find that it can't write or erase a particular bit cell.
When this happens, the error status is propagated to the
flash driver so it can take proper action (i.e., mark the bad
area and try to write/erase in another place).
This error-handling mechanism is transparent. Note that after several flash errors, all writes and erases that fail will eventually render the flash read-only. Fortunately, this situation shouldn't happen before several years of flash operation. Check your flash specification and analyze your application's data flow to flash in order to calculate its potential longevity or MTBF.
- Endian awareness
- The FFS3 filesystem is endian-aware, making it portable across different platforms. The optimal approach is to use the mkefs utility to select the target's endianness.
Utilities
The filesystem supports all the standard POSIX utilities such as ls, mkdir, rm, ln, mv, and cp. There are also some QNX OS utilities for managing the flash:
System calls
The filesystem supports all the standard POSIX I/O functions such as open(), close(), read(), and write(). Special functions such as erasing are supported using the non-POSIX devctl() function.