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