📄 write.c
字号:
/*
* COPYRIGHT: GNU GENERAL PUBLIC LICENSE VERSION 2
* PROJECT: ReiserFs file system driver for Windows NT/2000/XP/Vista.
* FILE: write.c
* PURPOSE:
* PROGRAMMER: Mark Piper, Matt Wu, Bo Brant閚.
* HOMEPAGE:
* UPDATE HISTORY:
*/
#if 0
/* INCLUDES *****************************************************************/
#include "rfsd.h"
/* GLOBALS ***************************************************************/
extern PRFSD_GLOBAL RfsdGlobal;
/* DEFINITIONS *************************************************************/
typedef struct _RFSD_FLPFLUSH_CONTEXT {
PRFSD_VCB Vcb;
PRFSD_FCB Fcb;
PFILE_OBJECT FileObject;
KDPC Dpc;
KTIMER Timer;
WORK_QUEUE_ITEM Item;
} RFSD_FLPFLUSH_CONTEXT, *PRFSD_FLPFLUSH_CONTEXT;
VOID
RfsdFloppyFlush(IN PVOID Parameter);
VOID
RfsdFloppyFlushDpc (
IN PKDPC Dpc,
IN PVOID DeferredContext,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2);
NTSTATUS
RfsdWriteComplete (IN PRFSD_IRP_CONTEXT IrpContext);
NTSTATUS
RfsdWriteFile (IN PRFSD_IRP_CONTEXT IrpContext);
NTSTATUS
RfsdWriteVolume (IN PRFSD_IRP_CONTEXT IrpContext);
VOID
RfsdDeferWrite(IN PRFSD_IRP_CONTEXT, PIRP Irp);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, RfsdFloppyFlush)
#pragma alloc_text(PAGE, RfsdStartFloppyFlushDpc)
#pragma alloc_text(PAGE, RfsdZeroHoles)
#pragma alloc_text(PAGE, RfsdWrite)
#pragma alloc_text(PAGE, RfsdWriteVolume)
#pragma alloc_text(PAGE, RfsdWriteInode)
#pragma alloc_text(PAGE, RfsdWriteFile)
#pragma alloc_text(PAGE, RfsdWriteComplete)
#endif
/* FUNCTIONS *************************************************************/
VOID
RfsdFloppyFlush(IN PVOID Parameter)
{
PRFSD_FLPFLUSH_CONTEXT Context;
PFILE_OBJECT FileObject;
PRFSD_FCB Fcb;
PRFSD_VCB Vcb;
Context = (PRFSD_FLPFLUSH_CONTEXT) Parameter;
FileObject = Context->FileObject;
Fcb = Context->Fcb;
Vcb = Context->Vcb;
RfsdPrint((DBG_USER, "RfsdFloppyFlushing ...\n"));
IoSetTopLevelIrp((PIRP)FSRTL_FSP_TOP_LEVEL_IRP);
if (Vcb) {
ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
ExReleaseResource(&Vcb->PagingIoResource);
CcFlushCache(&(Vcb->SectionObject), NULL, 0, NULL);
}
if (FileObject) {
ASSERT(Fcb == (PRFSD_FCB)FileObject->FsContext);
ExAcquireSharedStarveExclusive(&Fcb->PagingIoResource, TRUE);
ExReleaseResource(&Fcb->PagingIoResource);
CcFlushCache(&(Fcb->SectionObject), NULL, 0, NULL);
ObDereferenceObject(FileObject);
}
IoSetTopLevelIrp(NULL);
ExFreePool(Parameter);
}
VOID
RfsdFloppyFlushDpc (
IN PKDPC Dpc,
IN PVOID DeferredContext,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2
)
{
PRFSD_FLPFLUSH_CONTEXT Context;
Context = (PRFSD_FLPFLUSH_CONTEXT) DeferredContext;
RfsdPrint((DBG_USER, "RfsdFloppyFlushDpc is to be started...\n"));
ExInitializeWorkItem( &Context->Item,
RfsdFloppyFlush,
Context );
ExQueueWorkItem(&Context->Item, CriticalWorkQueue);
}
VOID
RfsdStartFloppyFlushDpc (
PRFSD_VCB Vcb,
PRFSD_FCB Fcb,
PFILE_OBJECT FileObject )
{
LARGE_INTEGER OneSecond;
PRFSD_FLPFLUSH_CONTEXT Context;
ASSERT(IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK));
Context = ExAllocatePool(NonPagedPool,sizeof(PRFSD_FLPFLUSH_CONTEXT));
if (!Context) {
DbgBreak();
return;
}
KeInitializeTimer(&Context->Timer);
KeInitializeDpc( &Context->Dpc,
RfsdFloppyFlushDpc,
Context );
Context->Vcb = Vcb;
Context->Fcb = Fcb;
Context->FileObject = FileObject;
if (FileObject) {
ObReferenceObject(FileObject);
}
OneSecond.QuadPart = (LONGLONG)-1*1000*1000*10;
KeSetTimer( &Context->Timer,
OneSecond,
&Context->Dpc );
}
BOOLEAN
RfsdZeroHoles (
IN PRFSD_IRP_CONTEXT IrpContext,
IN PRFSD_VCB Vcb,
IN PFILE_OBJECT FileObject,
IN LONGLONG Offset,
IN LONGLONG Count
)
{
LARGE_INTEGER StartAddr = {0,0};
LARGE_INTEGER EndAddr = {0,0};
StartAddr.QuadPart = (Offset + (SECTOR_SIZE - 1)) &
~((LONGLONG)SECTOR_SIZE - 1);
EndAddr.QuadPart = (Offset + Count + (SECTOR_SIZE - 1)) &
~((LONGLONG)SECTOR_SIZE - 1);
if (StartAddr.QuadPart < EndAddr.QuadPart) {
return CcZeroData( FileObject,
&StartAddr,
&EndAddr,
IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );
}
return TRUE;
}
VOID
RfsdDeferWrite(IN PRFSD_IRP_CONTEXT IrpContext, PIRP Irp)
{
ASSERT(IrpContext->Irp == Irp);
RfsdQueueRequest(IrpContext);
}
NTSTATUS
RfsdWriteVolume (IN PRFSD_IRP_CONTEXT IrpContext)
{
NTSTATUS Status = STATUS_UNSUCCESSFUL;
PRFSD_VCB Vcb;
PRFSD_CCB Ccb;
PRFSD_FCBVCB FcbOrVcb;
PFILE_OBJECT FileObject;
PDEVICE_OBJECT DeviceObject;
PIRP Irp;
PIO_STACK_LOCATION IoStackLocation;
ULONG Length;
LARGE_INTEGER ByteOffset;
BOOLEAN PagingIo;
BOOLEAN Nocache;
BOOLEAN SynchronousIo;
BOOLEAN MainResourceAcquired = FALSE;
BOOLEAN PagingIoResourceAcquired = FALSE;
BOOLEAN bDeferred = FALSE;
PUCHAR Buffer;
__try {
ASSERT(IrpContext);
ASSERT((IrpContext->Identifier.Type == RFSDICX) &&
(IrpContext->Identifier.Size == sizeof(RFSD_IRP_CONTEXT)));
DeviceObject = IrpContext->DeviceObject;
Vcb = (PRFSD_VCB) DeviceObject->DeviceExtension;
ASSERT(Vcb != NULL);
ASSERT((Vcb->Identifier.Type == RFSDVCB) &&
(Vcb->Identifier.Size == sizeof(RFSD_VCB)));
FileObject = IrpContext->FileObject;
FcbOrVcb = (PRFSD_FCBVCB) FileObject->FsContext;
ASSERT(FcbOrVcb);
if (!(FcbOrVcb->Identifier.Type == RFSDVCB && (PVOID)FcbOrVcb == (PVOID)Vcb)) {
Status = STATUS_INVALID_DEVICE_REQUEST;
__leave;
}
Ccb = (PRFSD_CCB) FileObject->FsContext2;
Irp = IrpContext->Irp;
IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
Length = IoStackLocation->Parameters.Write.Length;
ByteOffset = IoStackLocation->Parameters.Write.ByteOffset;
PagingIo = (Irp->Flags & IRP_PAGING_IO ? TRUE : FALSE);
Nocache = (Irp->Flags & IRP_NOCACHE ? TRUE : FALSE);
SynchronousIo = (FileObject->Flags & FO_SYNCHRONOUS_IO ? TRUE : FALSE);
RfsdPrint((DBG_INFO, "RfsdWriteVolume: Off=%I64xh Len=%xh Paging=%xh Nocache=%xh\n",
ByteOffset.QuadPart, Length, PagingIo, Nocache));
if (Length == 0) {
Irp->IoStatus.Information = 0;
Status = STATUS_SUCCESS;
__leave;
}
// For the case of "Direct Access Storage Device", we
// need flush/purge the cache
if (Ccb != NULL) {
ExAcquireResourceExclusive(&Vcb->MainResource, TRUE);
MainResourceAcquired = TRUE;
Status = RfsdPurgeVolume( Vcb, TRUE);
ExReleaseResource(&Vcb->MainResource);
MainResourceAcquired = FALSE;
if(!IsFlagOn(Ccb->Flags, CCB_ALLOW_EXTENDED_DASD_IO)) {
if (ByteOffset.QuadPart + Length > Vcb->Header.FileSize.QuadPart) {
Length = (ULONG)(Vcb->Header.FileSize.QuadPart - ByteOffset.QuadPart);
}
}
{
RFSD_BDL BlockArray;
if ((ByteOffset.LowPart & (SECTOR_SIZE - 1)) ||
(Length & (SECTOR_SIZE - 1)) ) {
Status = STATUS_INVALID_PARAMETER;
__leave;
}
Status = RfsdLockUserBuffer(
IrpContext->Irp,
Length,
IoReadAccess );
if (!NT_SUCCESS(Status)) {
__leave;
}
BlockArray.Irp = NULL;
BlockArray.Lba = ByteOffset.QuadPart;;
BlockArray.Offset = 0;
BlockArray.Length = Length;
Status = RfsdReadWriteBlocks(IrpContext,
Vcb,
&BlockArray,
Length,
1,
FALSE );
Irp = IrpContext->Irp;
__leave;
}
}
if (Nocache &&
(ByteOffset.LowPart & (SECTOR_SIZE - 1) ||
Length & (SECTOR_SIZE - 1))) {
Status = STATUS_INVALID_PARAMETER;
__leave;
}
if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC)) {
ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC);
Status = STATUS_PENDING;
__leave;
}
if (ByteOffset.QuadPart >=
Vcb->PartitionInformation.PartitionLength.QuadPart ) {
Irp->IoStatus.Information = 0;
Status = STATUS_END_OF_FILE;
__leave;
}
#if FALSE
if (!Nocache) {
BOOLEAN bAgain = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED);
BOOLEAN bWait = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
BOOLEAN bQueue = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED);
if ( !CcCanIWrite(
FileObject,
Length,
(bWait && bQueue),
bAgain ) ) {
SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED);
CcDeferWrite( FileObject,
(PCC_POST_DEFERRED_WRITE)RfsdDeferWrite,
IrpContext,
Irp,
Length,
bAgain );
bDeferred = TRUE;
DbgBreak();
Status = STATUS_PENDING;
__leave;
}
}
#endif
if (Nocache && !PagingIo && (Vcb->SectionObject.DataSectionObject != NULL)) {
ExAcquireResourceExclusive(&Vcb->MainResource, TRUE);
MainResourceAcquired = TRUE;
ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
ExReleaseResource(&Vcb->PagingIoResource);
CcFlushCache( &(Vcb->SectionObject),
&ByteOffset,
Length,
&(Irp->IoStatus));
if (!NT_SUCCESS(Irp->IoStatus.Status)) {
Status = Irp->IoStatus.Status;
__leave;
}
ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
ExReleaseResource(&Vcb->PagingIoResource);
CcPurgeCacheSection( &(Vcb->SectionObject),
(PLARGE_INTEGER)&(ByteOffset),
Length,
FALSE );
ExReleaseResource(&Vcb->MainResource);
MainResourceAcquired = FALSE;
}
if (!PagingIo) {
if (!ExAcquireResourceExclusiveLite(
&Vcb->MainResource,
IrpContext->IsSynchronous )) {
Status = STATUS_PENDING;
__leave;
}
MainResourceAcquired = TRUE;
} else {
/*
ULONG ResShCnt, ResExCnt;
ResShCnt = ExIsResourceAcquiredSharedLite(&Vcb->PagingIoResource);
ResExCnt = ExIsResourceAcquiredExclusiveLite(&Vcb->PagingIoResource);
RfsdPrint((DBG_USER, "PagingIoRes: %xh:%xh Synchronous=%xh\n", ResShCnt, ResExCnt, IrpContext->IsSynchronous));
*/
if (Ccb) {
if (!ExAcquireResourceSharedLite(
&Vcb->PagingIoResource,
IrpContext->IsSynchronous )) {
Status = STATUS_PENDING;
__leave;
}
PagingIoResourceAcquired = TRUE;
}
}
if (!Nocache) {
if ( (ByteOffset.QuadPart + Length) >
Vcb->PartitionInformation.PartitionLength.QuadPart ){
Length = (ULONG) (
Vcb->PartitionInformation.PartitionLength.QuadPart -
ByteOffset.QuadPart);
Length &= ~((ULONG)SECTOR_SIZE - 1);
}
if (FlagOn(IrpContext->MinorFunction, IRP_MN_MDL)) {
CcPrepareMdlWrite (
Vcb->StreamObj,
&ByteOffset,
Length,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -