Skip to content

Ext2 Ext3 Filesystem

Levente Santha edited this page May 11, 2026 · 2 revisions

Ext2/Ext3 Filesystem

JNode's implementation of the ext2/ext3 Linux-native filesystem with block groups, inodes, bitmaps, and journaling support (ext3).

Overview

JNode provides a native implementation of the Second Extended Filesystem (ext2) and Third Extended Filesystem (ext3), the standard Linux filesystems. The implementation handles block group organization, inode-based file management, block/inode bitmaps for allocation tracking, and feature compatibility checks for both ext2 and ext3 volumes.

The driver is located under fs/src/fs/org/jnode/fs/ext2/ and fs/src/fs/org/jnode/fs/ext3/ (the ext3 package exists but is largely unified with ext2 via feature flags).

Key Components

Class/File Role
Ext2FileSystem.java Main filesystem driver; extends AbstractFileSystem<Ext2Entry>. Handles mount, read, create, block/inode allocation, caching.
Ext2FileSystemType.java FileSystemType factory that probes devices for ext2 superblock magic (0xEF53).
Ext2FileSystemFormatter.java Creates new ext2 filesystems on devices.
Superblock.java Ext2 superblock structure (1024 bytes). Stores filesystem metadata: block count, inodes per group, feature flags, UUID, volume name.
GroupDescriptor.java Per-block-group metadata: block bitmap block, inode bitmap block, inode table block, free counts.
INode.java Inode structure with direct/indirect block addressing, extent support (ext4), xattr handling.
INodeDescriptor.java Non-persistent inode metadata: inode number, last allocated block index, block group, index in group. Tracks allocation state during writes/truncates.
INodeTable.java Manages the inode table for each block group; handles inode read/write.
INodeBitmap.java Inode allocation bitmap operations (findFreeINode).
BlockBitmap.java Block allocation bitmap operations (testAndSetBlock, findFreeBlocks, freeBit).
FSBitmap.java Abstract bitmap base class with isFree() helpers used by both block and inode bitmaps.
BlockReservation.java Result object returned by bitmap block allocation: allocated block index, preallocation count, free blocks count.
INodeReservation.java Result object returned by inode allocation: block group, index within group, success flag.
Ext2File.java File representation backed by an inode. Supports read/write, extent-based block lookup.
Ext2Directory.java Directory representation with linear directory records and iterator-based entry reading.
Ext2Entry.java VFS entry wrapper combining inode, file offset, name, and file type.
Ext2DirectoryRecord.java Directory entry record with variable-length structure (inode nr, rec_len, name_len, file type, name).
Ext2Constants.java All ext2/ext3/ext4 feature flags, inode modes, file types, and constants.
Ext2Utils.java Utility methods (date encoding/decoding, ceiling division).
BlockSize.java Enum for block sizes: _1Kb, _2Kb, _4Kb (1024/2048/4096 bytes).
Ext2Print.java Debug utility for printing filesystem structures.
INodeCache.java LRU cache for inodes with synchronized access.
BlockCache.java LRU cache for data blocks with configurable capacity and load factor.
xattr/XAttrHeader.java, xattr/XAttrEntry.java Extended attribute support within inodes and in dedicated blocks.

How It Works

Mounting

When Ext2FileSystem.read() is called, the driver:

  1. Reads the 1024-byte superblock at offset 1024 (skipping the boot sector).
  2. Validates the magic number 0xEF53.
  3. Computes block group count from blocksCount / blocksPerGroup.
  4. Reads group descriptors for each block group.
  5. Initializes inode tables for each group.
  6. Checks incompat and RO-compat feature flags; forces read-only mode for unsupported features (compression, journal_dev, 64bit, huge_file, btree_dir, etc.).
  7. If MMP (Multi-Mount Protection) is present, reads and checks the MMP block.
  8. Initializes block and inode LRU caches.

Block Group Layout

Each block group contains (in order):

superblock copy (if groupHasDescriptors)
group descriptor table copy
block bitmap
inode bitmap
inode table
free data blocks

The groupHasDescriptors() method implements the sparse_super heuristic: only groups whose number is a power of 3, 5, or 7 have descriptor copies (plus group 0).

