From 5fb6fad1759483ee2bc806ae7645f93ad879ede7 Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Thu, 27 Feb 2025 20:06:07 +0600 Subject: [PATCH] [FREELDR] iso.c: Remember the last directory that was accessed (#7734) This patch reduces the number of sectors read by 709 (from 8788 to 8079) --- boot/freeldr/freeldr/lib/fs/iso.c | 154 ++++++++++++++++++++++-------- 1 file changed, 113 insertions(+), 41 deletions(-) diff --git a/boot/freeldr/freeldr/lib/fs/iso.c b/boot/freeldr/freeldr/lib/fs/iso.c index 97feb6e2bb7..55ea802ebd2 100644 --- a/boot/freeldr/freeldr/lib/fs/iso.c +++ b/boot/freeldr/freeldr/lib/fs/iso.c @@ -33,10 +33,34 @@ typedef struct _ISO_VOLUME_INFO { ULONG PvdDirectorySector; ULONG PvdDirectoryLength; + ULONG DirectoryPathLength; + ULONG DirectoryLength; + PVOID DirectoryBuffer; + UCHAR DirectoryPath[261]; } ISO_VOLUME_INFO, *PISO_VOLUME_INFO; static PISO_VOLUME_INFO IsoVolumes[MAX_FDS]; +static +PCSTR +IsoLastPathSeparator( + _In_ PCSTR Path) +{ + PCSTR Last = NULL; + + ASSERT(Path != NULL); + + while (*Path != ANSI_NULL) + { + if (*Path == '\\' || *Path == '/') + Last = Path; + + ++Path; + } + + return Last; +} + static BOOLEAN IsoSearchDirectoryBufferForFile(PVOID DirectoryBuffer, ULONG DirectoryLength, PCHAR FileName, PISO_FILE_INFO IsoFileInfoPointer) { PDIR_RECORD Record; @@ -145,7 +169,6 @@ static ARC_STATUS IsoBufferDirectory(ULONG DeviceId, ULONG DirectoryStartSector, return ESUCCESS; } - /* * IsoLookupFile() * This function searches the file system for the @@ -154,76 +177,125 @@ static ARC_STATUS IsoBufferDirectory(ULONG DeviceId, ULONG DirectoryStartSector, */ static ARC_STATUS IsoLookupFile(PCSTR FileName, ULONG DeviceId, PISO_FILE_INFO IsoFileInfo) { + PCSTR FullPath = FileName; PISO_VOLUME_INFO Volume; - UINT32 i; - ULONG NumberOfPathParts; - CHAR PathPart[261]; - PVOID DirectoryBuffer; - ULONG DirectorySector; - ULONG DirectoryLength; + PCSTR FileNameStr; + ULONG i, DirectoryPathLength, DirectorySector, DirectoryLength; + PVOID DirectoryBuffer; + ULONG NumberOfPathParts; + CHAR PathBuffer[261]; + CHAR* PathPart; ARC_STATUS Status; + BOOLEAN DoFullLookup; TRACE("IsoLookupFile() FileName = %s\n", FileName); Volume = IsoVolumes[DeviceId]; - DirectorySector = Volume->PvdDirectorySector; - DirectoryLength = Volume->PvdDirectoryLength; + /* + * Extract the file name + * '\test.ini' --> 'test.ini' + * '\folder\app.exe' --> 'app.exe' + */ + FileNameStr = IsoLastPathSeparator(FileName) + 1; - /* Skip leading path separator, if any */ - if (*FileName == '\\' || *FileName == '/') - ++FileName; - // - // Figure out how many sub-directories we are nested in - // - NumberOfPathParts = FsGetNumPathParts(FileName); + /* + * Extract the directory path, including trailing slash + * '\test.ini' --> '\' + * '\folder\app.exe' --> '\folder\' + */ + DirectoryPathLength = FileNameStr - FileName; + + /* See if this directory has been buffered before */ + DoFullLookup = (DirectoryPathLength != Volume->DirectoryPathLength) || + !RtlEqualMemory(FileName, Volume->DirectoryPath, DirectoryPathLength); + if (!DoFullLookup) + { + PathPart = (CHAR*)FileNameStr; + DirectoryBuffer = Volume->DirectoryBuffer; + DirectoryLength = Volume->DirectoryLength; + + NumberOfPathParts = 1; + } + else + { + PathPart = PathBuffer; + DirectorySector = Volume->PvdDirectorySector; + DirectoryLength = Volume->PvdDirectoryLength; + + /* Skip leading path separator, if any */ + if (*FileName == '\\' || *FileName == '/') + ++FileName; + + /* Figure out how many sub-directories we are nested in */ + NumberOfPathParts = FsGetNumPathParts(FileName); + } // // Loop once for each part // for (i=0; i= NumberOfPathParts) + { + if (Volume->DirectoryBuffer) + FrLdrTempFree(Volume->DirectoryBuffer, TAG_ISO_BUFFER); + + Volume->DirectoryPathLength = DirectoryPathLength; + Volume->DirectoryBuffer = DirectoryBuffer; + Volume->DirectoryLength = DirectoryLength; + + RtlCopyMemory(Volume->DirectoryPath, FullPath, DirectoryPathLength); + } } - FileName++; - // - // Buffer the directory contents - // - Status = IsoBufferDirectory(DeviceId, DirectorySector, DirectoryLength, &DirectoryBuffer); - if (Status != ESUCCESS) - return Status; - - // - // Search for file name in directory - // - if (!IsoSearchDirectoryBufferForFile(DirectoryBuffer, DirectoryLength, PathPart, IsoFileInfo)) + /* Search for file name in directory */ + if (!IsoSearchDirectoryBufferForFile(DirectoryBuffer, + DirectoryLength, + PathPart, + IsoFileInfo)) { - FrLdrTempFree(DirectoryBuffer, TAG_ISO_BUFFER); + /* Free the directory buffer that wasn't cached */ + if ((i + 1) < NumberOfPathParts) + { + ASSERT(DirectoryBuffer != Volume->DirectoryBuffer); + FrLdrTempFree(DirectoryBuffer, TAG_ISO_BUFFER); + } return ENOENT; } - FrLdrTempFree(DirectoryBuffer, TAG_ISO_BUFFER); - // // If we have another sub-directory to go then // grab the start sector and file size // if ((i+1) < NumberOfPathParts) { + FrLdrTempFree(DirectoryBuffer, TAG_ISO_BUFFER); + DirectorySector = IsoFileInfo->FileStart; DirectoryLength = IsoFileInfo->FileSize; } - } return ESUCCESS;