1 /* $Id: copy.c,v 1.26 2004/06/20 02:10:07 vizzini Exp $
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
12 /* INCLUDES ******************************************************************/
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>
23 #include <internal/debug.h>
25 /* GLOBALS *******************************************************************/
27 #define ROUND_DOWN(N, S) ((N) - ((N) % (S)))
30 static PHYSICAL_ADDRESS CcZeroPage
= (PHYSICAL_ADDRESS
)0LL;
32 static PHYSICAL_ADDRESS CcZeroPage
= { 0 };
35 #define MAX_ZERO_LENGTH (256 * 1024)
36 #define MAX_RW_LENGTH (64 * 1024)
39 void * alloca(size_t size
);
40 #elif defined(_MSC_VER)
41 void* _alloca(size_t size
);
43 #error Unknown compiler for alloca intrinsic stack allocation "function"
46 ULONG EXPORTED CcFastMdlReadWait
;
47 ULONG EXPORTED CcFastReadNotPossible
;
48 ULONG EXPORTED CcFastReadWait
;
50 /* FUNCTIONS *****************************************************************/
53 CcInitCacheZeroPage(VOID
)
57 Status
= MmRequestPageMemoryConsumer(MC_NPPOOL
, FALSE
, &CcZeroPage
);
58 if (!NT_SUCCESS(Status
))
60 DbgPrint("Can't allocate CcZeroPage.\n");
63 Status
= MiZeroPage(CcZeroPage
);
64 if (!NT_SUCCESS(Status
))
66 DbgPrint("Can't zero out CcZeroPage.\n");
72 ReadCacheSegmentChain(PBCB Bcb
, ULONG ReadOffset
, ULONG Length
,
76 PCACHE_SEGMENT current
;
77 PCACHE_SEGMENT previous
;
79 LARGE_INTEGER SegOffset
;
85 Mdl
= alloca(MmSizeOfMdl(NULL
, MAX_RW_LENGTH
));
87 Status
= CcRosGetCacheSegmentChain(Bcb
, ReadOffset
, Length
, &head
);
88 if (!NT_SUCCESS(Status
))
93 while (current
!= NULL
)
96 * If the current segment is valid then copy it into the
101 TempLength
= min(Bcb
->CacheSegmentSize
, Length
);
102 memcpy(Buffer
, current
->BaseAddress
, TempLength
);
103 #if defined(__GNUC__)
104 Buffer
+= TempLength
;
107 char* pTemp
= Buffer
;
112 Length
= Length
- TempLength
;
114 current
= current
->NextInChain
;
115 CcRosReleaseCacheSegment(Bcb
, previous
, TRUE
, FALSE
, FALSE
);
118 * Otherwise read in as much as we can.
122 PCACHE_SEGMENT current2
;
128 * Count the maximum number of bytes we could read starting
129 * from the current segment.
133 while (current2
!= NULL
&& !current2
->Valid
)
135 current2
= current2
->NextInChain
;
136 current_size
+= Bcb
->CacheSegmentSize
;
140 * Create an MDL which contains all their pages.
142 MmInitializeMdl(Mdl
, NULL
, current_size
);
143 Mdl
->MdlFlags
|= (MDL_PAGES_LOCKED
| MDL_IO_PAGE_READ
);
146 while (current2
!= NULL
&& !current2
->Valid
)
148 for (i
= 0; i
< (Bcb
->CacheSegmentSize
/ PAGE_SIZE
); i
++)
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
;
157 current2
= current2
->NextInChain
;
161 * Read in the information.
163 SegOffset
.QuadPart
= current
->FileOffset
;
164 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
165 Status
= IoPageRead(Bcb
->FileObject
,
170 if (Status
== STATUS_PENDING
)
172 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
173 Status
= Iosb
.Status
;
175 MmUnmapLockedPages(Mdl
->MappedSystemVa
, Mdl
);
176 if (!NT_SUCCESS(Status
) && Status
!= STATUS_END_OF_FILE
)
178 while (current
!= NULL
)
181 current
= current
->NextInChain
;
182 CcRosReleaseCacheSegment(Bcb
, previous
, FALSE
, FALSE
, FALSE
);
186 while (current
!= NULL
&& !current
->Valid
)
189 current
= current
->NextInChain
;
190 TempLength
= min(Bcb
->CacheSegmentSize
, Length
);
191 memcpy(Buffer
, previous
->BaseAddress
, TempLength
);
192 #if defined(__GNUC__)
193 Buffer
+= TempLength
;
196 char* pTemp
= Buffer
;
201 Length
= Length
- TempLength
;
202 CcRosReleaseCacheSegment(Bcb
, previous
, TRUE
, FALSE
, FALSE
);
206 return(STATUS_SUCCESS
);
210 ReadCacheSegment(PCACHE_SEGMENT CacheSeg
)
215 LARGE_INTEGER SegOffset
;
216 IO_STATUS_BLOCK IoStatus
;
219 SegOffset
.QuadPart
= CacheSeg
->FileOffset
;
220 Size
= (ULONG
)(CacheSeg
->Bcb
->AllocationSize
.QuadPart
- CacheSeg
->FileOffset
);
221 if (Size
> CacheSeg
->Bcb
->CacheSegmentSize
)
223 Size
= CacheSeg
->Bcb
->CacheSegmentSize
;
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
)
233 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
234 Status
= IoStatus
.Status
;
237 if (!NT_SUCCESS(Status
) && Status
!= STATUS_END_OF_FILE
)
239 DPRINT1("IoPageRead failed, Status %x\n", Status
);
242 if (CacheSeg
->Bcb
->CacheSegmentSize
> Size
)
244 memset ((char*)CacheSeg
->BaseAddress
+ Size
, 0,
245 CacheSeg
->Bcb
->CacheSegmentSize
- Size
);
247 return STATUS_SUCCESS
;
251 WriteCacheSegment(PCACHE_SEGMENT CacheSeg
)
256 IO_STATUS_BLOCK IoStatus
;
257 LARGE_INTEGER SegOffset
;
260 CacheSeg
->Dirty
= FALSE
;
261 SegOffset
.QuadPart
= CacheSeg
->FileOffset
;
262 Size
= (ULONG
)(CacheSeg
->Bcb
->AllocationSize
.QuadPart
- CacheSeg
->FileOffset
);
263 if (Size
> CacheSeg
->Bcb
->CacheSegmentSize
)
265 Size
= CacheSeg
->Bcb
->CacheSegmentSize
;
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
)
275 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
276 Status
= IoStatus
.Status
;
278 if (!NT_SUCCESS(Status
) && (Status
!= STATUS_END_OF_FILE
))
280 DPRINT1("IoPageWrite failed, Status %x\n", Status
);
281 CacheSeg
->Dirty
= TRUE
;
284 return(STATUS_SUCCESS
);
294 IN PFILE_OBJECT FileObject
,
295 IN ULONG BytesToWrite
,
309 IN PFILE_OBJECT FileObject
,
310 IN PCC_POST_DEFERRED_WRITE PostRoutine
,
313 IN ULONG BytesToWrite
,
326 IN PFILE_OBJECT FileObject
,
331 OUT PIO_STATUS_BLOCK IoStatus
343 IN PFILE_OBJECT FileObject
,
344 IN PLARGE_INTEGER FileOffset
,
359 IN PDIRTY_PAGE_ROUTINE DirtyPageRoutine
,
375 CcGetFileObjectFromBcb (
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
418 CcGetLsnForFileObject (
419 IN PFILE_OBJECT FileObject
,
420 OUT PLARGE_INTEGER OldestLsn OPTIONAL
435 CcGetFlushedValidData (
436 IN PSECTION_OBJECT_POINTERS SectionObjectPointer
,
437 IN BOOLEAN BcbListHeld
454 IN PFILE_OBJECT FileObject
,
455 IN PLARGE_INTEGER FileOffset
,
458 OUT PIO_STATUS_BLOCK IoStatus
470 IN PFILE_OBJECT FileObject
,
471 IN PLARGE_INTEGER FileOffset
,
484 IN PFILE_OBJECT FileObject
,
498 IN PFILE_OBJECT FileObject
,
499 IN PLARGE_INTEGER FileOffset
,
515 IN PFILE_OBJECT FileObject
,
516 IN PLARGE_INTEGER FileOffset
,
533 IN PFILE_OBJECT FileObject
,
534 IN PLARGE_INTEGER FileOffset
,
537 OUT PIO_STATUS_BLOCK IoStatus
549 IN PFILE_OBJECT FileObject
,
550 IN PLARGE_INTEGER FileOffset
,
567 CcPurgeCacheSection (
568 IN PSECTION_OBJECT_POINTERS SectionObjectPointer
,
569 IN PLARGE_INTEGER FileOffset OPTIONAL
,
571 IN BOOLEAN UninitializeCacheMaps
607 CcScheduleReadAhead (
608 IN PFILE_OBJECT FileObject
,
609 IN PLARGE_INTEGER FileOffset
,
621 CcSetAdditionalCacheAttributes (
622 IN PFILE_OBJECT FileObject
,
623 IN BOOLEAN DisableReadAhead
,
624 IN BOOLEAN DisableWriteBehind
635 CcSetBcbOwnerPointer (
648 CcSetDirtyPageThreshold (
649 IN PFILE_OBJECT FileObject
,
650 IN ULONG DirtyPageThreshold
661 CcSetLogHandleForFile (
662 IN PFILE_OBJECT FileObject
,
664 IN PFLUSH_TO_LSN FlushToLsnRoutine
675 CcSetReadAheadGranularity (
676 IN PFILE_OBJECT FileObject
,
688 CcUninitializeCacheMap (
689 IN PFILE_OBJECT FileObject
,
690 IN PLARGE_INTEGER TruncateSize OPTIONAL
,
691 IN PCACHE_UNINITIALIZE_EVENT UninitializeCompleteEvent OPTIONAL
703 CcUnpinDataForThread (
705 IN ERESOURCE_THREAD ResourceThreadId
718 IN BOOLEAN WriteThrough
,
719 IN PIO_STATUS_BLOCK IoStatus
730 CcWaitForCurrentLazyWriterActivity (
735 return STATUS_NOT_IMPLEMENTED
;
744 CcCopyRead (IN PFILE_OBJECT FileObject
,
745 IN PLARGE_INTEGER FileOffset
,
749 OUT PIO_STATUS_BLOCK IoStatus
)
753 NTSTATUS Status
= STATUS_SUCCESS
;
755 PCACHE_SEGMENT CacheSeg
;
757 ULONG ReadLength
= 0;
760 PLIST_ENTRY current_entry
;
761 PCACHE_SEGMENT current
;
763 DPRINT("CcCopyRead(FileObject %x, FileOffset %x, "
764 "Length %d, Wait %d, Buffer %x, IoStatus %x)\n",
765 FileObject
, (ULONG
)FileOffset
->QuadPart
, Length
, Wait
,
768 Bcb
= FileObject
->SectionObjectPointer
->SharedCacheMap
;
769 ReadOffset
= (ULONG
)FileOffset
->QuadPart
;
771 DPRINT("AllocationSize %d, FileSize %d\n",
772 (ULONG
)Bcb
->AllocationSize
.QuadPart
,
773 (ULONG
)Bcb
->FileSize
.QuadPart
);
776 * Check for the nowait case that all the cache segments that would
777 * cover this read are in memory.
781 KeAcquireSpinLock(&Bcb
->BcbLock
, &oldirql
);
782 current_entry
= Bcb
->BcbSegmentListHead
.Flink
;
783 while (current_entry
!= &Bcb
->BcbSegmentListHead
)
785 current
= CONTAINING_RECORD(current_entry
, CACHE_SEGMENT
,
786 BcbSegmentListEntry
);
787 if (!current
->Valid
&& current
->FileOffset
< ReadOffset
+ Length
788 && current
->FileOffset
+ Bcb
->CacheSegmentSize
> ReadOffset
)
790 KeReleaseSpinLock(&Bcb
->BcbLock
, oldirql
);
791 IoStatus
->Status
= STATUS_UNSUCCESSFUL
;
792 IoStatus
->Information
= 0;
795 current_entry
= current_entry
->Flink
;
797 KeReleaseSpinLock(&Bcb
->BcbLock
, oldirql
);
800 TempLength
= ReadOffset
% Bcb
->CacheSegmentSize
;
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
))
810 IoStatus
->Information
= 0;
811 IoStatus
->Status
= Status
;
812 DPRINT("CcRosRequestCacheSegment faild, Status %x\n", Status
);
817 Status
= ReadCacheSegment(CacheSeg
);
818 if (!NT_SUCCESS(Status
))
820 IoStatus
->Information
= 0;
821 IoStatus
->Status
= Status
;
822 CcRosReleaseCacheSegment(Bcb
, CacheSeg
, FALSE
, FALSE
, FALSE
);
826 memcpy (Buffer
, (char*)BaseAddress
+ ReadOffset
% Bcb
->CacheSegmentSize
,
828 CcRosReleaseCacheSegment(Bcb
, CacheSeg
, TRUE
, FALSE
, FALSE
);
829 ReadLength
+= TempLength
;
830 Length
-= TempLength
;
831 ReadOffset
+= TempLength
;
832 Buffer
= (PVOID
)((char*)Buffer
+ TempLength
);
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
;
845 char* pTemp
= Buffer
;
851 IoStatus
->Status
= STATUS_SUCCESS
;
852 IoStatus
->Information
= ReadLength
;
853 DPRINT("CcCopyRead O.K.\n");
861 CcCopyWrite (IN PFILE_OBJECT FileObject
,
862 IN PLARGE_INTEGER FileOffset
,
871 PLIST_ENTRY current_entry
;
872 PCACHE_SEGMENT CacheSeg
;
877 DPRINT("CcCopyWrite(FileObject %x, FileOffset %x, "
878 "Length %d, Wait %d, Buffer %x)\n",
879 FileObject
, (ULONG
)FileOffset
->QuadPart
, Length
, Wait
, Buffer
);
881 Bcb
= FileObject
->SectionObjectPointer
->SharedCacheMap
;
882 WriteOffset
= (ULONG
)FileOffset
->QuadPart
;
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
)
891 CacheSeg
= CONTAINING_RECORD(current_entry
, CACHE_SEGMENT
,
892 BcbSegmentListEntry
);
893 if (!CacheSeg
->Valid
)
895 if ((WriteOffset
>= CacheSeg
->FileOffset
&&
896 WriteOffset
< CacheSeg
->FileOffset
+ Bcb
->CacheSegmentSize
)
897 || (WriteOffset
+ Length
> CacheSeg
->FileOffset
&&
898 WriteOffset
+ Length
<= CacheSeg
->FileOffset
+
899 Bcb
->CacheSegmentSize
))
901 KeReleaseSpinLock(&Bcb
->BcbLock
, oldirql
);
902 /* datas not available */
906 current_entry
= current_entry
->Flink
;
908 KeReleaseSpinLock(&Bcb
->BcbLock
, oldirql
);
911 TempLength
= WriteOffset
% Bcb
->CacheSegmentSize
;
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
))
925 if (!NT_SUCCESS(ReadCacheSegment(CacheSeg
)))
930 memcpy ((char*)BaseAddress
+ WriteOffset
% Bcb
->CacheSegmentSize
,
932 CcRosReleaseCacheSegment(Bcb
, CacheSeg
, TRUE
, TRUE
, FALSE
);
934 Length
-= TempLength
;
935 WriteOffset
+= TempLength
;
936 #if defined(__GNUC__)
937 Buffer
+= TempLength
;
940 char* pTemp
= Buffer
;
949 TempLength
= min (Bcb
->CacheSegmentSize
, Length
);
950 Status
= CcRosRequestCacheSegment(Bcb
, WriteOffset
,
951 &BaseAddress
, &Valid
, &CacheSeg
);
952 if (!NT_SUCCESS(Status
))
956 if (!Valid
&& TempLength
< Bcb
->CacheSegmentSize
)
958 if (!NT_SUCCESS(ReadCacheSegment(CacheSeg
)))
960 CcRosReleaseCacheSegment(Bcb
, CacheSeg
, FALSE
, FALSE
, FALSE
);
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
;
972 char* pTemp
= Buffer
;
985 CcZeroData (IN PFILE_OBJECT FileObject
,
986 IN PLARGE_INTEGER StartOffset
,
987 IN PLARGE_INTEGER EndOffset
,
991 LARGE_INTEGER WriteOffset
;
996 IO_STATUS_BLOCK Iosb
;
999 DPRINT("CcZeroData(FileObject %x, StartOffset %I64x, EndOffset %I64x, "
1000 "Wait %d)\n", FileObject
, StartOffset
->QuadPart
, EndOffset
->QuadPart
,
1003 Length
= EndOffset
->u
.LowPart
- StartOffset
->u
.LowPart
;
1004 WriteOffset
.QuadPart
= StartOffset
->QuadPart
;
1006 if (FileObject
->SectionObjectPointer
->SharedCacheMap
== NULL
)
1008 /* File is not cached */
1010 Mdl
= alloca(MmSizeOfMdl(NULL
, MAX_ZERO_LENGTH
));
1014 if (Length
+ WriteOffset
.u
.LowPart
% PAGE_SIZE
> MAX_ZERO_LENGTH
)
1016 CurrentLength
= MAX_ZERO_LENGTH
- WriteOffset
.u
.LowPart
% PAGE_SIZE
;
1020 CurrentLength
= Length
;
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
++)
1026 ((PULONG
)(Mdl
+ 1))[i
] = CcZeroPage
.QuadPart
>> PAGE_SHIFT
;
1028 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
1029 Status
= IoPageWrite(FileObject
, Mdl
, &WriteOffset
, &Event
, &Iosb
);
1030 if (Status
== STATUS_PENDING
)
1032 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
1033 Status
= Iosb
.Status
;
1035 MmUnmapLockedPages(Mdl
->MappedSystemVa
, Mdl
);
1036 if (!NT_SUCCESS(Status
))
1040 WriteOffset
.QuadPart
+= CurrentLength
;
1041 Length
-= CurrentLength
;
1046 /* File is cached */
1049 PLIST_ENTRY current_entry
;
1050 PCACHE_SEGMENT CacheSeg
, current
, previous
;
1053 Bcb
= FileObject
->SectionObjectPointer
->SharedCacheMap
;
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
)
1061 CacheSeg
= CONTAINING_RECORD(current_entry
, CACHE_SEGMENT
,
1062 BcbSegmentListEntry
);
1063 if (!CacheSeg
->Valid
)
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
))
1071 KeReleaseSpinLock(&Bcb
->BcbLock
, oldirql
);
1072 /* datas not available */
1076 current_entry
= current_entry
->Flink
;
1078 KeReleaseSpinLock(&Bcb
->BcbLock
, oldirql
);
1083 Offset
= WriteOffset
.u
.LowPart
% Bcb
->CacheSegmentSize
;
1084 if (Length
+ Offset
> MAX_ZERO_LENGTH
)
1086 CurrentLength
= MAX_ZERO_LENGTH
- Offset
;
1090 CurrentLength
= Length
;
1092 Status
= CcRosGetCacheSegmentChain (Bcb
, WriteOffset
.u
.LowPart
- Offset
,
1093 Offset
+ CurrentLength
, &CacheSeg
);
1094 if (!NT_SUCCESS(Status
))
1100 while (current
!= NULL
)
1102 Offset
= WriteOffset
.u
.LowPart
% Bcb
->CacheSegmentSize
;
1104 Offset
+ CurrentLength
< Bcb
->CacheSegmentSize
)
1106 if (!current
->Valid
)
1108 /* read the segment */
1109 Status
= ReadCacheSegment(current
);
1110 if (!NT_SUCCESS(Status
))
1112 DPRINT1("ReadCacheSegment failed, status %x\n",
1116 TempLength
= min (CurrentLength
, Bcb
->CacheSegmentSize
- Offset
);
1120 TempLength
= Bcb
->CacheSegmentSize
;
1122 memset ((PUCHAR
)current
->BaseAddress
+ Offset
, 0, TempLength
);
1124 WriteOffset
.QuadPart
+= TempLength
;
1125 CurrentLength
-= TempLength
;
1126 Length
-= TempLength
;
1128 current
= current
->NextInChain
;
1132 while (current
!= NULL
)
1135 current
= current
->NextInChain
;
1136 CcRosReleaseCacheSegment(Bcb
, previous
, TRUE
, TRUE
, FALSE
);