CloverBootloader/FileSystems/FatPkg/EnhancedFatDxe/DirectoryCache.c
2019-09-03 12:58:42 +03:00

235 lines
4.5 KiB
C

/*++
Copyright (c) 2005, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the Software
License Agreement which accompanies this distribution.
Module Name:
DirectoryCache.c
Abstract:
Functions for directory cache operation
Revision History
--*/
#include "Fat.h"
STATIC
VOID
FatFreeODir (
IN FAT_ODIR *ODir
)
/*++
Routine Description:
Free the directory structure and release the memory.
Arguments:
ODir - The directory to be freed.
Returns:
None.
--*/
{
FAT_DIRENT *DirEnt;
//
// Release Directory Entry Nodes
//
while (!IsListEmpty (&ODir->ChildList)) {
DirEnt = DIRENT_FROM_LINK (ODir->ChildList.ForwardLink);
RemoveEntryList (&DirEnt->Link);
//
// Make sure the OFile has been closed
//
ASSERT (DirEnt->OFile == NULL);
FatFreeDirEnt (DirEnt);
}
FreePool (ODir);
}
STATIC
FAT_ODIR *
FatAllocateODir (
IN FAT_OFILE *OFile
)
/*++
Routine Description:
Allocate the directory structure.
Arguments:
OFile - The corresponding OFile.
Returns:
None.
--*/
{
FAT_ODIR *ODir;
ODir = AllocateZeroPool (sizeof (FAT_ODIR));
if (ODir != NULL) {
//
// Initialize the directory entry list
//
ODir->Signature = FAT_ODIR_SIGNATURE;
InitializeListHead (&ODir->ChildList);
ODir->CurrentCursor = &ODir->ChildList;
}
return ODir;
}
VOID
FatDiscardODir (
IN FAT_OFILE *OFile
)
/*++
Routine Description:
Discard the directory structure when an OFile will be freed.
Volume will cache this directory if the OFile does not represent a deleted file.
Arguments:
OFile - The OFile whose directory structure is to be discarded.
Returns:
None.
--*/
{
FAT_ODIR *ODir;
FAT_VOLUME *Volume;
Volume = OFile->Volume;
ODir = OFile->ODir;
if (!OFile->DirEnt->Invalid) {
//
// If OFile does not represent a deleted file, then we will cache the directory
// We use OFile's first cluster as the directory's tag
//
ODir->DirCacheTag = OFile->FileCluster;
InsertHeadList (&Volume->DirCacheList, &ODir->DirCacheLink);
if (Volume->DirCacheCount == FAT_MAX_DIR_CACHE_COUNT) {
//
// Replace the least recent used directory
//
ODir = ODIR_FROM_DIRCACHELINK (Volume->DirCacheList.BackLink);
RemoveEntryList (&ODir->DirCacheLink);
} else {
//
// No need to find a replace
//
Volume->DirCacheCount++;
ODir = NULL;
}
}
//
// Release ODir Structure
//
if (ODir != NULL) {
FatFreeODir (ODir);
}
}
VOID
FatRequestODir (
IN FAT_OFILE *OFile
)
/*++
Routine Description:
Request the directory structure when an OFile is newly generated.
If the directory structure is cached by volume, then just return this directory;
Otherwise, allocate a new one for OFile.
Arguments:
OFile - The OFile which requests directory structure.
Returns:
None.
--*/
{
UINTN DirCacheTag;
FAT_VOLUME *Volume;
FAT_ODIR *ODir;
FAT_ODIR *CurrentODir;
LIST_ENTRY *CurrentODirLink;
Volume = OFile->Volume;
ODir = NULL;
DirCacheTag = OFile->FileCluster;
for (CurrentODirLink = Volume->DirCacheList.ForwardLink;
CurrentODirLink != &Volume->DirCacheList;
CurrentODirLink = CurrentODirLink->ForwardLink
) {
CurrentODir = ODIR_FROM_DIRCACHELINK (CurrentODirLink);
if (CurrentODir->DirCacheTag == DirCacheTag) {
RemoveEntryList (&CurrentODir->DirCacheLink);
Volume->DirCacheCount--;
ODir = CurrentODir;
break;
}
}
if (ODir == NULL) {
//
// This directory is not cached, then allocate a new one
//
ODir = FatAllocateODir (OFile);
}
OFile->ODir = ODir;
}
VOID
FatCleanupODirCache (
IN FAT_VOLUME *Volume
)
/*++
Routine Description:
Clean up all the cached directory structures when the volume is going to be abandoned.
Arguments:
Volume - FAT file system volume.
Returns:
None.
--*/
{
FAT_ODIR *ODir;
while (Volume->DirCacheCount > 0) {
ODir = ODIR_FROM_DIRCACHELINK (Volume->DirCacheList.BackLink);
RemoveEntryList (&ODir->DirCacheLink);
FatFreeODir (ODir);
Volume->DirCacheCount--;
}
}