1 ////////////////////////////////////////////////////////////////////
2 // Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine
4 ////////////////////////////////////////////////////////////////////
5 /*************************************************************************
9 * Module: UDF File System Driver (Kernel mode execution only)
12 * Contains code to handle the various "fast-io" calls.
14 *************************************************************************/
18 // define the file specific bug-check id
19 #define UDF_BUG_CHECK_ID UDF_FILE_FAST_IO
23 /*************************************************************************
25 * Function: UDFFastIoCheckIfPossible()
28 * To fast-io or not to fast-io, that is the question ...
29 * This routine helps the I/O Manager determine whether the FSD wishes
30 * to permit fast-io on a specific file stream.
32 * Expected Interrupt Level (for execution) :
36 * Return Value: TRUE/FALSE
38 *************************************************************************/
41 UDFFastIoCheckIfPossible(
42 IN PFILE_OBJECT FileObject
,
43 IN PLARGE_INTEGER FileOffset
,
47 IN BOOLEAN CheckForReadOperation
,
48 OUT PIO_STATUS_BLOCK IoStatus
,
49 IN PDEVICE_OBJECT DeviceObject
52 BOOLEAN ReturnedStatus
= FALSE
;
55 LARGE_INTEGER IoLength
;
57 // Obtain a pointer to the FCB and CCB for the file stream.
58 Ccb
= (PtrUDFCCB
)(FileObject
->FsContext2
);
63 // Validate that this is a fast-IO request to a regular file.
64 // The UDF FSD for example, will not allow fast-IO requests
65 // to volume objects, or to directories.
66 if ((Fcb
->NodeIdentifier
.NodeType
== UDF_NODE_TYPE_VCB
) ||
67 (Fcb
->FCBFlags
& UDF_FCB_DIRECTORY
)) {
68 // This is not allowed.
69 IoStatus
->Status
= STATUS_INVALID_PARAMETER
;
70 MmPrint((" UDFFastIoCheckIfPossible() TRUE, Failed\n"));
74 // back pressure for very smart and fast system cache ;)
75 if(Fcb->Vcb->VerifyCtx.ItemCount >= UDF_MAX_VERIFY_CACHE) {
76 AdPrint((" Verify queue overflow -> UDFFastIoCheckIfPossible() = FALSE\n"));
80 IoLength
.QuadPart
= Length
;
82 // The FSD can determine the checks that it needs to perform.
83 // Typically, a FSD will check whether there exist any byte-range
84 // locks that would prevent a fast-IO operation from proceeding.
86 // ... (FSD specific checks go here).
88 if (CheckForReadOperation
) {
89 // The following routine is exported by the FSRTL
90 // package and it returns TRUE if the read operation should be
91 // allowed to proceed based on the status of the current byte-range
92 // locks on the file stream. If we do not use the FSRTL package
93 // for byte-range locking support, then we must substitute our
94 // own checks over here.
95 ReturnedStatus
= FsRtlFastCheckLockForRead(&(Fcb
->NTRequiredFCB
->FileLock
),
96 FileOffset
, &IoLength
, LockKey
, FileObject
,
97 PsGetCurrentProcess());
99 // if(Fcb->Vcb->VCBFlags );
100 // This is a write request. Invoke the FSRTL byte-range lock package
101 // to see whether the write should be allowed to proceed.
102 ReturnedStatus
= FsRtlFastCheckLockForWrite(&(Fcb
->NTRequiredFCB
->FileLock
),
103 FileOffset
, &IoLength
, LockKey
, FileObject
,
104 PsGetCurrentProcess());
107 MmPrint((" UDFFastIoCheckIfPossible() %s\n", ReturnedStatus
? "TRUE" : "FALSE"));
108 return(ReturnedStatus
);
111 } // end UDFFastIoCheckIfPossible()
121 if( !(Fcb
->Vcb
->VCBFlags
& UDF_VCB_FLAGS_VOLUME_MOUNTED
) /*||
122 !FsRtlOplockIsFastIoPossible(&(Fcb->Oplock))*/ ) {
123 KdPrint((" FastIoIsNotPossible\n"));
124 return FastIoIsNotPossible
;
127 // back pressure for very smart and fast system cache ;)
128 if(Fcb->Vcb->VerifyCtx.ItemCount >= UDF_MAX_VERIFY_CACHE) {
129 AdPrint((" Verify queue overflow -> UDFIsFastIoPossible() = FastIoIsNotPossible\n"));
130 return FastIoIsNotPossible;
133 if(FsRtlAreThereCurrentFileLocks(&(Fcb
->NTRequiredFCB
->FileLock
)) ) {
134 KdPrint((" FastIoIsQuestionable\n"));
135 return FastIoIsQuestionable
;
137 KdPrint((" FastIoIsPossible\n"));
138 return FastIoIsPossible
;
139 } // end UDFIsFastIoPossible()
141 /*************************************************************************
143 * Function: UDFFastIoQueryBasicInfo()
146 * Bypass the traditional IRP method to perform a query basic
147 * information operation.
149 * Expected Interrupt Level (for execution) :
153 * Return Value: TRUE/FALSE
155 *************************************************************************/
158 UDFFastIoQueryBasicInfo(
159 IN PFILE_OBJECT FileObject
,
161 OUT PFILE_BASIC_INFORMATION Buffer
,
162 OUT PIO_STATUS_BLOCK IoStatus
,
163 IN PDEVICE_OBJECT DeviceObject
166 BOOLEAN ReturnedStatus
= FALSE
; // fast i/o failed/not allowed
167 NTSTATUS RC
= STATUS_SUCCESS
;
168 PtrUDFIrpContext PtrIrpContext
= NULL
;
169 LONG Length
= sizeof(FILE_BASIC_INFORMATION
);
172 PtrUDFNTRequiredFCB NtReqFcb
= NULL
;
173 BOOLEAN MainResourceAcquired
= FALSE
;
175 FsRtlEnterFileSystem();
177 KdPrint(("UDFFastIo \n"));
178 // if the file is already opended we can satisfy this request
179 // immediately 'cause all the data we need must be cached
184 // Get the FCB and CCB pointers.
185 Ccb
= (PtrUDFCCB
)(FileObject
->FsContext2
);
189 NtReqFcb
= Fcb
->NTRequiredFCB
;
190 //Fcb->Vcb->VCBFlags |= UDF_VCB_SKIP_EJECT_CHECK;
192 if (!(Fcb
->FCBFlags
& UDF_FCB_PAGE_FILE
)) {
193 // Acquire the MainResource shared.
194 UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb
);
195 if (!UDFAcquireResourceShared(&(NtReqFcb
->MainResource
), Wait
)) {
196 try_return(RC
= STATUS_CANT_WAIT
);
198 MainResourceAcquired
= TRUE
;
202 ((RC
= UDFGetBasicInformation(FileObject
, Fcb
, Buffer
, &Length
)) == STATUS_SUCCESS
);
204 } _SEH2_EXCEPT(UDFExceptionFilter(PtrIrpContext
, _SEH2_GetExceptionInformation())) {
206 RC
= UDFExceptionHandler(PtrIrpContext
, NULL
);
208 UDFLogEvent(UDF_ERROR_INTERNAL_ERROR
, RC
);
213 if (MainResourceAcquired
) {
214 UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb
);
215 UDFReleaseResource(&(NtReqFcb
->MainResource
));
216 MainResourceAcquired
= FALSE
;
218 IoStatus
->Status
= RC
;
220 IoStatus
->Information
= sizeof(FILE_BASIC_INFORMATION
);
222 IoStatus
->Information
= 0;
226 FsRtlExitFileSystem();
228 return(ReturnedStatus
);
229 } // end UDFFastIoQueryBasicInfo()
232 /*************************************************************************
234 * Function: UDFFastIoQueryStdInfo()
237 * Bypass the traditional IRP method to perform a query standard
238 * information operation.
240 * Expected Interrupt Level (for execution) :
244 * Return Value: TRUE/FALSE
246 *************************************************************************/
249 UDFFastIoQueryStdInfo(
250 IN PFILE_OBJECT FileObject
,
252 OUT PFILE_STANDARD_INFORMATION Buffer
,
253 OUT PIO_STATUS_BLOCK IoStatus
,
254 IN PDEVICE_OBJECT DeviceObject
)
256 BOOLEAN ReturnedStatus
= FALSE
; // fast i/o failed/not allowed
257 NTSTATUS RC
= STATUS_SUCCESS
;
258 PtrUDFIrpContext PtrIrpContext
= NULL
;
259 LONG Length
= sizeof(FILE_STANDARD_INFORMATION
);
262 PtrUDFNTRequiredFCB NtReqFcb
= NULL
;
263 // BOOLEAN MainResourceAcquired = FALSE;
265 FsRtlEnterFileSystem();
267 KdPrint(("UDFFastIo \n"));
268 // if the file is already opended we can satisfy this request
269 // immediately 'cause all the data we need must be cached
274 // Get the FCB and CCB pointers.
275 Ccb
= (PtrUDFCCB
)(FileObject
->FsContext2
);
279 NtReqFcb
= Fcb
->NTRequiredFCB
;
280 //Fcb->Vcb->VCBFlags |= UDF_VCB_SKIP_EJECT_CHECK;
283 if (!(Fcb->FCBFlags & UDF_FCB_PAGE_FILE)) {
284 // Acquire the MainResource shared.
285 UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb);
286 if (!UDFAcquireResourceShared(&(NtReqFcb->MainResource), Wait)) {
287 try_return(RC = STATUS_CANT_WAIT);
289 MainResourceAcquired = TRUE;
293 ((RC
= UDFGetStandardInformation(Fcb
, Buffer
, &Length
)) == STATUS_SUCCESS
);
295 } _SEH2_EXCEPT(UDFExceptionFilter(PtrIrpContext
, _SEH2_GetExceptionInformation())) {
297 RC
= UDFExceptionHandler(PtrIrpContext
, NULL
);
299 UDFLogEvent(UDF_ERROR_INTERNAL_ERROR
, RC
);
305 if (MainResourceAcquired) {
306 UDFReleaseResource(&(NtReqFcb->MainResource));
307 MainResourceAcquired = FALSE;
310 IoStatus
->Status
= RC
;
312 IoStatus
->Information
= sizeof(FILE_STANDARD_INFORMATION
);
314 IoStatus
->Information
= 0;
318 FsRtlExitFileSystem();
320 return(ReturnedStatus
);
321 } // end UDFFastIoQueryStdInfo()
324 /*************************************************************************
326 * Function: UDFFastIoAcqCreateSec()
329 * Not really a fast-io operation. Used by the VMM to acquire FSD resources
330 * before processing a file map (create section object) request.
332 * Expected Interrupt Level (for execution) :
336 * Return Value: None (we must be prepared to handle VMM initiated calls)
338 *************************************************************************/
341 UDFFastIoAcqCreateSec(
342 IN PFILE_OBJECT FileObject
345 PtrUDFNTRequiredFCB NtReqFcb
= (PtrUDFNTRequiredFCB
)(FileObject
->FsContext
);
347 MmPrint((" AcqForCreateSection()\n"));
348 // Acquire the MainResource exclusively for the file stream
349 if(!ExIsResourceAcquiredExclusiveLite(&(NtReqFcb
->MainResource
)) ||
350 !ExIsResourceAcquiredExclusiveLite(&(NtReqFcb
->PagingIoResource
)) ) {
351 UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb
);
353 MmPrint((" already acquired\n"));
355 UDFAcquireResourceExclusive(&(NtReqFcb
->MainResource
), TRUE
);
357 // Although this is typically not required, the UDF FSD will
358 // also acquire the PagingIoResource exclusively at this time
359 // to conform with the resource acquisition described in the set
360 // file information routine. Once again though, we will probably
361 // not need to do this.
362 UDFAcquireResourceExclusive(&(NtReqFcb
->PagingIoResource
), TRUE
);
363 NtReqFcb
->AcqSectionCount
++;
366 } // end UDFFastIoAcqCreateSec()
369 /*************************************************************************
371 * Function: UDFFastIoRelCreateSec()
374 * Not really a fast-io operation. Used by the VMM to release FSD resources
375 * after processing a file map (create section object) request.
377 * Expected Interrupt Level (for execution) :
383 *************************************************************************/
386 UDFFastIoRelCreateSec(
387 IN PFILE_OBJECT FileObject
)
389 PtrUDFNTRequiredFCB NtReqFcb
= (PtrUDFNTRequiredFCB
)(FileObject
->FsContext
);
391 MmPrint((" RelFromCreateSection()\n"));
393 NtReqFcb
->AcqSectionCount
--;
394 // Release the PagingIoResource for the file stream
395 UDFReleaseResource(&(NtReqFcb
->PagingIoResource
));
397 // Release the MainResource for the file stream
398 UDFReleaseResource(&(NtReqFcb
->MainResource
));
401 } // end UDFFastIoRelCreateSec()
404 /*************************************************************************
406 * Function: UDFAcqLazyWrite()
409 * Not really a fast-io operation. Used by the NT Cache Mgr to acquire FSD
410 * resources before performing a delayed write (write behind/lazy write)
412 * NOTE: this function really must succeed since the Cache Manager will
413 * typically ignore failure and continue on ...
415 * Expected Interrupt Level (for execution) :
419 * Return Value: TRUE/FALSE (Cache Manager does not tolerate FALSE well)
421 *************************************************************************/
422 BOOLEAN NTAPI
UDFAcqLazyWrite(
426 // The context is whatever we passed to the Cache Manager when invoking
427 // the CcInitializeCacheMaps() function. In the case of the UDF FSD
428 // implementation, this context is a pointer to the NT_REQ_FCB structure.
429 PtrUDFNTRequiredFCB NtReqFcb
= (PtrUDFNTRequiredFCB
)Context
;
431 MmPrint((" UDFAcqLazyWrite()\n"));
433 // Acquire the PagingIoResource in the NT_REQ_FCB exclusively. Then, set the
434 // lazy-writer thread id in the NT_REQ_FCB structure for identification
435 // when an actual write request is received by the FSD.
436 // Note: The lazy-writer typically always supplies WAIT set to TRUE.
437 if (!UDFAcquireResourceExclusive(&(NtReqFcb
->PagingIoResource
), Wait
))
440 // Now, set the lazy-writer thread id.
441 ASSERT(!(NtReqFcb
->LazyWriterThreadID
));
442 NtReqFcb
->LazyWriterThreadID
= (unsigned int)(PsGetCurrentThread());
444 ASSERT(IoGetTopLevelIrp() == NULL
);
445 IoSetTopLevelIrp((PIRP
)FSRTL_CACHE_TOP_LEVEL_IRP
);
447 // If our FSD needs to perform some special preparations in anticipation
448 // of receving a lazy-writer request, do so now.
450 } // end UDFAcqLazyWrite()
453 /*************************************************************************
455 * Function: UDFRelLazyWrite()
458 * Not really a fast-io operation. Used by the NT Cache Mgr to release FSD
459 * resources after performing a delayed write (write behind/lazy write)
462 * Expected Interrupt Level (for execution) :
468 *************************************************************************/
474 // The context is whatever we passed to the Cache Manager when invoking
475 // the CcInitializeCacheMaps() function. In the case of the UDF FSD
476 // implementation, this context is a pointer to the NT_REQ_FCB structure.
477 PtrUDFNTRequiredFCB NtReqFcb
= (PtrUDFNTRequiredFCB
)Context
;
479 MmPrint((" UDFRelLazyWrite()\n"));
481 // Remove the current thread-id from the NT_REQ_FCB
482 // and release the MainResource.
483 ASSERT((NtReqFcb
->LazyWriterThreadID
) == (unsigned int)PsGetCurrentThread());
484 NtReqFcb
->LazyWriterThreadID
= 0;
486 // Release the acquired resource.
487 UDFReleaseResource(&(NtReqFcb
->PagingIoResource
));
489 IoSetTopLevelIrp( NULL
);
491 } // end UDFRelLazyWrite()
494 /*************************************************************************
496 * Function: UDFAcqReadAhead()
499 * Not really a fast-io operation. Used by the NT Cache Mgr to acquire FSD
500 * resources before performing a read-ahead operation.
501 * NOTE: this function really must succeed since the Cache Manager will
502 * typically ignore failure and continue on ...
504 * Expected Interrupt Level (for execution) :
508 * Return Value: TRUE/FALSE (Cache Manager does not tolerate FALSE well)
510 *************************************************************************/
518 // The context is whatever we passed to the Cache Manager when invoking
519 // the CcInitializeCacheMaps() function. In the case of the UDF FSD
520 // implementation, this context is a pointer to the NT_REQ_FCB structure.
521 #define NtReqFcb ((PtrUDFNTRequiredFCB)Context)
523 MmPrint((" AcqForReadAhead()\n"));
525 // Acquire the MainResource in the NT_REQ_FCB shared.
526 // Note: The read-ahead thread typically always supplies WAIT set to TRUE.
527 UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb
);
528 if (!UDFAcquireResourceShared(&(NtReqFcb
->MainResource
), Wait
))
531 ASSERT(IoGetTopLevelIrp() == NULL
);
532 IoSetTopLevelIrp((PIRP
)FSRTL_CACHE_TOP_LEVEL_IRP
);
537 } // end UDFAcqReadAhead()
540 /*************************************************************************
542 * Function: UDFRelReadAhead()
545 * Not really a fast-io operation. Used by the NT Cache Mgr to release FSD
546 * resources after performing a read-ahead operation.
548 * Expected Interrupt Level (for execution) :
554 *************************************************************************/
560 // The context is whatever we passed to the Cache Manager when invoking
561 // the CcInitializeCacheMaps() function. In the case of the UDF FSD
562 // implementation, this context is a pointer to the NT_REQ_FCB structure.
563 #define NtReqFcb ((PtrUDFNTRequiredFCB)Context)
565 MmPrint((" RelFromReadAhead()\n"));
567 // Release the acquired resource.
568 UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb
);
569 UDFReleaseResource(&(NtReqFcb
->MainResource
));
571 // Of course, the FSD should undo whatever else seems appropriate at this
573 IoSetTopLevelIrp( NULL
);
577 } // end UDFRelReadAhead()
579 /* the remaining are only valid under NT Version 4.0 and later */
580 #if(_WIN32_WINNT >= 0x0400)
583 /*************************************************************************
585 * Function: UDFFastIoQueryNetInfo()
588 * Get information requested by a redirector across the network. This call
589 * will originate from the LAN Manager server.
591 * Expected Interrupt Level (for execution) :
595 * Return Value: TRUE/FALSE
597 *************************************************************************/
600 UDFFastIoQueryNetInfo(
601 IN PFILE_OBJECT FileObject
,
603 OUT PFILE_NETWORK_OPEN_INFORMATION Buffer
,
604 OUT PIO_STATUS_BLOCK IoStatus
,
605 IN PDEVICE_OBJECT DeviceObject
)
607 BOOLEAN ReturnedStatus
= FALSE
; // fast i/o failed/not allowed
608 NTSTATUS RC
= STATUS_SUCCESS
;
609 PtrUDFIrpContext PtrIrpContext
= NULL
;
610 LONG Length
= sizeof(FILE_NETWORK_OPEN_INFORMATION
);
613 PtrUDFNTRequiredFCB NtReqFcb
= NULL
;
614 BOOLEAN MainResourceAcquired
= FALSE
;
616 FsRtlEnterFileSystem();
618 KdPrint(("UDFFastIo \n"));
619 // if the file is already opended we can satisfy this request
620 // immediately 'cause all the data we need must be cached
625 // Get the FCB and CCB pointers.
626 Ccb
= (PtrUDFCCB
)(FileObject
->FsContext2
);
630 NtReqFcb
= Fcb
->NTRequiredFCB
;
631 //Fcb->Vcb->VCBFlags |= UDF_VCB_SKIP_EJECT_CHECK;
633 if (!(Fcb
->FCBFlags
& UDF_FCB_PAGE_FILE
)) {
634 // Acquire the MainResource shared.
635 UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb
);
636 if (!UDFAcquireResourceShared(&(NtReqFcb
->MainResource
), Wait
)) {
637 try_return(RC
= STATUS_CANT_WAIT
);
639 MainResourceAcquired
= TRUE
;
643 ((RC
= UDFGetNetworkInformation(Fcb
, Buffer
, &Length
)) == STATUS_SUCCESS
);
645 } _SEH2_EXCEPT(UDFExceptionFilter(PtrIrpContext
, _SEH2_GetExceptionInformation())) {
647 RC
= UDFExceptionHandler(PtrIrpContext
, NULL
);
649 UDFLogEvent(UDF_ERROR_INTERNAL_ERROR
, RC
);
654 if (MainResourceAcquired
) {
655 UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb
);
656 UDFReleaseResource(&(NtReqFcb
->MainResource
));
657 MainResourceAcquired
= FALSE
;
659 IoStatus
->Status
= RC
;
661 IoStatus
->Information
= sizeof(FILE_NETWORK_OPEN_INFORMATION
);
663 IoStatus
->Information
= 0;
667 FsRtlExitFileSystem();
669 return(ReturnedStatus
);
671 } // end UDFFastIoQueryNetInfo()
674 /*************************************************************************
676 * Function: UDFFastIoMdlRead()
679 * Bypass the traditional IRP method to perform a MDL read operation.
681 * Expected Interrupt Level (for execution) :
685 * Return Value: TRUE/FALSE
687 *************************************************************************/
688 /*BOOLEAN UDFFastIoMdlRead(
689 IN PFILE_OBJECT FileObject,
690 IN PLARGE_INTEGER FileOffset,
694 OUT PIO_STATUS_BLOCK IoStatus,
695 IN PDEVICE_OBJECT DeviceObject)
697 BOOLEAN ReturnedStatus = FALSE; // fast i/o failed/not allowed
698 NTSTATUS RC = STATUS_SUCCESS;
699 PtrUDFIrpContext PtrIrpContext = NULL;
701 FsRtlEnterFileSystem();
707 // See description in UDFFastIoRead() before filling-in the
712 } __except (UDFExceptionFilter(PtrIrpContext, GetExceptionInformation())) {
714 RC = UDFExceptionHandler(PtrIrpContext, NULL);
716 UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC);
726 FsRtlExitFileSystem();
728 return(ReturnedStatus);
732 /*************************************************************************
734 * Function: UDFFastIoMdlReadComplete()
737 * Bypass the traditional IRP method to inform the NT Cache Manager and the
738 * FSD that the caller no longer requires the data locked in the system cache
739 * or the MDL to stay around anymore ..
741 * Expected Interrupt Level (for execution) :
745 * Return Value: TRUE/FALSE
747 *************************************************************************/
748 /*BOOLEAN UDFFastIoMdlReadComplete(
749 IN PFILE_OBJECT FileObject,
751 IN PDEVICE_OBJECT DeviceObject)
753 BOOLEAN ReturnedStatus = FALSE; // fast i/o failed/not allowed
754 NTSTATUS RC = STATUS_SUCCESS;
755 PtrUDFIrpContext PtrIrpContext = NULL;
757 FsRtlEnterFileSystem();
763 // See description in UDFFastIoRead() before filling-in the
767 } __except (UDFExceptionFilter(PtrIrpContext, GetExceptionInformation())) {
769 RC = UDFExceptionHandler(PtrIrpContext, NULL);
771 UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC);
781 FsRtlExitFileSystem();
783 return(ReturnedStatus);
787 /*************************************************************************
789 * Function: UDFFastIoPrepareMdlWrite()
792 * Bypass the traditional IRP method to prepare for a MDL write operation.
794 * Expected Interrupt Level (for execution) :
798 * Return Value: TRUE/FALSE
800 *************************************************************************/
802 UDFFastIoPrepareMdlWrite(
803 IN PFILE_OBJECT FileObject,
804 IN PLARGE_INTEGER FileOffset,
808 OUT PIO_STATUS_BLOCK IoStatus,
809 IN PDEVICE_OBJECT DeviceObject
812 BOOLEAN ReturnedStatus = FALSE; // fast i/o failed/not allowed
813 NTSTATUS RC = STATUS_SUCCESS;
814 PtrUDFIrpContext PtrIrpContext = NULL;
816 FsRtlEnterFileSystem();
822 // See description in UDFFastIoRead() before filling-in the
826 } __except (UDFExceptionFilter(PtrIrpContext, GetExceptionInformation())) {
828 RC = UDFExceptionHandler(PtrIrpContext, NULL);
830 UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC);
840 FsRtlExitFileSystem();
842 return(ReturnedStatus);
846 /*************************************************************************
848 * Function: UDFFastIoMdlWriteComplete()
851 * Bypass the traditional IRP method to inform the NT Cache Manager and the
852 * FSD that the caller has updated the contents of the MDL. This data can
853 * now be asynchronously written out to secondary storage by the Cache Mgr.
855 * Expected Interrupt Level (for execution) :
859 * Return Value: TRUE/FALSE
861 *************************************************************************/
862 /*BOOLEAN UDFFastIoMdlWriteComplete(
863 IN PFILE_OBJECT FileObject,
864 IN PLARGE_INTEGER FileOffset,
866 IN PDEVICE_OBJECT DeviceObject)
868 BOOLEAN ReturnedStatus = FALSE; // fast i/o failed/not allowed
869 NTSTATUS RC = STATUS_SUCCESS;
870 PtrUDFIrpContext PtrIrpContext = NULL;
872 FsRtlEnterFileSystem();
878 // See description in UDFFastIoRead() before filling-in the
882 } __except (UDFExceptionFilter(PtrIrpContext, GetExceptionInformation())) {
884 RC = UDFExceptionHandler(PtrIrpContext, NULL);
886 UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC);
896 FsRtlExitFileSystem();
898 return(ReturnedStatus);
902 /*************************************************************************
904 * Function: UDFFastIoAcqModWrite()
907 * Not really a fast-io operation. Used by the VMM to acquire FSD resources
908 * before initiating a write operation via the Modified Page/Block Writer.
910 * Expected Interrupt Level (for execution) :
914 * Return Value: STATUS_SUCCESS/Error (__try not to return an error, will 'ya ? :-)
916 *************************************************************************/
919 UDFFastIoAcqModWrite(
920 IN PFILE_OBJECT FileObject
,
921 IN PLARGE_INTEGER EndingOffset
,
922 OUT PERESOURCE
*ResourceToRelease
,
923 IN PDEVICE_OBJECT DeviceObject
)
925 NTSTATUS RC
= STATUS_SUCCESS
;
927 FsRtlEnterFileSystem();
929 MmPrint((" AcqModW %I64x\n", EndingOffset
->QuadPart
));
931 #define NtReqFcb ((PtrUDFNTRequiredFCB)(FileObject->FsContext))
933 // We must determine which resource(s) we would like to
934 // acquire at this time. We know that a write is imminent;
935 // we will probably therefore acquire appropriate resources
938 // We must first get the FCB and CCB pointers from the file object
939 // that is passed in to this function (as an argument). Note that
940 // the ending offset (when examined in conjunction with current valid data
941 // length) may help us in determining the appropriate resource(s) to acquire.
943 // For example, if the ending offset is beyond current valid data length,
944 // We may decide to acquire *both* the MainResource and the PagingIoResource
945 // exclusively; otherwise, we may decide simply to acquire the PagingIoResource.
947 // Consult the text for more information on synchronization in FSDs.
949 // One final note; the VMM expects that we will return a pointer to
950 // the resource that we acquired (single return value). This pointer
951 // will be returned back to we in the release call (below).
953 if(UDFAcquireResourceShared(&(NtReqFcb
->PagingIoResource
), FALSE
)) {
954 if(EndingOffset
->QuadPart
<= NtReqFcb
->CommonFCBHeader
.ValidDataLength
.QuadPart
) {
955 UDFReleaseResource(&(NtReqFcb
->PagingIoResource
));
956 RC
= STATUS_CANT_WAIT
;
958 NtReqFcb
->AcqFlushCount
++;
959 (*ResourceToRelease
) = &(NtReqFcb
->PagingIoResource
);
960 MmPrint((" AcqModW OK\n"));
963 RC
= STATUS_CANT_WAIT
;
968 FsRtlExitFileSystem();
971 } // end UDFFastIoAcqModWrite()
974 /*************************************************************************
976 * Function: UDFFastIoRelModWrite()
979 * Not really a fast-io operation. Used by the VMM to release FSD resources
980 * after processing a modified page/block write operation.
982 * Expected Interrupt Level (for execution) :
986 * Return Value: STATUS_SUCCESS/Error (an error returned here is really not expected!)
988 *************************************************************************/
991 UDFFastIoRelModWrite(
992 IN PFILE_OBJECT FileObject
,
993 IN PERESOURCE ResourceToRelease
,
994 IN PDEVICE_OBJECT DeviceObject
)
996 FsRtlEnterFileSystem();
998 MmPrint((" RelModW\n"));
1000 #define NtReqFcb ((PtrUDFNTRequiredFCB)(FileObject->FsContext))
1002 // The MPW has complete the write for modified pages and therefore
1003 // wants us to release pre-acquired resource(s).
1005 // We must undo here whatever it is that we did in the
1006 // UDFFastIoAcqModWrite() call above.
1008 NtReqFcb
->AcqFlushCount
--;
1009 ASSERT(ResourceToRelease
== &(NtReqFcb
->PagingIoResource
));
1010 UDFReleaseResource(ResourceToRelease
);
1014 FsRtlExitFileSystem();
1016 return(STATUS_SUCCESS
);
1017 } // end UDFFastIoRelModWrite()
1020 /*************************************************************************
1022 * Function: UDFFastIoAcqCcFlush()
1025 * Not really a fast-io operation. Used by the NT Cache Mgr to acquire FSD
1026 * resources before performing a CcFlush() operation on a specific file
1029 * Expected Interrupt Level (for execution) :
1031 * IRQL_PASSIVE_LEVEL
1033 * Return Value: STATUS_SUCCESS/Error
1035 *************************************************************************/
1038 UDFFastIoAcqCcFlush(
1039 IN PFILE_OBJECT FileObject
,
1040 IN PDEVICE_OBJECT DeviceObject
)
1042 // NTSTATUS RC = STATUS_SUCCESS;
1044 FsRtlEnterFileSystem();
1046 MmPrint((" AcqCcFlush\n"));
1048 // Acquire appropriate resources that will allow correct synchronization
1049 // with a flush call (and avoid deadlock).
1051 #define NtReqFcb ((PtrUDFNTRequiredFCB)(FileObject->FsContext))
1053 // UDFAcquireResourceExclusive(&(NtReqFcb->MainResource), TRUE);
1054 UDFAcquireResourceExclusive(&(NtReqFcb
->PagingIoResource
), TRUE
);
1055 // ASSERT(!(NtReqFcb->AcqFlushCount));
1056 NtReqFcb
->AcqFlushCount
++;
1060 FsRtlExitFileSystem();
1062 return(STATUS_SUCCESS
);
1064 } // end UDFFastIoAcqCcFlush()
1066 /*************************************************************************
1068 * Function: UDFFastIoRelCcFlush()
1071 * Not really a fast-io operation. Used by the NT Cache Mgr to acquire FSD
1072 * resources before performing a CcFlush() operation on a specific file
1075 * Expected Interrupt Level (for execution) :
1077 * IRQL_PASSIVE_LEVEL
1079 * Return Value: STATUS_SUCCESS/Error
1081 *************************************************************************/
1084 UDFFastIoRelCcFlush(
1085 IN PFILE_OBJECT FileObject
,
1086 IN PDEVICE_OBJECT DeviceObject
1089 // NTSTATUS RC = STATUS_SUCCESS;
1091 FsRtlEnterFileSystem();
1093 MmPrint((" RelCcFlush\n"));
1095 #define NtReqFcb ((PtrUDFNTRequiredFCB)(FileObject->FsContext))
1097 // Release resources acquired in UDFFastIoAcqCcFlush() above.
1099 NtReqFcb
->AcqFlushCount
--;
1100 UDFReleaseResource(&(NtReqFcb
->PagingIoResource
));
1101 // UDFReleaseResource(&(NtReqFcb->MainResource));
1105 FsRtlExitFileSystem();
1107 return(STATUS_SUCCESS
);
1109 } // end UDFFastIoRelCcFlush()
1113 UDFFastIoDeviceControl (
1114 IN PFILE_OBJECT FileObject,
1116 IN PVOID InputBuffer OPTIONAL,
1117 IN ULONG InputBufferLength,
1118 OUT PVOID OutputBuffer OPTIONAL,
1119 IN ULONG OutputBufferLength,
1120 IN ULONG IoControlCode,
1121 OUT PIO_STATUS_BLOCK IoStatus,
1122 IN PDEVICE_OBJECT DeviceObject
1125 switch(IoControlCode) {
1126 case FSCTL_ALLOW_EXTENDED_DASD_IO: {
1127 IoStatus->Information = 0;
1128 IoStatus->Status = STATUS_SUCCESS;
1131 case FSCTL_IS_VOLUME_MOUNTED: {
1135 Ccb = (PtrUDFCCB)(FileObject->FsContext2);
1139 !(Fcb->Vcb->VCBFlags & UDF_VCB_FLAGS_RAW_DISK) &&
1140 !(Fcb->Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_LOCKED) ) {
1144 IoStatus->Information = 0;
1145 IoStatus->Status = STATUS_SUCCESS;
1155 #endif //_WIN32_WINNT >= 0x0400
1159 UDFFastIoCopyWrite (
1160 IN PFILE_OBJECT FileObject
,
1161 IN PLARGE_INTEGER FileOffset
,
1166 OUT PIO_STATUS_BLOCK IoStatus
,
1167 IN PDEVICE_OBJECT DeviceObject
1170 PtrUDFFCB Fcb
= NULL
;
1171 PtrUDFCCB Ccb
= NULL
;
1173 // Obtain a pointer to the FCB and CCB for the file stream.
1174 Ccb
= (PtrUDFCCB
)(FileObject
->FsContext2
);
1179 // back pressure for very smart and fast system cache ;)
1180 if(Fcb
->Vcb
->VerifyCtx
.QueuedCount
||
1181 Fcb
->Vcb
->VerifyCtx
.ItemCount
>= UDF_MAX_VERIFY_CACHE
) {
1182 AdPrint((" Verify queue overflow -> UDFFastIoCopyWrite() = FALSE\n"));
1185 if(Fcb
->NTRequiredFCB
->SectionObject
.DataSectionObject
&&
1186 Length
>= 0x10000 &&
1187 FileOffset
->LowPart
&&
1188 !(FileOffset
->LowPart
& 0x00ffffff)) {
1190 MmPrint((" no FastIo 16Mb\n"));
1193 return FsRtlCopyWrite(FileObject
, FileOffset
, Length
, Wait
, LockKey
, Buffer
, IoStatus
, DeviceObject
);
1195 } // end UDFFastIoCopyWrite()