Sync with trunk (48237)
[reactos.git] / ntoskrnl / cc / copy.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/cc/copy.c
5 * PURPOSE: Implements cache managers copy interface
6 *
7 * PROGRAMMERS:
8 */
9
10 /* INCLUDES ******************************************************************/
11
12 #include <ntoskrnl.h>
13 #define NDEBUG
14 #include <debug.h>
15
16 /* GLOBALS *******************************************************************/
17
18 static PFN_NUMBER CcZeroPage = 0;
19
20 #define MAX_ZERO_LENGTH (256 * 1024)
21 #define MAX_RW_LENGTH (256 * 1024)
22
23 ULONG CcFastMdlReadWait;
24 ULONG CcFastMdlReadNotPossible;
25 ULONG CcFastReadNotPossible;
26 ULONG CcFastReadWait;
27 ULONG CcFastReadNoWait;
28 ULONG CcFastReadResourceMiss;
29
30 /* FUNCTIONS *****************************************************************/
31
32 VOID
33 NTAPI
34 CcInitCacheZeroPage(VOID)
35 {
36 NTSTATUS Status;
37
38 Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE, &CcZeroPage);
39 if (!NT_SUCCESS(Status))
40 {
41 DbgPrint("Can't allocate CcZeroPage.\n");
42 KeBugCheck(CACHE_MANAGER);
43 }
44 Status = MiZeroPage(CcZeroPage);
45 if (!NT_SUCCESS(Status))
46 {
47 DbgPrint("Can't zero out CcZeroPage.\n");
48 KeBugCheck(CACHE_MANAGER);
49 }
50 }
51
52 NTSTATUS
53 NTAPI
54 ReadCacheSegmentChain(PBCB Bcb, ULONG ReadOffset, ULONG Length,
55 PVOID Buffer)
56 {
57 PCACHE_SEGMENT head;
58 PCACHE_SEGMENT current;
59 PCACHE_SEGMENT previous;
60 IO_STATUS_BLOCK Iosb;
61 LARGE_INTEGER SegOffset;
62 NTSTATUS Status;
63 ULONG TempLength;
64 KEVENT Event;
65 PMDL Mdl;
66
67 Mdl = _alloca(MmSizeOfMdl(NULL, MAX_RW_LENGTH));
68
69 Status = CcRosGetCacheSegmentChain(Bcb, ReadOffset, Length, &head);
70 if (!NT_SUCCESS(Status))
71 {
72 return(Status);
73 }
74 current = head;
75 while (current != NULL)
76 {
77 /*
78 * If the current segment is valid then copy it into the
79 * user buffer.
80 */
81 if (current->Valid)
82 {
83 TempLength = min(Bcb->CacheSegmentSize, Length);
84 memcpy(Buffer, current->BaseAddress, TempLength);
85
86 Buffer = (PVOID)((ULONG_PTR)Buffer + TempLength);
87
88 Length = Length - TempLength;
89 previous = current;
90 current = current->NextInChain;
91 CcRosReleaseCacheSegment(Bcb, previous, TRUE, FALSE, FALSE);
92 }
93 /*
94 * Otherwise read in as much as we can.
95 */
96 else
97 {
98 PCACHE_SEGMENT current2;
99 ULONG current_size;
100 ULONG i;
101 PPFN_NUMBER MdlPages;
102
103 /*
104 * Count the maximum number of bytes we could read starting
105 * from the current segment.
106 */
107 current2 = current;
108 current_size = 0;
109 while (current2 != NULL && !current2->Valid && current_size < MAX_RW_LENGTH)
110 {
111 current2 = current2->NextInChain;
112 current_size += Bcb->CacheSegmentSize;
113 }
114
115 /*
116 * Create an MDL which contains all their pages.
117 */
118 MmInitializeMdl(Mdl, NULL, current_size);
119 Mdl->MdlFlags |= (MDL_PAGES_LOCKED | MDL_IO_PAGE_READ);
120 current2 = current;
121 current_size = 0;
122 MdlPages = (PPFN_NUMBER)(Mdl + 1);
123 while (current2 != NULL && !current2->Valid && current_size < MAX_RW_LENGTH)
124 {
125 PVOID address = current2->BaseAddress;
126 for (i = 0; i < (Bcb->CacheSegmentSize / PAGE_SIZE); i++, address = RVA(address, PAGE_SIZE))
127 {
128 *MdlPages++ = MmGetPfnForProcess(NULL, address);
129 }
130 current2 = current2->NextInChain;
131 current_size += Bcb->CacheSegmentSize;
132 }
133
134 /*
135 * Read in the information.
136 */
137 SegOffset.QuadPart = current->FileOffset;
138 KeInitializeEvent(&Event, NotificationEvent, FALSE);
139 Status = IoPageRead(Bcb->FileObject,
140 Mdl,
141 &SegOffset,
142 &Event,
143 &Iosb);
144 if (Status == STATUS_PENDING)
145 {
146 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
147 Status = Iosb.Status;
148 }
149 if (Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA)
150 {
151 MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
152 }
153 if (!NT_SUCCESS(Status) && Status != STATUS_END_OF_FILE)
154 {
155 while (current != NULL)
156 {
157 previous = current;
158 current = current->NextInChain;
159 CcRosReleaseCacheSegment(Bcb, previous, FALSE, FALSE, FALSE);
160 }
161 return(Status);
162 }
163 current_size = 0;
164 while (current != NULL && !current->Valid && current_size < MAX_RW_LENGTH)
165 {
166 previous = current;
167 current = current->NextInChain;
168 TempLength = min(Bcb->CacheSegmentSize, Length);
169 memcpy(Buffer, previous->BaseAddress, TempLength);
170
171 Buffer = (PVOID)((ULONG_PTR)Buffer + TempLength);
172
173 Length = Length - TempLength;
174 CcRosReleaseCacheSegment(Bcb, previous, TRUE, FALSE, FALSE);
175 current_size += Bcb->CacheSegmentSize;
176 }
177 }
178 }
179 return(STATUS_SUCCESS);
180 }
181
182 NTSTATUS
183 NTAPI
184 ReadCacheSegment(PCACHE_SEGMENT CacheSeg)
185 {
186 ULONG Size;
187 PMDL Mdl;
188 NTSTATUS Status;
189 LARGE_INTEGER SegOffset;
190 IO_STATUS_BLOCK IoStatus;
191 KEVENT Event;
192
193 SegOffset.QuadPart = CacheSeg->FileOffset;
194 Size = (ULONG)(CacheSeg->Bcb->AllocationSize.QuadPart - CacheSeg->FileOffset);
195 if (Size > CacheSeg->Bcb->CacheSegmentSize)
196 {
197 Size = CacheSeg->Bcb->CacheSegmentSize;
198 }
199 Mdl = _alloca(MmSizeOfMdl(CacheSeg->BaseAddress, Size));
200 MmInitializeMdl(Mdl, CacheSeg->BaseAddress, Size);
201 MmBuildMdlForNonPagedPool(Mdl);
202 Mdl->MdlFlags |= MDL_IO_PAGE_READ;
203 KeInitializeEvent(&Event, NotificationEvent, FALSE);
204 Status = IoPageRead(CacheSeg->Bcb->FileObject, Mdl, &SegOffset, & Event, &IoStatus);
205 if (Status == STATUS_PENDING)
206 {
207 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
208 Status = IoStatus.Status;
209 }
210
211 if (!NT_SUCCESS(Status) && Status != STATUS_END_OF_FILE)
212 {
213 DPRINT1("IoPageRead failed, Status %x\n", Status);
214 return Status;
215 }
216 if (CacheSeg->Bcb->CacheSegmentSize > Size)
217 {
218 memset ((char*)CacheSeg->BaseAddress + Size, 0,
219 CacheSeg->Bcb->CacheSegmentSize - Size);
220 }
221 return STATUS_SUCCESS;
222 }
223
224 NTSTATUS
225 NTAPI
226 WriteCacheSegment(PCACHE_SEGMENT CacheSeg)
227 {
228 ULONG Size;
229 PMDL Mdl;
230 NTSTATUS Status;
231 IO_STATUS_BLOCK IoStatus;
232 LARGE_INTEGER SegOffset;
233 KEVENT Event;
234
235 CacheSeg->Dirty = FALSE;
236 SegOffset.QuadPart = CacheSeg->FileOffset;
237 Size = (ULONG)(CacheSeg->Bcb->AllocationSize.QuadPart - CacheSeg->FileOffset);
238 if (Size > CacheSeg->Bcb->CacheSegmentSize)
239 {
240 Size = CacheSeg->Bcb->CacheSegmentSize;
241 }
242 //
243 // Nonpaged pool PDEs in ReactOS must actually be synchronized between the
244 // MmGlobalPageDirectory and the real system PDE directory. What a mess...
245 //
246 {
247 int i = 0;
248 do
249 {
250 MmGetPfnForProcess(NULL, (PVOID)((ULONG_PTR)CacheSeg->BaseAddress + (i << PAGE_SHIFT)));
251 } while (++i < (Size >> PAGE_SHIFT));
252 }
253 Mdl = _alloca(MmSizeOfMdl(CacheSeg->BaseAddress, Size));
254 MmInitializeMdl(Mdl, CacheSeg->BaseAddress, Size);
255 MmBuildMdlForNonPagedPool(Mdl);
256 Mdl->MdlFlags |= MDL_IO_PAGE_READ;
257 KeInitializeEvent(&Event, NotificationEvent, FALSE);
258 Status = IoSynchronousPageWrite(CacheSeg->Bcb->FileObject, Mdl, &SegOffset, &Event, &IoStatus);
259 if (Status == STATUS_PENDING)
260 {
261 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
262 Status = IoStatus.Status;
263 }
264 if (!NT_SUCCESS(Status) && (Status != STATUS_END_OF_FILE))
265 {
266 DPRINT1("IoPageWrite failed, Status %x\n", Status);
267 CacheSeg->Dirty = TRUE;
268 return(Status);
269 }
270 return(STATUS_SUCCESS);
271 }
272
273
274 /*
275 * @unimplemented
276 */
277 BOOLEAN NTAPI
278 CcCanIWrite (
279 IN PFILE_OBJECT FileObject,
280 IN ULONG BytesToWrite,
281 IN BOOLEAN Wait,
282 IN BOOLEAN Retrying)
283 {
284 UNIMPLEMENTED;
285 return FALSE;
286 }
287
288
289 /*
290 * @implemented
291 */
292 BOOLEAN NTAPI
293 CcCopyRead (IN PFILE_OBJECT FileObject,
294 IN PLARGE_INTEGER FileOffset,
295 IN ULONG Length,
296 IN BOOLEAN Wait,
297 OUT PVOID Buffer,
298 OUT PIO_STATUS_BLOCK IoStatus)
299 {
300 ULONG ReadOffset;
301 ULONG TempLength;
302 NTSTATUS Status = STATUS_SUCCESS;
303 PVOID BaseAddress;
304 PCACHE_SEGMENT CacheSeg;
305 BOOLEAN Valid;
306 ULONG ReadLength = 0;
307 PBCB Bcb;
308 KIRQL oldirql;
309 PLIST_ENTRY current_entry;
310 PCACHE_SEGMENT current;
311
312 DPRINT("CcCopyRead(FileObject 0x%p, FileOffset %I64x, "
313 "Length %d, Wait %d, Buffer 0x%p, IoStatus 0x%p)\n",
314 FileObject, FileOffset->QuadPart, Length, Wait,
315 Buffer, IoStatus);
316
317 Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
318 ReadOffset = (ULONG)FileOffset->QuadPart;
319
320 DPRINT("AllocationSize %d, FileSize %d\n",
321 (ULONG)Bcb->AllocationSize.QuadPart,
322 (ULONG)Bcb->FileSize.QuadPart);
323
324 /*
325 * Check for the nowait case that all the cache segments that would
326 * cover this read are in memory.
327 */
328 if (!Wait)
329 {
330 KeAcquireSpinLock(&Bcb->BcbLock, &oldirql);
331 current_entry = Bcb->BcbSegmentListHead.Flink;
332 while (current_entry != &Bcb->BcbSegmentListHead)
333 {
334 current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT,
335 BcbSegmentListEntry);
336 if (!current->Valid && current->FileOffset < ReadOffset + Length
337 && current->FileOffset + Bcb->CacheSegmentSize > ReadOffset)
338 {
339 KeReleaseSpinLock(&Bcb->BcbLock, oldirql);
340 IoStatus->Status = STATUS_UNSUCCESSFUL;
341 IoStatus->Information = 0;
342 return FALSE;
343 }
344 current_entry = current_entry->Flink;
345 }
346 KeReleaseSpinLock(&Bcb->BcbLock, oldirql);
347 }
348
349 TempLength = ReadOffset % Bcb->CacheSegmentSize;
350 if (TempLength != 0)
351 {
352 TempLength = min (Length, Bcb->CacheSegmentSize - TempLength);
353 Status = CcRosRequestCacheSegment(Bcb,
354 ROUND_DOWN(ReadOffset,
355 Bcb->CacheSegmentSize),
356 &BaseAddress, &Valid, &CacheSeg);
357 if (!NT_SUCCESS(Status))
358 {
359 IoStatus->Information = 0;
360 IoStatus->Status = Status;
361 DPRINT("CcRosRequestCacheSegment faild, Status %x\n", Status);
362 return FALSE;
363 }
364 if (!Valid)
365 {
366 Status = ReadCacheSegment(CacheSeg);
367 if (!NT_SUCCESS(Status))
368 {
369 IoStatus->Information = 0;
370 IoStatus->Status = Status;
371 CcRosReleaseCacheSegment(Bcb, CacheSeg, FALSE, FALSE, FALSE);
372 return FALSE;
373 }
374 }
375 memcpy (Buffer, (char*)BaseAddress + ReadOffset % Bcb->CacheSegmentSize,
376 TempLength);
377 CcRosReleaseCacheSegment(Bcb, CacheSeg, TRUE, FALSE, FALSE);
378 ReadLength += TempLength;
379 Length -= TempLength;
380 ReadOffset += TempLength;
381 Buffer = (PVOID)((char*)Buffer + TempLength);
382 }
383 while (Length > 0)
384 {
385 TempLength = min(max(Bcb->CacheSegmentSize, MAX_RW_LENGTH), Length);
386 Status = ReadCacheSegmentChain(Bcb, ReadOffset, TempLength, Buffer);
387 if (!NT_SUCCESS(Status))
388 {
389 IoStatus->Information = 0;
390 IoStatus->Status = Status;
391 DPRINT1("ReadCacheSegmentChain failed, Status %x\n", Status);
392 return FALSE;
393 }
394
395 ReadLength += TempLength;
396 Length -= TempLength;
397 ReadOffset += TempLength;
398
399 Buffer = (PVOID)((ULONG_PTR)Buffer + TempLength);
400 }
401 IoStatus->Status = STATUS_SUCCESS;
402 IoStatus->Information = ReadLength;
403 DPRINT("CcCopyRead O.K.\n");
404 return TRUE;
405 }
406
407 /*
408 * @implemented
409 */
410 BOOLEAN NTAPI
411 CcCopyWrite (IN PFILE_OBJECT FileObject,
412 IN PLARGE_INTEGER FileOffset,
413 IN ULONG Length,
414 IN BOOLEAN Wait,
415 IN PVOID Buffer)
416 {
417 NTSTATUS Status;
418 ULONG WriteOffset;
419 KIRQL oldirql;
420 PBCB Bcb;
421 PLIST_ENTRY current_entry;
422 PCACHE_SEGMENT CacheSeg;
423 ULONG TempLength;
424 PVOID BaseAddress;
425 BOOLEAN Valid;
426
427 DPRINT("CcCopyWrite(FileObject 0x%p, FileOffset %I64x, "
428 "Length %d, Wait %d, Buffer 0x%p)\n",
429 FileObject, FileOffset->QuadPart, Length, Wait, Buffer);
430
431 Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
432 WriteOffset = (ULONG)FileOffset->QuadPart;
433
434 if (!Wait)
435 {
436 /* testing, if the requested datas are available */
437 KeAcquireSpinLock(&Bcb->BcbLock, &oldirql);
438 current_entry = Bcb->BcbSegmentListHead.Flink;
439 while (current_entry != &Bcb->BcbSegmentListHead)
440 {
441 CacheSeg = CONTAINING_RECORD(current_entry, CACHE_SEGMENT,
442 BcbSegmentListEntry);
443 if (!CacheSeg->Valid)
444 {
445 if ((WriteOffset >= CacheSeg->FileOffset &&
446 WriteOffset < CacheSeg->FileOffset + Bcb->CacheSegmentSize)
447 || (WriteOffset + Length > CacheSeg->FileOffset &&
448 WriteOffset + Length <= CacheSeg->FileOffset +
449 Bcb->CacheSegmentSize))
450 {
451 KeReleaseSpinLock(&Bcb->BcbLock, oldirql);
452 /* datas not available */
453 return(FALSE);
454 }
455 }
456 current_entry = current_entry->Flink;
457 }
458 KeReleaseSpinLock(&Bcb->BcbLock, oldirql);
459 }
460
461 TempLength = WriteOffset % Bcb->CacheSegmentSize;
462 if (TempLength != 0)
463 {
464 ULONG ROffset;
465 ROffset = ROUND_DOWN(WriteOffset, Bcb->CacheSegmentSize);
466 TempLength = min (Length, Bcb->CacheSegmentSize - TempLength);
467 Status = CcRosRequestCacheSegment(Bcb, ROffset,
468 &BaseAddress, &Valid, &CacheSeg);
469 if (!NT_SUCCESS(Status))
470 {
471 return(FALSE);
472 }
473 if (!Valid)
474 {
475 if (!NT_SUCCESS(ReadCacheSegment(CacheSeg)))
476 {
477 return(FALSE);
478 }
479 }
480 memcpy ((char*)BaseAddress + WriteOffset % Bcb->CacheSegmentSize,
481 Buffer, TempLength);
482 CcRosReleaseCacheSegment(Bcb, CacheSeg, TRUE, TRUE, FALSE);
483
484 Length -= TempLength;
485 WriteOffset += TempLength;
486
487 Buffer = (PVOID)((ULONG_PTR)Buffer + TempLength);
488 }
489
490 while (Length > 0)
491 {
492 TempLength = min (Bcb->CacheSegmentSize, Length);
493 Status = CcRosRequestCacheSegment(Bcb, WriteOffset,
494 &BaseAddress, &Valid, &CacheSeg);
495 if (!NT_SUCCESS(Status))
496 {
497 return(FALSE);
498 }
499 if (!Valid && TempLength < Bcb->CacheSegmentSize)
500 {
501 if (!NT_SUCCESS(ReadCacheSegment(CacheSeg)))
502 {
503 CcRosReleaseCacheSegment(Bcb, CacheSeg, FALSE, FALSE, FALSE);
504 return FALSE;
505 }
506 }
507 memcpy (BaseAddress, Buffer, TempLength);
508 CcRosReleaseCacheSegment(Bcb, CacheSeg, TRUE, TRUE, FALSE);
509 Length -= TempLength;
510 WriteOffset += TempLength;
511
512 Buffer = (PVOID)((ULONG_PTR)Buffer + TempLength);
513 }
514 return(TRUE);
515 }
516
517 /*
518 * @unimplemented
519 */
520 VOID
521 NTAPI
522 CcDeferWrite (
523 IN PFILE_OBJECT FileObject,
524 IN PCC_POST_DEFERRED_WRITE PostRoutine,
525 IN PVOID Context1,
526 IN PVOID Context2,
527 IN ULONG BytesToWrite,
528 IN BOOLEAN Retrying
529 )
530 {
531 UNIMPLEMENTED;
532 }
533
534 /*
535 * @unimplemented
536 */
537 VOID
538 NTAPI
539 CcFastCopyRead (
540 IN PFILE_OBJECT FileObject,
541 IN ULONG FileOffset,
542 IN ULONG Length,
543 IN ULONG PageCount,
544 OUT PVOID Buffer,
545 OUT PIO_STATUS_BLOCK IoStatus
546 )
547 {
548 UNIMPLEMENTED;
549 }
550 /*
551 * @unimplemented
552 */
553 VOID
554 NTAPI
555 CcFastCopyWrite(
556 IN PFILE_OBJECT FileObject,
557 IN ULONG FileOffset,
558 IN ULONG Length,
559 IN PVOID Buffer)
560 {
561 UNIMPLEMENTED;
562 }
563
564 /*
565 * @unimplemented
566 */
567 NTSTATUS
568 NTAPI
569 CcWaitForCurrentLazyWriterActivity (
570 VOID
571 )
572 {
573 UNIMPLEMENTED;
574 return STATUS_NOT_IMPLEMENTED;
575 }
576
577 /*
578 * @implemented
579 */
580 BOOLEAN NTAPI
581 CcZeroData (IN PFILE_OBJECT FileObject,
582 IN PLARGE_INTEGER StartOffset,
583 IN PLARGE_INTEGER EndOffset,
584 IN BOOLEAN Wait)
585 {
586 NTSTATUS Status;
587 LARGE_INTEGER WriteOffset;
588 ULONG Length;
589 ULONG CurrentLength;
590 PMDL Mdl;
591 ULONG i;
592 IO_STATUS_BLOCK Iosb;
593 KEVENT Event;
594
595 DPRINT("CcZeroData(FileObject 0x%p, StartOffset %I64x, EndOffset %I64x, "
596 "Wait %d)\n", FileObject, StartOffset->QuadPart, EndOffset->QuadPart,
597 Wait);
598
599 Length = EndOffset->u.LowPart - StartOffset->u.LowPart;
600 WriteOffset.QuadPart = StartOffset->QuadPart;
601
602 if (FileObject->SectionObjectPointer->SharedCacheMap == NULL)
603 {
604 /* File is not cached */
605
606 Mdl = _alloca(MmSizeOfMdl(NULL, MAX_ZERO_LENGTH));
607
608 while (Length > 0)
609 {
610 if (Length + WriteOffset.u.LowPart % PAGE_SIZE > MAX_ZERO_LENGTH)
611 {
612 CurrentLength = MAX_ZERO_LENGTH - WriteOffset.u.LowPart % PAGE_SIZE;
613 }
614 else
615 {
616 CurrentLength = Length;
617 }
618 MmInitializeMdl(Mdl, (PVOID)(ULONG_PTR)WriteOffset.QuadPart, CurrentLength);
619 Mdl->MdlFlags |= (MDL_PAGES_LOCKED | MDL_IO_PAGE_READ);
620 for (i = 0; i < ((Mdl->Size - sizeof(MDL)) / sizeof(ULONG)); i++)
621 {
622 ((PPFN_NUMBER)(Mdl + 1))[i] = CcZeroPage;
623 }
624 KeInitializeEvent(&Event, NotificationEvent, FALSE);
625 Status = IoSynchronousPageWrite(FileObject, Mdl, &WriteOffset, &Event, &Iosb);
626 if (Status == STATUS_PENDING)
627 {
628 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
629 Status = Iosb.Status;
630 }
631 MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
632 if (!NT_SUCCESS(Status))
633 {
634 return(FALSE);
635 }
636 WriteOffset.QuadPart += CurrentLength;
637 Length -= CurrentLength;
638 }
639 }
640 else
641 {
642 /* File is cached */
643 KIRQL oldirql;
644 PBCB Bcb;
645 PLIST_ENTRY current_entry;
646 PCACHE_SEGMENT CacheSeg, current, previous;
647 ULONG TempLength;
648
649 Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
650 if (Wait)
651 {
652 /* testing, if the requested datas are available */
653 KeAcquireSpinLock(&Bcb->BcbLock, &oldirql);
654 current_entry = Bcb->BcbSegmentListHead.Flink;
655 while (current_entry != &Bcb->BcbSegmentListHead)
656 {
657 CacheSeg = CONTAINING_RECORD(current_entry, CACHE_SEGMENT,
658 BcbSegmentListEntry);
659 if (!CacheSeg->Valid)
660 {
661 if ((WriteOffset.u.LowPart >= CacheSeg->FileOffset &&
662 WriteOffset.u.LowPart < CacheSeg->FileOffset + Bcb->CacheSegmentSize)
663 || (WriteOffset.u.LowPart + Length > CacheSeg->FileOffset &&
664 WriteOffset.u.LowPart + Length <=
665 CacheSeg->FileOffset + Bcb->CacheSegmentSize))
666 {
667 KeReleaseSpinLock(&Bcb->BcbLock, oldirql);
668 /* datas not available */
669 return(FALSE);
670 }
671 }
672 current_entry = current_entry->Flink;
673 }
674 KeReleaseSpinLock(&Bcb->BcbLock, oldirql);
675 }
676 while (Length > 0)
677 {
678 ULONG Offset;
679 Offset = WriteOffset.u.LowPart % Bcb->CacheSegmentSize;
680 if (Length + Offset > MAX_ZERO_LENGTH)
681 {
682 CurrentLength = MAX_ZERO_LENGTH - Offset;
683 }
684 else
685 {
686 CurrentLength = Length;
687 }
688 Status = CcRosGetCacheSegmentChain (Bcb, WriteOffset.u.LowPart - Offset,
689 Offset + CurrentLength, &CacheSeg);
690 if (!NT_SUCCESS(Status))
691 {
692 return FALSE;
693 }
694 current = CacheSeg;
695
696 while (current != NULL)
697 {
698 Offset = WriteOffset.u.LowPart % Bcb->CacheSegmentSize;
699 if (Offset != 0 ||
700 Offset + CurrentLength < Bcb->CacheSegmentSize)
701 {
702 if (!current->Valid)
703 {
704 /* read the segment */
705 Status = ReadCacheSegment(current);
706 if (!NT_SUCCESS(Status))
707 {
708 DPRINT1("ReadCacheSegment failed, status %x\n",
709 Status);
710 }
711 }
712 TempLength = min (CurrentLength, Bcb->CacheSegmentSize - Offset);
713 }
714 else
715 {
716 TempLength = Bcb->CacheSegmentSize;
717 }
718 memset ((PUCHAR)current->BaseAddress + Offset, 0, TempLength);
719
720 WriteOffset.QuadPart += TempLength;
721 CurrentLength -= TempLength;
722 Length -= TempLength;
723
724 current = current->NextInChain;
725 }
726
727 current = CacheSeg;
728 while (current != NULL)
729 {
730 previous = current;
731 current = current->NextInChain;
732 CcRosReleaseCacheSegment(Bcb, previous, TRUE, TRUE, FALSE);
733 }
734 }
735 }
736 return(TRUE);
737 }