fat32: fix pre-alloc cluster leak; add write-handle ref-count

- Remove FAT_WRITE_PREALLOC_BYTES (redundant at typical cluster sizes)
- Simplify fatPreallocClusterCount to always return MAX_CLUSTERS
- FAT32CloseFile: truncate pre-allocated tail clusters back to ByteSize
  on close, freeing FAT chain entries beyond the file's real size
- Add TFATWriteRef + WriteRefs[32] in TFATVolumeCtx and Registered flag
  on TFATOpenFile to track concurrent write handles per dir entry
- fatRegisterWriteHandle / fatUnregisterWriteHandle: CLI-guarded slot scan
  keyed by (DirLoc.SectorLBA, DirLoc.EntryIdx)
- Register on first FAT chain extension in FAT32EnsureCapacityForWrite
- Truncation in FAT32CloseFile skipped unless this is the last writer
  (prevents RunMap corruption in concurrent-open scenarios)
- Add forward decl for fatFreeClusterChain to fix ordering issue
- app.iotest: update default path to /disk/vol2/IOTEST.BIN
This commit is contained in:
2026-03-18 21:05:36 +00:00
parent 663bfbb0e4
commit 096db148d0
6 changed files with 818 additions and 27 deletions
+1 -1
View File
@@ -34,7 +34,7 @@ const
TICK_HZ = 1024; { timer ISR frequency }
IO_WAIT_TIMEOUT_TICKS = 10 * TICK_HZ;
DELETE_TIMEOUT_TICKS = 5 * TICK_HZ;
DEFAULT_PATH : pchar = '/disk/vol0/IOTEST.BIN';
DEFAULT_PATH : pchar = '/disk/vol2/IOTEST.BIN';
type
TIOTSyncWaitCtx = record
@@ -69,7 +69,7 @@ function send_read_capacity(device : PAHCI_Device; sectorCount : puint32; blockS
implementation
const
AHCI_ENABLE_NCQ = false;
AHCI_ENABLE_NCQ = true;
function min_u32(a : uint32; b : uint32) : uint32;
begin
@@ -421,15 +421,15 @@ begin
start_port(device^.port);
{ Re-enable port interrupts and bail — device is non-functional. }
device^.port^.int_enable := $40000003;
device^.port^.int_enable := $4000000B;
kfree(buffer);
exit;
end;
{ Re-enable port interrupts now that IDENTIFY polling is done.
$40000003 = bit 0 (D2H Register FIS) | bit 1 (PIO Setup FIS) | bit 30 (Task File Error)
These three bits cover all normal completions and hardware error events. }
device^.port^.int_enable := $40000003;
$4000000B = bit 0 (D2H Register FIS) | bit 1 (PIO Setup FIS) | bit 3 (Set Device Bits / NCQ) | bit 30 (Task File Error)
Bit 3 is required for NCQ completion notifications via SDB FIS. }
device^.port^.int_enable := $4000000B;
b8 := puint16(buffer);
memcpy(uint32(buffer), uint32(@device^.ata_info[0]), 512);
File diff suppressed because it is too large Load Diff
@@ -14,7 +14,8 @@ implementation
uses
io.syslog,
driver.storage.fs.fat32.old,
core.util,
driver.storage.fs.fat32.vol,
driver.storage.fs.fat32.core,
driver.storage.fs.fat32.transfer;
@@ -23,13 +24,13 @@ var
procedure FAT32ReleaseVolumeState(volume : PStorage_Volume);
begin
FAT32LegacyReleaseVolumeCtx(volume);
FAT32ReleaseVolumeCtx(volume);
end;
procedure init;
begin
io.syslog.logln('FAT32', 'init: registering FAT32 filesystem');
memset(uint32(@filesystem), 0, sizeof(TFilesystem));
filesystem.sName := 'FAT32';
filesystem.system_id := $0B;
filesystem.readDirCallback := @FAT32ReadDirectory;
@@ -52,6 +53,7 @@ begin
filesystem.readDirAsyncCallback := nil;
filesystem.formatParamFlags := FS_FORMAT_PARAM_CLUSTER_SIZE;
FAT32VolInit(@filesystem);
driver.storage.fs.mgr.register_filesystem(@filesystem);
end;
@@ -67,17 +67,16 @@ type
end;
const
FAT_CACHE_SETS = 512;
FAT_CACHE_WAYS = 2;
FAT_CACHE_SETS = 1024;
FAT_CACHE_WAYS = 4;
FAT_CACHE_LINES = FAT_CACHE_SETS * FAT_CACHE_WAYS;
FAT_TRANSFER_POOL_CAPACITY = 64;
FAT_ALLOC_HINT_SLOTS = 8;
FAT_DIR_HINT_SLOTS = 16;
FAT_WRITE_PREALLOC_BYTES = 16 * 1024 * 1024;
FAT_DIR_HINT_SLOTS = 8;
FAT_WRITE_PREALLOC_MAX_CLUSTERS = 2048;
FAT_WRITE_PREALLOC_MIN_CLUSTERS = 64;
FAT_MAX_IO_SECTORS = 2048;
FAT_MAX_IO_SECTORS = 2048 * 2;
FAT_OPEN_HANDLE_SLOTS = 65000;
type
TFATCacheLine = record
SectorIdx : uint32;
@@ -162,6 +161,13 @@ type
Exists : boolean;
FatDirty : boolean;
MetaDirty : boolean;
Registered : boolean; { true once registered in the volume write-ref table }
end;
TFATWriteRef = record
SectorLBA : uint32;
EntryIdx : uint32;
Count : uint32; { number of write handles with this dir entry open }
end;
TFATTransferMode = (ftmRead, ftmWrite);
@@ -215,6 +221,7 @@ type
HintStamp : uint32;
AllocHints : array[0..FAT_ALLOC_HINT_SLOTS - 1] of TFATAllocHint;
DirHints : array[0..FAT_DIR_HINT_SLOTS - 1] of TFATDirHint;
WriteRefs : array[0..FAT_OPEN_HANDLE_SLOTS - 1] of TFATWriteRef;
end;
implementation
File diff suppressed because it is too large Load Diff