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