Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

mdlsup.c File Reference

#include "cc.h"

Go to the source code of this file.

Defines

#define me   (0x00000010)

Functions

VOID CcMdlRead (IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, OUT PMDL *MdlChain, OUT PIO_STATUS_BLOCK IoStatus)
VOID CcMdlReadComplete (IN PFILE_OBJECT FileObject, IN PMDL MdlChain)
VOID CcMdlReadComplete2 (IN PFILE_OBJECT FileObject, IN PMDL MdlChain)
VOID CcPrepareMdlWrite (IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, OUT PMDL *MdlChain, OUT PIO_STATUS_BLOCK IoStatus)
VOID CcMdlWriteComplete (IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN PMDL MdlChain)
VOID CcMdlWriteComplete2 (IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN PMDL MdlChain)


Define Documentation

#define me   (0x00000010)
 

Definition at line 27 of file mdlsup.c.


Function Documentation

VOID CcMdlRead IN PFILE_OBJECT  FileObject,
IN PLARGE_INTEGER  FileOffset,
IN ULONG  Length,
OUT PMDL MdlChain,
OUT PIO_STATUS_BLOCK  IoStatus
 

Definition at line 30 of file mdlsup.c.

References ASSERT, _PRIVATE_CACHE_MAP::BeyondLastByte1, _PRIVATE_CACHE_MAP::BeyondLastByte2, CcFreeActiveVacb(), CcFreeVirtualAddress(), CcGetVirtualAddress(), CcMdlReadWait, CcMdlReadWaitMiss, CcMissCounter, CcScheduleReadAhead(), CcThrowAway, COMPUTE_PAGES_SPANNED, DebugTrace, DebugTrace2, ExRaiseStatus(), FALSE, _PRIVATE_CACHE_MAP::FileOffset1, _PRIVATE_CACHE_MAP::FileOffset2, _SHARED_CACHE_MAP::FileSize, FlagOn, FO_RANDOM_ACCESS, GetActiveVacb, IoAllocateMdl(), IoFreeMdl(), IoReadAccess, KernelMode, me, mm, MmProbeAndLockPages(), MmResetPageFaultReadAhead, MmSavePageFaultReadAhead, MmSetPageFaultReadAhead, MmUnlockPages(), _SHARED_CACHE_MAP::NeedToZero, _MDL::Next, NULL, PsGetCurrentThread, _PRIVATE_CACHE_MAP::ReadAheadEnabled, _PRIVATE_CACHE_MAP::ReadAheadLength, and TRUE.

Referenced by FsRtlMdlReadDev(), and UdfCommonRead().

