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