Add initial ext2 read/write and formatting support

Register ext2 at boot, integrate mode-aware VFS opens and volume cleanup, and queue asynchronous transfers through a persistent worker.

Validation: Pascal compiler check and git diff --check passed. Full build blocked by Docker engine HTTP 500; runtime and Linux interoperability remain unverified.
This commit is contained in:
Aaron committed 2026-10-31 19:49:36 +00:00
1 parent 720ba46630
commit c0c56a9c84
7 files changed
+1397 -4

No files matched your search

+1
View File
@@ -96,6 +96,7 @@ uses
driver.net.dev.e1000,
driver.bus.usb.ehci,
driver.storage.fs.fat32,
driver.storage.fs.ext2,
arch.x86.fault,
core.ds.fifo,
driver.storage.fs.mgr,
@@ -222,6 +222,8 @@ type
to read/write hooks. Also returns the current file size through the
var parameter. Returning nil is legal (disables per-call fast-path). }
PPOpenFileHook = function(volume : PStorage_Volume; directory : pchar; fileName : pchar; var fileSize : uint32) : pointer;
{ Mode-aware open avoids creating a missing file during a read-only open. }
PPOpenFileModeHook = function(volume : PStorage_Volume; directory : pchar; fileName : pchar; allowCreate : boolean; var fileSize : uint32) : pointer;
{ Per-file close hook: frees the context allocated by openFileCallback. }
PPCloseFileHook = procedure(ctx : pointer);
@@ -324,6 +326,7 @@ type
renameFileCallback : PPRenameFileHook;
{ Per-file open/close — nil if FS does not cache per-file metadata }
openFileCallback : PPOpenFileHook;
openFileModeCallback : PPOpenFileModeHook;
closeFileCallback : PPCloseFileHook;
formatParamFlags : uint32;
validateLabelCallback : PPValidateLabelHook;
+15 -4
View File
@@ -152,6 +152,7 @@ implementation
uses
driver.storage.fs.mgr,
driver.storage.fs.fat32,
driver.storage.fs.ext2,
proc.mgr,
proc.types,
io.stdio,
@@ -618,6 +619,8 @@ begin
if (vol^.filesystem <> nil) and (stringCompare(vol^.filesystem^.sName, 'FAT32') = 0) then
FAT32ReleaseVolumeState(vol);
if (vol^.filesystem <> nil) and (stringCompare(vol^.filesystem^.sName, 'EXT2') = 0) then
driver.storage.fs.ext2.ReleaseVolume(vol);
InvalidateVolume := true;
debug.tracer.push_trace('driver.storage.vfs.InvalidateVolume.exit');
@@ -1427,8 +1430,12 @@ begin
fd^.FSCloseHook := nil;
{ Cache per-file metadata and populate DataSize via FS open hook }
if (vol^.filesystem <> nil) and (vol^.filesystem^.openFileCallback <> nil) then begin
fd^.FSPrivate := vol^.filesystem^.openFileCallback(vol, dir, fname, fd^.DataSize);
if (vol^.filesystem <> nil) and ((vol^.filesystem^.openFileCallback <> nil) or
(vol^.filesystem^.openFileModeCallback <> nil)) then begin
if vol^.filesystem^.openFileModeCallback <> nil then
fd^.FSPrivate := vol^.filesystem^.openFileModeCallback(vol, dir, fname,
(OpenMode = omCreate) or (OpenMode = omWrite), fd^.DataSize)
else fd^.FSPrivate := vol^.filesystem^.openFileCallback(vol, dir, fname, fd^.DataSize);
if fd^.FSPrivate = nil then begin
if Error <> nil then begin
if (OpenMode = omCreate) or (OpenMode = omWrite) then
@@ -1724,8 +1731,12 @@ begin
fd^.FSCloseHook := nil;
OutHandle := slot;
if (vol^.filesystem <> nil) and (vol^.filesystem^.openFileCallback <> nil) then begin
fd^.FSPrivate := vol^.filesystem^.openFileCallback(vol, dir, fname, fd^.DataSize);
if (vol^.filesystem <> nil) and ((vol^.filesystem^.openFileCallback <> nil) or
(vol^.filesystem^.openFileModeCallback <> nil)) then begin
if vol^.filesystem^.openFileModeCallback <> nil then
fd^.FSPrivate := vol^.filesystem^.openFileModeCallback(vol, dir, fname,
(OpenMode = omCreate) or (OpenMode = omWrite), fd^.DataSize)
else fd^.FSPrivate := vol^.filesystem^.openFileCallback(vol, dir, fname, fd^.DataSize);
if fd^.FSPrivate = nil then begin
if Error <> nil then begin
if (OpenMode = omCreate) or (OpenMode = omWrite) then
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,62 @@
unit driver.storage.fs.ext2.types;
interface
uses driver.storage.types;
const
EXT2_MAGIC = $EF53;
EXT2_DIR = $4000;
EXT2_FILE = $8000;
EXT2_ROOT = 2;
type
TExt2Inode = packed record
Mode, UID : uint16;
Size, ATime, CTime, MTime, DTime : uint32;
GID, Links : uint16;
Sectors, Flags, OSData : uint32;
Blocks : array[0..14] of uint32;
Generation, ACL, SizeHigh, Fragment : uint32;
OSExtra : array[0..11] of uint8;
end;
PExt2Inode = ^TExt2Inode;
TExt2Group = packed record
BlockBitmap, InodeBitmap, InodeTable : uint32;
FreeBlocks, FreeInodes, Directories, Pad : uint16;
Reserved : array[0..2] of uint32;
end;
PExt2Group = ^TExt2Group;
TExt2Dirent = packed record
Inode : uint32;
Length : uint16;
NameLength, FileType : uint8;
end;
PExt2Dirent = ^TExt2Dirent;
PExt2Volume = ^TExt2Volume;
PExt2File = ^TExt2File;
TExt2Volume = record
Volume : PStorage_Volume;
Super, Groups : puint8;
BlockSize, SectorsPerBlock, BlockCount, InodeCount : uint32;
FirstBlock, BlocksPerGroup, InodesPerGroup, InodeSize : uint32;
GroupCount, GDTBlocks, AllocGroup : uint32;
Busy, Writable, Poisoned, FileTypes : boolean;
Files : PExt2File;
end;
TExt2File = record
Volume : PExt2Volume;
Inode : uint32;
Next : PExt2File;
end;
{ One operation owns its buffers. No DMA destination is shared with another
operation. The volume lock protects metadata and all read/modify/write. }
TExt2Op = record
V : PExt2Volume;
Scratch, Data : puint8;
Error : TError;
Mutating : boolean;
end;
PExt2Op = ^TExt2Op;
implementation
end.