/** @file Functions for directory cache operation. Copyright (c) 2005, Intel Corporation. All rights reserved.
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--; } }