2 Routines that check references and flush OFiles
4 Copyright (c) 2005 - 2013, 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
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.
20 Flushes all data associated with the file handle.
22 @param FHand - Handle to file to flush.
23 @param Token - A pointer to the token associated with the transaction.
25 @retval EFI_SUCCESS - Flushed the file successfully.
26 @retval EFI_WRITE_PROTECTED - The volume is read only.
27 @retval EFI_ACCESS_DENIED - The file is read only.
28 @return Others - Flushing of the file failed.
34 IN EFI_FILE_PROTOCOL
*FHand
,
35 IN EFI_FILE_IO_TOKEN
*Token
44 IFile
= IFILE_FROM_FHAND (FHand
);
46 Volume
= OFile
->Volume
;
50 // If the file has a permanent error, return it
52 if (EFI_ERROR (OFile
->Error
)) {
56 if (Volume
->ReadOnly
) {
57 return EFI_WRITE_PROTECTED
;
60 // If read only, return error
62 if (IFile
->ReadOnly
) {
63 return EFI_ACCESS_DENIED
;
67 FatWaitNonblockingTask (IFile
);
70 // Caller shouldn't call the non-blocking interfaces if the low layer doesn't support DiskIo2.
71 // But if it calls, the below check can avoid crash.
73 if (FHand
->Revision
< EFI_FILE_PROTOCOL_REVISION2
) {
74 return EFI_UNSUPPORTED
;
76 Task
= FatCreateTask (IFile
, Token
);
78 return EFI_OUT_OF_RESOURCES
;
86 Status
= FatOFileFlush (OFile
);
87 Status
= FatCleanupVolume (OFile
->Volume
, OFile
, Status
, Task
);
91 if (!EFI_ERROR (Status
)) {
92 Status
= FatQueueTask (IFile
, Task
);
94 FatDestroyTask (Task
);
103 Flushes all data associated with the file handle.
105 @param FHand - Handle to file to flush.
107 @retval EFI_SUCCESS - Flushed the file successfully.
108 @retval EFI_WRITE_PROTECTED - The volume is read only.
109 @retval EFI_ACCESS_DENIED - The file is read only.
110 @return Others - Flushing of the file failed.
116 IN EFI_FILE_PROTOCOL
*FHand
119 return FatFlushEx (FHand
, NULL
);
124 Flushes & Closes the file handle.
126 @param FHand - Handle to the file to delete.
128 @retval EFI_SUCCESS - Closed the file successfully.
134 IN EFI_FILE_PROTOCOL
*FHand
141 IFile
= IFILE_FROM_FHAND (FHand
);
142 OFile
= IFile
->OFile
;
143 Volume
= OFile
->Volume
;
151 // Close the file instance handle
153 FatIFileClose (IFile
);
156 // Done. Unlock the volume
158 FatCleanupVolume (Volume
, OFile
, EFI_SUCCESS
, NULL
);
162 // Close always succeed
169 Close the open file instance.
171 @param IFile - Open file instance.
173 @retval EFI_SUCCESS - Closed the file successfully.
184 OFile
= IFile
->OFile
;
185 Volume
= OFile
->Volume
;
187 ASSERT_VOLUME_LOCKED (Volume
);
189 FatWaitNonblockingTask (IFile
);
192 // Remove the IFile struct
194 RemoveEntryList (&IFile
->Link
);
197 // Add the OFile to the check reference list
199 if (OFile
->CheckLink
.ForwardLink
== NULL
) {
200 InsertHeadList (&Volume
->CheckRef
, &OFile
->CheckLink
);
203 // Done. Free the open instance structure
211 Flush the data associated with an open file.
212 In this implementation, only last Mod/Access time is updated.
214 @param OFile - The open file.
216 @retval EFI_SUCCESS - The OFile is flushed successfully.
217 @return Others - An error occurred when flushing this OFile.
228 FAT_DATE_TIME FatNow
;
231 // Flush each entry up the tree while dirty
235 // If the file has a permanant error, then don't write any
236 // of its data to the device (may be from different media)
238 if (EFI_ERROR (OFile
->Error
)) {
242 Parent
= OFile
->Parent
;
243 DirEnt
= OFile
->DirEnt
;
246 // Update the last modification time
248 FatGetCurrentFatTime (&FatNow
);
249 CopyMem (&DirEnt
->Entry
.FileLastAccess
, &FatNow
.Date
, sizeof (FAT_DATE
));
250 if (!OFile
->PreserveLastModification
) {
251 FatGetCurrentFatTime (&DirEnt
->Entry
.FileModificationTime
);
254 OFile
->PreserveLastModification
= FALSE
;
255 if (OFile
->Archive
) {
256 DirEnt
->Entry
.Attributes
|= FAT_ATTRIBUTE_ARCHIVE
;
257 OFile
->Archive
= FALSE
;
260 // Write the directory entry
262 if (Parent
!= NULL
&& !DirEnt
->Invalid
) {
264 // Write the OFile's directory entry
266 Status
= FatStoreDirEnt (Parent
, DirEnt
);
267 if (EFI_ERROR (Status
)) {
272 OFile
->Dirty
= FALSE
;
278 } while (OFile
!= NULL
);
284 Check the references of the OFile.
285 If the OFile (that is checked) is no longer
286 referenced, then it is freed.
288 @param OFile - The OFile to be checked.
290 @retval TRUE - The OFile is not referenced and freed.
291 @retval FALSE - The OFile is kept.
300 // If the OFile is on the check ref list, remove it
302 if (OFile
->CheckLink
.ForwardLink
!= NULL
) {
303 RemoveEntryList (&OFile
->CheckLink
);
304 OFile
->CheckLink
.ForwardLink
= NULL
;
307 FatOFileFlush (OFile
);
309 // Are there any references to this OFile?
311 if (!IsListEmpty (&OFile
->Opens
) || !IsListEmpty (&OFile
->ChildHead
)) {
313 // The OFile cannot be freed
320 FatCloseDirEnt (OFile
->DirEnt
);
326 Check the references of all open files on the volume.
327 Any open file (that is checked) that is no longer
328 referenced, is freed - and it's parent open file
329 is then referenced checked.
331 @param Volume - The volume to check the pending open file list.
337 IN FAT_VOLUME
*Volume
344 // Check all files on the pending check list
346 while (!IsListEmpty (&Volume
->CheckRef
)) {
348 // Start with the first file listed
350 Parent
= OFILE_FROM_CHECKLINK (Volume
->CheckRef
.ForwardLink
);
352 // Go up the tree cleaning up any un-referenced OFiles
354 while (Parent
!= NULL
) {
356 Parent
= OFile
->Parent
;
357 if (!FatCheckOFileRef (OFile
)) {
366 Set error status for a specific OFile, reference checking the volume.
367 If volume is already marked as invalid, and all resources are freed
368 after reference checking, the file system protocol is uninstalled and
369 the volume structure is freed.
371 @param Volume - the Volume that is to be reference checked and unlocked.
372 @param OFile - the OFile whose permanent error code is to be set.
373 @param EfiStatus - error code to be set.
374 @param Task point to task instance.
376 @retval EFI_SUCCESS - Clean up the volume successfully.
377 @return Others - Cleaning up of the volume is failed.
382 IN FAT_VOLUME
*Volume
,
384 IN EFI_STATUS EfiStatus
,
393 FatSetVolumeError (OFile
, EfiStatus
);
396 // Clean up any dangling OFiles that don't have IFiles
397 // we don't check return status here because we want the
398 // volume be cleaned up even the volume is invalid.
400 FatCheckVolumeRef (Volume
);
403 // Update the free hint info. Volume->FreeInfoPos != 0
404 // indicates this a FAT32 volume
406 if (Volume
->FreeInfoValid
&& Volume
->FatDirty
&& Volume
->FreeInfoPos
) {
407 Status
= FatDiskIo (Volume
, WriteDisk
, Volume
->FreeInfoPos
, sizeof (FAT_INFO_SECTOR
), &Volume
->FatInfoSector
, Task
);
408 if (EFI_ERROR (Status
)) {
413 // Update that the volume is not dirty
415 if (Volume
->FatDirty
&& Volume
->FatType
!= Fat12
) {
416 Volume
->FatDirty
= FALSE
;
417 Status
= FatAccessVolumeDirty (Volume
, WriteFat
, &Volume
->NotDirtyValue
);
418 if (EFI_ERROR (Status
)) {
423 // Flush all dirty cache entries to disk
425 Status
= FatVolumeFlushCache (Volume
, Task
);
426 if (EFI_ERROR (Status
)) {
431 // If the volume is cleared , remove it.
432 // The only time volume be invalidated is in DriverBindingStop.
434 if (Volume
->Root
== NULL
&& !Volume
->Valid
) {
436 // Free the volume structure
438 FatFreeVolume (Volume
);
446 Set the OFile and its child OFile with the error Status
448 @param OFile - The OFile whose permanent error code is to be set.
449 @param Status - Error code to be set.
459 FAT_OFILE
*ChildOFile
;
462 // If this OFile doesn't already have an error, set one
464 if (!EFI_ERROR (OFile
->Error
)) {
465 OFile
->Error
= Status
;
468 // Set the error on each child OFile
470 for (Link
= OFile
->ChildHead
.ForwardLink
; Link
!= &OFile
->ChildHead
; Link
= Link
->ForwardLink
) {
471 ChildOFile
= OFILE_FROM_CHILDLINK (Link
);
472 FatSetVolumeError (ChildOFile
, Status
);