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 FatFreeODir(IN FAT_ODIR * ODir)27FatFreeODir ( 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 * FatAllocateODir(IN FAT_OFILE * OFile)58FatAllocateODir ( 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 FatDiscardODir(IN FAT_OFILE * OFile)86FatDiscardODir ( 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 FatRequestODir(IN FAT_OFILE * OFile)135FatRequestODir ( 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 FatCleanupODirCache(IN FAT_VOLUME * Volume)179FatCleanupODirCache ( 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