Flash-Friendly File System (F2FS) Design
The Flash-Friendly File System (F2FS) was designed by Samsung specifically for NAND flash memory-based storage devices. Traditional file systems like EXT4 are built on the assumption of spinning magnetic disks where seek time is a massive bottleneck. Flash storage, however, exhibits completely different characteristics: random reads are fast, but random writes degrade performance and cause wear on the memory cells.
F2FS addresses these challenges by using a Log-structured File System (LFS) approach, turning random writes into sequential writes, which aligns perfectly with how flash memory prefers to be written.
Log-Structured Layout
In F2FS, the entire storage space is divided into logical units. The hierarchy is as follows:
- Sectors and Blocks: The fundamental units of data.
- Segments: A collection of blocks (typically 2MB). This is the basic unit for Garbage Collection.
- Sections: A collection of segments. This is the unit for cleaning operations.
- Zones: A collection of sections.
The volume is divided into six main areas:
- Superblock (SB): Stores basic partition information.
- Checkpoint (CP): Maintains file system status, bitmaps for valid NAT/SIT sets, and orphan inodes. F2FS writes checkpoints to ensure consistency during sudden power losses.
- Segment Information Table (SIT): Contains information about the valid block count and a bitmap of valid blocks for each main area segment.
- Node Address Table (NAT): Maps Node IDs (NIDs) to physical block addresses. This indirection layer is crucial: when a data block changes, only the direct node changes its physical address, minimizing the "wandering tree" problem common in log-structured file systems.
- Segment Summary Area (SSA): Stores summary entries (e.g., parent inode number) for each block in the main area.
- Main Area: Contains file data and node blocks (inodes, direct, and indirect nodes).
Garbage Collection (GC) in F2FS
Because F2FS is log-structured, it continuously writes new data sequentially to free segments, invalidating the old data. Eventually, the file system runs out of fully clean segments, necessitating Garbage Collection.
The GC process involves two main phases:
- Victim Selection: Finding segments with the most invalidated blocks. F2FS uses two policies:
- Greedy: Selects the segment with the smallest number of valid blocks. Used primarily during foreground GC.
- Cost-Benefit: Considers the age of the segment to reduce wear. Used mainly in background GC.
- Block Migration: Reading the valid blocks from the victim segment and writing them to a new, clean segment.
F2FS on userdata and Its Advantages
Android heavily relies on F2FS for the /data (userdata) partition on modern devices. Since the userdata partition experiences frequent random writes (databases, SharedPreferences, cache), F2FS provides a substantial performance boost over EXT4.
Benefits on Android
- Reduced Write Amplification: By aligning writes with flash erase blocks, F2FS extends the lifespan of the eMMC/UFS storage.
- Faster SQLite Performance: SQLite database operations (frequent in Android apps) perform significantly better due to improved random write speeds via sequential log writing.
- Inline Dentries and Data: Small files and directory entries can be stored directly within the inode block, saving space and improving read times.
Practical Commands
You can interact with F2FS via the ADB shell.
Checking the filesystem type of /data:
adb shell df -T /data
Viewing F2FS specific statistics:
adb shell cat /sys/kernel/debug/f2fs/status
Checking F2FS segment information:
adb shell dump.f2fs -d 1 /dev/block/bootdevice/by-name/userdata