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