Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygencopy.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS kernel 00004 * FILE: ntoskrnl/cc/copy.c 00005 * PURPOSE: Implements cache managers copy interface 00006 * 00007 * PROGRAMMERS: 00008 */ 00009 00010 /* INCLUDES ******************************************************************/ 00011 00012 #include <ntoskrnl.h> 00013 #define NDEBUG 00014 #include <debug.h> 00015 00016 /* GLOBALS *******************************************************************/ 00017 00018 static PFN_NUMBER CcZeroPage = 0; 00019 00020 #define MAX_ZERO_LENGTH (256 * 1024) 00021 #define MAX_RW_LENGTH (256 * 1024) 00022 00023 ULONG CcFastMdlReadWait; 00024 ULONG CcFastMdlReadNotPossible; 00025 ULONG CcFastReadNotPossible; 00026 ULONG CcFastReadWait; 00027 ULONG CcFastReadNoWait; 00028 ULONG CcFastReadResourceMiss; 00029 00030 /* FUNCTIONS *****************************************************************/ 00031 00032 VOID 00033 NTAPI 00034 MiZeroPhysicalPage( 00035 IN PFN_NUMBER PageFrameIndex 00036 ); 00037 00038 VOID 00039 NTAPI 00040 CcInitCacheZeroPage(VOID) 00041 { 00042 NTSTATUS Status; 00043 00044 MI_SET_USAGE(MI_USAGE_CACHE); 00045 //MI_SET_PROCESS2(PsGetCurrentProcess()->ImageFileName); 00046 Status = MmRequestPageMemoryConsumer(MC_SYSTEM, TRUE, &CcZeroPage); 00047 if (!NT_SUCCESS(Status)) 00048 { 00049 DbgPrint("Can't allocate CcZeroPage.\n"); 00050 KeBugCheck(CACHE_MANAGER); 00051 } 00052 MiZeroPhysicalPage(CcZeroPage); 00053 } 00054 00055 NTSTATUS 00056 NTAPI 00057 ReadCacheSegmentChain(PBCB Bcb, ULONG ReadOffset, ULONG Length, 00058 PVOID Buffer) 00059 { 00060 PCACHE_SEGMENT head; 00061 PCACHE_SEGMENT current; 00062 PCACHE_SEGMENT previous; 00063 IO_STATUS_BLOCK Iosb; 00064 LARGE_INTEGER SegOffset; 00065 NTSTATUS Status; 00066 ULONG TempLength; 00067 KEVENT Event; 00068 PMDL Mdl; 00069 00070 Mdl = _alloca(MmSizeOfMdl(NULL, MAX_RW_LENGTH)); 00071 00072 Status = CcRosGetCacheSegmentChain(Bcb, ReadOffset, Length, &head); 00073 if (!NT_SUCCESS(Status)) 00074 { 00075 return(Status); 00076 } 00077 current = head; 00078 while (current != NULL) 00079 { 00080 /* 00081 * If the current segment is valid then copy it into the 00082 * user buffer. 00083 */ 00084 if (current->Valid) 00085 { 00086 TempLength = min(Bcb->CacheSegmentSize, Length); 00087 memcpy(Buffer, current->BaseAddress, TempLength); 00088 00089 Buffer = (PVOID)((ULONG_PTR)Buffer + TempLength); 00090 00091 Length = Length - TempLength; 00092 previous = current; 00093 current = current->NextInChain; 00094 CcRosReleaseCacheSegment(Bcb, previous, TRUE, FALSE, FALSE); 00095 } 00096 /* 00097 * Otherwise read in as much as we can. 00098 */ 00099 else 00100 { 00101 PCACHE_SEGMENT current2; 00102 ULONG current_size; 00103 ULONG i; 00104 PPFN_NUMBER MdlPages; 00105 00106 /* 00107 * Count the maximum number of bytes we could read starting 00108 * from the current segment. 00109 */ 00110 current2 = current; 00111 current_size = 0; 00112 while (current2 != NULL && !current2->Valid && current_size < MAX_RW_LENGTH) 00113 { 00114 current2 = current2->NextInChain; 00115 current_size += Bcb->CacheSegmentSize; 00116 } 00117 00118 /* 00119 * Create an MDL which contains all their pages. 00120 */ 00121 MmInitializeMdl(Mdl, NULL, current_size); 00122 Mdl->MdlFlags |= (MDL_PAGES_LOCKED | MDL_IO_PAGE_READ); 00123 current2 = current; 00124 current_size = 0; 00125 MdlPages = (PPFN_NUMBER)(Mdl + 1); 00126 while (current2 != NULL && !current2->Valid && current_size < MAX_RW_LENGTH) 00127 { 00128 PVOID address = current2->BaseAddress; 00129 for (i = 0; i < (Bcb->CacheSegmentSize / PAGE_SIZE); i++, address = RVA(address, PAGE_SIZE)) 00130 { 00131 *MdlPages++ = MmGetPfnForProcess(NULL, address); 00132 } 00133 current2 = current2->NextInChain; 00134 current_size += Bcb->CacheSegmentSize; 00135 } 00136 00137 /* 00138 * Read in the information. 00139 */ 00140 SegOffset.QuadPart = current->FileOffset; 00141 KeInitializeEvent(&Event, NotificationEvent, FALSE); 00142 Status = IoPageRead(Bcb->FileObject, 00143 Mdl, 00144 &SegOffset, 00145 &Event, 00146 &Iosb); 00147 if (Status == STATUS_PENDING) 00148 { 00149 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 00150 Status = Iosb.Status; 00151 } 00152 if (Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA) 00153 { 00154 MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl); 00155 } 00156 if (!NT_SUCCESS(Status) && Status != STATUS_END_OF_FILE) 00157 { 00158 while (current != NULL) 00159 { 00160 previous = current; 00161 current = current->NextInChain; 00162 CcRosReleaseCacheSegment(Bcb, previous, FALSE, FALSE, FALSE); 00163 } 00164 return(Status); 00165 } 00166 current_size = 0; 00167 while (current != NULL && !current->Valid && current_size < MAX_RW_LENGTH) 00168 { 00169 previous = current; 00170 current = current->NextInChain; 00171 TempLength = min(Bcb->CacheSegmentSize, Length); 00172 memcpy(Buffer, previous->BaseAddress, TempLength); 00173 00174 Buffer = (PVOID)((ULONG_PTR)Buffer + TempLength); 00175 00176 Length = Length - TempLength; 00177 CcRosReleaseCacheSegment(Bcb, previous, TRUE, FALSE, FALSE); 00178 current_size += Bcb->CacheSegmentSize; 00179 } 00180 } 00181 } 00182 return(STATUS_SUCCESS); 00183 } 00184 00185 NTSTATUS 00186 NTAPI 00187 ReadCacheSegment(PCACHE_SEGMENT CacheSeg) 00188 { 00189 ULONG Size; 00190 PMDL Mdl; 00191 NTSTATUS Status; 00192 LARGE_INTEGER SegOffset; 00193 IO_STATUS_BLOCK IoStatus; 00194 KEVENT Event; 00195 00196 SegOffset.QuadPart = CacheSeg->FileOffset; 00197 Size = (ULONG)(CacheSeg->Bcb->AllocationSize.QuadPart - CacheSeg->FileOffset); 00198 if (Size > CacheSeg->Bcb->CacheSegmentSize) 00199 { 00200 Size = CacheSeg->Bcb->CacheSegmentSize; 00201 } 00202 00203 Mdl = IoAllocateMdl(CacheSeg->BaseAddress, Size, FALSE, FALSE, NULL); 00204 if (!Mdl) 00205 { 00206 return STATUS_INSUFFICIENT_RESOURCES; 00207 } 00208 MmBuildMdlForNonPagedPool(Mdl); 00209 Mdl->MdlFlags |= MDL_IO_PAGE_READ; 00210 KeInitializeEvent(&Event, NotificationEvent, FALSE); 00211 Status = IoPageRead(CacheSeg->Bcb->FileObject, Mdl, &SegOffset, &Event, &IoStatus); 00212 if (Status == STATUS_PENDING) 00213 { 00214 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 00215 Status = IoStatus.Status; 00216 } 00217 00218 IoFreeMdl(Mdl); 00219 00220 if (!NT_SUCCESS(Status) && Status != STATUS_END_OF_FILE) 00221 { 00222 DPRINT1("IoPageRead failed, Status %x\n", Status); 00223 return Status; 00224 } 00225 00226 if (CacheSeg->Bcb->CacheSegmentSize > Size) 00227 { 00228 RtlZeroMemory((char*)CacheSeg->BaseAddress + Size, 00229 CacheSeg->Bcb->CacheSegmentSize - Size); 00230 } 00231 00232 return STATUS_SUCCESS; 00233 } 00234 00235 NTSTATUS 00236 NTAPI 00237 WriteCacheSegment(PCACHE_SEGMENT CacheSeg) 00238 { 00239 ULONG Size; 00240 PMDL Mdl; 00241 NTSTATUS Status; 00242 IO_STATUS_BLOCK IoStatus; 00243 LARGE_INTEGER SegOffset; 00244 KEVENT Event; 00245 00246 CacheSeg->Dirty = FALSE; 00247 SegOffset.QuadPart = CacheSeg->FileOffset; 00248 Size = (ULONG)(CacheSeg->Bcb->AllocationSize.QuadPart - CacheSeg->FileOffset); 00249 if (Size > CacheSeg->Bcb->CacheSegmentSize) 00250 { 00251 Size = CacheSeg->Bcb->CacheSegmentSize; 00252 } 00253 // 00254 // Nonpaged pool PDEs in ReactOS must actually be synchronized between the 00255 // MmGlobalPageDirectory and the real system PDE directory. What a mess... 00256 // 00257 { 00258 ULONG i = 0; 00259 do 00260 { 00261 MmGetPfnForProcess(NULL, (PVOID)((ULONG_PTR)CacheSeg->BaseAddress + (i << PAGE_SHIFT))); 00262 } while (++i < (Size >> PAGE_SHIFT)); 00263 } 00264 00265 Mdl = IoAllocateMdl(CacheSeg->BaseAddress, Size, FALSE, FALSE, NULL); 00266 if (!Mdl) 00267 { 00268 return STATUS_INSUFFICIENT_RESOURCES; 00269 } 00270 MmBuildMdlForNonPagedPool(Mdl); 00271 Mdl->MdlFlags |= MDL_IO_PAGE_READ; 00272 KeInitializeEvent(&Event, NotificationEvent, FALSE); 00273 Status = IoSynchronousPageWrite(CacheSeg->Bcb->FileObject, Mdl, &SegOffset, &Event, &IoStatus); 00274 if (Status == STATUS_PENDING) 00275 { 00276 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 00277 Status = IoStatus.Status; 00278 } 00279 IoFreeMdl(Mdl); 00280 if (!NT_SUCCESS(Status) && (Status != STATUS_END_OF_FILE)) 00281 { 00282 DPRINT1("IoPageWrite failed, Status %x\n", Status); 00283 CacheSeg->Dirty = TRUE; 00284 return Status; 00285 } 00286 00287 return STATUS_SUCCESS; 00288 } 00289 00290 00291 /* 00292 * @unimplemented 00293 */ 00294 BOOLEAN NTAPI 00295 CcCanIWrite ( 00296 IN PFILE_OBJECT FileObject, 00297 IN ULONG BytesToWrite, 00298 IN BOOLEAN Wait, 00299 IN BOOLEAN Retrying) 00300 { 00301 UNIMPLEMENTED; 00302 return FALSE; 00303 } 00304 00305 00306 /* 00307 * @implemented 00308 */ 00309 BOOLEAN NTAPI 00310 CcCopyRead (IN PFILE_OBJECT FileObject, 00311 IN PLARGE_INTEGER FileOffset, 00312 IN ULONG Length, 00313 IN BOOLEAN Wait, 00314 OUT PVOID Buffer, 00315 OUT PIO_STATUS_BLOCK IoStatus) 00316 { 00317 ULONG ReadOffset; 00318 ULONG TempLength; 00319 NTSTATUS Status = STATUS_SUCCESS; 00320 PVOID BaseAddress; 00321 PCACHE_SEGMENT CacheSeg; 00322 BOOLEAN Valid; 00323 ULONG ReadLength = 0; 00324 PBCB Bcb; 00325 KIRQL oldirql; 00326 PLIST_ENTRY current_entry; 00327 PCACHE_SEGMENT current; 00328 00329 DPRINT("CcCopyRead(FileObject 0x%p, FileOffset %I64x, " 00330 "Length %d, Wait %d, Buffer 0x%p, IoStatus 0x%p)\n", 00331 FileObject, FileOffset->QuadPart, Length, Wait, 00332 Buffer, IoStatus); 00333 00334 Bcb = FileObject->SectionObjectPointer->SharedCacheMap; 00335 ReadOffset = (ULONG)FileOffset->QuadPart; 00336 00337 DPRINT("AllocationSize %d, FileSize %d\n", 00338 (ULONG)Bcb->AllocationSize.QuadPart, 00339 (ULONG)Bcb->FileSize.QuadPart); 00340 00341 /* 00342 * Check for the nowait case that all the cache segments that would 00343 * cover this read are in memory. 00344 */ 00345 if (!Wait) 00346 { 00347 KeAcquireSpinLock(&Bcb->BcbLock, &oldirql); 00348 current_entry = Bcb->BcbSegmentListHead.Flink; 00349 while (current_entry != &Bcb->BcbSegmentListHead) 00350 { 00351 current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, 00352 BcbSegmentListEntry); 00353 if (!current->Valid && current->FileOffset < ReadOffset + Length 00354 && current->FileOffset + Bcb->CacheSegmentSize > ReadOffset) 00355 { 00356 KeReleaseSpinLock(&Bcb->BcbLock, oldirql); 00357 IoStatus->Status = STATUS_UNSUCCESSFUL; 00358 IoStatus->Information = 0; 00359 return FALSE; 00360 } 00361 current_entry = current_entry->Flink; 00362 } 00363 KeReleaseSpinLock(&Bcb->BcbLock, oldirql); 00364 } 00365 00366 TempLength = ReadOffset % Bcb->CacheSegmentSize; 00367 if (TempLength != 0) 00368 { 00369 TempLength = min (Length, Bcb->CacheSegmentSize - TempLength); 00370 Status = CcRosRequestCacheSegment(Bcb, 00371 ROUND_DOWN(ReadOffset, 00372 Bcb->CacheSegmentSize), 00373 &BaseAddress, &Valid, &CacheSeg); 00374 if (!NT_SUCCESS(Status)) 00375 { 00376 IoStatus->Information = 0; 00377 IoStatus->Status = Status; 00378 DPRINT("CcRosRequestCacheSegment faild, Status %x\n", Status); 00379 return FALSE; 00380 } 00381 if (!Valid) 00382 { 00383 Status = ReadCacheSegment(CacheSeg); 00384 if (!NT_SUCCESS(Status)) 00385 { 00386 IoStatus->Information = 0; 00387 IoStatus->Status = Status; 00388 CcRosReleaseCacheSegment(Bcb, CacheSeg, FALSE, FALSE, FALSE); 00389 return FALSE; 00390 } 00391 } 00392 memcpy (Buffer, (char*)BaseAddress + ReadOffset % Bcb->CacheSegmentSize, 00393 TempLength); 00394 CcRosReleaseCacheSegment(Bcb, CacheSeg, TRUE, FALSE, FALSE); 00395 ReadLength += TempLength; 00396 Length -= TempLength; 00397 ReadOffset += TempLength; 00398 Buffer = (PVOID)((char*)Buffer + TempLength); 00399 } 00400 while (Length > 0) 00401 { 00402 TempLength = min(max(Bcb->CacheSegmentSize, MAX_RW_LENGTH), Length); 00403 Status = ReadCacheSegmentChain(Bcb, ReadOffset, TempLength, Buffer); 00404 if (!NT_SUCCESS(Status)) 00405 { 00406 IoStatus->Information = 0; 00407 IoStatus->Status = Status; 00408 DPRINT("ReadCacheSegmentChain failed, Status %x\n", Status); 00409 return FALSE; 00410 } 00411 00412 ReadLength += TempLength; 00413 Length -= TempLength; 00414 ReadOffset += TempLength; 00415 00416 Buffer = (PVOID)((ULONG_PTR)Buffer + TempLength); 00417 } 00418 IoStatus->Status = STATUS_SUCCESS; 00419 IoStatus->Information = ReadLength; 00420 DPRINT("CcCopyRead O.K.\n"); 00421 return TRUE; 00422 } 00423 00424 /* 00425 * @implemented 00426 */ 00427 BOOLEAN NTAPI 00428 CcCopyWrite (IN PFILE_OBJECT FileObject, 00429 IN PLARGE_INTEGER FileOffset, 00430 IN ULONG Length, 00431 IN BOOLEAN Wait, 00432 IN PVOID Buffer) 00433 { 00434 NTSTATUS Status; 00435 ULONG WriteOffset; 00436 KIRQL oldirql; 00437 PBCB Bcb; 00438 PLIST_ENTRY current_entry; 00439 PCACHE_SEGMENT CacheSeg; 00440 ULONG TempLength; 00441 PVOID BaseAddress; 00442 BOOLEAN Valid; 00443 00444 DPRINT("CcCopyWrite(FileObject 0x%p, FileOffset %I64x, " 00445 "Length %d, Wait %d, Buffer 0x%p)\n", 00446 FileObject, FileOffset->QuadPart, Length, Wait, Buffer); 00447 00448 Bcb = FileObject->SectionObjectPointer->SharedCacheMap; 00449 WriteOffset = (ULONG)FileOffset->QuadPart; 00450 00451 if (!Wait) 00452 { 00453 /* testing, if the requested datas are available */ 00454 KeAcquireSpinLock(&Bcb->BcbLock, &oldirql); 00455 current_entry = Bcb->BcbSegmentListHead.Flink; 00456 while (current_entry != &Bcb->BcbSegmentListHead) 00457 { 00458 CacheSeg = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, 00459 BcbSegmentListEntry); 00460 if (!CacheSeg->Valid) 00461 { 00462 if ((WriteOffset >= CacheSeg->FileOffset && 00463 WriteOffset < CacheSeg->FileOffset + Bcb->CacheSegmentSize) 00464 || (WriteOffset + Length > CacheSeg->FileOffset && 00465 WriteOffset + Length <= CacheSeg->FileOffset + 00466 Bcb->CacheSegmentSize)) 00467 { 00468 KeReleaseSpinLock(&Bcb->BcbLock, oldirql); 00469 /* datas not available */ 00470 return(FALSE); 00471 } 00472 } 00473 current_entry = current_entry->Flink; 00474 } 00475 KeReleaseSpinLock(&Bcb->BcbLock, oldirql); 00476 } 00477 00478 TempLength = WriteOffset % Bcb->CacheSegmentSize; 00479 if (TempLength != 0) 00480 { 00481 ULONG ROffset; 00482 ROffset = ROUND_DOWN(WriteOffset, Bcb->CacheSegmentSize); 00483 TempLength = min (Length, Bcb->CacheSegmentSize - TempLength); 00484 Status = CcRosRequestCacheSegment(Bcb, ROffset, 00485 &BaseAddress, &Valid, &CacheSeg); 00486 if (!NT_SUCCESS(Status)) 00487 { 00488 return(FALSE); 00489 } 00490 if (!Valid) 00491 { 00492 if (!NT_SUCCESS(ReadCacheSegment(CacheSeg))) 00493 { 00494 return(FALSE); 00495 } 00496 } 00497 memcpy ((char*)BaseAddress + WriteOffset % Bcb->CacheSegmentSize, 00498 Buffer, TempLength); 00499 CcRosReleaseCacheSegment(Bcb, CacheSeg, TRUE, TRUE, FALSE); 00500 00501 Length -= TempLength; 00502 WriteOffset += TempLength; 00503 00504 Buffer = (PVOID)((ULONG_PTR)Buffer + TempLength); 00505 } 00506 00507 while (Length > 0) 00508 { 00509 TempLength = min (Bcb->CacheSegmentSize, Length); 00510 Status = CcRosRequestCacheSegment(Bcb, WriteOffset, 00511 &BaseAddress, &Valid, &CacheSeg); 00512 if (!NT_SUCCESS(Status)) 00513 { 00514 return(FALSE); 00515 } 00516 if (!Valid && TempLength < Bcb->CacheSegmentSize) 00517 { 00518 if (!NT_SUCCESS(ReadCacheSegment(CacheSeg))) 00519 { 00520 CcRosReleaseCacheSegment(Bcb, CacheSeg, FALSE, FALSE, FALSE); 00521 return FALSE; 00522 } 00523 } 00524 memcpy (BaseAddress, Buffer, TempLength); 00525 CcRosReleaseCacheSegment(Bcb, CacheSeg, TRUE, TRUE, FALSE); 00526 Length -= TempLength; 00527 WriteOffset += TempLength; 00528 00529 Buffer = (PVOID)((ULONG_PTR)Buffer + TempLength); 00530 } 00531 return(TRUE); 00532 } 00533 00534 /* 00535 * @unimplemented 00536 */ 00537 VOID 00538 NTAPI 00539 CcDeferWrite ( 00540 IN PFILE_OBJECT FileObject, 00541 IN PCC_POST_DEFERRED_WRITE PostRoutine, 00542 IN PVOID Context1, 00543 IN PVOID Context2, 00544 IN ULONG BytesToWrite, 00545 IN BOOLEAN Retrying 00546 ) 00547 { 00548 UNIMPLEMENTED; 00549 } 00550 00551 /* 00552 * @unimplemented 00553 */ 00554 VOID 00555 NTAPI 00556 CcFastCopyRead ( 00557 IN PFILE_OBJECT FileObject, 00558 IN ULONG FileOffset, 00559 IN ULONG Length, 00560 IN ULONG PageCount, 00561 OUT PVOID Buffer, 00562 OUT PIO_STATUS_BLOCK IoStatus 00563 ) 00564 { 00565 UNIMPLEMENTED; 00566 } 00567 /* 00568 * @unimplemented 00569 */ 00570 VOID 00571 NTAPI 00572 CcFastCopyWrite( 00573 IN PFILE_OBJECT FileObject, 00574 IN ULONG FileOffset, 00575 IN ULONG Length, 00576 IN PVOID Buffer) 00577 { 00578 UNIMPLEMENTED; 00579 } 00580 00581 /* 00582 * @unimplemented 00583 */ 00584 NTSTATUS 00585 NTAPI 00586 CcWaitForCurrentLazyWriterActivity ( 00587 VOID 00588 ) 00589 { 00590 UNIMPLEMENTED; 00591 return STATUS_NOT_IMPLEMENTED; 00592 } 00593 00594 /* 00595 * @implemented 00596 */ 00597 BOOLEAN NTAPI 00598 CcZeroData (IN PFILE_OBJECT FileObject, 00599 IN PLARGE_INTEGER StartOffset, 00600 IN PLARGE_INTEGER EndOffset, 00601 IN BOOLEAN Wait) 00602 { 00603 NTSTATUS Status; 00604 LARGE_INTEGER WriteOffset; 00605 ULONG Length; 00606 ULONG CurrentLength; 00607 PMDL Mdl; 00608 ULONG i; 00609 IO_STATUS_BLOCK Iosb; 00610 KEVENT Event; 00611 00612 DPRINT("CcZeroData(FileObject 0x%p, StartOffset %I64x, EndOffset %I64x, " 00613 "Wait %d)\n", FileObject, StartOffset->QuadPart, EndOffset->QuadPart, 00614 Wait); 00615 00616 Length = EndOffset->u.LowPart - StartOffset->u.LowPart; 00617 WriteOffset.QuadPart = StartOffset->QuadPart; 00618 00619 if (FileObject->SectionObjectPointer->SharedCacheMap == NULL) 00620 { 00621 /* File is not cached */ 00622 00623 Mdl = _alloca(MmSizeOfMdl(NULL, MAX_ZERO_LENGTH)); 00624 00625 while (Length > 0) 00626 { 00627 if (Length + WriteOffset.u.LowPart % PAGE_SIZE > MAX_ZERO_LENGTH) 00628 { 00629 CurrentLength = MAX_ZERO_LENGTH - WriteOffset.u.LowPart % PAGE_SIZE; 00630 } 00631 else 00632 { 00633 CurrentLength = Length; 00634 } 00635 MmInitializeMdl(Mdl, (PVOID)(ULONG_PTR)WriteOffset.QuadPart, CurrentLength); 00636 Mdl->MdlFlags |= (MDL_PAGES_LOCKED | MDL_IO_PAGE_READ); 00637 for (i = 0; i < ((Mdl->Size - sizeof(MDL)) / sizeof(ULONG)); i++) 00638 { 00639 ((PPFN_NUMBER)(Mdl + 1))[i] = CcZeroPage; 00640 } 00641 KeInitializeEvent(&Event, NotificationEvent, FALSE); 00642 Status = IoSynchronousPageWrite(FileObject, Mdl, &WriteOffset, &Event, &Iosb); 00643 if (Status == STATUS_PENDING) 00644 { 00645 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 00646 Status = Iosb.Status; 00647 } 00648 if (Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA) 00649 { 00650 MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl); 00651 } 00652 if (!NT_SUCCESS(Status)) 00653 { 00654 return(FALSE); 00655 } 00656 WriteOffset.QuadPart += CurrentLength; 00657 Length -= CurrentLength; 00658 } 00659 } 00660 else 00661 { 00662 /* File is cached */ 00663 KIRQL oldirql; 00664 PBCB Bcb; 00665 PLIST_ENTRY current_entry; 00666 PCACHE_SEGMENT CacheSeg, current, previous; 00667 ULONG TempLength; 00668 00669 Bcb = FileObject->SectionObjectPointer->SharedCacheMap; 00670 if (Wait) 00671 { 00672 /* testing, if the requested datas are available */ 00673 KeAcquireSpinLock(&Bcb->BcbLock, &oldirql); 00674 current_entry = Bcb->BcbSegmentListHead.Flink; 00675 while (current_entry != &Bcb->BcbSegmentListHead) 00676 { 00677 CacheSeg = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, 00678 BcbSegmentListEntry); 00679 if (!CacheSeg->Valid) 00680 { 00681 if ((WriteOffset.u.LowPart >= CacheSeg->FileOffset && 00682 WriteOffset.u.LowPart < CacheSeg->FileOffset + Bcb->CacheSegmentSize) 00683 || (WriteOffset.u.LowPart + Length > CacheSeg->FileOffset && 00684 WriteOffset.u.LowPart + Length <= 00685 CacheSeg->FileOffset + Bcb->CacheSegmentSize)) 00686 { 00687 KeReleaseSpinLock(&Bcb->BcbLock, oldirql); 00688 /* datas not available */ 00689 return(FALSE); 00690 } 00691 } 00692 current_entry = current_entry->Flink; 00693 } 00694 KeReleaseSpinLock(&Bcb->BcbLock, oldirql); 00695 } 00696 while (Length > 0) 00697 { 00698 ULONG Offset; 00699 Offset = WriteOffset.u.LowPart % Bcb->CacheSegmentSize; 00700 if (Length + Offset > MAX_ZERO_LENGTH) 00701 { 00702 CurrentLength = MAX_ZERO_LENGTH - Offset; 00703 } 00704 else 00705 { 00706 CurrentLength = Length; 00707 } 00708 Status = CcRosGetCacheSegmentChain (Bcb, WriteOffset.u.LowPart - Offset, 00709 Offset + CurrentLength, &CacheSeg); 00710 if (!NT_SUCCESS(Status)) 00711 { 00712 return FALSE; 00713 } 00714 current = CacheSeg; 00715 00716 while (current != NULL) 00717 { 00718 Offset = WriteOffset.u.LowPart % Bcb->CacheSegmentSize; 00719 if (Offset != 0 || 00720 Offset + CurrentLength < Bcb->CacheSegmentSize) 00721 { 00722 if (!current->Valid) 00723 { 00724 /* read the segment */ 00725 Status = ReadCacheSegment(current); 00726 if (!NT_SUCCESS(Status)) 00727 { 00728 DPRINT1("ReadCacheSegment failed, status %x\n", 00729 Status); 00730 } 00731 } 00732 TempLength = min (CurrentLength, Bcb->CacheSegmentSize - Offset); 00733 } 00734 else 00735 { 00736 TempLength = Bcb->CacheSegmentSize; 00737 } 00738 memset ((PUCHAR)current->BaseAddress + Offset, 0, TempLength); 00739 00740 WriteOffset.QuadPart += TempLength; 00741 CurrentLength -= TempLength; 00742 Length -= TempLength; 00743 00744 current = current->NextInChain; 00745 } 00746 00747 current = CacheSeg; 00748 while (current != NULL) 00749 { 00750 previous = current; 00751 current = current->NextInChain; 00752 CcRosReleaseCacheSegment(Bcb, previous, TRUE, TRUE, FALSE); 00753 } 00754 } 00755 } 00756 return(TRUE); 00757 } Generated on Sun May 27 2012 04:18:11 for ReactOS by
1.7.6.1
|