Compare commits

...
Author SHA1 Message Date
Aaron 7e99bc2db1 fat
continuous-integration/drone/push Build is passing
2026-03-24 18:10:04 +00:00
Aaron 096db148d0 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
2026-03-18 21:05:36 +00:00
Aaron 663bfbb0e4 storage: lifecycle watch system, PFSFormatParams, vol busy/format flags, diskutil improvements
- Add TStorageLifecycleWatch with watch_lifecycle/unwatch_lifecycle API (up to 32 watchers)
- Add notify_lifecycle to broadcast mount/unmount/format events to registered callbacks
- Replace raw puint32 config in format_volume with typed PFSFormatParams
- Add volume_is_busy, volume_is_formatting, volume_set_mounted helpers
- Add lifecycleFlags field to TStorage_Volume for tracking busy/formatting state
- Expand app.diskutil with improved commands and volume state reporting
- Minor improvements to core.util, arch.x86.util, proc.mgr, VFS, and flatfs
- Remove obsolete driver.storage.fs.fat32.old.pas
2026-03-16 23:03:43 +00:00
Aaron aadc59f831 fat32 rewrite and storage stability fixes 2026-03-16 21:18:44 +00:00
Aaron 5d7aacc28f more improvements 2026-03-15 23:58:52 +00:00
Aaron 4810617922 FAT improvements and switch to 2-way associative cache 2026-03-15 19:46:31 +00:00
Aaron 666a011a9f refactor fat32 2026-03-15 15:11:00 +00:00
Aaron a6e81bf5d3 VFS improvements, IO fixes, IO performance improvements. 2026-03-15 14:02:17 +00:00
29 changed files with 7463 additions and 3333 deletions
+500
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+69 -9
View File
@@ -195,6 +195,7 @@ procedure do_refresh_load(state: PFileBrowserState); forward;
procedure do_refresh_build(state: PFileBrowserState); forward;
procedure schedule_refresh(state: PFileBrowserState); forward;
procedure fb_refresh_poll_cb(tmr: Plv_timer); cdecl; forward;
function fb_error_name(err : TError) : pchar; forward;
procedure fb_collect_cb(key: pchar; data: void; ud: void); forward;
procedure do_refresh(state: PFileBrowserState); forward;
procedure navigate_to(state: PFileBrowserState; newDir: pchar); forward;
@@ -582,6 +583,51 @@ begin
puint32(@state^.refresh_pending)^ := 1;
end;
function fb_error_name(err : TError) : pchar;
begin
case err of
eNone: fb_error_name := 'eNone';
eUnknown: fb_error_name := 'eUnknown';
eNotSupported: fb_error_name := 'eNotSupported';
eOutOfMemory: fb_error_name := 'eOutOfMemory';
eInvalidArgument: fb_error_name := 'eInvalidArgument';
eFileInUse: fb_error_name := 'eFileInUse';
eFileDoesNotExist: fb_error_name := 'eFileDoesNotExist';
eInvalidFileName: fb_error_name := 'eInvalidFileName';
eInvalidFileExtension: fb_error_name := 'eInvalidFileExtension';
eFilenameTooLong: fb_error_name := 'eFilenameTooLong';
eDirectoryDoesNotExist: fb_error_name := 'eDirectoryDoesNotExist';
eDirectoryAlreadyExists: fb_error_name := 'eDirectoryAlreadyExists';
eDirectoryNotEmpty: fb_error_name := 'eDirectoryNotEmpty';
eDirectoryFull: fb_error_name := 'eDirectoryFull';
eNotADirectory: fb_error_name := 'eNotADirectory';
eWriteOnly: fb_error_name := 'eWriteOnly';
eReadOnly: fb_error_name := 'eReadOnly';
ePermissionDenied: fb_error_name := 'ePermissionDenied';
eInvalidPath: fb_error_name := 'eInvalidPath';
eTooManyOpenFiles: fb_error_name := 'eTooManyOpenFiles';
eInvalidHandle: fb_error_name := 'eInvalidHandle';
eFileNotLoaded: fb_error_name := 'eFileNotLoaded';
eAlreadyExists: fb_error_name := 'eAlreadyExists';
eDiskFull: fb_error_name := 'eDiskFull';
eIOError: fb_error_name := 'eIOError';
eIOTimeout: fb_error_name := 'eIOTimeout';
eIOCancelled: fb_error_name := 'eIOCancelled';
eDeviceNotReady: fb_error_name := 'eDeviceNotReady';
eDeviceRemoved: fb_error_name := 'eDeviceRemoved';
eDeviceNotFound: fb_error_name := 'eDeviceNotFound';
eQueueFull: fb_error_name := 'eQueueFull';
eNoFreeSlot: fb_error_name := 'eNoFreeSlot';
eCorruptFilesystem: fb_error_name := 'eCorruptFilesystem';
eBadSector: fb_error_name := 'eBadSector';
eAlreadyMounted: fb_error_name := 'eAlreadyMounted';
eNotMounted: fb_error_name := 'eNotMounted';
eUnsupportedFilesystem: fb_error_name := 'eUnsupportedFilesystem';
eInvalidPartitionTable: fb_error_name := 'eInvalidPartitionTable';
eVolumeNotFound: fb_error_name := 'eVolumeNotFound';
end;
end;
{ fb_refresh_poll_cb — 50ms LVGL poll timer; when rd_ready=1, build UI }
procedure fb_refresh_poll_cb(tmr: Plv_timer); cdecl;
var
@@ -604,9 +650,12 @@ begin
case state^.wop_kind of
1: lv_msgbox_add_text(mbox, 'Could not create folder.');
2: lv_msgbox_add_text(mbox, 'Could not rename item.');
3: lv_msgbox_add_text(mbox, 'Could not create file.');
4: lv_msgbox_add_text(mbox, 'Could not delete item.');
else
lv_msgbox_add_text(mbox, 'Operation failed.');
end;
lv_msgbox_add_text(mbox, fb_error_name(state^.wop_result));
ok_b := lv_msgbox_add_footer_button(mbox, 'OK');
lv_obj_add_event_cb(ok_b, @fb_mbox_close_cb, LV_EVENT_CLICKED, mbox);
end;
@@ -619,8 +668,8 @@ begin
kfree(void(state^.wop_path2));
state^.wop_path2 := nil;
end;
{ For rename, clear selection }
if state^.wop_kind = 2 then
{ For rename/delete, clear selection }
if (state^.wop_kind = 2) or (state^.wop_kind = 4) then
clear_selection(state);
schedule_refresh(state);
end;
@@ -1591,15 +1640,16 @@ begin
@fb_delete_done, state);
end;
{ Async completion callback — runs in ISR/worker context, defer to LVGL }
{ Async completion callback — runs outside the LVGL thread, so only set flags. }
procedure fb_delete_done(error: TError; userdata: pointer);
var
state: PFileBrowserState;
begin
state := PFileBrowserState(userdata);
if state = nil then exit;
state^.op_err := error;
lv_timer_create(@fb_delete_done_timer, 1, state);
state^.wop_kind := 4;
state^.wop_result := error;
puint32(@state^.wop_done)^ := 1;
end;
{ Deferred UI update after delete }
@@ -1860,15 +1910,20 @@ begin
if (error = eNone) and (nfctx^.handle <> 0) then begin
{ WriteFileAsync needs a non-nil buffer; Length=0 so it is never read }
driver.storage.vfs.WriteFileAsync(nfctx^.handle, 0,
puint8(@nfctx^.err), 0, @fb_newfile_written, nfctx);
puint8(@nfctx^.err), 0, nil, @fb_newfile_written, nfctx);
end else begin
if nfctx^.handle <> 0 then
driver.storage.vfs.CloseFile(nfctx^.handle);
lv_timer_create(@fb_newfile_done_timer, 1, nfctx);
if nfctx^.state <> nil then begin
nfctx^.state^.wop_kind := 3;
nfctx^.state^.wop_result := nfctx^.err;
puint32(@nfctx^.state^.wop_done)^ := 1;
end;
kfree(void(nfctx));
end;
end;
{ Async step 2: write complete — close handle and schedule UI refresh }
{ Async step 2: write complete — close handle and defer UI work via poll flags }
procedure fb_newfile_written(error: TError; userdata: pointer);
var
nfctx : PNewFileCtx;
@@ -1878,7 +1933,12 @@ begin
if error <> eNone then nfctx^.err := error;
if nfctx^.handle <> 0 then
driver.storage.vfs.CloseFile(nfctx^.handle);
lv_timer_create(@fb_newfile_done_timer, 1, nfctx);
if nfctx^.state <> nil then begin
nfctx^.state^.wop_kind := 3;
nfctx^.state^.wop_result := nfctx^.err;
puint32(@nfctx^.state^.wop_done)^ := 1;
end;
kfree(void(nfctx));
end;
procedure fb_newfile_done_timer(tmr: Plv_timer); cdecl;
File diff suppressed because it is too large Load Diff
+2 -1
View File
@@ -26,7 +26,7 @@ uses
boot.mgr,
debug.tracer, io.stdio, proc.mgr,
//progs
app.base64, app.md5sum, app.dhclient, app.vbeinfo, app.testcmd, app.ping, app.meminfo, app.setres,
app.base64, app.md5sum, app.dhclient, app.vbeinfo, app.testcmd, app.ping, app.meminfo, app.setres, app.iotest,
//drivers
driver.storage.ctl.ram, driver.mgr,
//network
@@ -92,6 +92,7 @@ begin
app.bsod.init();
app.vterminal.init;
app.filebrowser.init();
app.iotest.init();
end;
Initialization
+14
View File
@@ -44,6 +44,7 @@ function inl(port : uint16) : uint32;
procedure io_wait;
procedure __SSE_128_memcpy(source : uint32; dest : uint32);
procedure __REP_MOVSB_memcpy(source : uint32; dest : uint32; size : uint32);
procedure halt_and_catch_fire();
procedure halt_and_dont_catch_fire();
@@ -113,6 +114,19 @@ asm
MOVAPS [EAX], XMM1
end;
procedure __REP_MOVSB_memcpy(source : uint32; dest : uint32; size : uint32); assembler;
asm
push esi
push edi
cld
mov esi, source
mov edi, dest
mov ecx, size
rep movsb
pop edi
pop esi
end;
function getESP : uint32;
var
tmp: uint32;
+28 -9
View File
@@ -42,6 +42,26 @@ function HexCharToDecimal(hex : char) : uint8;
function abs(x : sint32) : uint32;
implementation
{$ifdef CPU386}
uses
arch.x86.util;
const
MEMCPY_X86_SMALL_COPY_THRESHOLD = 16;
{$endif}
procedure scalar_memcpy(source : uint32; dest : uint32; size : uint32);
var
src, dst : puint8;
i : uint32;
begin
if size = 0 then exit;
for i := 0 to size - 1 do begin
src := puint8(source + i);
dst := puint8(dest + i);
dst^ := src^;
end;
end;
function abs(x : sint32) : uint32;
var
@@ -123,17 +143,16 @@ begin
end;
procedure memcpy(source : uint32; dest : uint32; size : uint32);
var
src, dst : puint8;
i : uint32;
begin
if size = 0 then exit;
for i:=0 to size-1 do begin
src:= puint8(source + i);
dst:= puint8(dest + i);
dst^:= src^;
end;
{$ifdef CPU386}
if size < MEMCPY_X86_SMALL_COPY_THRESHOLD then
scalar_memcpy(source, dest, size)
else
arch.x86.util.__REP_MOVSB_memcpy(source, dest, size);
{$else}
scalar_memcpy(source, dest, size);
{$endif}
end;
function getWord(i : uint32; hi : boolean) : uint16;
File diff suppressed because it is too large Load Diff
@@ -269,6 +269,9 @@ type
port : PHBA_Port;
device_type : TDeviceType;
ata_info : TIdentResponse;
supportsNCQ : boolean;
queueDepth : uint32; { safe active depth for this device }
slotCount : uint32; { controller slot count from CAP.NCS + 1 }
command_list : PHBA_CMD_HEADER;
fis : PHBA_FIS;
command_table: PHBA_CMD_TABLE;
@@ -335,4 +338,3 @@ end;
// end;
end.
@@ -82,38 +82,12 @@ end;
{ ---- Filesystem hook callbacks ---- }
{ PPReadHook — load entire file into a new kalloc'd buffer.
Sets buffer^ to the data pointer, bytecount^ to the size.
Returns 0 on success, 1 on failure. }
function rd_Read(volume : PStorage_Volume; directory : pchar;
fileName : pchar; buffer : puint32;
bytecount : puint32) : uint32;
var
clean : pchar;
idx : sint32;
dest : puint8;
begin
rd_Read := 1;
clean := stripLeadingSlash(fileName);
if clean = nil then exit;
idx := findFileByName(clean);
if idx < 0 then exit;
{ VFS expects a fresh buffer it can own }
dest := puint8(kalloc(Files[idx].Size));
if dest = nil then exit;
memcpy(uint32(Files[idx].Data), uint32(dest), Files[idx].Size);
buffer^ := uint32(dest);
bytecount^ := Files[idx].Size;
rd_Read := 0;
end;
{ PPReadOffsetHook — read byteCount bytes at offset into caller buffer.
Returns actual bytes copied. }
function rd_ReadOffset(volume : PStorage_Volume; directory : pchar;
fileName : pchar; offset : uint32;
buffer : puint32; byteCount : uint32) : uint32;
buffer : puint32; byteCount : uint32;
ctx : pointer) : uint32;
var
clean : pchar;
idx : sint32;
@@ -133,6 +107,20 @@ begin
rd_ReadOffset := copyLen;
end;
function rd_FileSize(volume : PStorage_Volume; directory : pchar;
fileName : pchar) : uint32;
var
clean : pchar;
idx : sint32;
begin
rd_FileSize := 0;
clean := stripLeadingSlash(fileName);
if clean = nil then exit;
idx := findFileByName(clean);
if idx < 0 then exit;
rd_FileSize := Files[idx].Size;
end;
{ PPReadDirHook — return a linked list of TDirectory_Entry for all files.
VFS owns the returned list and frees each entry^.fileName. }
function rd_ReadDir(volume : PStorage_Volume; directory : pchar;
@@ -269,9 +257,9 @@ begin
{ Set up a minimal filesystem descriptor with our callbacks }
memset(uint32(@RAMFS), 0, sizeof(TFilesystem));
RAMFS.sName := 'ramfs';
RAMFS.readCallback := @rd_Read;
RAMFS.readDirCallback := @rd_ReadDir;
RAMFS.readOffsetCallback := @rd_ReadOffset;
RAMFS.fileSizeCallback := @rd_FileSize;
RAMFS.identifyCallback := @rd_Identify;
{ Set up a virtual volume backed by our filesystem }
@@ -45,10 +45,12 @@ const
ATA_CMD_READ_PIO_EXT = $24;
ATA_CMD_READ_DMA = $C8;
ATA_CMD_READ_DMA_EXT = $25;
ATA_CMD_READ_FPDMA_QUEUED = $60;
ATA_CMD_WRITE_PIO = $30;
ATA_CMD_WRITE_PIO_EXT = $34;
ATA_CMD_WRITE_DMA = $CA;
ATA_CMD_WRITE_DMA_EXT = $35;
ATA_CMD_WRITE_FPDMA_QUEUED = $61;
ATA_CMD_CACHE_FLUSH = $E7;
ATA_CMD_CACHE_FLUSH_EXT = $EA;
ATA_CMD_PACKET = $A0;
@@ -146,4 +148,4 @@ type
implementation
end.
end.
+61 -10
View File
@@ -37,17 +37,17 @@ type
PFileDescriptor = ^TFileDescriptor;
TFileDescriptor = record
InUse : boolean;
AsyncRefs : uint32; { in-flight async ops using this descriptor }
Volume : PStorage_Volume;
Directory : pchar; { directory path within the volume }
FileName : pchar; { filename within that directory }
VFSDir : pchar; { full VFS parent directory path, e.g. '/sys' }
OpenMode : uint8; { TOpenMode ordinal — avoids VFS type dependency }
DataBuffer : puint32; { pre-loaded data for small files, nil otherwise }
DataSize : uint32; { size of pre-loaded data in bytes }
Loaded : boolean; { true if pre-loaded into DataBuffer }
StreamOff : uint32; { current byte offset for streaming / on-demand reads }
DataSize : uint32; { cached file size in bytes (from fileSizeCallback) }
DeviceOps : pointer; { PVFSDeviceOps — non-nil for device FDs }
DeviceData : pointer; { opaque data passed to device callbacks }
FSPrivate : pointer; { opaque FS-level per-file metadata (from openFileCallback) }
FSCloseHook : pointer; { procedure(pointer) — frees FSPrivate on close }
end;
PFDTable = ^TFDTable;
@@ -71,6 +71,9 @@ function fd_alloc(table : PFDTable) : uint32;
{ Get a pointer to the descriptor for a 1-based handle.
Returns nil if handle is out of range or the slot is not in use. }
function fd_get(table : PFDTable; handle : uint32) : PFileDescriptor;
function fd_begin_async(entry : PFileDescriptor) : boolean;
procedure fd_end_async(entry : PFileDescriptor);
function fd_has_async(entry : PFileDescriptor) : boolean;
{ Close a single file descriptor: free its buffers and core.strings,
mark the slot as not-in-use.
@@ -81,6 +84,10 @@ function fd_close(table : PFDTable; handle : uint32) : boolean;
Used during process cleanup. }
procedure fd_close_all(table : PFDTable);
{ Close all file descriptors in the table that reference a specific volume.
Called when a volume is removed to prevent dangling pointers. }
procedure fd_close_for_volume(table : PFDTable; vol : PStorage_Volume);
implementation
function fd_table_new : PFDTable;
@@ -93,15 +100,20 @@ begin
fd_table_new := tbl;
end;
type
TFSPrivateClose = procedure(data : pointer);
procedure fd_free_entry(entry : PFileDescriptor);
begin
if entry = nil then exit;
if not entry^.InUse then exit;
if entry^.DataBuffer <> nil then begin
kfree(entry^.DataBuffer);
entry^.DataBuffer := nil;
end;
{ Free FS-level per-file metadata first }
if (entry^.FSPrivate <> nil) and (entry^.FSCloseHook <> nil) then
TFSPrivateClose(entry^.FSCloseHook)(entry^.FSPrivate);
entry^.FSPrivate := nil;
entry^.FSCloseHook := nil;
if entry^.Directory <> nil then begin
kfree(void(entry^.Directory));
entry^.Directory := nil;
@@ -116,9 +128,8 @@ begin
end;
entry^.InUse := false;
entry^.Loaded := false;
entry^.AsyncRefs := 0;
entry^.DataSize := 0;
entry^.StreamOff := 0;
entry^.DeviceOps := nil;
entry^.DeviceData := nil;
end;
@@ -153,6 +164,34 @@ begin
fd_get := @table^.Entries[handle - 1];
end;
function fd_begin_async(entry : PFileDescriptor) : boolean;
begin
fd_begin_async := false;
if entry = nil then exit;
asm pushf; cli end;
if entry^.InUse then begin
entry^.AsyncRefs := entry^.AsyncRefs + 1;
fd_begin_async := true;
end;
asm popf end;
end;
procedure fd_end_async(entry : PFileDescriptor);
begin
if entry = nil then exit;
asm pushf; cli end;
if entry^.AsyncRefs > 0 then
entry^.AsyncRefs := entry^.AsyncRefs - 1;
asm popf end;
end;
function fd_has_async(entry : PFileDescriptor) : boolean;
begin
fd_has_async := false;
if entry = nil then exit;
fd_has_async := entry^.AsyncRefs > 0;
end;
function fd_close(table : PFDTable; handle : uint32) : boolean;
begin
fd_close := false;
@@ -174,4 +213,16 @@ begin
end;
end;
procedure fd_close_for_volume(table : PFDTable; vol : PStorage_Volume);
var
i : uint32;
begin
if table = nil then exit;
if vol = nil then exit;
for i := 0 to MAX_FDS - 1 do begin
if table^.Entries[i].InUse and (table^.Entries[i].Volume = vol) then
fd_free_entry(@table^.Entries[i]);
end;
end;
end.
@@ -219,10 +219,9 @@ begin
validity := driver.storage.vfs.PathValid(absPath);
if validity <> pvFile then exit;
{ 2. Open the file in stream mode — only reads the bytes we ask for,
avoids pre-loading the entire file just to check a few magic bytes. }
{ 2. Open the file for reading — reads the magic bytes on demand. }
err := eNone;
fh := driver.storage.vfs.OpenFile(absPath, omStream, @err);
fh := driver.storage.vfs.OpenFile(absPath, omRead, @err);
if fh = 0 then exit;
memset(uint32(@headerBuf[0]), 0, MAX_MAGIC_LEN);
@@ -14,7 +14,7 @@
{
Driver->Storage->IORequest - I/O request allocation and lifecycle helpers.
Provides heap allocation/free for TIORequest records used by the
Provides fixed-pool allocation/free for TIORequest records used by the
submit_io / complete_io path in driver.storage.mgr.pas.
@author(Aaron Hance <[email protected]>)
@@ -27,7 +27,7 @@ uses
memory.heap,
driver.storage.types;
{ Allocate a new TIORequest on the heap and initialise its core fields.
{ Allocate a new TIORequest from the fixed request pool and initialise its core fields.
Caller, State, Error and ByteCount are zeroed (caller fills as needed). }
function ioreq_alloc(reqType : TIORequestType;
device : PStorage_Device;
@@ -35,16 +35,90 @@ function ioreq_alloc(reqType : TIORequestType;
sectors : uint32;
buf : pointer) : PIORequest;
{ Free a heap-allocated TIORequest. Safe to call with nil. }
{ Return a pooled TIORequest to the free list. Safe to call with nil. }
procedure ioreq_free(req : PIORequest);
{ Copy an existing TIORequest into a new heap allocation (deep copy of the
{ Copy an existing TIORequest into a new pooled allocation (deep copy of the
record, NOT the buffer it points to). Used by dispatch_next to create an
ISR-safe copy from the CFIFO value-element. }
function ioreq_copy(src : PIORequest) : PIORequest;
implementation
const
IOREQ_POOL_CAPACITY = 512;
IOREQ_REQ_OFFSET = sizeof(pointer);
type
PIORequestPoolNode = ^TIORequestPoolNode;
TIORequestPoolNode = record
Next : PIORequestPoolNode;
Req : TIORequest;
end;
var
ioreqPoolReady : boolean;
ioreqPoolBuf : pointer;
ioreqFreeList : PIORequestPoolNode;
procedure ioreq_pool_init();
var
i : uint32;
base : uint32;
node : PIORequestPoolNode;
begin
if ioreqPoolReady then exit;
ioreqPoolBuf := kalloc(IOREQ_POOL_CAPACITY * sizeof(TIORequestPoolNode));
if ioreqPoolBuf = nil then exit;
ioreqFreeList := nil;
base := uint32(ioreqPoolBuf);
if IOREQ_POOL_CAPACITY > 0 then
for i := 0 to IOREQ_POOL_CAPACITY - 1 do begin
node := PIORequestPoolNode(base + (i * sizeof(TIORequestPoolNode)));
node^.Next := ioreqFreeList;
ioreqFreeList := node;
end;
ioreqPoolReady := true;
end;
function ioreq_take() : PIORequest;
var
node : PIORequestPoolNode;
begin
if not ioreqPoolReady then
ioreq_pool_init();
if not ioreqPoolReady then begin
ioreq_take := nil;
exit;
end;
asm pushf; cli end;
node := ioreqFreeList;
if node <> nil then
ioreqFreeList := node^.Next;
asm popf end;
if node = nil then
ioreq_take := nil
else
ioreq_take := @node^.Req;
end;
procedure ioreq_release(req : PIORequest);
var
node : PIORequestPoolNode;
begin
if req = nil then exit;
node := PIORequestPoolNode(uint32(req) - IOREQ_REQ_OFFSET);
asm pushf; cli end;
node^.Next := ioreqFreeList;
ioreqFreeList := node;
asm popf end;
end;
function ioreq_alloc(reqType : TIORequestType;
device : PStorage_Device;
lba : uint32;
@@ -53,7 +127,7 @@ function ioreq_alloc(reqType : TIORequestType;
var
req : PIORequest;
begin
req := PIORequest(kalloc(SizeOf(TIORequest)));
req := ioreq_take();
if req = nil then begin
ioreq_alloc := nil;
exit;
@@ -75,15 +149,14 @@ end;
procedure ioreq_free(req : PIORequest);
begin
if req <> nil then
kfree(void(req));
ioreq_release(req);
end;
function ioreq_copy(src : PIORequest) : PIORequest;
var
dst : PIORequest;
begin
dst := PIORequest(kalloc(SizeOf(TIORequest)));
dst := ioreq_take();
if dst = nil then begin
ioreq_copy := nil;
exit;
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
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

Some files were not shown because too many files have changed in this diff Show More