mirror of
https://github.com/reactos/reactos.git
synced 2025-07-31 14:51:44 +00:00
Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers into modules, and delete rossubsys.
This commit is contained in:
parent
b94e2d8ca0
commit
c2c66aff7d
24198 changed files with 0 additions and 37285 deletions
632
drivers/filesystems/udfs/flush.cpp
Normal file
632
drivers/filesystems/udfs/flush.cpp
Normal file
|
@ -0,0 +1,632 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine
|
||||
// All rights reserved
|
||||
// This file was released under the GPLv2 on June 2015.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
/*************************************************************************
|
||||
*
|
||||
* File: Flush.cpp
|
||||
*
|
||||
* Module: UDF File System Driver (Kernel mode execution only)
|
||||
*
|
||||
* Description:
|
||||
* Contains code to handle the "Flush Buffers" dispatch entry point.
|
||||
*
|
||||
*************************************************************************/
|
||||
|
||||
#include "udffs.h"
|
||||
|
||||
// define the file specific bug-check id
|
||||
#define UDF_BUG_CHECK_ID UDF_FILE_FLUSH
|
||||
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Function: UDFFlush()
|
||||
*
|
||||
* Description:
|
||||
* The I/O Manager will invoke this routine to handle a flush buffers
|
||||
* request
|
||||
*
|
||||
* Expected Interrupt Level (for execution) :
|
||||
*
|
||||
* IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution
|
||||
* to be deferred to a worker thread context)
|
||||
*
|
||||
* Return Value: STATUS_SUCCESS/Error
|
||||
*
|
||||
*************************************************************************/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
UDFFlush(
|
||||
PDEVICE_OBJECT DeviceObject, // the logical volume device object
|
||||
PIRP Irp) // I/O Request Packet
|
||||
{
|
||||
NTSTATUS RC = STATUS_SUCCESS;
|
||||
PtrUDFIrpContext PtrIrpContext = NULL;
|
||||
BOOLEAN AreWeTopLevel = FALSE;
|
||||
|
||||
UDFPrint(("UDFFlush: \n"));
|
||||
|
||||
FsRtlEnterFileSystem();
|
||||
ASSERT(DeviceObject);
|
||||
ASSERT(Irp);
|
||||
|
||||
// set the top level context
|
||||
AreWeTopLevel = UDFIsIrpTopLevel(Irp);
|
||||
ASSERT(!UDFIsFSDevObj(DeviceObject));
|
||||
|
||||
_SEH2_TRY {
|
||||
|
||||
// get an IRP context structure and issue the request
|
||||
PtrIrpContext = UDFAllocateIrpContext(Irp, DeviceObject);
|
||||
if(PtrIrpContext) {
|
||||
RC = UDFCommonFlush(PtrIrpContext, Irp);
|
||||
} else {
|
||||
RC = STATUS_INSUFFICIENT_RESOURCES;
|
||||
Irp->IoStatus.Status = RC;
|
||||
Irp->IoStatus.Information = 0;
|
||||
// complete the IRP
|
||||
IoCompleteRequest(Irp, IO_DISK_INCREMENT);
|
||||
}
|
||||
|
||||
} _SEH2_EXCEPT(UDFExceptionFilter(PtrIrpContext, _SEH2_GetExceptionInformation())) {
|
||||
|
||||
RC = UDFExceptionHandler(PtrIrpContext, Irp);
|
||||
|
||||
UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC);
|
||||
} _SEH2_END;
|
||||
|
||||
if (AreWeTopLevel) {
|
||||
IoSetTopLevelIrp(NULL);
|
||||
}
|
||||
|
||||
FsRtlExitFileSystem();
|
||||
|
||||
return(RC);
|
||||
} // end UDFFlush()
|
||||
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Function: UDFCommonFlush()
|
||||
*
|
||||
* Description:
|
||||
* The actual work is performed here. This routine may be invoked in one'
|
||||
* of the two possible contexts:
|
||||
* (a) in the context of a system worker thread
|
||||
* (b) in the context of the original caller
|
||||
*
|
||||
* Expected Interrupt Level (for execution) :
|
||||
*
|
||||
* IRQL_PASSIVE_LEVEL
|
||||
*
|
||||
* Return Value: STATUS_SUCCESS/Error
|
||||
*
|
||||
*************************************************************************/
|
||||
NTSTATUS
|
||||
UDFCommonFlush(
|
||||
PtrUDFIrpContext PtrIrpContext,
|
||||
PIRP Irp
|
||||
)
|
||||
{
|
||||
NTSTATUS RC = STATUS_SUCCESS;
|
||||
PIO_STACK_LOCATION IrpSp = NULL;
|
||||
PFILE_OBJECT FileObject = NULL;
|
||||
PtrUDFFCB Fcb = NULL;
|
||||
PtrUDFCCB Ccb = NULL;
|
||||
PVCB Vcb = NULL;
|
||||
PtrUDFNTRequiredFCB NtReqFcb = NULL;
|
||||
BOOLEAN AcquiredVCB = FALSE;
|
||||
BOOLEAN AcquiredFCB = FALSE;
|
||||
BOOLEAN PostRequest = FALSE;
|
||||
BOOLEAN CanWait = TRUE;
|
||||
|
||||
UDFPrint(("UDFCommonFlush: \n"));
|
||||
|
||||
_SEH2_TRY {
|
||||
|
||||
// Get some of the parameters supplied to us
|
||||
CanWait = ((PtrIrpContext->IrpContextFlags & UDF_IRP_CONTEXT_CAN_BLOCK) ? TRUE : FALSE);
|
||||
// If we cannot wait, post the request immediately since a flush is inherently blocking/synchronous.
|
||||
if (!CanWait) {
|
||||
PostRequest = TRUE;
|
||||
try_return(RC);
|
||||
}
|
||||
|
||||
// First, get a pointer to the current I/O stack location
|
||||
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||
ASSERT(IrpSp);
|
||||
|
||||
FileObject = IrpSp->FileObject;
|
||||
ASSERT(FileObject);
|
||||
|
||||
// Get the FCB and CCB pointers
|
||||
Ccb = (PtrUDFCCB)(FileObject->FsContext2);
|
||||
ASSERT(Ccb);
|
||||
Fcb = Ccb->Fcb;
|
||||
ASSERT(Fcb);
|
||||
NtReqFcb = Fcb->NTRequiredFCB;
|
||||
|
||||
// Check the type of object passed-in. That will determine the course of
|
||||
// action we take.
|
||||
if ((Fcb->NodeIdentifier.NodeType == UDF_NODE_TYPE_VCB) || (Fcb->FCBFlags & UDF_FCB_ROOT_DIRECTORY)) {
|
||||
|
||||
if (Fcb->NodeIdentifier.NodeType == UDF_NODE_TYPE_VCB) {
|
||||
Vcb = (PVCB)(Fcb);
|
||||
} else {
|
||||
Vcb = Fcb->Vcb;
|
||||
}
|
||||
Vcb->VCBFlags |= UDF_VCB_SKIP_EJECT_CHECK;
|
||||
|
||||
#ifdef UDF_DELAYED_CLOSE
|
||||
UDFCloseAllDelayed(Vcb);
|
||||
#endif //UDF_DELAYED_CLOSE
|
||||
|
||||
UDFAcquireResourceExclusive(&(Vcb->VCBResource), TRUE);
|
||||
AcquiredVCB = TRUE;
|
||||
// The caller wishes to flush all files for the mounted
|
||||
// logical volume. The flush volume routine below should simply
|
||||
// walk through all of the open file streams, acquire the
|
||||
// VCB resource, and request the flush operation from the Cache
|
||||
// Manager. Basically, the sequence of operations listed below
|
||||
// for a single file should be executed on all open files.
|
||||
|
||||
UDFFlushLogicalVolume(PtrIrpContext, Irp, Vcb, 0);
|
||||
|
||||
UDFReleaseResource(&(Vcb->VCBResource));
|
||||
AcquiredVCB = FALSE;
|
||||
|
||||
try_return(RC);
|
||||
} else
|
||||
if (!(Fcb->FCBFlags & UDF_FCB_DIRECTORY)) {
|
||||
// This is a regular file.
|
||||
Vcb = Fcb->Vcb;
|
||||
ASSERT(Vcb);
|
||||
if(!ExIsResourceAcquiredExclusiveLite(&(Vcb->VCBResource)) &&
|
||||
!ExIsResourceAcquiredSharedLite(&(Vcb->VCBResource))) {
|
||||
UDFAcquireResourceShared(&(Vcb->VCBResource), TRUE);
|
||||
AcquiredVCB = TRUE;
|
||||
}
|
||||
UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb);
|
||||
UDFAcquireResourceExclusive(&(NtReqFcb->MainResource), TRUE);
|
||||
AcquiredFCB = TRUE;
|
||||
|
||||
// Request the Cache Manager to perform a flush operation.
|
||||
// Further, instruct the Cache Manager that we wish to flush the
|
||||
// entire file stream.
|
||||
UDFFlushAFile(Fcb, Ccb, &(Irp->IoStatus), 0);
|
||||
RC = Irp->IoStatus.Status;
|
||||
|
||||
// Some log-based FSD implementations may wish to flush their
|
||||
// log files at this time. Finally, we should update the time-stamp
|
||||
// values for the file stream appropriately. This would involve
|
||||
// obtaining the current time and modifying the appropriate directory
|
||||
// entry fields.
|
||||
} else {
|
||||
Vcb = Fcb->Vcb;
|
||||
}
|
||||
|
||||
try_exit: NOTHING;
|
||||
|
||||
} _SEH2_FINALLY {
|
||||
|
||||
if (AcquiredFCB) {
|
||||
UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb);
|
||||
UDFReleaseResource(&(NtReqFcb->MainResource));
|
||||
AcquiredFCB = FALSE;
|
||||
}
|
||||
if (AcquiredVCB) {
|
||||
UDFReleaseResource(&(Vcb->VCBResource));
|
||||
AcquiredVCB = FALSE;
|
||||
}
|
||||
|
||||
if(!_SEH2_AbnormalTermination()) {
|
||||
if (PostRequest) {
|
||||
// Nothing to lock now.
|
||||
BrutePoint();
|
||||
RC = UDFPostRequest(PtrIrpContext, Irp);
|
||||
} else {
|
||||
// Some applications like this request very much
|
||||
// (ex. WinWord). But it's not a good idea for CD-R/RW media
|
||||
if(Vcb->FlushMedia) {
|
||||
PIO_STACK_LOCATION PtrNextIoStackLocation = NULL;
|
||||
NTSTATUS RC1 = STATUS_SUCCESS;
|
||||
|
||||
// Send the request down at this point.
|
||||
// To do this, we must set the next IRP stack location, and
|
||||
// maybe set a completion routine.
|
||||
// Be careful about marking the IRP pending if the lower level
|
||||
// driver returned pending and we do have a completion routine!
|
||||
PtrNextIoStackLocation = IoGetNextIrpStackLocation(Irp);
|
||||
*PtrNextIoStackLocation = *IrpSp;
|
||||
|
||||
// Set the completion routine to "eat-up" any
|
||||
// STATUS_INVALID_DEVICE_REQUEST error code returned by the lower
|
||||
// level driver.
|
||||
IoSetCompletionRoutine(Irp, UDFFlushCompletion, NULL, TRUE, TRUE, TRUE);
|
||||
|
||||
RC1 = IoCallDriver(Vcb->TargetDeviceObject, Irp);
|
||||
|
||||
RC = ((RC1 == STATUS_INVALID_DEVICE_REQUEST) ? RC : RC1);
|
||||
|
||||
// Release the IRP context at this time.
|
||||
UDFReleaseIrpContext(PtrIrpContext);
|
||||
} else {
|
||||
Irp->IoStatus.Status = RC;
|
||||
Irp->IoStatus.Information = 0;
|
||||
// Free up the Irp Context
|
||||
UDFReleaseIrpContext(PtrIrpContext);
|
||||
// complete the IRP
|
||||
IoCompleteRequest(Irp, IO_DISK_INCREMENT);
|
||||
}
|
||||
}
|
||||
}
|
||||
} _SEH2_END;
|
||||
|
||||
return(RC);
|
||||
} // end UDFCommonFlush()
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Function: UDFFlushAFile()
|
||||
*
|
||||
* Description:
|
||||
* Tell the Cache Manager to perform a flush.
|
||||
*
|
||||
* Expected Interrupt Level (for execution) :
|
||||
*
|
||||
* IRQL_PASSIVE_LEVEL
|
||||
*
|
||||
* Return Value: None
|
||||
*
|
||||
*************************************************************************/
|
||||
ULONG
|
||||
UDFFlushAFile(
|
||||
IN PtrUDFFCB Fcb,
|
||||
IN PtrUDFCCB Ccb,
|
||||
OUT PIO_STATUS_BLOCK PtrIoStatus,
|
||||
IN ULONG FlushFlags
|
||||
)
|
||||
{
|
||||
BOOLEAN SetArchive = FALSE;
|
||||
// BOOLEAN PurgeCache = FALSE;
|
||||
ULONG ret_val = 0;
|
||||
|
||||
UDFPrint(("UDFFlushAFile: \n"));
|
||||
if(!Fcb)
|
||||
return 0;
|
||||
|
||||
_SEH2_TRY {
|
||||
if(Fcb->Vcb->VCBFlags & UDF_VCB_FLAGS_RAW_DISK)
|
||||
return 0;
|
||||
} _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
|
||||
BrutePoint();
|
||||
} _SEH2_END;
|
||||
#ifndef UDF_READ_ONLY_BUILD
|
||||
// Flush Security if required
|
||||
_SEH2_TRY {
|
||||
UDFWriteSecurity(Fcb->Vcb, Fcb, &(Fcb->NTRequiredFCB->SecurityDesc));
|
||||
} _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
|
||||
BrutePoint();
|
||||
} _SEH2_END;
|
||||
#endif //UDF_READ_ONLY_BUILD
|
||||
// Flush SDir if any
|
||||
_SEH2_TRY {
|
||||
if(UDFHasAStreamDir(Fcb->FileInfo) &&
|
||||
Fcb->FileInfo->Dloc->SDirInfo &&
|
||||
!UDFIsSDirDeleted(Fcb->FileInfo->Dloc->SDirInfo) ) {
|
||||
ret_val |=
|
||||
UDFFlushADirectory(Fcb->Vcb, Fcb->FileInfo->Dloc->SDirInfo, PtrIoStatus, FlushFlags);
|
||||
}
|
||||
} _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
|
||||
BrutePoint();
|
||||
} _SEH2_END;
|
||||
// Flush File
|
||||
_SEH2_TRY {
|
||||
if((Fcb->CachedOpenHandleCount || !Fcb->OpenHandleCount) &&
|
||||
Fcb->NTRequiredFCB->SectionObject.DataSectionObject) {
|
||||
if(!(Fcb->NTRequiredFCB->NtReqFCBFlags & UDF_NTREQ_FCB_DELETED)
|
||||
&&
|
||||
((Fcb->NTRequiredFCB->NtReqFCBFlags & UDF_NTREQ_FCB_MODIFIED) ||
|
||||
(Ccb && !(Ccb->CCBFlags & UDF_CCB_FLUSHED)) )) {
|
||||
MmPrint((" CcFlushCache()\n"));
|
||||
CcFlushCache(&(Fcb->NTRequiredFCB->SectionObject), NULL, 0, PtrIoStatus);
|
||||
}
|
||||
// notice, that we should purge cache
|
||||
// we can't do it now, because it may cause last Close
|
||||
// request & thus, structure deallocation
|
||||
// PurgeCache = TRUE;
|
||||
|
||||
#ifndef UDF_READ_ONLY_BUILD
|
||||
if(Ccb) {
|
||||
if( (Ccb->FileObject->Flags & FO_FILE_MODIFIED) &&
|
||||
!(Ccb->CCBFlags & UDF_CCB_WRITE_TIME_SET)) {
|
||||
if(Fcb->Vcb->CompatFlags & UDF_VCB_IC_UPDATE_MODIFY_TIME) {
|
||||
LONGLONG NtTime;
|
||||
KeQuerySystemTime((PLARGE_INTEGER)&NtTime);
|
||||
UDFSetFileXTime(Fcb->FileInfo, NULL, NULL, NULL, &NtTime);
|
||||
Fcb->NTRequiredFCB->LastWriteTime.QuadPart = NtTime;
|
||||
}
|
||||
SetArchive = TRUE;
|
||||
Ccb->FileObject->Flags &= ~FO_FILE_MODIFIED;
|
||||
}
|
||||
if(Ccb->FileObject->Flags & FO_FILE_SIZE_CHANGED) {
|
||||
LONGLONG ASize = UDFGetFileAllocationSize(Fcb->Vcb, Fcb->FileInfo);
|
||||
UDFSetFileSizeInDirNdx(Fcb->Vcb, Fcb->FileInfo, &ASize);
|
||||
Ccb->FileObject->Flags &= ~FO_FILE_SIZE_CHANGED;
|
||||
}
|
||||
}
|
||||
#endif //UDF_READ_ONLY_BUILD
|
||||
}
|
||||
} _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
|
||||
BrutePoint();
|
||||
} _SEH2_END;
|
||||
|
||||
_SEH2_TRY {
|
||||
#ifndef UDF_READ_ONLY_BUILD
|
||||
if(SetArchive &&
|
||||
(Fcb->Vcb->CompatFlags & UDF_VCB_IC_UPDATE_ARCH_BIT)) {
|
||||
ULONG Attr;
|
||||
PDIR_INDEX_ITEM DirNdx;
|
||||
DirNdx = UDFDirIndex(UDFGetDirIndexByFileInfo(Fcb->FileInfo), Fcb->FileInfo->Index);
|
||||
// Archive bit
|
||||
Attr = UDFAttributesToNT(DirNdx, Fcb->FileInfo->Dloc->FileEntry);
|
||||
if(!(Attr & FILE_ATTRIBUTE_ARCHIVE))
|
||||
UDFAttributesToUDF(DirNdx, Fcb->FileInfo->Dloc->FileEntry, Attr | FILE_ATTRIBUTE_ARCHIVE);
|
||||
}
|
||||
#endif //UDF_READ_ONLY_BUILD
|
||||
UDFFlushFile__( Fcb->Vcb, Fcb->FileInfo, FlushFlags);
|
||||
} _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
|
||||
BrutePoint();
|
||||
} _SEH2_END;
|
||||
|
||||
/* if(PurgeCache) {
|
||||
_SEH2_TRY {
|
||||
MmPrint((" CcPurgeCacheSection()\n"));
|
||||
CcPurgeCacheSection( &(Fcb->NTRequiredFCB->SectionObject), NULL, 0, FALSE );
|
||||
} _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
|
||||
BrutePoint();
|
||||
} _SEH2_END;
|
||||
}*/
|
||||
|
||||
return ret_val;
|
||||
} // end UDFFlushAFile()
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Function: UDFFlushADirectory()
|
||||
*
|
||||
* Description:
|
||||
* Tell the Cache Manager to perform a flush for all files
|
||||
* in current directory & all subdirectories and flush all metadata
|
||||
*
|
||||
* Expected Interrupt Level (for execution) :
|
||||
*
|
||||
* IRQL_PASSIVE_LEVEL
|
||||
*
|
||||
* Return Value: None
|
||||
*
|
||||
*************************************************************************/
|
||||
ULONG
|
||||
UDFFlushADirectory(
|
||||
IN PVCB Vcb,
|
||||
IN PUDF_FILE_INFO FI,
|
||||
OUT PIO_STATUS_BLOCK PtrIoStatus,
|
||||
IN ULONG FlushFlags
|
||||
)
|
||||
{
|
||||
UDFPrint(("UDFFlushADirectory: \n"));
|
||||
// PDIR_INDEX_HDR hDI;
|
||||
PDIR_INDEX_ITEM DI;
|
||||
// BOOLEAN Referenced = FALSE;
|
||||
ULONG ret_val = 0;
|
||||
|
||||
if(Vcb->VCBFlags & UDF_VCB_FLAGS_RAW_DISK)
|
||||
return 0;
|
||||
|
||||
if(!FI || !FI->Dloc || !FI->Dloc->DirIndex) goto SkipFlushDir;
|
||||
// hDI = FI->Dloc->DirIndex;
|
||||
|
||||
// Flush Security if required
|
||||
_SEH2_TRY {
|
||||
UDFWriteSecurity(Vcb, FI->Fcb, &(FI->Fcb->NTRequiredFCB->SecurityDesc));
|
||||
} _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
|
||||
BrutePoint();
|
||||
} _SEH2_END;
|
||||
// Flush SDir if any
|
||||
_SEH2_TRY {
|
||||
if(UDFHasAStreamDir(FI) &&
|
||||
FI->Dloc->SDirInfo &&
|
||||
!UDFIsSDirDeleted(FI->Dloc->SDirInfo) ) {
|
||||
ret_val |=
|
||||
UDFFlushADirectory(Vcb, FI->Dloc->SDirInfo, PtrIoStatus, FlushFlags);
|
||||
}
|
||||
} _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
|
||||
BrutePoint();
|
||||
} _SEH2_END;
|
||||
|
||||
// Flush Dir Tree
|
||||
_SEH2_TRY {
|
||||
UDF_DIR_SCAN_CONTEXT ScanContext;
|
||||
PUDF_FILE_INFO tempFI;
|
||||
|
||||
if(UDFDirIndexInitScan(FI, &ScanContext, 2)) {
|
||||
while((DI = UDFDirIndexScan(&ScanContext, &tempFI))) {
|
||||
// Flush Dir entry
|
||||
_SEH2_TRY {
|
||||
if(!tempFI) continue;
|
||||
if(UDFIsADirectory(tempFI)) {
|
||||
UDFFlushADirectory(Vcb, tempFI, PtrIoStatus, FlushFlags);
|
||||
} else {
|
||||
UDFFlushAFile(tempFI->Fcb, NULL, PtrIoStatus, FlushFlags);
|
||||
}
|
||||
} _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
|
||||
BrutePoint();
|
||||
} _SEH2_END;
|
||||
if(UDFFlushIsBreaking(Vcb, FlushFlags)) {
|
||||
ret_val |= UDF_FLUSH_FLAGS_INTERRUPTED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
|
||||
BrutePoint();
|
||||
} _SEH2_END;
|
||||
SkipFlushDir:
|
||||
// Flush Dir
|
||||
_SEH2_TRY {
|
||||
UDFFlushFile__( Vcb, FI, FlushFlags );
|
||||
} _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
|
||||
BrutePoint();
|
||||
} _SEH2_END;
|
||||
|
||||
return ret_val;
|
||||
} // end UDFFlushADirectory()
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Function: UDFFlushLogicalVolume()
|
||||
*
|
||||
* Description:
|
||||
* Flush everything beginning from root directory.
|
||||
* Vcb must be previously acquired exclusively.
|
||||
*
|
||||
* Expected Interrupt Level (for execution) :
|
||||
*
|
||||
* IRQL_PASSIVE_LEVEL
|
||||
*
|
||||
* Return Value: None
|
||||
*
|
||||
*************************************************************************/
|
||||
ULONG
|
||||
UDFFlushLogicalVolume(
|
||||
IN PtrUDFIrpContext PtrIrpContext,
|
||||
IN PIRP Irp,
|
||||
IN PVCB Vcb,
|
||||
IN ULONG FlushFlags
|
||||
)
|
||||
{
|
||||
ULONG ret_val = 0;
|
||||
#ifndef UDF_READ_ONLY_BUILD
|
||||
IO_STATUS_BLOCK IoStatus;
|
||||
|
||||
UDFPrint(("UDFFlushLogicalVolume: \n"));
|
||||
|
||||
_SEH2_TRY {
|
||||
if(Vcb->VCBFlags & (UDF_VCB_FLAGS_RAW_DISK/* |
|
||||
UDF_VCB_FLAGS_MEDIA_READ_ONLY*/))
|
||||
return 0;
|
||||
if(Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_READ_ONLY)
|
||||
return 0;
|
||||
if(!(Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_MOUNTED))
|
||||
return 0;
|
||||
|
||||
// NOTE: This function may also be invoked internally as part of
|
||||
// processing a shutdown request.
|
||||
ASSERT(Vcb->RootDirFCB);
|
||||
ret_val |= UDFFlushADirectory(Vcb, Vcb->RootDirFCB->FileInfo, &IoStatus, FlushFlags);
|
||||
|
||||
// if(UDFFlushIsBreaking(Vcb, FlushFlags))
|
||||
// return;
|
||||
// flush internal cache
|
||||
if(FlushFlags & UDF_FLUSH_FLAGS_LITE) {
|
||||
UDFPrint((" Lite flush, keep Modified=%d.\n", Vcb->Modified));
|
||||
} else {
|
||||
if(Vcb->VerifyOnWrite) {
|
||||
UDFPrint(("UDF: Flushing cache for verify\n"));
|
||||
//WCacheFlushAll__(&(Vcb->FastCache), Vcb);
|
||||
WCacheFlushBlocks__(&(Vcb->FastCache), Vcb, 0, Vcb->LastLBA);
|
||||
UDFVFlush(Vcb);
|
||||
}
|
||||
// umount (this is internal operation, NT will "dismount" volume later)
|
||||
UDFUmount__(Vcb);
|
||||
|
||||
UDFPreClrModified(Vcb);
|
||||
WCacheFlushAll__(&(Vcb->FastCache), Vcb);
|
||||
UDFClrModified(Vcb);
|
||||
}
|
||||
|
||||
} _SEH2_FINALLY {
|
||||
;
|
||||
} _SEH2_END;
|
||||
#endif //UDF_READ_ONLY_BUILD
|
||||
|
||||
return ret_val;
|
||||
} // end UDFFlushLogicalVolume()
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Function: UDFFlushCompletion()
|
||||
*
|
||||
* Description:
|
||||
* Eat up any bad errors.
|
||||
*
|
||||
* Expected Interrupt Level (for execution) :
|
||||
*
|
||||
* IRQL_PASSIVE_LEVEL
|
||||
*
|
||||
* Return Value: None
|
||||
*
|
||||
*************************************************************************/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
UDFFlushCompletion(
|
||||
PDEVICE_OBJECT PtrDeviceObject,
|
||||
PIRP Irp,
|
||||
PVOID Context
|
||||
)
|
||||
{
|
||||
// NTSTATUS RC = STATUS_SUCCESS;
|
||||
|
||||
UDFPrint(("UDFFlushCompletion: \n"));
|
||||
|
||||
if (Irp->PendingReturned) {
|
||||
IoMarkIrpPending(Irp);
|
||||
}
|
||||
|
||||
if (Irp->IoStatus.Status == STATUS_INVALID_DEVICE_REQUEST) {
|
||||
// cannot do much here, can we?
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
} // end UDFFlushCompletion()
|
||||
|
||||
|
||||
/*
|
||||
Check if we should break FlushTree process
|
||||
*/
|
||||
BOOLEAN
|
||||
UDFFlushIsBreaking(
|
||||
IN PVCB Vcb,
|
||||
IN ULONG FlushFlags
|
||||
)
|
||||
{
|
||||
BOOLEAN ret_val = FALSE;
|
||||
// if(!(FlushFlags & UDF_FLUSH_FLAGS_BREAKABLE))
|
||||
return FALSE;
|
||||
UDFAcquireResourceExclusive(&(Vcb->FlushResource),TRUE);
|
||||
ret_val = (Vcb->VCBFlags & UDF_VCB_FLAGS_FLUSH_BREAK_REQ) ? TRUE : FALSE;
|
||||
Vcb->VCBFlags &= ~UDF_VCB_FLAGS_FLUSH_BREAK_REQ;
|
||||
UDFReleaseResource(&(Vcb->FlushResource));
|
||||
return ret_val;
|
||||
} // end UDFFlushIsBreaking()
|
||||
|
||||
/*
|
||||
Signal FlushTree break request. Note, this is
|
||||
treated as recommendation only
|
||||
*/
|
||||
VOID
|
||||
UDFFlushTryBreak(
|
||||
IN PVCB Vcb
|
||||
)
|
||||
{
|
||||
UDFAcquireResourceExclusive(&(Vcb->FlushResource),TRUE);
|
||||
Vcb->VCBFlags |= UDF_VCB_FLAGS_FLUSH_BREAK_REQ;
|
||||
UDFReleaseResource(&(Vcb->FlushResource));
|
||||
} // end UDFFlushTryBreak()
|
Loading…
Add table
Add a link
Reference in a new issue