added stubs for the Cache Manager by Alex Ionescu.
[reactos.git] / reactos / ntoskrnl / cc / copy.c
1 /* $Id: copy.c,v 1.24 2004/06/19 05:04:33 sedwards 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 #if defined(__GNUC__)
30 static PHYSICAL_ADDRESS CcZeroPage = (PHYSICAL_ADDRESS)0LL;
31 #else
32 static PHYSICAL_ADDRESS CcZeroPage = { 0 };
33 #endif
34
35 #define MAX_ZERO_LENGTH (256 * 1024)
36 #define MAX_RW_LENGTH (64 * 1024)
37
38 #if defined(__GNUC__)
39 void * alloca(size_t size);
40 #elif defined(_MSC_VER)
41 void* _alloca(size_t size);
42 #else
43 #error Unknown compiler for alloca intrinsic stack allocation "function"
44 #endif
45
46 ULONG EXPORTED CcFastMdlReadWait;
47 ULONG EXPORTED CcFastReadNotPossible;
48 ULONG EXPORTED CcFastReadWait;
49
50 /* FUNCTIONS *****************************************************************/
51
52 VOID
53 CcInitCacheZeroPage(VOID)
54 {
55 NTSTATUS Status;
56
57 Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &CcZeroPage);
58 if (!NT_SUCCESS(Status))
59 {
60 DbgPrint("Can't allocate CcZeroPage.\n");
61 KEBUGCHECK(0);
62 }
63 Status = MiZeroPage(CcZeroPage);
64 if (!NT_SUCCESS(Status))
65 {
66 DbgPrint("Can't zero out CcZeroPage.\n");
67 KEBUGCHECK(0);
68 }
69 }
70
71 NTSTATUS
72 ReadCacheSegmentChain(PBCB Bcb, ULONG ReadOffset, ULONG Length,
73 PVOID Buffer)
74 {
75 PCACHE_SEGMENT head;
76 PCACHE_SEGMENT current;
77 PCACHE_SEGMENT previous;
78 IO_STATUS_BLOCK Iosb;
79 LARGE_INTEGER SegOffset;
80 NTSTATUS Status;
81 ULONG TempLength;
82 KEVENT Event;
83 PMDL Mdl;
84
85 Mdl = alloca(MmSizeOfMdl(NULL, MAX_RW_LENGTH));
86
87 Status = CcRosGetCacheSegmentChain(Bcb, ReadOffset, Length, &head);
88 if (!NT_SUCCESS(Status))
89 {
90 return(Status);
91 }
92 current = head;
93 while (current != NULL)
94 {
95 /*
96 * If the current segment is valid then copy it into the
97 * user buffer.
98 */
99 if (current->Valid)
100 {
101 TempLength = min(Bcb->CacheSegmentSize, Length);
102 memcpy(Buffer, current->BaseAddress, TempLength);
103 #if defined(__GNUC__)
104 Buffer += TempLength;
105 #else
106 {
107 char* pTemp = Buffer;
108 pTemp += TempLength;
109 Buffer = pTemp;
110 }
111 #endif
112 Length = Length - TempLength;
113 previous = current;
114 current = current->NextInChain;
115 CcRosReleaseCacheSegment(Bcb, previous, TRUE, FALSE, FALSE);
116 }
117 /*
118 * Otherwise read in as much as we can.
119 */
120 else
121 {
122 PCACHE_SEGMENT current2;
123 ULONG current_size;
124 ULONG i;
125 ULONG offset;
126
127 /*
128 * Count the maximum number of bytes we could read starting
129 * from the current segment.
130 */
131 current2 = current;
132 current_size = 0;
133 while (current2 != NULL && !current2->Valid)
134 {
135 current2 = current2->NextInChain;
136 current_size += Bcb->CacheSegmentSize;
137 }
138
139 /*
140 * Create an MDL which contains all their pages.
141 */
142 MmInitializeMdl(Mdl, NULL, current_size);
143 Mdl->MdlFlags |= (MDL_PAGES_LOCKED | MDL_IO_PAGE_READ);
144 current2 = current;
145 offset = 0;
146 while (current2 != NULL && !current2->Valid)
147 {
148 for (i = 0; i < (Bcb->CacheSegmentSize / PAGE_SIZE); i++)
149 {
150 PVOID address;
151 PHYSICAL_ADDRESS page;
152 address = (char*)current2->BaseAddress + (i * PAGE_SIZE);
153 page = MmGetPhysicalAddressForProcess(NULL, address);
154 ((PULONG)(Mdl + 1))[offset] = page.QuadPart >> PAGE_SHIFT;
155 offset++;
156 }
157 current2 = current2->NextInChain;
158 }
159
160 /*
161 * Read in the information.
162 */
163 SegOffset.QuadPart = current->FileOffset;
164 KeInitializeEvent(&Event, NotificationEvent, FALSE);
165 Status = IoPageRead(Bcb->FileObject,
166 Mdl,
167 &SegOffset,
168 &Event,
169 &Iosb);
170 if (Status == STATUS_PENDING)
171 {
172 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
173 Status = Iosb.Status;
174 }
175 MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
176 if (!NT_SUCCESS(Status) && Status != STATUS_END_OF_FILE)
177 {
178 while (current != NULL)
179 {
180 previous = current;
181 current = current->NextInChain;
182 CcRosReleaseCacheSegment(Bcb, previous, FALSE, FALSE, FALSE);
183 }
184 return(Status);
185 }
186 while (current != NULL && !current->Valid)
187 {
188 previous = current;
189 current = current->NextInChain;
190 TempLength = min(Bcb->CacheSegmentSize, Length);
191 memcpy(Buffer, previous->BaseAddress, TempLength);
192 #if defined(__GNUC__)
193 Buffer += TempLength;
194 #else
195 {
196 char* pTemp = Buffer;
197 pTemp += TempLength;
198 Buffer = pTemp;
199 }
200 #endif
201 Length = Length - TempLength;
202 CcRosReleaseCacheSegment(Bcb, previous, TRUE, FALSE, FALSE);
203 }
204 }
205 }
206 return(STATUS_SUCCESS);
207 }
208
209 NTSTATUS
210 ReadCacheSegment(PCACHE_SEGMENT CacheSeg)
211 {
212 ULONG Size;
213 PMDL Mdl;
214 NTSTATUS Status;
215 LARGE_INTEGER SegOffset;
216 IO_STATUS_BLOCK IoStatus;
217 KEVENT Event;
218
219 SegOffset.QuadPart = CacheSeg->FileOffset;
220 Size = (ULONG)(CacheSeg->Bcb->AllocationSize.QuadPart - CacheSeg->FileOffset);
221 if (Size > CacheSeg->Bcb->CacheSegmentSize)
222 {
223 Size = CacheSeg->Bcb->CacheSegmentSize;
224 }
225 Mdl = alloca(MmSizeOfMdl(CacheSeg->BaseAddress, Size));
226 MmInitializeMdl(Mdl, CacheSeg->BaseAddress, Size);
227 MmBuildMdlForNonPagedPool(Mdl);
228 Mdl->MdlFlags |= MDL_IO_PAGE_READ;
229 KeInitializeEvent(&Event, NotificationEvent, FALSE);
230 Status = IoPageRead(CacheSeg->Bcb->FileObject, Mdl, &SegOffset, & Event, &IoStatus);
231 if (Status == STATUS_PENDING)
232 {
233 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
234 Status = IoStatus.Status;
235 }
236
237 if (!NT_SUCCESS(Status) && Status != STATUS_END_OF_FILE)
238 {
239 DPRINT1("IoPageRead failed, Status %x\n", Status);
240 return Status;
241 }
242 if (CacheSeg->Bcb->CacheSegmentSize > Size)
243 {
244 memset ((char*)CacheSeg->BaseAddress + Size, 0,
245 CacheSeg->Bcb->CacheSegmentSize - Size);
246 }
247 return STATUS_SUCCESS;
248 }
249
250 NTSTATUS
251 WriteCacheSegment(PCACHE_SEGMENT CacheSeg)
252 {
253 ULONG Size;
254 PMDL Mdl;
255 NTSTATUS Status;
256 IO_STATUS_BLOCK IoStatus;
257 LARGE_INTEGER SegOffset;
258 KEVENT Event;
259
260 CacheSeg->Dirty = FALSE;
261 SegOffset.QuadPart = CacheSeg->FileOffset;
262 Size = (ULONG)(CacheSeg->Bcb->AllocationSize.QuadPart - CacheSeg->FileOffset);
263 if (Size > CacheSeg->Bcb->CacheSegmentSize)
264 {
265 Size = CacheSeg->Bcb->CacheSegmentSize;
266 }
267 Mdl = alloca(MmSizeOfMdl(CacheSeg->BaseAddress, Size));
268 MmInitializeMdl(Mdl, CacheSeg->BaseAddress, Size);
269 MmBuildMdlForNonPagedPool(Mdl);
270 Mdl->MdlFlags |= MDL_IO_PAGE_READ;
271 KeInitializeEvent(&Event, NotificationEvent, FALSE);
272 Status = IoPageWrite(CacheSeg->Bcb->FileObject, Mdl, &SegOffset, &Event, &IoStatus);
273 if (Status == STATUS_PENDING)
274 {
275 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
276 Status = IoStatus.Status;
277 }
278 if (!NT_SUCCESS(Status) && (Status != STATUS_END_OF_FILE))
279 {
280 DPRINT1("IoPageWrite failed, Status %x\n", Status);
281 CacheSeg->Dirty = TRUE;
282 return(Status);
283 }
284 return(STATUS_SUCCESS);
285 }
286
287 /* STUBS */
288
289 /*
290 * @unimplemented
291 */
292 BOOLEAN STDCALL
293 CcCanIWrite (
294 IN PFILE_OBJECT FileObject,
295 IN ULONG BytesToWrite,
296 IN BOOLEAN Wait,
297 IN BOOLEAN Retrying)
298 {
299 UNIMPLEMENTED;
300 return FALSE;
301 }
302
303 /*
304 * @unimplemented
305 */
306 VOID
307 STDCALL
308 CcDeferWrite (
309 IN PFILE_OBJECT FileObject,
310 IN PCC_POST_DEFERRED_WRITE PostRoutine,
311 IN PVOID Context1,
312 IN PVOID Context2,
313 IN ULONG BytesToWrite,
314 IN BOOLEAN Retrying
315 )
316 {
317 UNIMPLEMENTED;
318 }
319
320 /*
321 * @unimplemented
322 */
323 BOOLEAN
324 STDCALL
325 CcFastCopyRead (
326 IN PFILE_OBJECT FileObject,
327 IN ULONG FileOffset,
328 IN ULONG Length,
329 IN ULONG PageCount,
330 OUT PVOID Buffer,
331 OUT PIO_STATUS_BLOCK IoStatus
332 )
333 {
334 UNIMPLEMENTED;
335 return FALSE;
336 }
337 /*
338 * @unimplemented
339 */
340 BOOLEAN
341 STDCALL
342 CcFastCopyWrite (
343 IN PFILE_OBJECT FileObject,
344 IN PLARGE_INTEGER FileOffset,
345 IN ULONG Length,
346 IN PVOID Buffer
347 )
348 {
349 UNIMPLEMENTED;
350 return FALSE;
351 }
352 /*
353 * @unimplemented
354 */
355 LARGE_INTEGER
356 STDCALL
357 CcGetDirtyPages (
358 IN PVOID LogHandle,
359 IN PDIRTY_PAGE_ROUTINE DirtyPageRoutine,
360 IN PVOID Context1,
361 IN PVOID Context2
362 )
363 {
364 UNIMPLEMENTED;
365
366 LARGE_INTEGER i;
367 i.QuadPart = 0;
368 return i;
369 }
370 /*
371 * @unimplemented
372 */
373 PFILE_OBJECT
374 STDCALL
375 CcGetFileObjectFromBcb (
376 IN PVOID Bcb
377 )
378 {
379 UNIMPLEMENTED;
380 return 0;
381 }
382
383 /*
384 * @unimplemented
385 */
386 VOID
387 STDCALL
388 CcInitializeCacheMap (
389 IN PFILE_OBJECT FileObject,
390 IN PCC_FILE_SIZES FileSizes,
391 IN BOOLEAN PinAccess,
392 IN PCACHE_MANAGER_CALLBACKS CallBacks,
393 IN PVOID LazyWriterContext
394 )
395 {
396 UNIMPLEMENTED;
397 }
398
399 /*
400 * @unimplemented
401 */
402 BOOLEAN
403 STDCALL
404 CcIsThereDirtyData (
405 IN PVPB Vpb
406 )
407 {
408 UNIMPLEMENTED;
409 return FALSE;
410 }
411
412
413 /*
414 * @unimplemented
415 */
416 LARGE_INTEGER
417 STDCALL
418 CcGetLsnForFileObject (
419 IN PFILE_OBJECT FileObject,
420 OUT PLARGE_INTEGER OldestLsn OPTIONAL
421 )
422 {
423 UNIMPLEMENTED;
424
425 LARGE_INTEGER i;
426 i.QuadPart = 0;
427 return i;
428 }
429
430 /*
431 * @unimplemented
432 */
433 LARGE_INTEGER
434 STDCALL
435 CcGetFlushedValidData (
436 IN PSECTION_OBJECT_POINTERS SectionObjectPointer,
437 IN BOOLEAN BcbListHeld
438 )
439 {
440 UNIMPLEMENTED;
441
442 LARGE_INTEGER i;
443 i.QuadPart = 0;
444 return i;
445 }
446
447
448 /*
449 * @unimplemented
450 */
451 VOID
452 STDCALL
453 CcMdlRead (
454 IN PFILE_OBJECT FileObject,
455 IN PLARGE_INTEGER FileOffset,
456 IN ULONG Length,
457 OUT PMDL * MdlChain,
458 OUT PIO_STATUS_BLOCK IoStatus
459 )
460 {
461 UNIMPLEMENTED;
462 }
463
464 /*
465 * @unimplemented
466 */
467 VOID
468 STDCALL
469 CcMdlWriteComplete (
470 IN PFILE_OBJECT FileObject,
471 IN PLARGE_INTEGER FileOffset,
472 IN PMDL MdlChain
473 )
474 {
475 UNIMPLEMENTED;
476 }
477
478 /*
479 * @unimplemented
480 */
481 VOID
482 STDCALL
483 CcMdlWriteAbort (
484 IN PFILE_OBJECT FileObject,
485 IN PMDL MdlChain
486 )
487 {
488 UNIMPLEMENTED;
489 }
490
491
492 /*
493 * @unimplemented
494 */
495 BOOLEAN
496 STDCALL
497 CcPinMappedData (
498 IN PFILE_OBJECT FileObject,
499 IN PLARGE_INTEGER FileOffset,
500 IN ULONG Length,
501 IN BOOLEAN Wait,
502 OUT PVOID * Bcb
503 )
504 {
505 UNIMPLEMENTED;
506 return FALSE;
507 }
508
509 /*
510 * @unimplemented
511 */
512 BOOLEAN
513 STDCALL
514 CcPinRead (
515 IN PFILE_OBJECT FileObject,
516 IN PLARGE_INTEGER FileOffset,
517 IN ULONG Length,
518 IN BOOLEAN Wait,
519 OUT PVOID * Bcb,
520 OUT PVOID * Buffer
521 )
522 {
523 UNIMPLEMENTED;
524 return FALSE;
525 }
526
527 /*
528 * @unimplemented
529 */
530 VOID
531 STDCALL
532 CcPrepareMdlWrite (
533 IN PFILE_OBJECT FileObject,
534 IN PLARGE_INTEGER FileOffset,
535 IN ULONG Length,
536 OUT PMDL * MdlChain,
537 OUT PIO_STATUS_BLOCK IoStatus
538 )
539 {
540 UNIMPLEMENTED;
541 }
542
543 /*
544 * @unimplemented
545 */
546 BOOLEAN
547 STDCALL
548 CcPreparePinWrite (
549 IN PFILE_OBJECT FileObject,
550 IN PLARGE_INTEGER FileOffset,
551 IN ULONG Length,
552 IN BOOLEAN Zero,
553 IN BOOLEAN Wait,
554 OUT PVOID * Bcb,
555 OUT PVOID * Buffer
556 )
557 {
558 UNIMPLEMENTED;
559 return FALSE;
560 }
561
562 /*
563 * @unimplemented
564 */
565 BOOLEAN
566 STDCALL
567 CcPurgeCacheSection (
568 IN PSECTION_OBJECT_POINTERS SectionObjectPointer,
569 IN PLARGE_INTEGER FileOffset OPTIONAL,
570 IN ULONG Length,
571 IN BOOLEAN UninitializeCacheMaps
572 )
573 {
574 UNIMPLEMENTED;
575 return FALSE;
576 }
577
578 /*
579 * @unimplemented
580 */
581 VOID
582 STDCALL
583 CcRepinBcb (
584 IN PVOID Bcb
585 )
586 {
587 UNIMPLEMENTED;
588 }
589
590 /*
591 * @unimplemented
592 */
593 VOID
594 STDCALL
595 CcRemapBcb (
596 IN PVOID Bcb
597 )
598 {
599 UNIMPLEMENTED;
600 }
601
602 /*
603 * @unimplemented
604 */
605 VOID
606 STDCALL
607 CcScheduleReadAhead (
608 IN PFILE_OBJECT FileObject,
609 IN PLARGE_INTEGER FileOffset,
610 IN ULONG Length
611 )
612 {
613 UNIMPLEMENTED;
614 }
615
616 /*
617 * @unimplemented
618 */
619 VOID
620 STDCALL
621 CcSetAdditionalCacheAttributes (
622 IN PFILE_OBJECT FileObject,
623 IN BOOLEAN DisableReadAhead,
624 IN BOOLEAN DisableWriteBehind
625 )
626 {
627 UNIMPLEMENTED;
628 }
629
630 /*
631 * @unimplemented
632 */
633 VOID
634 STDCALL
635 CcSetBcbOwnerPointer (
636 IN PVOID Bcb,
637 IN PVOID Owner
638 )
639 {
640 UNIMPLEMENTED;
641 }
642
643 /*
644 * @unimplemented
645 */
646 VOID
647 STDCALL
648 CcSetDirtyPageThreshold (
649 IN PFILE_OBJECT FileObject,
650 IN ULONG DirtyPageThreshold
651 )
652 {
653 UNIMPLEMENTED;
654 }
655
656 /*
657 * @unimplemented
658 */
659 VOID
660 STDCALL
661 CcSetLogHandleForFile (
662 IN PFILE_OBJECT FileObject,
663 IN PVOID LogHandle,
664 IN PFLUSH_TO_LSN FlushToLsnRoutine
665 )
666 {
667 UNIMPLEMENTED;
668 }
669
670 /*
671 * @unimplemented
672 */
673 VOID
674 STDCALL
675 CcSetReadAheadGranularity (
676 IN PFILE_OBJECT FileObject,
677 IN ULONG Granularity
678 )
679 {
680 UNIMPLEMENTED;
681 }
682
683 /*
684 * @unimplemented
685 */
686 BOOLEAN
687 STDCALL
688 CcUninitializeCacheMap (
689 IN PFILE_OBJECT FileObject,
690 IN PLARGE_INTEGER TruncateSize OPTIONAL,
691 IN PCACHE_UNINITIALIZE_EVENT UninitializeCompleteEvent OPTIONAL
692 )
693 {
694 UNIMPLEMENTED;
695 return FALSE;
696 }
697
698 /*
699 * @unimplemented
700 */
701 VOID
702 STDCALL
703 CcUnpinDataForThread (
704 IN PVOID Bcb,
705 IN ERESOURCE_THREAD ResourceThreadId
706 )
707 {
708 UNIMPLEMENTED;
709 }
710
711 /*
712 * @unimplemented
713 */
714 VOID
715 STDCALL
716 CcUnpinRepinnedBcb (
717 IN PVOID Bcb,
718 IN BOOLEAN WriteThrough,
719 IN PIO_STATUS_BLOCK IoStatus
720 )
721 {
722 UNIMPLEMENTED;
723 }
724
725 /*
726 * @unimplemented
727 */
728 NTSTATUS
729 STDCALL
730 CcWaitForCurrentLazyWriterActivity (
731 VOID
732 )
733 {
734 UNIMPLEMENTED;
735 return STATUS_NOT_IMPLEMENTED;
736 }
737
738 /* STUBS END!!! */
739
740 /*
741 * @implemented
742 */
743 BOOLEAN STDCALL
744 CcCopyRead (IN PFILE_OBJECT FileObject,
745 IN PLARGE_INTEGER FileOffset,
746 IN ULONG Length,
747 IN BOOLEAN Wait,
748 OUT PVOID Buffer,
749 OUT PIO_STATUS_BLOCK IoStatus)
750 {
751 ULONG ReadOffset;
752 ULONG TempLength;
753 NTSTATUS Status = STATUS_SUCCESS;
754 PVOID BaseAddress;
755 PCACHE_SEGMENT CacheSeg;
756 BOOLEAN Valid;
757 ULONG ReadLength = 0;
758 PBCB Bcb;
759 KIRQL oldirql;
760 PLIST_ENTRY current_entry;
761 PCACHE_SEGMENT current;
762
763 DPRINT("CcCopyRead(FileObject %x, FileOffset %x, "
764 "Length %d, Wait %d, Buffer %x, IoStatus %x)\n",
765 FileObject, (ULONG)FileOffset->QuadPart, Length, Wait,
766 Buffer, IoStatus);
767
768 Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
769 ReadOffset = (ULONG)FileOffset->QuadPart;
770
771 DPRINT("AllocationSize %d, FileSize %d\n",
772 (ULONG)Bcb->AllocationSize.QuadPart,
773 (ULONG)Bcb->FileSize.QuadPart);
774
775 /*
776 * Check for the nowait case that all the cache segments that would
777 * cover this read are in memory.
778 */
779 if (!Wait)
780 {
781 KeAcquireSpinLock(&Bcb->BcbLock, &oldirql);
782 current_entry = Bcb->BcbSegmentListHead.Flink;
783 while (current_entry != &Bcb->BcbSegmentListHead)
784 {
785 current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT,
786 BcbSegmentListEntry);
787 if (!current->Valid && current->FileOffset < ReadOffset + Length
788 && current->FileOffset + Bcb->CacheSegmentSize > ReadOffset)
789 {
790 KeReleaseSpinLock(&Bcb->BcbLock, oldirql);
791 IoStatus->Status = STATUS_UNSUCCESSFUL;
792 IoStatus->Information = 0;
793 return FALSE;
794 }
795 current_entry = current_entry->Flink;
796 }
797 KeReleaseSpinLock(&Bcb->BcbLock, oldirql);
798 }
799
800 TempLength = ReadOffset % Bcb->CacheSegmentSize;
801 if (TempLength != 0)
802 {
803 TempLength = min (Length, Bcb->CacheSegmentSize - TempLength);
804 Status = CcRosRequestCacheSegment(Bcb,
805 ROUND_DOWN(ReadOffset,
806 Bcb->CacheSegmentSize),
807 &BaseAddress, &Valid, &CacheSeg);
808 if (!NT_SUCCESS(Status))
809 {
810 IoStatus->Information = 0;
811 IoStatus->Status = Status;
812 DPRINT("CcRosRequestCacheSegment faild, Status %x\n", Status);
813 return FALSE;
814 }
815 if (!Valid)
816 {
817 Status = ReadCacheSegment(CacheSeg);
818 if (!NT_SUCCESS(Status))
819 {
820 IoStatus->Information = 0;
821 IoStatus->Status = Status;
822 CcRosReleaseCacheSegment(Bcb, CacheSeg, FALSE, FALSE, FALSE);
823 return FALSE;
824 }
825 }
826 memcpy (Buffer, (char*)BaseAddress + ReadOffset % Bcb->CacheSegmentSize,
827 TempLength);
828 CcRosReleaseCacheSegment(Bcb, CacheSeg, TRUE, FALSE, FALSE);
829 ReadLength += TempLength;
830 Length -= TempLength;
831 ReadOffset += TempLength;
832 Buffer = (PVOID)((char*)Buffer + TempLength);
833 }
834 while (Length > 0)
835 {
836 TempLength = min(max(Bcb->CacheSegmentSize, MAX_RW_LENGTH), Length);
837 ReadCacheSegmentChain(Bcb, ReadOffset, TempLength, Buffer);
838 ReadLength += TempLength;
839 Length -= TempLength;
840 ReadOffset += TempLength;
841 #if defined(__GNUC__)
842 Buffer += TempLength;
843 #else
844 {
845 char* pTemp = Buffer;
846 pTemp += TempLength;
847 Buffer = pTemp;
848 }
849 #endif
850 }
851 IoStatus->Status = STATUS_SUCCESS;
852 IoStatus->Information = ReadLength;
853 DPRINT("CcCopyRead O.K.\n");
854 return TRUE;
855 }
856
857 /*
858 * @implemented
859 */
860 BOOLEAN STDCALL
861 CcCopyWrite (IN PFILE_OBJECT FileObject,
862 IN PLARGE_INTEGER FileOffset,
863 IN ULONG Length,
864 IN BOOLEAN Wait,
865 IN PVOID Buffer)
866 {
867 NTSTATUS Status;
868 ULONG WriteOffset;
869 KIRQL oldirql;
870 PBCB Bcb;
871 PLIST_ENTRY current_entry;
872 PCACHE_SEGMENT CacheSeg;
873 ULONG TempLength;
874 PVOID BaseAddress;
875 BOOLEAN Valid;
876
877 DPRINT("CcCopyWrite(FileObject %x, FileOffset %x, "
878 "Length %d, Wait %d, Buffer %x)\n",
879 FileObject, (ULONG)FileOffset->QuadPart, Length, Wait, Buffer);
880
881 Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
882 WriteOffset = (ULONG)FileOffset->QuadPart;
883
884 if (!Wait)
885 {
886 /* testing, if the requested datas are available */
887 KeAcquireSpinLock(&Bcb->BcbLock, &oldirql);
888 current_entry = Bcb->BcbSegmentListHead.Flink;
889 while (current_entry != &Bcb->BcbSegmentListHead)
890 {
891 CacheSeg = CONTAINING_RECORD(current_entry, CACHE_SEGMENT,
892 BcbSegmentListEntry);
893 if (!CacheSeg->Valid)
894 {
895 if ((WriteOffset >= CacheSeg->FileOffset &&
896 WriteOffset < CacheSeg->FileOffset + Bcb->CacheSegmentSize)
897 || (WriteOffset + Length > CacheSeg->FileOffset &&
898 WriteOffset + Length <= CacheSeg->FileOffset +
899 Bcb->CacheSegmentSize))
900 {
901 KeReleaseSpinLock(&Bcb->BcbLock, oldirql);
902 /* datas not available */
903 return(FALSE);
904 }
905 }
906 current_entry = current_entry->Flink;
907 }
908 KeReleaseSpinLock(&Bcb->BcbLock, oldirql);
909 }
910
911 TempLength = WriteOffset % Bcb->CacheSegmentSize;
912 if (TempLength != 0)
913 {
914 ULONG ROffset;
915 ROffset = ROUND_DOWN(WriteOffset, Bcb->CacheSegmentSize);
916 TempLength = min (Length, Bcb->CacheSegmentSize - TempLength);
917 Status = CcRosRequestCacheSegment(Bcb, ROffset,
918 &BaseAddress, &Valid, &CacheSeg);
919 if (!NT_SUCCESS(Status))
920 {
921 return(FALSE);
922 }
923 if (!Valid)
924 {
925 if (!NT_SUCCESS(ReadCacheSegment(CacheSeg)))
926 {
927 return(FALSE);
928 }
929 }
930 memcpy ((char*)BaseAddress + WriteOffset % Bcb->CacheSegmentSize,
931 Buffer, TempLength);
932 CcRosReleaseCacheSegment(Bcb, CacheSeg, TRUE, TRUE, FALSE);
933
934 Length -= TempLength;
935 WriteOffset += TempLength;
936 #if defined(__GNUC__)
937 Buffer += TempLength;
938 #else
939 {
940 char* pTemp = Buffer;
941 pTemp += TempLength;
942 Buffer = pTemp;
943 }
944 #endif
945 }
946
947 while (Length > 0)
948 {
949 TempLength = min (Bcb->CacheSegmentSize, Length);
950 Status = CcRosRequestCacheSegment(Bcb, WriteOffset,
951 &BaseAddress, &Valid, &CacheSeg);
952 if (!NT_SUCCESS(Status))
953 {
954 return(FALSE);
955 }
956 if (!Valid && TempLength < Bcb->CacheSegmentSize)
957 {
958 if (!NT_SUCCESS(ReadCacheSegment(CacheSeg)))
959 {
960 CcRosReleaseCacheSegment(Bcb, CacheSeg, FALSE, FALSE, FALSE);
961 return FALSE;
962 }
963 }
964 memcpy (BaseAddress, Buffer, TempLength);
965 CcRosReleaseCacheSegment(Bcb, CacheSeg, TRUE, TRUE, FALSE);
966 Length -= TempLength;
967 WriteOffset += TempLength;
968 #if defined(__GNUC__)
969 Buffer += TempLength;
970 #else
971 {
972 char* pTemp = Buffer;
973 pTemp += TempLength;
974 Buffer = pTemp;
975 }
976 #endif
977 }
978 return(TRUE);
979 }
980
981 /*
982 * @implemented
983 */
984 BOOLEAN STDCALL
985 CcZeroData (IN PFILE_OBJECT FileObject,
986 IN PLARGE_INTEGER StartOffset,
987 IN PLARGE_INTEGER EndOffset,
988 IN BOOLEAN Wait)
989 {
990 NTSTATUS Status;
991 LARGE_INTEGER WriteOffset;
992 ULONG Length;
993 ULONG CurrentLength;
994 PMDL Mdl;
995 ULONG i;
996 IO_STATUS_BLOCK Iosb;
997 KEVENT Event;
998
999 DPRINT("CcZeroData(FileObject %x, StartOffset %I64x, EndOffset %I64x, "
1000 "Wait %d)\n", FileObject, StartOffset->QuadPart, EndOffset->QuadPart,
1001 Wait);
1002
1003 Length = EndOffset->u.LowPart - StartOffset->u.LowPart;
1004 WriteOffset.QuadPart = StartOffset->QuadPart;
1005
1006 if (FileObject->SectionObjectPointer->SharedCacheMap == NULL)
1007 {
1008 /* File is not cached */
1009
1010 Mdl = alloca(MmSizeOfMdl(NULL, MAX_ZERO_LENGTH));
1011
1012 while (Length > 0)
1013 {
1014 if (Length + WriteOffset.u.LowPart % PAGE_SIZE > MAX_ZERO_LENGTH)
1015 {
1016 CurrentLength = MAX_ZERO_LENGTH - WriteOffset.u.LowPart % PAGE_SIZE;
1017 }
1018 else
1019 {
1020 CurrentLength = Length;
1021 }
1022 MmInitializeMdl(Mdl, (PVOID)WriteOffset.u.LowPart, CurrentLength);
1023 Mdl->MdlFlags |= (MDL_PAGES_LOCKED | MDL_IO_PAGE_READ);
1024 for (i = 0; i < ((Mdl->Size - sizeof(MDL)) / sizeof(ULONG)); i++)
1025 {
1026 ((PULONG)(Mdl + 1))[i] = CcZeroPage.QuadPart >> PAGE_SHIFT;
1027 }
1028 KeInitializeEvent(&Event, NotificationEvent, FALSE);
1029 Status = IoPageWrite(FileObject, Mdl, &WriteOffset, &Event, &Iosb);
1030 if (Status == STATUS_PENDING)
1031 {
1032 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
1033 Status = Iosb.Status;
1034 }
1035 MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
1036 if (!NT_SUCCESS(Status))
1037 {
1038 return(FALSE);
1039 }
1040 WriteOffset.QuadPart += CurrentLength;
1041 Length -= CurrentLength;
1042 }
1043 }
1044 else
1045 {
1046 /* File is cached */
1047 KIRQL oldirql;
1048 PBCB Bcb;
1049 PLIST_ENTRY current_entry;
1050 PCACHE_SEGMENT CacheSeg, current, previous;
1051 ULONG TempLength;
1052
1053 Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
1054 if (Wait)
1055 {
1056 /* testing, if the requested datas are available */
1057 KeAcquireSpinLock(&Bcb->BcbLock, &oldirql);
1058 current_entry = Bcb->BcbSegmentListHead.Flink;
1059 while (current_entry != &Bcb->BcbSegmentListHead)
1060 {
1061 CacheSeg = CONTAINING_RECORD(current_entry, CACHE_SEGMENT,
1062 BcbSegmentListEntry);
1063 if (!CacheSeg->Valid)
1064 {
1065 if ((WriteOffset.u.LowPart >= CacheSeg->FileOffset &&
1066 WriteOffset.u.LowPart < CacheSeg->FileOffset + Bcb->CacheSegmentSize)
1067 || (WriteOffset.u.LowPart + Length > CacheSeg->FileOffset &&
1068 WriteOffset.u.LowPart + Length <=
1069 CacheSeg->FileOffset + Bcb->CacheSegmentSize))
1070 {
1071 KeReleaseSpinLock(&Bcb->BcbLock, oldirql);
1072 /* datas not available */
1073 return(FALSE);
1074 }
1075 }
1076 current_entry = current_entry->Flink;
1077 }
1078 KeReleaseSpinLock(&Bcb->BcbLock, oldirql);
1079 }
1080 while (Length > 0)
1081 {
1082 ULONG Offset;
1083 Offset = WriteOffset.u.LowPart % Bcb->CacheSegmentSize;
1084 if (Length + Offset > MAX_ZERO_LENGTH)
1085 {
1086 CurrentLength = MAX_ZERO_LENGTH - Offset;
1087 }
1088 else
1089 {
1090 CurrentLength = Length;
1091 }
1092 Status = CcRosGetCacheSegmentChain (Bcb, WriteOffset.u.LowPart - Offset,
1093 Offset + CurrentLength, &CacheSeg);
1094 if (!NT_SUCCESS(Status))
1095 {
1096 return FALSE;
1097 }
1098 current = CacheSeg;
1099
1100 while (current != NULL)
1101 {
1102 Offset = WriteOffset.u.LowPart % Bcb->CacheSegmentSize;
1103 if (Offset != 0 ||
1104 Offset + CurrentLength < Bcb->CacheSegmentSize)
1105 {
1106 if (!current->Valid)
1107 {
1108 /* read the segment */
1109 Status = ReadCacheSegment(current);
1110 if (!NT_SUCCESS(Status))
1111 {
1112 DPRINT1("ReadCacheSegment failed, status %x\n",
1113 Status);
1114 }
1115 }
1116 TempLength = min (CurrentLength, Bcb->CacheSegmentSize - Offset);
1117 }
1118 else
1119 {
1120 TempLength = Bcb->CacheSegmentSize;
1121 }
1122 memset ((PUCHAR)current->BaseAddress + Offset, 0, TempLength);
1123
1124 WriteOffset.QuadPart += TempLength;
1125 CurrentLength -= TempLength;
1126 Length -= TempLength;
1127
1128 current = current->NextInChain;
1129 }
1130
1131 current = CacheSeg;
1132 while (current != NULL)
1133 {
1134 previous = current;
1135 current = current->NextInChain;
1136 CcRosReleaseCacheSegment(Bcb, previous, TRUE, TRUE, FALSE);
1137 }
1138 }
1139 }
1140 return(TRUE);
1141 }
1142