/** @file | |
Functions for directory cache operation. | |
Copyright (c) 2005, Intel Corporation. All rights reserved.<BR> | |
SPDX-License-Identifier: BSD-2-Clause-Patent | |
**/ | |
#include "Fat.h" | |
/** | |
Free the directory structure and release the memory. | |
@param ODir - The directory to be freed. | |
**/ | |
STATIC | |
VOID | |
FatFreeODir ( | |
IN FAT_ODIR *ODir | |
) | |
{ | |
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); | |
} | |
/** | |
Allocate the directory structure. | |
@param OFile - The corresponding OFile. | |
**/ | |
STATIC | |
FAT_ODIR * | |
FatAllocateODir ( | |
IN FAT_OFILE *OFile | |
) | |
{ | |
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; | |
} | |
/** | |
Discard the directory structure when an OFile will be freed. | |
Volume will cache this directory if the OFile does not represent a deleted file. | |
@param OFile - The OFile whose directory structure is to be discarded. | |
**/ | |
VOID | |
FatDiscardODir ( | |
IN FAT_OFILE *OFile | |
) | |
{ | |
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); | |
} | |
} | |
/** | |
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. | |
@param OFile - The OFile which requests directory structure. | |
**/ | |
VOID | |
FatRequestODir ( | |
IN FAT_OFILE *OFile | |
) | |
{ | |
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; | |
} | |
/** | |
Clean up all the cached directory structures when the volume is going to be abandoned. | |
@param Volume - FAT file system volume. | |
**/ | |
VOID | |
FatCleanupODirCache ( | |
IN FAT_VOLUME *Volume | |
) | |
{ | |
FAT_ODIR *ODir; | |
while (Volume->DirCacheCount > 0) { | |
ODir = ODIR_FROM_DIRCACHELINK (Volume->DirCacheList.BackLink); | |
RemoveEntryList (&ODir->DirCacheLink); | |
FatFreeODir (ODir); | |
Volume->DirCacheCount--; | |
} | |
} |