1 ////////////////////////////////////////////////////////////////////
2 // Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine
4 // This file was released under the GPLv2 on June 2015.
5 ////////////////////////////////////////////////////////////////////
6 /*************************************************************************
10 * Module: UDF File System Driver (Kernel mode execution only)
13 * Contains code to handle the various "fast-io" calls.
15 *************************************************************************/
19 // define the file specific bug-check id
20 #define UDF_BUG_CHECK_ID UDF_FILE_FAST_IO
24 /*************************************************************************
26 * Function: UDFFastIoCheckIfPossible()
29 * To fast-io or not to fast-io, that is the question ...
30 * This routine helps the I/O Manager determine whether the FSD wishes
31 * to permit fast-io on a specific file stream.
33 * Expected Interrupt Level (for execution) :
37 * Return Value: TRUE/FALSE
39 *************************************************************************/
42 UDFFastIoCheckIfPossible(
43 IN PFILE_OBJECT FileObject
,
44 IN PLARGE_INTEGER FileOffset
,
48 IN BOOLEAN CheckForReadOperation
,
49 OUT PIO_STATUS_BLOCK IoStatus
,
50 IN PDEVICE_OBJECT DeviceObject
53 BOOLEAN ReturnedStatus
= FALSE
;
56 LARGE_INTEGER IoLength
;
58 // Obtain a pointer to the FCB and CCB for the file stream.
59 Ccb
= (PtrUDFCCB
)(FileObject
->FsContext2
);
64 // Validate that this is a fast-IO request to a regular file.
65 // The UDF FSD for example, will not allow fast-IO requests
66 // to volume objects, or to directories.
67 if ((Fcb
->NodeIdentifier
.NodeType
== UDF_NODE_TYPE_VCB
) ||
68 (Fcb
->FCBFlags
& UDF_FCB_DIRECTORY
)) {
69 // This is not allowed.
70 IoStatus
->Status
= STATUS_INVALID_PARAMETER
;
71 MmPrint((" UDFFastIoCheckIfPossible() TRUE, Failed\n"));
75 // back pressure for very smart and fast system cache ;)
76 if(Fcb->Vcb->VerifyCtx.ItemCount >= UDF_MAX_VERIFY_CACHE) {
77 AdPrint((" Verify queue overflow -> UDFFastIoCheckIfPossible() = FALSE\n"));
81 IoLength
.QuadPart
= Length
;
83 // The FSD can determine the checks that it needs to perform.
84 // Typically, a FSD will check whether there exist any byte-range
85 // locks that would prevent a fast-IO operation from proceeding.
87 // ... (FSD specific checks go here).
89 if (CheckForReadOperation
) {
90 // The following routine is exported by the FSRTL
91 // package and it returns TRUE if the read operation should be
92 // allowed to proceed based on the status of the current byte-range
93 // locks on the file stream. If we do not use the FSRTL package
94 // for byte-range locking support, then we must substitute our
95 // own checks over here.
96 ReturnedStatus
= FsRtlFastCheckLockForRead(&(Fcb
->NTRequiredFCB
->FileLock
),
97 FileOffset
, &IoLength
, LockKey
, FileObject
,
98 PsGetCurrentProcess());
100 // if(Fcb->Vcb->VCBFlags );
101 // This is a write request. Invoke the FSRTL byte-range lock package
102 // to see whether the write should be allowed to proceed.
103 ReturnedStatus
= FsRtlFastCheckLockForWrite(&(Fcb
->NTRequiredFCB
->FileLock
),
104 FileOffset
, &IoLength
, LockKey
, FileObject
,
105 PsGetCurrentProcess());
108 MmPrint((" UDFFastIoCheckIfPossible() %s\n", ReturnedStatus
? "TRUE" : "FALSE"));
109 return(ReturnedStatus
);
112 } // end UDFFastIoCheckIfPossible()
122 if( !(Fcb
->Vcb
->VCBFlags
& UDF_VCB_FLAGS_VOLUME_MOUNTED
) /*||
123 !FsRtlOplockIsFastIoPossible(&(Fcb->Oplock))*/ ) {
124 UDFPrint((" FastIoIsNotPossible\n"));
125 return FastIoIsNotPossible
;
128 // back pressure for very smart and fast system cache ;)
129 if(Fcb->Vcb->VerifyCtx.ItemCount >= UDF_MAX_VERIFY_CACHE) {
130 AdPrint((" Verify queue overflow -> UDFIsFastIoPossible() = FastIoIsNotPossible\n"));
131 return FastIoIsNotPossible;
134 if(FsRtlAreThereCurrentFileLocks(&(Fcb
->NTRequiredFCB
->FileLock
)) ) {
135 UDFPrint((" FastIoIsQuestionable\n"));
136 return FastIoIsQuestionable
;
138 UDFPrint((" FastIoIsPossible\n"));
139 return FastIoIsPossible
;
140 } // end UDFIsFastIoPossible()
142 /*************************************************************************
144 * Function: UDFFastIoQueryBasicInfo()
147 * Bypass the traditional IRP method to perform a query basic
148 * information operation.
150 * Expected Interrupt Level (for execution) :
154 * Return Value: TRUE/FALSE
156 *************************************************************************/
159 UDFFastIoQueryBasicInfo(
160 IN PFILE_OBJECT FileObject
,
162 OUT PFILE_BASIC_INFORMATION Buffer
,
163 OUT PIO_STATUS_BLOCK IoStatus
,
164 IN PDEVICE_OBJECT DeviceObject
167 BOOLEAN ReturnedStatus
= FALSE
; // fast i/o failed/not allowed
168 NTSTATUS RC
= STATUS_SUCCESS
;
169 PtrUDFIrpContext PtrIrpContext
= NULL
;
170 LONG Length
= sizeof(FILE_BASIC_INFORMATION
);
173 PtrUDFNTRequiredFCB NtReqFcb
= NULL
;
174 BOOLEAN MainResourceAcquired
= FALSE
;
176 FsRtlEnterFileSystem();
178 UDFPrint(("UDFFastIo \n"));
179 // if the file is already opended we can satisfy this request
180 // immediately 'cause all the data we need must be cached
185 // Get the FCB and CCB pointers.
186 Ccb
= (PtrUDFCCB
)(FileObject
->FsContext2
);
190 NtReqFcb
= Fcb
->NTRequiredFCB
;
191 //Fcb->Vcb->VCBFlags |= UDF_VCB_SKIP_EJECT_CHECK;
193 if (!(Fcb
->FCBFlags
& UDF_FCB_PAGE_FILE
)) {
194 // Acquire the MainResource shared.
195 UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb
);
196 if (!UDFAcquireResourceShared(&(NtReqFcb
->MainResource
), Wait
)) {
197 try_return(RC
= STATUS_CANT_WAIT
);
199 MainResourceAcquired
= TRUE
;
203 ((RC
= UDFGetBasicInformation(FileObject
, Fcb
, Buffer
, &Length
)) == STATUS_SUCCESS
);
205 } _SEH2_EXCEPT(UDFExceptionFilter(PtrIrpContext
, _SEH2_GetExceptionInformation())) {
207 RC
= UDFExceptionHandler(PtrIrpContext
, NULL
);
209 UDFLogEvent(UDF_ERROR_INTERNAL_ERROR
, RC
);
214 if (MainResourceAcquired
) {
215 UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb
);
216 UDFReleaseResource(&(NtReqFcb
->MainResource
));
217 MainResourceAcquired
= FALSE
;
219 IoStatus
->Status
= RC
;
221 IoStatus
->Information
= sizeof(FILE_BASIC_INFORMATION
);
223 IoStatus
->Information
= 0;
227 FsRtlExitFileSystem();
229 return(ReturnedStatus
);
230 } // end UDFFastIoQueryBasicInfo()
233 /*************************************************************************
235 * Function: UDFFastIoQueryStdInfo()
238 * Bypass the traditional IRP method to perform a query standard
239 * information operation.
241 * Expected Interrupt Level (for execution) :
245 * Return Value: TRUE/FALSE
247 *************************************************************************/
250 UDFFastIoQueryStdInfo(
251 IN PFILE_OBJECT FileObject
,
253 OUT PFILE_STANDARD_INFORMATION Buffer
,
254 OUT PIO_STATUS_BLOCK IoStatus
,
255 IN PDEVICE_OBJECT DeviceObject
)
257 BOOLEAN ReturnedStatus
= FALSE
; // fast i/o failed/not allowed
258 NTSTATUS RC
= STATUS_SUCCESS
;
259 PtrUDFIrpContext PtrIrpContext
= NULL
;
260 LONG Length
= sizeof(FILE_STANDARD_INFORMATION
);
263 // PtrUDFNTRequiredFCB NtReqFcb = NULL;
264 // BOOLEAN MainResourceAcquired = FALSE;
266 FsRtlEnterFileSystem();
268 UDFPrint(("UDFFastIo \n"));
269 // if the file is already opended we can satisfy this request
270 // immediately 'cause all the data we need must be cached
275 // Get the FCB and CCB pointers.
276 Ccb
= (PtrUDFCCB
)(FileObject
->FsContext2
);
280 // NtReqFcb = Fcb->NTRequiredFCB;
281 //Fcb->Vcb->VCBFlags |= UDF_VCB_SKIP_EJECT_CHECK;
284 if (!(Fcb->FCBFlags & UDF_FCB_PAGE_FILE)) {
285 // Acquire the MainResource shared.
286 UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb);
287 if (!UDFAcquireResourceShared(&(NtReqFcb->MainResource), Wait)) {
288 try_return(RC = STATUS_CANT_WAIT);
290 MainResourceAcquired = TRUE;
294 ((RC
= UDFGetStandardInformation(Fcb
, Buffer
, &Length
)) == STATUS_SUCCESS
);
296 } _SEH2_EXCEPT(UDFExceptionFilter(PtrIrpContext
, _SEH2_GetExceptionInformation())) {
298 RC
= UDFExceptionHandler(PtrIrpContext
, NULL
);
300 UDFLogEvent(UDF_ERROR_INTERNAL_ERROR
, RC
);
306 if (MainResourceAcquired) {
307 UDFReleaseResource(&(NtReqFcb->MainResource));
308 MainResourceAcquired = FALSE;
311 IoStatus
->Status
= RC
;
313 IoStatus
->Information
= sizeof(FILE_STANDARD_INFORMATION
);
315 IoStatus
->Information
= 0;
319 FsRtlExitFileSystem();
321 return(ReturnedStatus
);
322 } // end UDFFastIoQueryStdInfo()
325 /*************************************************************************
327 * Function: UDFFastIoAcqCreateSec()
330 * Not really a fast-io operation. Used by the VMM to acquire FSD resources
331 * before processing a file map (create section object) request.
333 * Expected Interrupt Level (for execution) :
337 * Return Value: None (we must be prepared to handle VMM initiated calls)
339 *************************************************************************/
342 UDFFastIoAcqCreateSec(
343 IN PFILE_OBJECT FileObject
346 PtrUDFNTRequiredFCB NtReqFcb
= (PtrUDFNTRequiredFCB
)(FileObject
->FsContext
);
348 MmPrint((" AcqForCreateSection()\n"));
349 // Acquire the MainResource exclusively for the file stream
350 if(!ExIsResourceAcquiredExclusiveLite(&(NtReqFcb
->MainResource
)) ||
351 !ExIsResourceAcquiredExclusiveLite(&(NtReqFcb
->PagingIoResource
)) ) {
352 UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb
);
354 MmPrint((" already acquired\n"));
356 UDFAcquireResourceExclusive(&(NtReqFcb
->MainResource
), TRUE
);
358 // Although this is typically not required, the UDF FSD will
359 // also acquire the PagingIoResource exclusively at this time
360 // to conform with the resource acquisition described in the set
361 // file information routine. Once again though, we will probably
362 // not need to do this.
363 UDFAcquireResourceExclusive(&(NtReqFcb
->PagingIoResource
), TRUE
);
364 NtReqFcb
->AcqSectionCount
++;
367 } // end UDFFastIoAcqCreateSec()
370 /*************************************************************************
372 * Function: UDFFastIoRelCreateSec()
375 * Not really a fast-io operation. Used by the VMM to release FSD resources
376 * after processing a file map (create section object) request.
378 * Expected Interrupt Level (for execution) :
384 *************************************************************************/
387 UDFFastIoRelCreateSec(
388 IN PFILE_OBJECT FileObject
)
390 PtrUDFNTRequiredFCB NtReqFcb
= (PtrUDFNTRequiredFCB
)(FileObject
->FsContext
);
392 MmPrint((" RelFromCreateSection()\n"));
394 NtReqFcb
->AcqSectionCount
--;
395 // Release the PagingIoResource for the file stream
396 UDFReleaseResource(&(NtReqFcb
->PagingIoResource
));
398 // Release the MainResource for the file stream
399 UDFReleaseResource(&(NtReqFcb
->MainResource
));
402 } // end UDFFastIoRelCreateSec()
405 /*************************************************************************
407 * Function: UDFAcqLazyWrite()
410 * Not really a fast-io operation. Used by the NT Cache Mgr to acquire FSD
411 * resources before performing a delayed write (write behind/lazy write)
413 * NOTE: this function really must succeed since the Cache Manager will
414 * typically ignore failure and continue on ...
416 * Expected Interrupt Level (for execution) :
420 * Return Value: TRUE/FALSE (Cache Manager does not tolerate FALSE well)
422 *************************************************************************/
423 BOOLEAN NTAPI
UDFAcqLazyWrite(
427 // The context is whatever we passed to the Cache Manager when invoking
428 // the CcInitializeCacheMaps() function. In the case of the UDF FSD
429 // implementation, this context is a pointer to the NT_REQ_FCB structure.
430 PtrUDFNTRequiredFCB NtReqFcb
= (PtrUDFNTRequiredFCB
)Context
;
432 MmPrint((" UDFAcqLazyWrite()\n"));
434 // Acquire the PagingIoResource in the NT_REQ_FCB exclusively. Then, set the
435 // lazy-writer thread id in the NT_REQ_FCB structure for identification
436 // when an actual write request is received by the FSD.
437 // Note: The lazy-writer typically always supplies WAIT set to TRUE.
438 if (!UDFAcquireResourceExclusive(&(NtReqFcb
->PagingIoResource
), Wait
))
441 // Now, set the lazy-writer thread id.
442 ASSERT(!(NtReqFcb
->LazyWriterThreadID
));
443 NtReqFcb
->LazyWriterThreadID
= (unsigned int)(PsGetCurrentThread());
445 ASSERT(IoGetTopLevelIrp() == NULL
);
446 IoSetTopLevelIrp((PIRP
)FSRTL_CACHE_TOP_LEVEL_IRP
);
448 // If our FSD needs to perform some special preparations in anticipation
449 // of receving a lazy-writer request, do so now.
451 } // end UDFAcqLazyWrite()
454 /*************************************************************************
456 * Function: UDFRelLazyWrite()
459 * Not really a fast-io operation. Used by the NT Cache Mgr to release FSD
460 * resources after performing a delayed write (write behind/lazy write)
463 * Expected Interrupt Level (for execution) :
469 *************************************************************************/
475 // The context is whatever we passed to the Cache Manager when invoking
476 // the CcInitializeCacheMaps() function. In the case of the UDF FSD
477 // implementation, this context is a pointer to the NT_REQ_FCB structure.
478 PtrUDFNTRequiredFCB NtReqFcb
= (PtrUDFNTRequiredFCB
)Context
;
480 MmPrint((" UDFRelLazyWrite()\n"));
482 // Remove the current thread-id from the NT_REQ_FCB
483 // and release the MainResource.
484 ASSERT((NtReqFcb
->LazyWriterThreadID
) == (unsigned int)PsGetCurrentThread());
485 NtReqFcb
->LazyWriterThreadID
= 0;
487 // Release the acquired resource.
488 UDFReleaseResource(&(NtReqFcb
->PagingIoResource
));
490 IoSetTopLevelIrp( NULL
);
492 } // end UDFRelLazyWrite()
495 /*************************************************************************
497 * Function: UDFAcqReadAhead()
500 * Not really a fast-io operation. Used by the NT Cache Mgr to acquire FSD
501 * resources before performing a read-ahead operation.
502 * NOTE: this function really must succeed since the Cache Manager will
503 * typically ignore failure and continue on ...
505 * Expected Interrupt Level (for execution) :
509 * Return Value: TRUE/FALSE (Cache Manager does not tolerate FALSE well)
511 *************************************************************************/
519 // The context is whatever we passed to the Cache Manager when invoking
520 // the CcInitializeCacheMaps() function. In the case of the UDF FSD
521 // implementation, this context is a pointer to the NT_REQ_FCB structure.
522 #define NtReqFcb ((PtrUDFNTRequiredFCB)Context)
524 MmPrint((" AcqForReadAhead()\n"));
526 // Acquire the MainResource in the NT_REQ_FCB shared.
527 // Note: The read-ahead thread typically always supplies WAIT set to TRUE.
528 UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb
);
529 if (!UDFAcquireResourceShared(&(NtReqFcb
->MainResource
), Wait
))
532 ASSERT(IoGetTopLevelIrp() == NULL
);
533 IoSetTopLevelIrp((PIRP
)FSRTL_CACHE_TOP_LEVEL_IRP
);
538 } // end UDFAcqReadAhead()
541 /*************************************************************************
543 * Function: UDFRelReadAhead()
546 * Not really a fast-io operation. Used by the NT Cache Mgr to release FSD
547 * resources after performing a read-ahead operation.
549 * Expected Interrupt Level (for execution) :
555 *************************************************************************/
561 // The context is whatever we passed to the Cache Manager when invoking
562 // the CcInitializeCacheMaps() function. In the case of the UDF FSD
563 // implementation, this context is a pointer to the NT_REQ_FCB structure.
564 #define NtReqFcb ((PtrUDFNTRequiredFCB)Context)
566 MmPrint((" RelFromReadAhead()\n"));
568 // Release the acquired resource.
569 UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb
);
570 UDFReleaseResource(&(NtReqFcb
->MainResource
));
572 // Of course, the FSD should undo whatever else seems appropriate at this
574 IoSetTopLevelIrp( NULL
);
578 } // end UDFRelReadAhead()
580 /* the remaining are only valid under NT Version 4.0 and later */
581 #if(_WIN32_WINNT >= 0x0400)
584 /*************************************************************************
586 * Function: UDFFastIoQueryNetInfo()
589 * Get information requested by a redirector across the network. This call
590 * will originate from the LAN Manager server.
592 * Expected Interrupt Level (for execution) :
596 * Return Value: TRUE/FALSE
598 *************************************************************************/
601 UDFFastIoQueryNetInfo(
602 IN PFILE_OBJECT FileObject
,
604 OUT PFILE_NETWORK_OPEN_INFORMATION Buffer
,
605 OUT PIO_STATUS_BLOCK IoStatus
,
606 IN PDEVICE_OBJECT DeviceObject
)
608 BOOLEAN ReturnedStatus
= FALSE
; // fast i/o failed/not allowed
609 NTSTATUS RC
= STATUS_SUCCESS
;
610 PtrUDFIrpContext PtrIrpContext
= NULL
;
611 LONG Length
= sizeof(FILE_NETWORK_OPEN_INFORMATION
);
614 PtrUDFNTRequiredFCB NtReqFcb
= NULL
;
615 BOOLEAN MainResourceAcquired
= FALSE
;
617 FsRtlEnterFileSystem();
619 UDFPrint(("UDFFastIo \n"));
620 // if the file is already opended we can satisfy this request
621 // immediately 'cause all the data we need must be cached
626 // Get the FCB and CCB pointers.
627 Ccb
= (PtrUDFCCB
)(FileObject
->FsContext2
);
631 NtReqFcb
= Fcb
->NTRequiredFCB
;
632 //Fcb->Vcb->VCBFlags |= UDF_VCB_SKIP_EJECT_CHECK;
634 if (!(Fcb
->FCBFlags
& UDF_FCB_PAGE_FILE
)) {
635 // Acquire the MainResource shared.
636 UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb
);
637 if (!UDFAcquireResourceShared(&(NtReqFcb
->MainResource
), Wait
)) {
638 try_return(RC
= STATUS_CANT_WAIT
);
640 MainResourceAcquired
= TRUE
;
644 ((RC
= UDFGetNetworkInformation(Fcb
, Buffer
, &Length
)) == STATUS_SUCCESS
);
646 } _SEH2_EXCEPT(UDFExceptionFilter(PtrIrpContext
, _SEH2_GetExceptionInformation())) {
648 RC
= UDFExceptionHandler(PtrIrpContext
, NULL
);
650 UDFLogEvent(UDF_ERROR_INTERNAL_ERROR
, RC
);
655 if (MainResourceAcquired
) {
656 UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb
);
657 UDFReleaseResource(&(NtReqFcb
->MainResource
));
658 MainResourceAcquired
= FALSE
;
660 IoStatus
->Status
= RC
;
662 IoStatus
->Information
= sizeof(FILE_NETWORK_OPEN_INFORMATION
);
664 IoStatus
->Information
= 0;
668 FsRtlExitFileSystem();
670 return(ReturnedStatus
);
672 } // end UDFFastIoQueryNetInfo()
675 /*************************************************************************
677 * Function: UDFFastIoMdlRead()
680 * Bypass the traditional IRP method to perform a MDL read operation.
682 * Expected Interrupt Level (for execution) :
686 * Return Value: TRUE/FALSE
688 *************************************************************************/
689 /*BOOLEAN UDFFastIoMdlRead(
690 IN PFILE_OBJECT FileObject,
691 IN PLARGE_INTEGER FileOffset,
695 OUT PIO_STATUS_BLOCK IoStatus,
696 IN PDEVICE_OBJECT DeviceObject)
698 BOOLEAN ReturnedStatus = FALSE; // fast i/o failed/not allowed
699 NTSTATUS RC = STATUS_SUCCESS;
700 PtrUDFIrpContext PtrIrpContext = NULL;
702 FsRtlEnterFileSystem();
708 // See description in UDFFastIoRead() before filling-in the
713 } __except (UDFExceptionFilter(PtrIrpContext, GetExceptionInformation())) {
715 RC = UDFExceptionHandler(PtrIrpContext, NULL);
717 UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC);
727 FsRtlExitFileSystem();
729 return(ReturnedStatus);
733 /*************************************************************************
735 * Function: UDFFastIoMdlReadComplete()
738 * Bypass the traditional IRP method to inform the NT Cache Manager and the
739 * FSD that the caller no longer requires the data locked in the system cache
740 * or the MDL to stay around anymore ..
742 * Expected Interrupt Level (for execution) :
746 * Return Value: TRUE/FALSE
748 *************************************************************************/
749 /*BOOLEAN UDFFastIoMdlReadComplete(
750 IN PFILE_OBJECT FileObject,
752 IN PDEVICE_OBJECT DeviceObject)
754 BOOLEAN ReturnedStatus = FALSE; // fast i/o failed/not allowed
755 NTSTATUS RC = STATUS_SUCCESS;
756 PtrUDFIrpContext PtrIrpContext = NULL;
758 FsRtlEnterFileSystem();
764 // See description in UDFFastIoRead() before filling-in the
768 } __except (UDFExceptionFilter(PtrIrpContext, GetExceptionInformation())) {
770 RC = UDFExceptionHandler(PtrIrpContext, NULL);
772 UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC);
782 FsRtlExitFileSystem();
784 return(ReturnedStatus);
788 /*************************************************************************
790 * Function: UDFFastIoPrepareMdlWrite()
793 * Bypass the traditional IRP method to prepare for a MDL write operation.
795 * Expected Interrupt Level (for execution) :
799 * Return Value: TRUE/FALSE
801 *************************************************************************/
803 UDFFastIoPrepareMdlWrite(
804 IN PFILE_OBJECT FileObject,
805 IN PLARGE_INTEGER FileOffset,
809 OUT PIO_STATUS_BLOCK IoStatus,
810 IN PDEVICE_OBJECT DeviceObject
813 BOOLEAN ReturnedStatus = FALSE; // fast i/o failed/not allowed
814 NTSTATUS RC = STATUS_SUCCESS;
815 PtrUDFIrpContext PtrIrpContext = NULL;
817 FsRtlEnterFileSystem();
823 // See description in UDFFastIoRead() before filling-in the
827 } __except (UDFExceptionFilter(PtrIrpContext, GetExceptionInformation())) {
829 RC = UDFExceptionHandler(PtrIrpContext, NULL);
831 UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC);
841 FsRtlExitFileSystem();
843 return(ReturnedStatus);
847 /*************************************************************************
849 * Function: UDFFastIoMdlWriteComplete()
852 * Bypass the traditional IRP method to inform the NT Cache Manager and the
853 * FSD that the caller has updated the contents of the MDL. This data can
854 * now be asynchronously written out to secondary storage by the Cache Mgr.
856 * Expected Interrupt Level (for execution) :
860 * Return Value: TRUE/FALSE
862 *************************************************************************/
863 /*BOOLEAN UDFFastIoMdlWriteComplete(
864 IN PFILE_OBJECT FileObject,
865 IN PLARGE_INTEGER FileOffset,
867 IN PDEVICE_OBJECT DeviceObject)
869 BOOLEAN ReturnedStatus = FALSE; // fast i/o failed/not allowed
870 NTSTATUS RC = STATUS_SUCCESS;
871 PtrUDFIrpContext PtrIrpContext = NULL;
873 FsRtlEnterFileSystem();
879 // See description in UDFFastIoRead() before filling-in the
883 } __except (UDFExceptionFilter(PtrIrpContext, GetExceptionInformation())) {
885 RC = UDFExceptionHandler(PtrIrpContext, NULL);
887 UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC);
897 FsRtlExitFileSystem();
899 return(ReturnedStatus);
903 /*************************************************************************
905 * Function: UDFFastIoAcqModWrite()
908 * Not really a fast-io operation. Used by the VMM to acquire FSD resources
909 * before initiating a write operation via the Modified Page/Block Writer.
911 * Expected Interrupt Level (for execution) :
915 * Return Value: STATUS_SUCCESS/Error (__try not to return an error, will 'ya ? :-)
917 *************************************************************************/
920 UDFFastIoAcqModWrite(
921 IN PFILE_OBJECT FileObject
,
922 IN PLARGE_INTEGER EndingOffset
,
923 OUT PERESOURCE
*ResourceToRelease
,
924 IN PDEVICE_OBJECT DeviceObject
)
926 NTSTATUS RC
= STATUS_SUCCESS
;
928 FsRtlEnterFileSystem();
930 MmPrint((" AcqModW %I64x\n", EndingOffset
->QuadPart
));
932 #define NtReqFcb ((PtrUDFNTRequiredFCB)(FileObject->FsContext))
934 // We must determine which resource(s) we would like to
935 // acquire at this time. We know that a write is imminent;
936 // we will probably therefore acquire appropriate resources
939 // We must first get the FCB and CCB pointers from the file object
940 // that is passed in to this function (as an argument). Note that
941 // the ending offset (when examined in conjunction with current valid data
942 // length) may help us in determining the appropriate resource(s) to acquire.
944 // For example, if the ending offset is beyond current valid data length,
945 // We may decide to acquire *both* the MainResource and the PagingIoResource
946 // exclusively; otherwise, we may decide simply to acquire the PagingIoResource.
948 // Consult the text for more information on synchronization in FSDs.
950 // One final note; the VMM expects that we will return a pointer to
951 // the resource that we acquired (single return value). This pointer
952 // will be returned back to we in the release call (below).
954 if(UDFAcquireResourceShared(&(NtReqFcb
->PagingIoResource
), FALSE
)) {
955 if(EndingOffset
->QuadPart
<= NtReqFcb
->CommonFCBHeader
.ValidDataLength
.QuadPart
) {
956 UDFReleaseResource(&(NtReqFcb
->PagingIoResource
));
957 RC
= STATUS_CANT_WAIT
;
959 NtReqFcb
->AcqFlushCount
++;
960 (*ResourceToRelease
) = &(NtReqFcb
->PagingIoResource
);
961 MmPrint((" AcqModW OK\n"));
964 RC
= STATUS_CANT_WAIT
;
969 FsRtlExitFileSystem();
972 } // end UDFFastIoAcqModWrite()
975 /*************************************************************************
977 * Function: UDFFastIoRelModWrite()
980 * Not really a fast-io operation. Used by the VMM to release FSD resources
981 * after processing a modified page/block write operation.
983 * Expected Interrupt Level (for execution) :
987 * Return Value: STATUS_SUCCESS/Error (an error returned here is really not expected!)
989 *************************************************************************/
992 UDFFastIoRelModWrite(
993 IN PFILE_OBJECT FileObject
,
994 IN PERESOURCE ResourceToRelease
,
995 IN PDEVICE_OBJECT DeviceObject
)
997 FsRtlEnterFileSystem();
999 MmPrint((" RelModW\n"));
1001 #define NtReqFcb ((PtrUDFNTRequiredFCB)(FileObject->FsContext))
1003 // The MPW has complete the write for modified pages and therefore
1004 // wants us to release pre-acquired resource(s).
1006 // We must undo here whatever it is that we did in the
1007 // UDFFastIoAcqModWrite() call above.
1009 NtReqFcb
->AcqFlushCount
--;
1010 ASSERT(ResourceToRelease
== &(NtReqFcb
->PagingIoResource
));
1011 UDFReleaseResource(ResourceToRelease
);
1015 FsRtlExitFileSystem();
1017 return(STATUS_SUCCESS
);
1018 } // end UDFFastIoRelModWrite()
1021 /*************************************************************************
1023 * Function: UDFFastIoAcqCcFlush()
1026 * Not really a fast-io operation. Used by the NT Cache Mgr to acquire FSD
1027 * resources before performing a CcFlush() operation on a specific file
1030 * Expected Interrupt Level (for execution) :
1032 * IRQL_PASSIVE_LEVEL
1034 * Return Value: STATUS_SUCCESS/Error
1036 *************************************************************************/
1039 UDFFastIoAcqCcFlush(
1040 IN PFILE_OBJECT FileObject
,
1041 IN PDEVICE_OBJECT DeviceObject
)
1043 // NTSTATUS RC = STATUS_SUCCESS;
1045 FsRtlEnterFileSystem();
1047 MmPrint((" AcqCcFlush\n"));
1049 // Acquire appropriate resources that will allow correct synchronization
1050 // with a flush call (and avoid deadlock).
1052 #define NtReqFcb ((PtrUDFNTRequiredFCB)(FileObject->FsContext))
1054 // UDFAcquireResourceExclusive(&(NtReqFcb->MainResource), TRUE);
1055 UDFAcquireResourceExclusive(&(NtReqFcb
->PagingIoResource
), TRUE
);
1056 // ASSERT(!(NtReqFcb->AcqFlushCount));
1057 NtReqFcb
->AcqFlushCount
++;
1061 FsRtlExitFileSystem();
1063 return(STATUS_SUCCESS
);
1065 } // end UDFFastIoAcqCcFlush()
1067 /*************************************************************************
1069 * Function: UDFFastIoRelCcFlush()
1072 * Not really a fast-io operation. Used by the NT Cache Mgr to acquire FSD
1073 * resources before performing a CcFlush() operation on a specific file
1076 * Expected Interrupt Level (for execution) :
1078 * IRQL_PASSIVE_LEVEL
1080 * Return Value: STATUS_SUCCESS/Error
1082 *************************************************************************/
1085 UDFFastIoRelCcFlush(
1086 IN PFILE_OBJECT FileObject
,
1087 IN PDEVICE_OBJECT DeviceObject
1090 // NTSTATUS RC = STATUS_SUCCESS;
1092 FsRtlEnterFileSystem();
1094 MmPrint((" RelCcFlush\n"));
1096 #define NtReqFcb ((PtrUDFNTRequiredFCB)(FileObject->FsContext))
1098 // Release resources acquired in UDFFastIoAcqCcFlush() above.
1100 NtReqFcb
->AcqFlushCount
--;
1101 UDFReleaseResource(&(NtReqFcb
->PagingIoResource
));
1102 // UDFReleaseResource(&(NtReqFcb->MainResource));
1106 FsRtlExitFileSystem();
1108 return(STATUS_SUCCESS
);
1110 } // end UDFFastIoRelCcFlush()
1114 UDFFastIoDeviceControl (
1115 IN PFILE_OBJECT FileObject,
1117 IN PVOID InputBuffer OPTIONAL,
1118 IN ULONG InputBufferLength,
1119 OUT PVOID OutputBuffer OPTIONAL,
1120 IN ULONG OutputBufferLength,
1121 IN ULONG IoControlCode,
1122 OUT PIO_STATUS_BLOCK IoStatus,
1123 IN PDEVICE_OBJECT DeviceObject
1126 switch(IoControlCode) {
1127 case FSCTL_ALLOW_EXTENDED_DASD_IO: {
1128 IoStatus->Information = 0;
1129 IoStatus->Status = STATUS_SUCCESS;
1132 case FSCTL_IS_VOLUME_MOUNTED: {
1136 Ccb = (PtrUDFCCB)(FileObject->FsContext2);
1140 !(Fcb->Vcb->VCBFlags & UDF_VCB_FLAGS_RAW_DISK) &&
1141 !(Fcb->Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_LOCKED) ) {
1145 IoStatus->Information = 0;
1146 IoStatus->Status = STATUS_SUCCESS;
1156 #endif //_WIN32_WINNT >= 0x0400
1160 UDFFastIoCopyWrite (
1161 IN PFILE_OBJECT FileObject
,
1162 IN PLARGE_INTEGER FileOffset
,
1167 OUT PIO_STATUS_BLOCK IoStatus
,
1168 IN PDEVICE_OBJECT DeviceObject
1171 PtrUDFFCB Fcb
= NULL
;
1172 PtrUDFCCB Ccb
= NULL
;
1174 // Obtain a pointer to the FCB and CCB for the file stream.
1175 Ccb
= (PtrUDFCCB
)(FileObject
->FsContext2
);
1180 // back pressure for very smart and fast system cache ;)
1181 if(Fcb
->Vcb
->VerifyCtx
.QueuedCount
||
1182 Fcb
->Vcb
->VerifyCtx
.ItemCount
>= UDF_MAX_VERIFY_CACHE
) {
1183 AdPrint((" Verify queue overflow -> UDFFastIoCopyWrite() = FALSE\n"));
1186 if(Fcb
->NTRequiredFCB
->SectionObject
.DataSectionObject
&&
1187 Length
>= 0x10000 &&
1188 FileOffset
->LowPart
&&
1189 !(FileOffset
->LowPart
& 0x00ffffff)) {
1191 MmPrint((" no FastIo 16Mb\n"));
1194 return FsRtlCopyWrite(FileObject
, FileOffset
, Length
, Wait
, LockKey
, Buffer
, IoStatus
, DeviceObject
);
1196 } // end UDFFastIoCopyWrite()