185 lines
3.9 KiB
C
185 lines
3.9 KiB
C
|
/** @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--;
|
||
|
}
|
||
|
}
|