DirectoryCache.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. /** @file
  2. Functions for directory cache operation.
  3. Copyright (c) 2005, Intel Corporation. All rights reserved.<BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include "Fat.h"
  7. /**
  8. Free the directory structure and release the memory.
  9. @param ODir - The directory to be freed.
  10. **/
  11. STATIC
  12. VOID
  13. FatFreeODir (
  14. IN FAT_ODIR *ODir
  15. )
  16. {
  17. FAT_DIRENT *DirEnt;
  18. //
  19. // Release Directory Entry Nodes
  20. //
  21. while (!IsListEmpty (&ODir->ChildList)) {
  22. DirEnt = DIRENT_FROM_LINK (ODir->ChildList.ForwardLink);
  23. RemoveEntryList (&DirEnt->Link);
  24. //
  25. // Make sure the OFile has been closed
  26. //
  27. ASSERT (DirEnt->OFile == NULL);
  28. FatFreeDirEnt (DirEnt);
  29. }
  30. FreePool (ODir);
  31. }
  32. /**
  33. Allocate the directory structure.
  34. @param OFile - The corresponding OFile.
  35. **/
  36. STATIC
  37. FAT_ODIR *
  38. FatAllocateODir (
  39. IN FAT_OFILE *OFile
  40. )
  41. {
  42. FAT_ODIR *ODir;
  43. ODir = AllocateZeroPool (sizeof (FAT_ODIR));
  44. if (ODir != NULL) {
  45. //
  46. // Initialize the directory entry list
  47. //
  48. ODir->Signature = FAT_ODIR_SIGNATURE;
  49. InitializeListHead (&ODir->ChildList);
  50. ODir->CurrentCursor = &ODir->ChildList;
  51. }
  52. return ODir;
  53. }
  54. /**
  55. Discard the directory structure when an OFile will be freed.
  56. Volume will cache this directory if the OFile does not represent a deleted file.
  57. @param OFile - The OFile whose directory structure is to be discarded.
  58. **/
  59. VOID
  60. FatDiscardODir (
  61. IN FAT_OFILE *OFile
  62. )
  63. {
  64. FAT_ODIR *ODir;
  65. FAT_VOLUME *Volume;
  66. Volume = OFile->Volume;
  67. ODir = OFile->ODir;
  68. if (!OFile->DirEnt->Invalid) {
  69. //
  70. // If OFile does not represent a deleted file, then we will cache the directory
  71. // We use OFile's first cluster as the directory's tag
  72. //
  73. ODir->DirCacheTag = OFile->FileCluster;
  74. InsertHeadList (&Volume->DirCacheList, &ODir->DirCacheLink);
  75. if (Volume->DirCacheCount == FAT_MAX_DIR_CACHE_COUNT) {
  76. //
  77. // Replace the least recent used directory
  78. //
  79. ODir = ODIR_FROM_DIRCACHELINK (Volume->DirCacheList.BackLink);
  80. RemoveEntryList (&ODir->DirCacheLink);
  81. } else {
  82. //
  83. // No need to find a replace
  84. //
  85. Volume->DirCacheCount++;
  86. ODir = NULL;
  87. }
  88. }
  89. //
  90. // Release ODir Structure
  91. //
  92. if (ODir != NULL) {
  93. FatFreeODir (ODir);
  94. }
  95. }
  96. /**
  97. Request the directory structure when an OFile is newly generated.
  98. If the directory structure is cached by volume, then just return this directory;
  99. Otherwise, allocate a new one for OFile.
  100. @param OFile - The OFile which requests directory structure.
  101. **/
  102. VOID
  103. FatRequestODir (
  104. IN FAT_OFILE *OFile
  105. )
  106. {
  107. UINTN DirCacheTag;
  108. FAT_VOLUME *Volume;
  109. FAT_ODIR *ODir;
  110. FAT_ODIR *CurrentODir;
  111. LIST_ENTRY *CurrentODirLink;
  112. Volume = OFile->Volume;
  113. ODir = NULL;
  114. DirCacheTag = OFile->FileCluster;
  115. for (CurrentODirLink = Volume->DirCacheList.ForwardLink;
  116. CurrentODirLink != &Volume->DirCacheList;
  117. CurrentODirLink = CurrentODirLink->ForwardLink
  118. ) {
  119. CurrentODir = ODIR_FROM_DIRCACHELINK (CurrentODirLink);
  120. if (CurrentODir->DirCacheTag == DirCacheTag) {
  121. RemoveEntryList (&CurrentODir->DirCacheLink);
  122. Volume->DirCacheCount--;
  123. ODir = CurrentODir;
  124. break;
  125. }
  126. }
  127. if (ODir == NULL) {
  128. //
  129. // This directory is not cached, then allocate a new one
  130. //
  131. ODir = FatAllocateODir (OFile);
  132. }
  133. OFile->ODir = ODir;
  134. }
  135. /**
  136. Clean up all the cached directory structures when the volume is going to be abandoned.
  137. @param Volume - FAT file system volume.
  138. **/
  139. VOID
  140. FatCleanupODirCache (
  141. IN FAT_VOLUME *Volume
  142. )
  143. {
  144. FAT_ODIR *ODir;
  145. while (Volume->DirCacheCount > 0) {
  146. ODir = ODIR_FROM_DIRCACHELINK (Volume->DirCacheList.BackLink);
  147. RemoveEntryList (&ODir->DirCacheLink);
  148. FatFreeODir (ODir);
  149. Volume->DirCacheCount--;
  150. }
  151. }