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:
1 parent
663bfbb0e4
commit
096db148d0
6 files changed
+818
-27
No files matched your search
@@ -34,7 +34,7 @@ const
|
|||||||
TICK_HZ = 1024; { timer ISR frequency }
|
TICK_HZ = 1024; { timer ISR frequency }
|
||||||
IO_WAIT_TIMEOUT_TICKS = 10 * TICK_HZ;
|
IO_WAIT_TIMEOUT_TICKS = 10 * TICK_HZ;
|
||||||
DELETE_TIMEOUT_TICKS = 5 * TICK_HZ;
|
DELETE_TIMEOUT_TICKS = 5 * TICK_HZ;
|
||||||
DEFAULT_PATH : pchar = '/disk/vol0/IOTEST.BIN';
|
DEFAULT_PATH : pchar = '/disk/vol2/IOTEST.BIN';
|
||||||
|
|
||||||
type
|
type
|
||||||
TIOTSyncWaitCtx = record
|
TIOTSyncWaitCtx = record
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ function send_read_capacity(device : PAHCI_Device; sectorCount : puint32; blockS
|
|||||||
implementation
|
implementation
|
||||||
|
|
||||||
const
|
const
|
||||||
AHCI_ENABLE_NCQ = false;
|
AHCI_ENABLE_NCQ = true;
|
||||||
|
|
||||||
function min_u32(a : uint32; b : uint32) : uint32;
|
function min_u32(a : uint32; b : uint32) : uint32;
|
||||||
begin
|
begin
|
||||||
@@ -421,15 +421,15 @@ begin
|
|||||||
start_port(device^.port);
|
start_port(device^.port);
|
||||||
|
|
||||||
{ Re-enable port interrupts and bail — device is non-functional. }
|
{ Re-enable port interrupts and bail — device is non-functional. }
|
||||||
device^.port^.int_enable := $40000003;
|
device^.port^.int_enable := $4000000B;
|
||||||
kfree(buffer);
|
kfree(buffer);
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ Re-enable port interrupts now that IDENTIFY polling is done.
|
{ 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)
|
$4000000B = bit 0 (D2H Register FIS) | bit 1 (PIO Setup FIS) | bit 3 (Set Device Bits / NCQ) | bit 30 (Task File Error)
|
||||||
These three bits cover all normal completions and hardware error events. }
|
Bit 3 is required for NCQ completion notifications via SDB FIS. }
|
||||||
device^.port^.int_enable := $40000003;
|
device^.port^.int_enable := $4000000B;
|
||||||
|
|
||||||
b8 := puint16(buffer);
|
b8 := puint16(buffer);
|
||||||
memcpy(uint32(buffer), uint32(@device^.ata_info[0]), 512);
|
memcpy(uint32(buffer), uint32(@device^.ata_info[0]), 512);
|
||||||
|
|||||||
File diff suppressed because it is too large.
Load diff
+4
-2
@@ -14,7 +14,8 @@ implementation
|
|||||||
|
|
||||||
uses
|
uses
|
||||||
io.syslog,
|
io.syslog,
|
||||||
driver.storage.fs.fat32.old,
|
core.util,
|
||||||
|
driver.storage.fs.fat32.vol,
|
||||||
driver.storage.fs.fat32.core,
|
driver.storage.fs.fat32.core,
|
||||||
driver.storage.fs.fat32.transfer;
|
driver.storage.fs.fat32.transfer;
|
||||||
|
|
||||||
@@ -23,13 +24,13 @@ var
|
|||||||
|
|
||||||
procedure FAT32ReleaseVolumeState(volume : PStorage_Volume);
|
procedure FAT32ReleaseVolumeState(volume : PStorage_Volume);
|
||||||
begin
|
begin
|
||||||
FAT32LegacyReleaseVolumeCtx(volume);
|
|
||||||
FAT32ReleaseVolumeCtx(volume);
|
FAT32ReleaseVolumeCtx(volume);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure init;
|
procedure init;
|
||||||
begin
|
begin
|
||||||
io.syslog.logln('FAT32', 'init: registering FAT32 filesystem');
|
io.syslog.logln('FAT32', 'init: registering FAT32 filesystem');
|
||||||
|
memset(uint32(@filesystem), 0, sizeof(TFilesystem));
|
||||||
filesystem.sName := 'FAT32';
|
filesystem.sName := 'FAT32';
|
||||||
filesystem.system_id := $0B;
|
filesystem.system_id := $0B;
|
||||||
filesystem.readDirCallback := @FAT32ReadDirectory;
|
filesystem.readDirCallback := @FAT32ReadDirectory;
|
||||||
@@ -52,6 +53,7 @@ begin
|
|||||||
filesystem.readDirAsyncCallback := nil;
|
filesystem.readDirAsyncCallback := nil;
|
||||||
filesystem.formatParamFlags := FS_FORMAT_PARAM_CLUSTER_SIZE;
|
filesystem.formatParamFlags := FS_FORMAT_PARAM_CLUSTER_SIZE;
|
||||||
|
|
||||||
|
FAT32VolInit(@filesystem);
|
||||||
driver.storage.fs.mgr.register_filesystem(@filesystem);
|
driver.storage.fs.mgr.register_filesystem(@filesystem);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -67,17 +67,16 @@ type
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
const
|
const
|
||||||
FAT_CACHE_SETS = 512;
|
FAT_CACHE_SETS = 1024;
|
||||||
FAT_CACHE_WAYS = 2;
|
FAT_CACHE_WAYS = 4;
|
||||||
FAT_CACHE_LINES = FAT_CACHE_SETS * FAT_CACHE_WAYS;
|
FAT_CACHE_LINES = FAT_CACHE_SETS * FAT_CACHE_WAYS;
|
||||||
FAT_TRANSFER_POOL_CAPACITY = 64;
|
FAT_TRANSFER_POOL_CAPACITY = 64;
|
||||||
FAT_ALLOC_HINT_SLOTS = 8;
|
FAT_ALLOC_HINT_SLOTS = 8;
|
||||||
FAT_DIR_HINT_SLOTS = 16;
|
FAT_DIR_HINT_SLOTS = 8;
|
||||||
FAT_WRITE_PREALLOC_BYTES = 16 * 1024 * 1024;
|
|
||||||
FAT_WRITE_PREALLOC_MAX_CLUSTERS = 2048;
|
FAT_WRITE_PREALLOC_MAX_CLUSTERS = 2048;
|
||||||
FAT_WRITE_PREALLOC_MIN_CLUSTERS = 64;
|
FAT_WRITE_PREALLOC_MIN_CLUSTERS = 64;
|
||||||
FAT_MAX_IO_SECTORS = 2048;
|
FAT_MAX_IO_SECTORS = 2048 * 2;
|
||||||
|
FAT_OPEN_HANDLE_SLOTS = 65000;
|
||||||
type
|
type
|
||||||
TFATCacheLine = record
|
TFATCacheLine = record
|
||||||
SectorIdx : uint32;
|
SectorIdx : uint32;
|
||||||
@@ -162,6 +161,13 @@ type
|
|||||||
Exists : boolean;
|
Exists : boolean;
|
||||||
FatDirty : boolean;
|
FatDirty : boolean;
|
||||||
MetaDirty : 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;
|
end;
|
||||||
|
|
||||||
TFATTransferMode = (ftmRead, ftmWrite);
|
TFATTransferMode = (ftmRead, ftmWrite);
|
||||||
@@ -215,6 +221,7 @@ type
|
|||||||
HintStamp : uint32;
|
HintStamp : uint32;
|
||||||
AllocHints : array[0..FAT_ALLOC_HINT_SLOTS - 1] of TFATAllocHint;
|
AllocHints : array[0..FAT_ALLOC_HINT_SLOTS - 1] of TFATAllocHint;
|
||||||
DirHints : array[0..FAT_DIR_HINT_SLOTS - 1] of TFATDirHint;
|
DirHints : array[0..FAT_DIR_HINT_SLOTS - 1] of TFATDirHint;
|
||||||
|
WriteRefs : array[0..FAT_OPEN_HANDLE_SLOTS - 1] of TFATWriteRef;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|||||||
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user