Home | History | Annotate | Download | only in EnhancedFatDxe
      1 /** @file
      2   Functions for directory cache operation.
      3 
      4 Copyright (c) 2005, Intel Corporation. All rights reserved.<BR>
      5 This program and the accompanying materials are licensed and made available
      6 under the terms and conditions of the BSD License which accompanies this
      7 distribution. The full text of the license may be found at
      8 http://opensource.org/licenses/bsd-license.php
      9 
     10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 
     14 **/
     15 
     16 #include "Fat.h"
     17 
     18 /**
     19 
     20   Free the directory structure and release the memory.
     21 
     22   @param  ODir                  - The directory to be freed.
     23 
     24 **/
     25 STATIC
     26 VOID
     27 FatFreeODir (
     28   IN FAT_ODIR    *ODir
     29   )
     30 {
     31   FAT_DIRENT  *DirEnt;
     32 
     33   //
     34   // Release Directory Entry Nodes
     35   //
     36   while (!IsListEmpty (&ODir->ChildList)) {
     37     DirEnt = DIRENT_FROM_LINK (ODir->ChildList.ForwardLink);
     38     RemoveEntryList (&DirEnt->Link);
     39     //
     40     // Make sure the OFile has been closed
     41     //
     42     ASSERT (DirEnt->OFile == NULL);
     43     FatFreeDirEnt (DirEnt);
     44   }
     45 
     46   FreePool (ODir);
     47 }
     48 
     49 /**
     50 
     51   Allocate the directory structure.
     52 
     53   @param  OFile                   - The corresponding OFile.
     54 
     55 **/
     56 STATIC
     57 FAT_ODIR *
     58 FatAllocateODir (
     59   IN FAT_OFILE   *OFile
     60   )
     61 {
     62   FAT_ODIR  *ODir;
     63 
     64   ODir = AllocateZeroPool (sizeof (FAT_ODIR));
     65   if (ODir != NULL) {
     66     //
     67     // Initialize the directory entry list
     68     //
     69     ODir->Signature = FAT_ODIR_SIGNATURE;
     70     InitializeListHead (&ODir->ChildList);
     71     ODir->CurrentCursor = &ODir->ChildList;
     72   }
     73 
     74   return ODir;
     75 }
     76 
     77 /**
     78 
     79   Discard the directory structure when an OFile will be freed.
     80   Volume will cache this directory if the OFile does not represent a deleted file.
     81 
     82   @param  OFile                 - The OFile whose directory structure is to be discarded.
     83 
     84 **/
     85 VOID
     86 FatDiscardODir (
     87   IN FAT_OFILE    *OFile
     88   )
     89 {
     90   FAT_ODIR    *ODir;
     91   FAT_VOLUME  *Volume;
     92 
     93   Volume  = OFile->Volume;
     94   ODir    = OFile->ODir;
     95   if (!OFile->DirEnt->Invalid) {
     96     //
     97     // If OFile does not represent a deleted file, then we will cache the directory
     98     // We use OFile's first cluster as the directory's tag
     99     //
    100     ODir->DirCacheTag = OFile->FileCluster;
    101     InsertHeadList (&Volume->DirCacheList, &ODir->DirCacheLink);
    102     if (Volume->DirCacheCount == FAT_MAX_DIR_CACHE_COUNT) {
    103       //
    104       // Replace the least recent used directory
    105       //
    106       ODir = ODIR_FROM_DIRCACHELINK (Volume->DirCacheList.BackLink);
    107       RemoveEntryList (&ODir->DirCacheLink);
    108     } else {
    109       //
    110       // No need to find a replace
    111       //
    112       Volume->DirCacheCount++;
    113       ODir = NULL;
    114     }
    115   }
    116   //
    117   // Release ODir Structure
    118   //
    119   if (ODir != NULL) {
    120     FatFreeODir (ODir);
    121   }
    122 }
    123 
    124 /**
    125 
    126 
    127   Request the directory structure when an OFile is newly generated.
    128   If the directory structure is cached by volume, then just return this directory;
    129   Otherwise, allocate a new one for OFile.
    130 
    131   @param  OFile                 - The OFile which requests directory structure.
    132 
    133 **/
    134 VOID
    135 FatRequestODir (
    136   IN FAT_OFILE    *OFile
    137   )
    138 {
    139   UINTN           DirCacheTag;
    140   FAT_VOLUME      *Volume;
    141   FAT_ODIR        *ODir;
    142   FAT_ODIR        *CurrentODir;
    143   LIST_ENTRY      *CurrentODirLink;
    144 
    145   Volume      = OFile->Volume;
    146   ODir        = NULL;
    147   DirCacheTag = OFile->FileCluster;
    148   for (CurrentODirLink  = Volume->DirCacheList.ForwardLink;
    149        CurrentODirLink != &Volume->DirCacheList;
    150        CurrentODirLink  = CurrentODirLink->ForwardLink
    151       ) {
    152     CurrentODir = ODIR_FROM_DIRCACHELINK (CurrentODirLink);
    153     if (CurrentODir->DirCacheTag == DirCacheTag) {
    154       RemoveEntryList (&CurrentODir->DirCacheLink);
    155       Volume->DirCacheCount--;
    156       ODir = CurrentODir;
    157       break;
    158     }
    159   }
    160 
    161   if (ODir == NULL) {
    162     //
    163     // This directory is not cached, then allocate a new one
    164     //
    165     ODir = FatAllocateODir (OFile);
    166   }
    167 
    168   OFile->ODir = ODir;
    169 }
    170 
    171 /**
    172 
    173   Clean up all the cached directory structures when the volume is going to be abandoned.
    174 
    175   @param  Volume                - FAT file system volume.
    176 
    177 **/
    178 VOID
    179 FatCleanupODirCache (
    180   IN FAT_VOLUME         *Volume
    181   )
    182 {
    183   FAT_ODIR  *ODir;
    184   while (Volume->DirCacheCount > 0) {
    185     ODir = ODIR_FROM_DIRCACHELINK (Volume->DirCacheList.BackLink);
    186     RemoveEntryList (&ODir->DirCacheLink);
    187     FatFreeODir (ODir);
    188     Volume->DirCacheCount--;
    189   }
    190 }
    191