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