1 /* $Id: copy.c,v 1.1 2001/10/10 21:46:13 hbirr 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)))
29 /* FUNCTIONS *****************************************************************/
31 NTSTATUS
ReadCacheSegment(PCACHE_SEGMENT CacheSeg
)
36 LARGE_INTEGER SegOffset
;
37 IO_STATUS_BLOCK IoStatus
;
39 SegOffset
.QuadPart
= CacheSeg
->FileOffset
;
40 Size
= CacheSeg
->Bcb
->AllocationSize
.QuadPart
- CacheSeg
->FileOffset
;
41 if (Size
> CacheSeg
->Bcb
->CacheSegmentSize
)
43 Size
= CacheSeg
->Bcb
->CacheSegmentSize
;
45 Mdl
= MmCreateMdl(NULL
, CacheSeg
->BaseAddress
, Size
);
46 MmBuildMdlForNonPagedPool(Mdl
);
47 Status
= IoPageRead(CacheSeg
->Bcb
->FileObject
, Mdl
, &SegOffset
, &IoStatus
, TRUE
);
48 if (!NT_SUCCESS(Status
) && Status
!= STATUS_END_OF_FILE
)
50 CcRosReleaseCacheSegment(CacheSeg
->Bcb
, CacheSeg
, FALSE
);
51 DPRINT1("IoPageRead failed, Status %x\n", Status
);
54 if (CacheSeg
->Bcb
->CacheSegmentSize
> Size
)
56 memset (CacheSeg
->BaseAddress
+ Size
, 0, CacheSeg
->Bcb
->CacheSegmentSize
- Size
);
58 return STATUS_SUCCESS
;
61 NTSTATUS
WriteCacheSegment(PCACHE_SEGMENT CacheSeg
)
66 IO_STATUS_BLOCK IoStatus
;
67 LARGE_INTEGER SegOffset
;
69 SegOffset
.QuadPart
= CacheSeg
->FileOffset
;
70 Size
= CacheSeg
->Bcb
->AllocationSize
.QuadPart
- CacheSeg
->FileOffset
;
71 if (Size
> CacheSeg
->Bcb
->CacheSegmentSize
)
73 Size
= CacheSeg
->Bcb
->CacheSegmentSize
;
75 Mdl
= MmCreateMdl(NULL
, CacheSeg
->BaseAddress
, Size
);
76 MmBuildMdlForNonPagedPool(Mdl
);
77 Status
= IoPageWrite(CacheSeg
->Bcb
->FileObject
, Mdl
, &SegOffset
, &IoStatus
, TRUE
);
78 if (!NT_SUCCESS(Status
))
80 DPRINT1("IoPageWrite failed, Status %x\n", Status
);
87 IN PFILE_OBJECT FileObject
,
88 IN PLARGE_INTEGER FileOffset
,
92 OUT PIO_STATUS_BLOCK IoStatus
)
96 NTSTATUS Status
= STATUS_SUCCESS
;
98 PCACHE_SEGMENT CacheSeg
;
100 ULONG ReadLength
= 0;
103 PLIST_ENTRY current_entry
;
104 PCACHE_SEGMENT current
;
106 DPRINT("CcCopyRead(FileObject %x, FileOffset %x, "
107 "Length %d, Wait %d, Buffer %x, IoStatus %x)\n",
108 FileObject
, (ULONG
)FileOffset
->QuadPart
, Length
, Wait
,
111 Bcb
= ((REACTOS_COMMON_FCB_HEADER
*)FileObject
->FsContext
)->Bcb
;
112 ReadOffset
= FileOffset
->QuadPart
;
114 DPRINT("AllocationSize %d, FileSize %d\n",
115 (ULONG
)Bcb
->AllocationSize
.QuadPart
,
116 (ULONG
)Bcb
->FileSize
.QuadPart
);
120 KeAcquireSpinLock(&Bcb
->BcbLock
, &oldirql
);
121 current_entry
= Bcb
->CacheSegmentListHead
.Flink
;
122 while (current_entry
!= &Bcb
->CacheSegmentListHead
)
124 current
= CONTAINING_RECORD(current_entry
, CACHE_SEGMENT
, BcbListEntry
);
125 if (!current
->Valid
&& current
->FileOffset
< ReadOffset
+ Length
126 && current
->FileOffset
+ Bcb
->CacheSegmentSize
> ReadOffset
)
128 KeReleaseSpinLock(&Bcb
->BcbLock
, oldirql
);
129 IoStatus
->Status
= STATUS_UNSUCCESSFUL
;
130 IoStatus
->Information
= 0;
133 current_entry
= current_entry
->Flink
;
135 KeReleaseSpinLock(&Bcb
->BcbLock
, oldirql
);
138 TempLength
= ReadOffset
% Bcb
->CacheSegmentSize
;
141 TempLength
= min (Length
, Bcb
->CacheSegmentSize
- TempLength
);
142 Status
= CcRosRequestCacheSegment(Bcb
,
143 ROUND_DOWN(ReadOffset
, Bcb
->CacheSegmentSize
),
144 &BaseAddress
, &Valid
, &CacheSeg
);
145 if (!NT_SUCCESS(Status
))
147 IoStatus
->Information
= 0;
148 IoStatus
->Status
= Status
;
149 DPRINT("CcRosRequestCacheSegment faild, Status %x\n", Status
);
154 Status
= ReadCacheSegment(CacheSeg
);
155 if (!NT_SUCCESS(Status
))
157 IoStatus
->Information
= 0;
158 IoStatus
->Status
= Status
;
162 memcpy (Buffer
, BaseAddress
+ ReadOffset
% Bcb
->CacheSegmentSize
, TempLength
);
163 CcRosReleaseCacheSegment(Bcb
, CacheSeg
, TRUE
);
164 ReadLength
+= TempLength
;
165 Length
-= TempLength
;
166 ReadOffset
+= TempLength
;
167 Buffer
+= TempLength
;
172 TempLength
= min (Bcb
->CacheSegmentSize
, Length
);
173 Status
= CcRosRequestCacheSegment(Bcb
, ReadOffset
,
174 &BaseAddress
, &Valid
, &CacheSeg
);
175 if (!NT_SUCCESS(Status
))
177 IoStatus
->Information
= 0;
178 IoStatus
->Status
= Status
;
179 DPRINT("CcRosRequestCacheSegment faild, Status %x\n", Status
);
184 Status
= ReadCacheSegment(CacheSeg
);
185 if (!NT_SUCCESS(Status
))
187 IoStatus
->Information
= 0;
188 IoStatus
->Status
= Status
;
192 memcpy (Buffer
, BaseAddress
, TempLength
);
193 CcRosReleaseCacheSegment(Bcb
, CacheSeg
, TRUE
);
194 ReadLength
+= TempLength
;
195 Length
-= TempLength
;
196 ReadOffset
+= TempLength
;
197 Buffer
+= TempLength
;
199 IoStatus
->Status
= STATUS_SUCCESS
;
200 IoStatus
->Information
= ReadLength
;
201 DPRINT("CcCopyRead O.K.\n");
207 IN PFILE_OBJECT FileObject
,
208 IN PLARGE_INTEGER FileOffset
,
217 PLIST_ENTRY current_entry
;
218 PCACHE_SEGMENT CacheSeg
;
223 DPRINT("CcCopyWrite(FileObject %x, FileOffset %x, "
224 "Length %d, Wait %d, Buffer %x)\n",
225 FileObject
, (ULONG
)FileOffset
->QuadPart
, Length
, Wait
, Buffer
);
227 Bcb
= ((REACTOS_COMMON_FCB_HEADER
*)FileObject
->FsContext
)->Bcb
;
228 WriteOffset
= (ULONG
)FileOffset
->QuadPart
;
232 // testing, if the requested datas are available
233 KeAcquireSpinLock(&Bcb
->BcbLock
, &oldirql
);
234 current_entry
= Bcb
->CacheSegmentListHead
.Flink
;
235 while (current_entry
!= &Bcb
->CacheSegmentListHead
)
237 CacheSeg
= CONTAINING_RECORD(current_entry
, CACHE_SEGMENT
, BcbListEntry
);
238 if (!CacheSeg
->Valid
)
240 if ((WriteOffset
>= CacheSeg
->FileOffset
&& WriteOffset
< CacheSeg
->FileOffset
+ Bcb
->CacheSegmentSize
)
241 || (WriteOffset
+ Length
> CacheSeg
->FileOffset
&& WriteOffset
+ Length
<= CacheSeg
->FileOffset
+ Bcb
->CacheSegmentSize
))
243 KeReleaseSpinLock(&Bcb
->BcbLock
, oldirql
);
244 // datas not available
248 current_entry
= current_entry
->Flink
;
250 KeReleaseSpinLock(&Bcb
->BcbLock
, oldirql
);
253 TempLength
= WriteOffset
% Bcb
->CacheSegmentSize
;
256 TempLength
= min (Length
, Bcb
->CacheSegmentSize
- TempLength
);
257 Status
= CcRosRequestCacheSegment(Bcb
,
258 ROUND_DOWN(WriteOffset
, Bcb
->CacheSegmentSize
),
259 &BaseAddress
, &Valid
, &CacheSeg
);
260 if (!NT_SUCCESS(Status
))
266 if (!NT_SUCCESS(ReadCacheSegment(CacheSeg
)))
271 memcpy (BaseAddress
+ WriteOffset
% Bcb
->CacheSegmentSize
, Buffer
, TempLength
);
272 if (!NT_SUCCESS(WriteCacheSegment(CacheSeg
)))
276 CcRosReleaseCacheSegment(Bcb
, CacheSeg
, TRUE
);
278 Length
-= TempLength
;
279 WriteOffset
+= TempLength
;
280 Buffer
+= TempLength
;
285 TempLength
= min (Bcb
->CacheSegmentSize
, Length
);
286 Status
= CcRosRequestCacheSegment(Bcb
, WriteOffset
,
287 &BaseAddress
, &Valid
, &CacheSeg
);
288 if (!NT_SUCCESS(Status
))
292 if (!Valid
&& TempLength
< Bcb
->CacheSegmentSize
)
294 if (!NT_SUCCESS(ReadCacheSegment(CacheSeg
)))
299 memcpy (BaseAddress
, Buffer
, TempLength
);
300 if (!NT_SUCCESS(WriteCacheSegment(CacheSeg
)))
304 CcRosReleaseCacheSegment(Bcb
, CacheSeg
, TRUE
);
305 Length
-= TempLength
;
306 WriteOffset
+= TempLength
;
307 Buffer
+= TempLength
;