]>
git.proxmox.com Git - mirror_edk2.git/blob - FatPkg/EnhancedFatDxe/Flush.c
3 Copyright (c) 2005 - 2009, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials are licensed and made available
5 under the terms and conditions of the BSD License which accompanies this
6 distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 Routines that check references and flush OFiles
30 IN EFI_FILE_PROTOCOL
*FHand
36 Flushes all data associated with the file handle.
40 FHand - Handle to file to flush.
44 EFI_SUCCESS - Flushed the file successfully.
45 EFI_WRITE_PROTECTED - The volume is read only.
46 EFI_ACCESS_DENIED - The file is read only.
47 Others - Flushing of the file failed.
56 IFile
= IFILE_FROM_FHAND (FHand
);
58 Volume
= OFile
->Volume
;
61 // If the file has a permanent error, return it
63 if (EFI_ERROR (OFile
->Error
)) {
67 if (Volume
->ReadOnly
) {
68 return EFI_WRITE_PROTECTED
;
71 // If read only, return error
73 if (IFile
->ReadOnly
) {
74 return EFI_ACCESS_DENIED
;
80 Status
= FatOFileFlush (OFile
);
81 Status
= FatCleanupVolume (OFile
->Volume
, OFile
, Status
);
89 IN EFI_FILE_PROTOCOL
*FHand
95 Flushes & Closes the file handle.
99 FHand - Handle to the file to delete.
103 EFI_SUCCESS - Closed the file successfully.
111 IFile
= IFILE_FROM_FHAND (FHand
);
112 OFile
= IFile
->OFile
;
113 Volume
= OFile
->Volume
;
121 // Close the file instance handle
123 FatIFileClose (IFile
);
126 // Done. Unlock the volume
128 FatCleanupVolume (Volume
, OFile
, EFI_SUCCESS
);
132 // Close always succeed
145 Close the open file instance.
149 IFile - Open file instance.
153 EFI_SUCCESS - Closed the file successfully.
160 OFile
= IFile
->OFile
;
161 Volume
= OFile
->Volume
;
163 ASSERT_VOLUME_LOCKED (Volume
);
166 // Remove the IFile struct
168 RemoveEntryList (&IFile
->Link
);
171 // Add the OFile to the check reference list
173 if (OFile
->CheckLink
.ForwardLink
== NULL
) {
174 InsertHeadList (&Volume
->CheckRef
, &OFile
->CheckLink
);
177 // Done. Free the open instance structure
191 Flush the data associated with an open file.
192 In this implementation, only last Mod/Access time is updated.
196 OFile - The open file.
200 EFI_SUCCESS - The OFile is flushed successfully.
201 Others - An error occurred when flushing this OFile.
208 FAT_DATE_TIME FatNow
;
211 // Flush each entry up the tree while dirty
215 // If the file has a permanant error, then don't write any
216 // of its data to the device (may be from different media)
218 if (EFI_ERROR (OFile
->Error
)) {
222 Parent
= OFile
->Parent
;
223 DirEnt
= OFile
->DirEnt
;
226 // Update the last modification time
228 FatGetCurrentFatTime (&FatNow
);
229 CopyMem (&DirEnt
->Entry
.FileLastAccess
, &FatNow
.Date
, sizeof (FAT_DATE
));
230 if (!OFile
->PreserveLastModification
) {
231 FatGetCurrentFatTime (&DirEnt
->Entry
.FileModificationTime
);
234 OFile
->PreserveLastModification
= FALSE
;
235 if (OFile
->Archive
) {
236 DirEnt
->Entry
.Attributes
|= FAT_ATTRIBUTE_ARCHIVE
;
237 OFile
->Archive
= FALSE
;
240 // Write the directory entry
242 if (Parent
!= NULL
&& !DirEnt
->Invalid
) {
244 // Write the OFile's directory entry
246 Status
= FatStoreDirEnt (Parent
, DirEnt
);
247 if (EFI_ERROR (Status
)) {
252 OFile
->Dirty
= FALSE
;
258 } while (OFile
!= NULL
);
270 Check the references of the OFile.
271 If the OFile (that is checked) is no longer
272 referenced, then it is freed.
276 OFile - The OFile to be checked.
280 TRUE - The OFile is not referenced and freed.
281 FALSE - The OFile is kept.
286 // If the OFile is on the check ref list, remove it
288 if (OFile
->CheckLink
.ForwardLink
!= NULL
) {
289 RemoveEntryList (&OFile
->CheckLink
);
290 OFile
->CheckLink
.ForwardLink
= NULL
;
293 FatOFileFlush (OFile
);
295 // Are there any references to this OFile?
297 if (!IsListEmpty (&OFile
->Opens
) || !IsListEmpty (&OFile
->ChildHead
)) {
299 // The OFile cannot be freed
306 FatCloseDirEnt (OFile
->DirEnt
);
313 IN FAT_VOLUME
*Volume
319 Check the references of all open files on the volume.
320 Any open file (that is checked) that is no longer
321 referenced, is freed - and it's parent open file
322 is then referenced checked.
326 Volume - The volume to check the pending open file list.
338 // Check all files on the pending check list
340 while (!IsListEmpty (&Volume
->CheckRef
)) {
342 // Start with the first file listed
344 Parent
= OFILE_FROM_CHECKLINK (Volume
->CheckRef
.ForwardLink
);
346 // Go up the tree cleaning up any un-referenced OFiles
348 while (Parent
!= NULL
) {
350 Parent
= OFile
->Parent
;
351 if (!FatCheckOFileRef (OFile
)) {
360 IN FAT_VOLUME
*Volume
,
362 IN EFI_STATUS EfiStatus
368 Set error status for a specific OFile, reference checking the volume.
369 If volume is already marked as invalid, and all resources are freed
370 after reference checking, the file system protocol is uninstalled and
371 the volume structure is freed.
375 Volume - the Volume that is to be reference checked and unlocked.
376 OFile - the OFile whose permanent error code is to be set.
377 EfiStatus - error code to be set.
381 EFI_SUCCESS - Clean up the volume successfully.
382 Others - Cleaning up of the volume is failed.
391 FatSetVolumeError (OFile
, EfiStatus
);
394 // Clean up any dangling OFiles that don't have IFiles
395 // we don't check return status here because we want the
396 // volume be cleaned up even the volume is invalid.
398 FatCheckVolumeRef (Volume
);
401 // Update the free hint info. Volume->FreeInfoPos != 0
402 // indicates this a FAT32 volume
404 if (Volume
->FreeInfoValid
&& Volume
->FatDirty
&& Volume
->FreeInfoPos
) {
405 Status
= FatDiskIo (Volume
, WRITE_DISK
, Volume
->FreeInfoPos
, sizeof (FAT_INFO_SECTOR
), &Volume
->FatInfoSector
);
406 if (EFI_ERROR (Status
)) {
411 // Update that the volume is not dirty
413 if (Volume
->FatDirty
&& Volume
->FatType
!= FAT12
) {
414 Volume
->FatDirty
= FALSE
;
415 Status
= FatAccessVolumeDirty (Volume
, WRITE_FAT
, &Volume
->NotDirtyValue
);
416 if (EFI_ERROR (Status
)) {
421 // Flush all dirty cache entries to disk
423 Status
= FatVolumeFlushCache (Volume
);
424 if (EFI_ERROR (Status
)) {
429 // If the volume is cleared , remove it.
430 // The only time volume be invalidated is in DriverBindingStop.
432 if (Volume
->Root
== NULL
&& !Volume
->Valid
) {
434 // Free the volume structure
436 FatFreeVolume (Volume
);
451 Set the OFile and its child OFile with the error Status
455 OFile - The OFile whose permanent error code is to be set.
456 Status - Error code to be set.
465 FAT_OFILE
*ChildOFile
;
468 // If this OFile doesn't already have an error, set one
470 if (!EFI_ERROR (OFile
->Error
)) {
471 OFile
->Error
= Status
;
474 // Set the error on each child OFile
476 for (Link
= OFile
->ChildHead
.ForwardLink
; Link
!= &OFile
->ChildHead
; Link
= Link
->ForwardLink
) {
477 ChildOFile
= OFILE_FROM_CHILDLINK (Link
);
478 FatSetVolumeError (ChildOFile
, Status
);