-
Notifications
You must be signed in to change notification settings - Fork 0
Ext2 Ext3 Filesystem
JNode's implementation of the ext2/ext3 Linux-native filesystem with block groups, inodes, bitmaps, and journaling support (ext3).
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).
| 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. |
When Ext2FileSystem.read() is called, the driver:
- Reads the 1024-byte superblock at offset 1024 (skipping the boot sector).
- Validates the magic number
0xEF53. - Computes block group count from
blocksCount / blocksPerGroup. - Reads group descriptors for each block group.
- Initializes inode tables for each group.
- Checks incompat and RO-compat feature flags; forces read-only mode for unsupported features (compression, journal_dev, 64bit, huge_file, btree_dir, etc.).
- If MMP (Multi-Mount Protection) is present, reads and checks the MMP block.
- Initializes block and inode LRU caches.
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).
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.
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.
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 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.
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)
- 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 theEXT4_INODE_EXTENTS_FLAGflag. - Directories with
EXT2_INDEX_FL(hash-indexed) orEXT4_HUGE_FILE_FLare mounted read-only because the hash and huge file features are not fully implemented. -
BlockSizeis encoded in the superblock asS_LOG_BLOCK_SIZE; block size =1024 << logBlockSize. - The
Superblockwrites 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. -
INodeDescriptorstores transient allocation state; itslastAllocatedBlockIndexmay 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 (
preallocCountinBlockReservation) 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.
-
BlockSizeenum values (_1Kb,_2Kb,_4Kb) represent kilobytes, converted viaBinaryScaleFactor.K.getMultiplier().
- 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