00040 : 00041 00042 This routine attempts to lock the specified file data in the cache 00043 and return a description of it in an Mdl along with the correct 00044 I/O status. It is *not* safe to call this routine from Dpc level. 00045 00046 This routine is synchronous, and raises on errors. 00047 00048 As each call returns, the pages described by the Mdl are 00049 locked in memory, but not mapped in system space. If the caller 00050 needs the pages mapped in system space, then it must map them. 00051 00052 Note that each call is a "single shot" which should be followed by 00053 a call to CcMdlReadComplete. To resume an Mdl-based transfer, the 00054 caller must form one or more subsequent calls to CcMdlRead with 00055 appropriately adjusted parameters. 00056 00057 Arguments: 00058 00059 FileObject - Pointer to the file object for a file which was 00060 opened with NO_INTERMEDIATE_BUFFERING clear, i.e., for 00061 which CcInitializeCacheMap was called by the file system. 00062 00063 FileOffset - Byte offset in file for desired data. 00064 00065 Length - Length of desired data in bytes. 00066 00067 MdlChain - On output it returns a pointer to an Mdl chain describing 00068 the desired data. Note that even if FALSE is returned, 00069 one or more Mdls may have been allocated, as may be ascertained 00070 by the IoStatus.Information field (see below). 00071 00072 IoStatus - Pointer to standard I/O status block to receive the status 00073 for the transfer. (STATUS_SUCCESS guaranteed for cache 00074 hits, otherwise the actual I/O status is returned.) The 00075 I/O Information Field indicates how many bytes have been 00076 successfully locked down in the Mdl Chain. 00077 00078 Return Value: 00079 00080 None 00081 00082 Raises: 00083 00084 STATUS_INSUFFICIENT_RESOURCES - If a pool allocation failure occurs. 00085 00086 --*/ 00087 00088 { 00089 PSHARED_CACHE_MAP SharedCacheMap; 00090 PPRIVATE_CACHE_MAP PrivateCacheMap; 00091 PVOID CacheBuffer; 00092 LARGE_INTEGER FOffset; 00093 PMDL Mdl = NULL; 00094 PMDL MdlTemp; 00095 PETHREAD Thread = PsGetCurrentThread(); 00096 ULONG SavedState = 0; 00097 ULONG OriginalLength = Length; 00098 ULONG Information = 0; 00099 PVACB Vacb = NULL; 00100 ULONG SavedMissCounter = 0; 00101 00102 KIRQL OldIrql; 00103 ULONG ActivePage; 00104 ULONG PageIsDirty; 00105 PVACB ActiveVacb = NULL; 00106 00107 DebugTrace(+1, me, "CcMdlRead\n", 0 ); 00108 DebugTrace( 0, me, " FileObject = %08lx\n", FileObject ); 00109 DebugTrace2(0, me, " FileOffset = %08lx, %08lx\n", FileOffset->LowPart, 00110 FileOffset->HighPart ); 00111 DebugTrace( 0, me, " Length = %08lx\n", Length ); 00112 00113 // 00114 // Save the current readahead hints. 00115 // 00116 00117 MmSavePageFaultReadAhead( Thread, &SavedState ); 00118 00119 // 00120 // Get pointer to SharedCacheMap. 00121 // 00122 00123 SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap; 00124 PrivateCacheMap = FileObject->PrivateCacheMap; 00125 00126 // 00127 // See if we have an active Vacb, that we need to free. 00128 // 00129 00130 GetActiveVacb( SharedCacheMap, OldIrql, ActiveVacb, ActivePage, PageIsDirty ); 00131 00132 // 00133 // If there is an end of a page to be zeroed, then free that page now, 00134 // so we don't send Greg the uninitialized data... 00135 // 00136 00137 if ((ActiveVacb != NULL) || (SharedCacheMap->NeedToZero != NULL)) { 00138 00139 CcFreeActiveVacb( SharedCacheMap, ActiveVacb, ActivePage, PageIsDirty ); 00140 } 00141 00142 // 00143 // If read ahead is enabled, then do the read ahead here so it 00144 // overlaps with the copy (otherwise we will do it below). 00145 // Note that we are assuming that we will not get ahead of our 00146 // current transfer - if read ahead is working it should either 00147 // already be in memory or else underway. 00148 // 00149 00150 if (PrivateCacheMap->ReadAheadEnabled && (PrivateCacheMap->ReadAheadLength[1] == 0)) { 00151 CcScheduleReadAhead( FileObject, FileOffset, Length ); 00152 } 00153 00154 // 00155 // Increment performance counters 00156 // 00157 00158 CcMdlReadWait += 1; 00159 00160 // 00161 // This is not an exact solution, but when IoPageRead gets a miss, 00162 // it cannot tell whether it was CcCopyRead or CcMdlRead, but since 00163 // the miss should occur very soon, by loading the pointer here 00164 // probably the right counter will get incremented, and in any case, 00165 // we hope the errrors average out! 00166 // 00167 00168 CcMissCounter = &CcMdlReadWaitMiss; 00169 00170 FOffset = *FileOffset; 00171 00172 // 00173 // Check for read past file size, the caller must filter this case out. 00174 // 00175 00176 ASSERT( ( FOffset.QuadPart + (LONGLONG)Length ) <= SharedCacheMap->FileSize.QuadPart ); 00177 00178 // 00179 // Put try-finally around the loop to deal with any exceptions 00180 // 00181 00182 try { 00183 00184 // 00185 // Not all of the transfer will come back at once, so we have to loop 00186 // until the entire transfer is complete. 00187 // 00188 00189 while (Length != 0) { 00190 00191 ULONG ReceivedLength; 00192 LARGE_INTEGER BeyondLastByte; 00193 00194 // 00195 // Map the data and read it in (if necessary) with the 00196 // MmProbeAndLockPages call below. 00197 // 00198 00199 CacheBuffer = CcGetVirtualAddress( SharedCacheMap, 00200 FOffset, 00201 &Vacb, 00202 &ReceivedLength ); 00203 00204 if (ReceivedLength > Length) { 00205 ReceivedLength = Length; 00206 } 00207 00208 BeyondLastByte.QuadPart = FOffset.QuadPart + (LONGLONG)ReceivedLength; 00209 00210 // 00211 // Now attempt to allocate an Mdl to describe the mapped data. 00212 // 00213 00214 DebugTrace( 0, mm, "IoAllocateMdl:\n", 0 ); 00215 DebugTrace( 0, mm, " BaseAddress = %08lx\n", CacheBuffer ); 00216 DebugTrace( 0, mm, " Length = %08lx\n", ReceivedLength ); 00217 00218 Mdl = IoAllocateMdl( CacheBuffer, 00219 ReceivedLength, 00220 FALSE, 00221 FALSE, 00222 NULL ); 00223 00224 DebugTrace( 0, mm, " <Mdl = %08lx\n", Mdl ); 00225 00226 if (Mdl == NULL) { 00227 DebugTrace( 0, 0, "Failed to allocate Mdl\n", 0 ); 00228 00229 ExRaiseStatus( STATUS_INSUFFICIENT_RESOURCES ); 00230 } 00231 00232 DebugTrace( 0, mm, "MmProbeAndLockPages:\n", 0 ); 00233 DebugTrace( 0, mm, " Mdl = %08lx\n", Mdl ); 00234 00235 // 00236 // Set to see if the miss counter changes in order to 00237 // detect when we should turn on read ahead. 00238 // 00239 00240 SavedMissCounter += CcMdlReadWaitMiss; 00241 00242 MmSetPageFaultReadAhead( Thread, COMPUTE_PAGES_SPANNED( CacheBuffer, ReceivedLength ) - 1); 00243 MmProbeAndLockPages( Mdl, KernelMode, IoReadAccess ); 00244 00245 SavedMissCounter -= CcMdlReadWaitMiss; 00246 00247 // 00248 // Unmap the data now, now that the pages are locked down. 00249 // 00250 00251 CcFreeVirtualAddress( Vacb ); 00252 Vacb = NULL; 00253 00254 // 00255 // Now link the Mdl into the caller's chain 00256 // 00257 00258 if ( *MdlChain == NULL ) { 00259 *MdlChain = Mdl; 00260 } else { 00261 MdlTemp = CONTAINING_RECORD( *MdlChain, MDL, Next ); 00262 while (MdlTemp->Next != NULL) { 00263 MdlTemp = MdlTemp->Next; 00264 } 00265 MdlTemp->Next = Mdl; 00266 } 00267 Mdl = NULL; 00268 00269 // 00270 // Assume we did not get all the data we wanted, and set FOffset 00271 // to the end of the returned data. 00272 // 00273 00274 FOffset = BeyondLastByte; 00275 00276 // 00277 // Update number of bytes transferred. 00278 // 00279 00280 Information += ReceivedLength; 00281 00282 // 00283 // Calculate length left to transfer. 00284 // 00285 00286 Length -= ReceivedLength; 00287 } 00288 } 00289 finally { 00290 00291 CcMissCounter = &CcThrowAway; 00292 00293 // 00294 // Restore the readahead hints. 00295 // 00296 00297 MmResetPageFaultReadAhead( Thread, SavedState ); 00298 00299 if (AbnormalTermination()) { 00300 00301 // 00302 // We may have failed to allocate an Mdl while still having 00303 // data mapped. 00304 // 00305 00306 if (Vacb != NULL) { 00307 CcFreeVirtualAddress( Vacb ); 00308 } 00309 00310 if (Mdl != NULL) { 00311 IoFreeMdl( Mdl ); 00312 } 00313 00314 // 00315 // Otherwise loop to deallocate the Mdls 00316 // 00317 00318 while (*MdlChain != NULL) { 00319 MdlTemp = (*MdlChain)->Next; 00320 00321 DebugTrace( 0, mm, "MmUnlockPages/IoFreeMdl:\n", 0 ); 00322 DebugTrace( 0, mm, " Mdl = %08lx\n", *MdlChain ); 00323 00324 MmUnlockPages( *MdlChain ); 00325 IoFreeMdl( *MdlChain ); 00326 00327 *MdlChain = MdlTemp; 00328 } 00329 00330 DebugTrace(-1, me, "CcMdlRead -> Unwinding\n", 0 ); 00331 00332 } 00333 else { 00334 00335 // 00336 // Now enable read ahead if it looks like we got any misses, and do 00337 // the first one. 00338 // 00339 00340 if (!FlagOn( FileObject->Flags, FO_RANDOM_ACCESS ) && 00341 !PrivateCacheMap->ReadAheadEnabled && 00342 (SavedMissCounter != 0)) { 00343 00344 PrivateCacheMap->ReadAheadEnabled = TRUE; 00345 CcScheduleReadAhead( FileObject, FileOffset, OriginalLength ); 00346 } 00347 00348 // 00349 // Now that we have described our desired read ahead, let's 00350 // shift the read history down. 00351 // 00352 00353 PrivateCacheMap->FileOffset1 = PrivateCacheMap->FileOffset2; 00354 PrivateCacheMap->BeyondLastByte1 = PrivateCacheMap->BeyondLastByte2; 00355 PrivateCacheMap->FileOffset2 = *FileOffset; 00356 PrivateCacheMap->BeyondLastByte2.QuadPart = 00357 FileOffset->QuadPart + (LONGLONG)OriginalLength; 00358 00359 IoStatus->Status = STATUS_SUCCESS; 00360 IoStatus->Information = Information; 00361 } 00362 } 00363 00364 00365 DebugTrace( 0, me, " <MdlChain = %08lx\n", *MdlChain ); 00366 DebugTrace2(0, me, " <IoStatus = %08lx, %08lx\n", IoStatus->Status, 00367 IoStatus->Information ); 00368 DebugTrace(-1, me, "CcMdlRead -> VOID\n", 0 ); 00369 00370 return; 00371 }

VOID CcMdlReadComplete IN PFILE_OBJECT  FileObject,
IN PMDL  MdlChain
 

Definition at line 381 of file mdlsup.c.

References CcMdlReadComplete2(), _DEVICE_OBJECT::DriverObject, _DRIVER_OBJECT::FastIoDispatch, IoGetRelatedDeviceObject(), _FAST_IO_DISPATCH::MdlReadComplete, NULL, and _FAST_IO_DISPATCH::SizeOfFastIoDispatch.

Referenced by UdfCompleteMdl().

00386 { 00387 PDEVICE_OBJECT DeviceObject; 00388 PFAST_IO_DISPATCH FastIoDispatch; 00389 00390 DeviceObject = IoGetRelatedDeviceObject( FileObject ); 00391 FastIoDispatch = DeviceObject->DriverObject->FastIoDispatch; 00392 00393 if ((FastIoDispatch != NULL) && 00394 (FastIoDispatch->SizeOfFastIoDispatch > FIELD_OFFSET(FAST_IO_DISPATCH, MdlWriteComplete)) && 00395 (FastIoDispatch->MdlReadComplete != NULL) && 00396 FastIoDispatch->MdlReadComplete( FileObject, MdlChain, DeviceObject )) { 00397 00398 NOTHING; 00399 00400 } else { 00401 CcMdlReadComplete2( FileObject, MdlChain ); 00402 } 00403 }

VOID CcMdlReadComplete2 IN PFILE_OBJECT  FileObject,
IN PMDL  MdlChain
 

Definition at line 406 of file mdlsup.c.

References DebugTrace, IoFreeMdl(), me, mm, MmUnlockPages(), _MDL::Next, and NULL.

Referenced by CcMdlReadComplete(), and FsRtlMdlReadCompleteDev().

00413 : 00414 00415 This routine must be called at IPL0 after a call to CcMdlRead. The 00416 caller must simply supply the address of the MdlChain returned in 00417 CcMdlRead. 00418 00419 This call does the following: 00420 00421 Deletes the MdlChain 00422 00423 Arguments: 00424 00425 FileObject - Pointer to the file object for a file which was 00426 opened with NO_INTERMEDIATE_BUFFERING clear, i.e., for 00427 which CcInitializeCacheMap was called by the file system. 00428 00429 MdlChain - same as returned from corresponding call to CcMdlRead. 00430 00431 Return Value: 00432 00433 None. 00434 --*/ 00435 00436 { 00437 PMDL MdlNext; 00438 00439 DebugTrace(+1, me, "CcMdlReadComplete\n", 0 ); 00440 DebugTrace( 0, me, " FileObject = %08lx\n", FileObject ); 00441 DebugTrace( 0, me, " MdlChain = %08lx\n", MdlChain ); 00442 00443 // 00444 // Deallocate the Mdls 00445 // 00446 00447 while (MdlChain != NULL) { 00448 00449 MdlNext = MdlChain->Next; 00450 00451 DebugTrace( 0, mm, "MmUnlockPages/IoFreeMdl:\n", 0 ); 00452 DebugTrace( 0, mm, " Mdl = %08lx\n", MdlChain ); 00453 00454 MmUnlockPages( MdlChain ); 00455 00456 IoFreeMdl( MdlChain ); 00457 00458 MdlChain = MdlNext; 00459 } 00460 00461 DebugTrace(-1, me, "CcMdlReadComplete -> VOID\n", 0 ); 00462 }

VOID CcMdlWriteComplete IN PFILE_OBJECT  FileObject,
IN PLARGE_INTEGER  FileOffset,
IN PMDL  MdlChain
 

Definition at line 812 of file mdlsup.c.

References CcMdlWriteComplete2(), _DEVICE_OBJECT::DriverObject, _DRIVER_OBJECT::FastIoDispatch, IoGetRelatedDeviceObject(), _FAST_IO_DISPATCH::MdlWriteComplete, NULL, and _FAST_IO_DISPATCH::SizeOfFastIoDispatch.

00818 { 00819 PDEVICE_OBJECT DeviceObject; 00820 PFAST_IO_DISPATCH FastIoDispatch; 00821 00822 DeviceObject = IoGetRelatedDeviceObject( FileObject ); 00823 FastIoDispatch = DeviceObject->DriverObject->FastIoDispatch; 00824 00825 if ((FastIoDispatch != NULL) && 00826 (FastIoDispatch->SizeOfFastIoDispatch > FIELD_OFFSET(FAST_IO_DISPATCH, MdlWriteComplete)) && 00827 (FastIoDispatch->MdlWriteComplete != NULL) && 00828 FastIoDispatch->MdlWriteComplete( FileObject, FileOffset, MdlChain, DeviceObject )) { 00829 00830 NOTHING; 00831 00832 } else { 00833 CcMdlWriteComplete2( FileObject, FileOffset, MdlChain ); 00834 } 00835 }

VOID CcMdlWriteComplete2 IN PFILE_OBJECT  FileObject,
IN PLARGE_INTEGER  FileOffset,
IN PMDL  MdlChain
 

Definition at line 838 of file mdlsup.c.

References CcAcquireMasterLock, CcDecrementOpenCount, CcDirtySharedCacheMapList, CcReleaseMasterLock, CcScheduleLazyWriteScan(), CcSetDirtyInMask(), DebugTrace, _SHARED_CACHE_MAP::DirtyPages, FlagOn, _SHARED_CACHE_MAP::Flags, FO_WRITE_THROUGH, FsRtlNormalizeNtstatus(), IoFreeMdl(), LazyWriter, me, mm, MmFlushSection(), MmUnlockPages(), _MDL::Next, NT_SUCCESS, NTSTATUS(), NULL, _SHARED_CACHE_MAP::OpenCount, _LAZY_WRITER::OtherWork, _LAZY_WRITER::ScanActive, _SHARED_CACHE_MAP::SharedCacheMapLinks, _SHARED_CACHE_MAP_LIST_CURSOR::SharedCacheMapLinks, TRUE, and WRITE_QUEUED.

Referenced by CcMdlWriteComplete(), and FsRtlMdlWriteCompleteDev().

00846 : 00847 00848 This routine must be called at IPL0 after a call to CcPrepareMdlWrite. 00849 The caller supplies the ActualLength of data that it actually wrote 00850 into the buffer, which may be less than or equal to the Length specified 00851 in CcPrepareMdlWrite. 00852 00853 This call does the following: 00854 00855 Makes sure the data up to ActualLength eventually gets written. 00856 If WriteThrough is FALSE, the data will not be written immediately. 00857 If WriteThrough is TRUE, then the data is written synchronously. 00858 00859 Unmaps the pages (if mapped), unlocks them and deletes the MdlChain 00860 00861 Arguments: 00862 00863 FileObject - Pointer to the file object for a file which was 00864 opened with NO_INTERMEDIATE_BUFFERING clear, i.e., for 00865 which CcInitializeCacheMap was called by the file system. 00866 00867 FileOffset - Original file offset read above. 00868 00869 MdlChain - same as returned from corresponding call to CcPrepareMdlWrite. 00870 00871 Return Value: 00872 00873 None 00874 00875 --*/ 00876 00877 { 00878 PMDL MdlNext; 00879 PSHARED_CACHE_MAP SharedCacheMap; 00880 LARGE_INTEGER FOffset; 00881 IO_STATUS_BLOCK IoStatus; 00882 KIRQL OldIrql; 00883 NTSTATUS StatusToRaise = STATUS_SUCCESS; 00884 00885 DebugTrace(+1, me, "CcMdlWriteComplete\n", 0 ); 00886 DebugTrace( 0, me, " FileObject = %08lx\n", FileObject ); 00887 DebugTrace( 0, me, " MdlChain = %08lx\n", MdlChain ); 00888 00889 SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap; 00890 00891 // 00892 // Deallocate the Mdls 00893 // 00894 00895 FOffset.QuadPart = *(LONGLONG UNALIGNED *)FileOffset; 00896 while (MdlChain != NULL) { 00897 00898 MdlNext = MdlChain->Next; 00899 00900 DebugTrace( 0, mm, "MmUnlockPages/IoFreeMdl:\n", 0 ); 00901 DebugTrace( 0, mm, " Mdl = %08lx\n", MdlChain ); 00902 00903 // 00904 // Now clear the dirty bits in the Pte and set them in the 00905 // Pfn. 00906 // 00907 00908 MmUnlockPages( MdlChain ); 00909 00910 // 00911 // Extract the File Offset for this part of the transfer. 00912 // 00913 00914 if (FlagOn(FileObject->Flags, FO_WRITE_THROUGH)) { 00915 00916 MmFlushSection ( FileObject->SectionObjectPointer, 00917 &FOffset, 00918 MdlChain->ByteCount, 00919 &IoStatus, 00920 TRUE ); 00921 00922 // 00923 // If we got an I/O error, remember it. 00924 // 00925 00926 if (!NT_SUCCESS(IoStatus.Status)) { 00927 StatusToRaise = IoStatus.Status; 00928 } 00929 00930 } else { 00931 00932 // 00933 // Ignore the only exception (allocation error), and console 00934 // ourselves for having tried. 00935 // 00936 00937 CcSetDirtyInMask( SharedCacheMap, &FOffset, MdlChain->ByteCount ); 00938 } 00939 00940 FOffset.QuadPart = FOffset.QuadPart + (LONGLONG)(MdlChain->ByteCount); 00941 00942 IoFreeMdl( MdlChain ); 00943 00944 MdlChain = MdlNext; 00945 } 00946 00947 // 00948 // Now release our open count. 00949 // 00950 00951 CcAcquireMasterLock( &OldIrql ); 00952 00953 CcDecrementOpenCount( SharedCacheMap, 'ldmC' ); 00954 00955 if ((SharedCacheMap->OpenCount == 0) && 00956 !FlagOn(SharedCacheMap->Flags, WRITE_QUEUED) && 00957 (SharedCacheMap->DirtyPages == 0)) { 00958 00959 // 00960 // Move to the dirty list. 00961 // 00962 00963 RemoveEntryList( &SharedCacheMap->SharedCacheMapLinks ); 00964 InsertTailList( &CcDirtySharedCacheMapList.SharedCacheMapLinks, 00965 &SharedCacheMap->SharedCacheMapLinks ); 00966 00967 // 00968 // Make sure the Lazy Writer will wake up, because we 00969 // want him to delete this SharedCacheMap. 00970 // 00971 00972 LazyWriter.OtherWork = TRUE; 00973 if (!LazyWriter.ScanActive) { 00974 CcScheduleLazyWriteScan(); 00975 } 00976 } 00977 00978 CcReleaseMasterLock( OldIrql ); 00979 00980 // 00981 // If we got an I/O error, raise it now. 00982 // 00983 00984 if (!NT_SUCCESS(StatusToRaise)) { 00985 FsRtlNormalizeNtstatus( StatusToRaise, 00986 STATUS_UNEXPECTED_IO_ERROR ); 00987 } 00988 00989 DebugTrace(-1, me, "CcMdlWriteComplete -> TRUE\n", 0 ); 00990 00991 return; 00992 }

VOID CcPrepareMdlWrite IN PFILE_OBJECT  FileObject,
IN PLARGE_INTEGER  FileOffset,
IN ULONG  Length,
OUT PMDL MdlChain,
OUT PIO_STATUS_BLOCK  IoStatus
 

Definition at line 466 of file mdlsup.c.

References _SHARED_CACHE_MAP::BcbSpinLock, CcAcquireMasterLock, CcFreeActiveVacb(), CcFreeVirtualAddress(), CcGetVirtualAddress(), CcIncrementOpenCount, CcMapAndRead(), CcReleaseMasterLock, CcSetDirtyInMask(), DebugTrace, DebugTrace2, ExRaiseStatus(), FALSE, GetActiveVacb, IoAllocateMdl(), IoFreeMdl(), IoWriteAccess, KernelMode, me, mm, MmDisablePageFaultClustering, MmEnablePageFaultClustering, MmProbeAndLockPages(), MmUnlockPages(), _SHARED_CACHE_MAP::NeedToZero, _MDL::Next, NULL, PAGE_SIZE, TRUE, _SHARED_CACHE_MAP::ValidDataGoal, VOID(), ZERO_FIRST_PAGE, ZERO_LAST_PAGE, and ZERO_MIDDLE_PAGES.

Referenced by FsRtlPrepareMdlWriteDev().

00476 : 00477 00478 This routine attempts to lock the specified file data in the cache 00479 and return a description of it in an Mdl along with the correct 00480 I/O status. Pages to be completely overwritten may be satisfied 00481 with emtpy pages. It is *not* safe to call this routine from Dpc level. 00482 00483 This call is synchronous and raises on error. 00484 00485 When this call returns, the caller may immediately begin 00486 to transfer data into the buffers via the Mdl. 00487 00488 When the call returns with TRUE, the pages described by the Mdl are 00489 locked in memory, but not mapped in system space. If the caller 00490 needs the pages mapped in system space, then it must map them. 00491 On the subsequent call to CcMdlWriteComplete the pages will be 00492 unmapped if they were mapped, and in any case unlocked and the Mdl 00493 deallocated. 00494 00495 Arguments: 00496 00497 FileObject - Pointer to the file object for a file which was 00498 opened with NO_INTERMEDIATE_BUFFERING clear, i.e., for 00499 which CcInitializeCacheMap was called by the file system. 00500 00501 FileOffset - Byte offset in file for desired data. 00502 00503 Length - Length of desired data in bytes. 00504 00505 MdlChain - On output it returns a pointer to an Mdl chain describing 00506 the desired data. Note that even if FALSE is returned, 00507 one or more Mdls may have been allocated, as may be ascertained 00508 by the IoStatus.Information field (see below). 00509 00510 IoStatus - Pointer to standard I/O status block to receive the status 00511 for the in-transfer of the data. (STATUS_SUCCESS guaranteed 00512 for cache hits, otherwise the actual I/O status is returned.) 00513 The I/O Information Field indicates how many bytes have been 00514 successfully locked down in the Mdl Chain. 00515 00516 Return Value: 00517 00518 None 00519 00520 --*/ 00521 00522 { 00523 PSHARED_CACHE_MAP SharedCacheMap; 00524 PVOID CacheBuffer; 00525 LARGE_INTEGER FOffset; 00526 PMDL Mdl = NULL; 00527 PMDL MdlTemp; 00528 LARGE_INTEGER Temp; 00529 ULONG SavedState = 0; 00530 ULONG ZeroFlags = 0; 00531 ULONG Information = 0; 00532 00533 KIRQL OldIrql; 00534 ULONG ActivePage; 00535 ULONG PageIsDirty; 00536 PVACB Vacb = NULL; 00537 00538 DebugTrace(+1, me, "CcPrepareMdlWrite\n", 0 ); 00539 DebugTrace( 0, me, " FileObject = %08lx\n", FileObject ); 00540 DebugTrace2(0, me, " FileOffset = %08lx, %08lx\n", FileOffset->LowPart, 00541 FileOffset->HighPart ); 00542 DebugTrace( 0, me, " Length = %08lx\n", Length ); 00543 00544 // 00545 // Get pointer to SharedCacheMap. 00546 // 00547 00548 SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap; 00549 00550 // 00551 // See if we have an active Vacb, that we need to free. 00552 // 00553 00554 GetActiveVacb( SharedCacheMap, OldIrql, Vacb, ActivePage, PageIsDirty ); 00555 00556 // 00557 // If there is an end of a page to be zeroed, then free that page now, 00558 // so it does not cause our data to get zeroed. If there is an active 00559 // page, free it so we have the correct ValidDataGoal. 00560 // 00561 00562 if ((Vacb != NULL) || (SharedCacheMap->NeedToZero != NULL)) { 00563 00564 CcFreeActiveVacb( SharedCacheMap, Vacb, ActivePage, PageIsDirty ); 00565 Vacb = NULL; 00566 } 00567 00568 FOffset = *FileOffset; 00569 00570 // 00571 // Put try-finally around the loop to deal with exceptions 00572 // 00573 00574 try { 00575 00576 // 00577 // Not all of the transfer will come back at once, so we have to loop 00578 // until the entire transfer is complete. 00579 // 00580 00581 while (Length != 0) { 00582 00583 ULONG ReceivedLength; 00584 LARGE_INTEGER BeyondLastByte; 00585 00586 // 00587 // Map and see how much we could potentially access at this 00588 // FileOffset, then cut it down if it is more than we need. 00589 // 00590 00591 CacheBuffer = CcGetVirtualAddress( SharedCacheMap, 00592 FOffset, 00593 &Vacb, 00594 &ReceivedLength ); 00595 00596 if (ReceivedLength > Length) { 00597 ReceivedLength = Length; 00598 } 00599 00600 BeyondLastByte.QuadPart = FOffset.QuadPart + (LONGLONG)ReceivedLength; 00601 00602 // 00603 // At this point we can calculate the ZeroFlags. 00604 // 00605 00606 // 00607 // We can always zero middle pages, if any. 00608 // 00609 00610 ZeroFlags = ZERO_MIDDLE_PAGES; 00611 00612 // 00613 // See if we are completely overwriting the first or last page. 00614 // 00615 00616 if (((FOffset.LowPart & (PAGE_SIZE - 1)) == 0) && 00617 (ReceivedLength >= PAGE_SIZE)) { 00618 ZeroFlags |= ZERO_FIRST_PAGE; 00619 } 00620 00621 if ((BeyondLastByte.LowPart & (PAGE_SIZE - 1)) == 0) { 00622 ZeroFlags |= ZERO_LAST_PAGE; 00623 } 00624 00625 // 00626 // See if the entire transfer is beyond valid data length, 00627 // or at least starting from the second page. 00628 // 00629 00630 Temp = FOffset; 00631 Temp.LowPart &= ~(PAGE_SIZE -1); 00632 ExAcquireFastLock( &SharedCacheMap->BcbSpinLock, &OldIrql ); 00633 Temp.QuadPart = SharedCacheMap->ValidDataGoal.QuadPart - Temp.QuadPart; 00634 ExReleaseFastLock( &SharedCacheMap->BcbSpinLock, OldIrql ); 00635 00636 if (Temp.QuadPart <= 0) { 00637 ZeroFlags |= ZERO_FIRST_PAGE | ZERO_MIDDLE_PAGES | ZERO_LAST_PAGE; 00638 } else if ((Temp.HighPart == 0) && (Temp.LowPart <= PAGE_SIZE)) { 00639 ZeroFlags |= ZERO_MIDDLE_PAGES | ZERO_LAST_PAGE; 00640 } 00641 00642 (VOID)CcMapAndRead( SharedCacheMap, 00643 &FOffset, 00644 ReceivedLength, 00645 ZeroFlags, 00646 TRUE, 00647 CacheBuffer ); 00648 00649 // 00650 // Now attempt to allocate an Mdl to describe the mapped data. 00651 // 00652 00653 DebugTrace( 0, mm, "IoAllocateMdl:\n", 0 ); 00654 DebugTrace( 0, mm, " BaseAddress = %08lx\n", CacheBuffer ); 00655 DebugTrace( 0, mm, " Length = %08lx\n", ReceivedLength ); 00656 00657 Mdl = IoAllocateMdl( CacheBuffer, 00658 ReceivedLength, 00659 FALSE, 00660 FALSE, 00661 NULL ); 00662 00663 DebugTrace( 0, mm, " <Mdl = %08lx\n", Mdl ); 00664 00665 if (Mdl == NULL) { 00666 DebugTrace( 0, 0, "Failed to allocate Mdl\n", 0 ); 00667 00668 ExRaiseStatus( STATUS_INSUFFICIENT_RESOURCES ); 00669 } 00670 00671 DebugTrace( 0, mm, "MmProbeAndLockPages:\n", 0 ); 00672 DebugTrace( 0, mm, " Mdl = %08lx\n", Mdl ); 00673 00674 MmDisablePageFaultClustering(&SavedState); 00675 MmProbeAndLockPages( Mdl, KernelMode, IoWriteAccess ); 00676 MmEnablePageFaultClustering(SavedState); 00677 SavedState = 0; 00678 00679 // 00680 // Now that some data (maybe zeros) is locked in memory and 00681 // set dirty, it is safe, and necessary for us to advance 00682 // valid data goal, so that we will not subsequently ask 00683 // for a zero page. Note if we are extending valid data, 00684 // our caller has the file exclusive. 00685 // 00686 00687 ExAcquireFastLock( &SharedCacheMap->BcbSpinLock, &OldIrql ); 00688 if (BeyondLastByte.QuadPart > SharedCacheMap->ValidDataGoal.QuadPart) { 00689 SharedCacheMap->ValidDataGoal = BeyondLastByte; 00690 } 00691 ExReleaseFastLock( &SharedCacheMap->BcbSpinLock, OldIrql ); 00692 00693 // 00694 // Unmap the data now, now that the pages are locked down. 00695 // 00696 00697 CcFreeVirtualAddress( Vacb ); 00698 Vacb = NULL; 00699 00700 // 00701 // Now link the Mdl into the caller's chain 00702 // 00703 00704 if ( *MdlChain == NULL ) { 00705 *MdlChain = Mdl; 00706 } else { 00707 MdlTemp = CONTAINING_RECORD( *MdlChain, MDL, Next ); 00708 while (MdlTemp->Next != NULL) { 00709 MdlTemp = MdlTemp->Next; 00710 } 00711 MdlTemp->Next = Mdl; 00712 } 00713 Mdl = NULL; 00714 00715 // 00716 // Assume we did not get all the data we wanted, and set FOffset 00717 // to the end of the returned data. 00718 // 00719 00720 FOffset = BeyondLastByte; 00721 00722 // 00723 // Update number of bytes transferred. 00724 // 00725 00726 Information += ReceivedLength; 00727 00728 // 00729 // Calculate length left to transfer. 00730 // 00731 00732 Length -= ReceivedLength; 00733 } 00734 } 00735 finally { 00736 00737 if (AbnormalTermination()) { 00738 00739 if (SavedState != 0) { 00740 MmEnablePageFaultClustering(SavedState); 00741 } 00742 00743 if (Vacb != NULL) { 00744 CcFreeVirtualAddress( Vacb ); 00745 } 00746 00747 if (Mdl != NULL) { 00748 IoFreeMdl( Mdl ); 00749 } 00750 00751 // 00752 // Otherwise loop to deallocate the Mdls 00753 // 00754 00755 FOffset = *FileOffset; 00756 while (*MdlChain != NULL) { 00757 MdlTemp = (*MdlChain)->Next; 00758 00759 DebugTrace( 0, mm, "MmUnlockPages/IoFreeMdl:\n", 0 ); 00760 DebugTrace( 0, mm, " Mdl = %08lx\n", *MdlChain ); 00761 00762 MmUnlockPages( *MdlChain ); 00763 00764 // 00765 // Extract the File Offset for this part of the transfer, and 00766 // tell the lazy writer to write these pages, since we have 00767 // marked them dirty. Ignore the only exception (allocation 00768 // error), and console ourselves for having tried. 00769 // 00770 00771 CcSetDirtyInMask( SharedCacheMap, &FOffset, (*MdlChain)->ByteCount ); 00772 00773 FOffset.QuadPart = FOffset.QuadPart + (LONGLONG)((*MdlChain)->ByteCount); 00774 00775 IoFreeMdl( *MdlChain ); 00776 00777 *MdlChain = MdlTemp; 00778 } 00779 00780 DebugTrace(-1, me, "CcPrepareMdlWrite -> Unwinding\n", 0 ); 00781 } 00782 else { 00783 00784 IoStatus->Status = STATUS_SUCCESS; 00785 IoStatus->Information = Information; 00786 00787 // 00788 // Make sure the SharedCacheMap does not go away while 00789 // the Mdl write is in progress. We decrment below. 00790 // 00791 00792 CcAcquireMasterLock( &OldIrql ); 00793 CcIncrementOpenCount( SharedCacheMap, 'ldmP' ); 00794 CcReleaseMasterLock( OldIrql ); 00795 } 00796 } 00797 00798 DebugTrace( 0, me, " <MdlChain = %08lx\n", *MdlChain ); 00799 DebugTrace(-1, me, "CcPrepareMdlWrite -> VOID\n", 0 ); 00800 00801 return; 00802 }


Generated on Sat May 15 19:44:37 2004 for test by doxygen 1.3.7