Inode Structure

The inode (INode.java) stores:

  • Mode and file type (from i_mode)
  • Timestamps: atime, ctime, mtime, dtime
  • Size (supports 32-bit and 64-bit via EXT4_HUGE_FILE_FL)
  • Direct block pointers (12 entries in i_block[0..11])
  • Single indirect pointer (i_block[12])
  • Double indirect pointer (i_block[13])
  • Triple indirect pointer (i_block[14])
  • Flags (extents, huge file, hash-indexed directory)
  • Extended attributes (inline or in dedicated block)

Block lookup uses either the traditional indirect addressing or extents (ext4 feature EXT4_INODE_EXTENTS_FLAG) via ExtentHeader.

Block Allocation

Ext2FileSystem.testAndSetBlock() and findFreeBlocks() search the block bitmap for free blocks. Block allocation prefers blocks near the last allocated block (up to 15 blocks before/after) and uses preallocation to reduce fragmentation. If the preferred area is full, it falls back to searching block groups with at least 5% free space.

Directory Format

Directories use linear directory records (Ext2DirectoryRecord). Each record contains:

  • Inode number (4 bytes)
  • Record length (2 bytes) — includes padding
  • Name length (1 byte)
  • File type (1 byte)
  • File name (variable)

Records are not aligned to specific boundaries; the rec_len field handles variable-length entries. Unused entries have inode number 0.

ext3 Journaling

ext3 support is integrated via feature flags in Ext2Constants:

  • EXT3_FEATURE_INCOMPAT_RECOVER — filesystem needs recovery
  • EXT3_FEATURE_INCOMPAT_JOURNAL_DEV — dedicated journal device (unsupported)
  • Journal UUID, inode, and dev stored in superblock

The JNode implementation currently handles ext3 as read-only unless the journaling features are absent.

Feature Compatibility

Ext2FileSystem checks three feature tiers:

  • Incompat: compression, journal_dev (mount fails), 64bit, flex_bg, mmp, meta_bg (force readonly)
  • RO-Compat: large_file, btree_dir, huge_file, gdt_csum, dir_nlink, extra_isize (force readonly)
  • Compat: sparse_super, filetype (set during create)

Gotchas

  • The block cache uses a synchronized map; double-checked locking patterns in getBlock() are intentional to minimize lock hold time during disk I/O.
  • Inode caches are similarly synchronized; inode locking (incLocked/decLocked) prevents flushing while other threads access the same inode.
  • INode.getDataBlockNr() dispatches to either indirect addressing or extent-based lookup based on the EXT4_INODE_EXTENTS_FLAG flag.
  • Directories with EXT2_INDEX_FL (hash-indexed) or EXT4_HUGE_FILE_FL are mounted read-only because the hash and huge file features are not fully implemented.
  • BlockSize is encoded in the superblock as S_LOG_BLOCK_SIZE; block size = 1024 << logBlockSize.
  • The Superblock writes copies to every block group that has descriptors (sparse_super layout).
  • xattr support stores attributes inline within the inode (after the standard 128 bytes) or in a dedicated block referenced by i_file_acl.
  • INodeDescriptor stores transient allocation state; its lastAllocatedBlockIndex may differ from the size-derived block count during write-in-progress or truncate-in-progress operations.
  • FSBitmap.isFree() uses byte/bit index arithmetic: byteIndex = index / 8, mask = 1 << (index % 8).
  • Preallocation (preallocCount in BlockReservation) is used by block allocation to reduce fragmentation by reserving multiple sequential blocks at once.
  • Block allocation prefers blocks within ±15 of the last allocated block; falls back to block groups with at least 5% free space.
  • BlockSize enum values (_1Kb, _2Kb, _4Kb) represent kilobytes, converted via BinaryScaleFactor.K.getMultiplier().

Related Pages

  • VFS-Layer — JNode's virtual filesystem layer that sits above ext2
  • Filesystem-Layer — Overview of filesystem drivers including ext2/ext3
  • Block-Device-Layer — The block I/O layer that ext2 reads from and writes to

Clone this wiki locally