captive_shared_cache_map_object_FileSizes_changed(): Improved performance.
[captive.git] / src / libcaptive / cc / bcbpin.c
1 /* $Id$
2  * reactos Cache Manager (Cc*) pin Bcb handling of libcaptive
3  * Copyright (C) 2003 Jan Kratochvil <project-captive@jankratochvil.net>
4  * 
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; exactly version 2 of June 1991 is required
8  * 
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  * 
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19
20 #include "config.h"
21
22 #include "privatebcbpin.h"
23 #include "reactos/ddk/ccfuncs.h"
24 #include "privatebcb.h"
25 #include "captive/macros.h"
26
27
28 /**
29  * CcPinMappedData:
30  * @FileObject: Initialized open #FileObject to map.
31  * %NULL value is forbidden.
32  * @MappedFileOffset: The @FileObject file offset from where to map the region from.
33  * Negative value is forbidden.
34  * @MappedLength: Requested length of the region to map from @FileObject.
35  * FIXME: Value %0 is currently forbidden by libcaptive; it should be allowed.
36  * @Wait: Whether disk waiting is permitted for this function.
37  * Value currently ignored by libcaptive as the data must have been mapped by CcMapData() already anyway.
38  * @Flags: %PIN_WAIT means whether disk waiting is permitted for this function.
39  * Value without %PIN_WAIT is currently permtted by libcaptive as the data must have been mapped by CcMapData() already anyway.
40  * %PIN_NO_READ is the same as %MAP_NO_READ - see CcMapData().
41  * FIXME: %PIN_EXCLUSIVE for exclusive @Bcb access is now ignored by libcaptive.
42  * %PIN_IF_BCB if @Bcb should never be created; function is successful only if @Bcb already exists.
43  * @Bcb: Returns initialized #PUBLIC_BCB to refer to the mapped region.
44  * The memory region can be larger than requested as it is %PAGE_SIZE aligned.
45  * %NULL pointer is forbidden.
46  * @Buffer: Returns the mapped memory region start address.
47  * This address may not be %PAGE_SIZE aligned.
48  * %NULL pointer is forbidden.
49  *
50  * This function will allow you to modify the data mapped by CcMapData().
51  * libcaptive does not differentiate this function with CcMapData().
52  *
53  * This call does not set the buffer as dirty - such buffer will not be flushed automatically.
54  *
55  * NEVER re-read any memory from FileObject here!
56  * at least fastfat.sys directory create relies on the fact of CcPinRead()
57  * with already modified buffers to be left intact.
58  *
59  * This call will proceed as CcPinRead() if such #Bcb does not yet exist.
60  * This is IMO just a bug workaround for a peruse by fastfat.sys FatLocateVolumeLabel().
61  *
62  * Every call to this function must be matched by a one corresponding CcUnpinData() call.
63  *
64  * Returns: %TRUE if the region was successfuly mapped.
65  * @Bcb with the initialized new memory region.
66  * @Buffer with the address of the exact byte specified by @FileOffset.
67  */
68 BOOLEAN CcPinMappedData
69                 (IN PFILE_OBJECT FileObject,IN PLARGE_INTEGER FileOffset,IN ULONG Length,IN ULONG Flags,OUT PVOID *Bcb)
70 {
71 CaptiveSharedCacheMapObject *SharedCacheMap;
72 CaptivePrivateBcbPinObject *captive_private_bcb_pin_object;
73 BOOLEAN r;
74
75         g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"enter: CcPinMappedData: FileObject=0x%lX,FileOffset=0x%lX,Length=0x%lX,Flags=0x%lX",
76                         (long)FileObject,(!FileOffset ? -1 : (long)FileOffset->QuadPart),Length,Flags);
77
78         g_return_val_if_fail(FileObject!=NULL,FALSE);
79         g_return_val_if_fail(FileOffset!=NULL,FALSE);
80         g_return_val_if_fail(FileOffset->QuadPart>=0,FALSE);
81         g_return_val_if_fail(Length>0,FALSE);   /* FIXME: not handled below; 0 should be allowed */
82         g_return_val_if_fail(Flags==PIN_WAIT,FALSE);    /* FIXME */
83         g_return_val_if_fail(Bcb!=NULL,FALSE);
84
85         g_assert(Length<=PAGE_SIZE);
86         /* Check PAGE_SIZE crossing */
87         g_assert((FileOffset->QuadPart&~(PAGE_SIZE-1))==((FileOffset->QuadPart+Length-1)&~(PAGE_SIZE-1)));
88
89         SharedCacheMap=captive_FileObject_to_SharedCacheMap(FileObject);
90         /* Do not invalide 'map'ped data otherwise ntfs.sys of NT-5.1sp1 mount crashes.
91          */
92         captive_private_bcb_pin_object=captive_private_bcb_pin_object_get_ref(SharedCacheMap,
93                         CAPTIVE_ROUND_DOWN64(FileOffset->QuadPart,PAGE_SIZE),
94                         FALSE); /* invalidate_new */
95
96         captive_shared_cache_map_data_validate_noread(SharedCacheMap,FileOffset->QuadPart,FileOffset->QuadPart+Length);
97
98         *Bcb=captive_private_bcb_object_get_PublicBcb(CAPTIVE_PRIVATE_BCB_OBJECT(captive_private_bcb_pin_object));
99         r=TRUE;
100
101         g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"leave: CcPinMappedData: r=%d,Bcb=0x%lX",
102                         r,(!Bcb ? -1 : (long)*Bcb));
103
104         return r;
105 }
106
107
108 /**
109  * CcPinRead:
110  * @FileObject: Initialized open #FileObject to map.
111  * %NULL value is forbidden.
112  * @FileOffset: The @FileObject file offset from where to map the region from.
113  * Negative value is forbidden.
114  * @Length: Requested length of the region to map from @FileObject.
115  * FIXME: Value %0 is currently forbidden by libcaptive; it should be allowed.
116  * @Flags: %PIN_WAIT means whether disk waiting is permitted for this function.
117  * Value without %PIN_WAIT is currently permtted by libcaptive as the data must have been mapped by CcMapData() already anyway.
118  * %PIN_NO_READ is the same as %MAP_NO_READ - see CcMapData().
119  * FIXME: %PIN_EXCLUSIVE for exclusive @Bcb access is now ignored by libcaptive.
120  * %PIN_IF_BCB if @Bcb should never be created; function is successful only if @Bcb already exists.
121  * @Bcb: Returns initialized #PUBLIC_BCB to refer to the mapped region.
122  * The memory region can be larger than requested as it is %PAGE_SIZE aligned.
123  * %NULL pointer is forbidden.
124  * @Buffer: Returns the mapped memory region start address.
125  * This address may not be %PAGE_SIZE aligned.
126  * %NULL pointer is forbidden.
127  *
128  * Merely a shortcut call for CcMapData() and CcPinMappedData() afterwards.
129  * See these two functions for the details. It has a difference to subsequent
130  * calling of CcMapData() and CcPinMappedData() instead as this call counts
131  * only as one function for a corresponding CcUnpinData() call.
132  *
133  * This call does not set the buffer as dirty - such buffer will not be flushed automatically.
134  *
135  * Every call to this function must be matched by a one corresponding CcUnpinData() call.
136  *
137  * Returns: %TRUE if the region was successfuly mapped.
138  * @Bcb with the initialized new memory region.
139  * @Buffer with the address of the exact byte specified by @FileOffset.
140  */
141 BOOLEAN CcPinRead(IN PFILE_OBJECT FileObject,
142                 IN PLARGE_INTEGER FileOffset,IN ULONG Length,IN ULONG Flags,OUT PVOID *Bcb,OUT PVOID *Buffer)
143 {
144 CaptiveSharedCacheMapObject *SharedCacheMap;
145 CaptivePrivateBcbPinObject *captive_private_bcb_pin_object;
146 BOOLEAN r;
147
148         g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"enter: CcPinRead: FileObject=0x%lX,FileOffset=0x%lX,Length=0x%lX,Flags=0x%lX",
149                         (long)FileObject,(!FileOffset ? -1 : (long)FileOffset->QuadPart),Length,Flags);
150
151         g_return_val_if_fail(FileObject!=NULL,FALSE);
152         g_return_val_if_fail(FileOffset!=NULL,FALSE);
153         g_return_val_if_fail(FileOffset->QuadPart>=0,FALSE);
154         g_return_val_if_fail(Length>0,FALSE);   /* FIXME: not handled below; 0 should be allowed */
155         g_return_val_if_fail((Flags&~PIN_IF_BCB)==PIN_WAIT,FALSE);      /* FIXME */
156         g_return_val_if_fail(Bcb!=NULL,FALSE);
157         g_return_val_if_fail(Buffer!=NULL,FALSE);
158
159         g_assert(Length<=PAGE_SIZE);
160         /* Check PAGE_SIZE crossing */
161         g_assert((FileOffset->QuadPart&~(PAGE_SIZE-1))==((FileOffset->QuadPart+Length-1)&~(PAGE_SIZE-1)));
162
163         SharedCacheMap=captive_FileObject_to_SharedCacheMap(FileObject);
164
165         if (Flags&PIN_IF_BCB) {
166                 if ((captive_private_bcb_pin_object=captive_private_bcb_pin_object_get(SharedCacheMap,
167                                 CAPTIVE_ROUND_DOWN64(FileOffset->QuadPart,PAGE_SIZE))))
168                         g_object_ref(captive_private_bcb_pin_object);
169                 }
170         else {
171                 /* Invalide possibly only 'map'ped data as we need to re-read them on CcPinRead().
172                  * Otherwise any file written by fastfat.sys of NT-5.1sp1 will corrupt
173                  * the code+55AA of DOS boot sector (disk offset 0x0).
174                  */
175                 captive_private_bcb_pin_object=captive_private_bcb_pin_object_get_ref(SharedCacheMap,
176                                 CAPTIVE_ROUND_DOWN64(FileOffset->QuadPart,PAGE_SIZE),
177                                 TRUE);  /* invalidate_new */
178                 }
179
180         if (captive_private_bcb_pin_object) {
181                 captive_shared_cache_map_data_validate_read(SharedCacheMap,FileObject,FileOffset->QuadPart,FileOffset->QuadPart+Length);
182
183                 *Bcb=captive_private_bcb_object_get_PublicBcb(CAPTIVE_PRIVATE_BCB_OBJECT(captive_private_bcb_pin_object));
184                 }
185         *Buffer=captive_shared_cache_map_get_buffer(SharedCacheMap)+FileOffset->QuadPart;
186         r=!!captive_private_bcb_pin_object;
187
188         g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"leave: CcPinRead: r=%d,Bcb=0x%lX,Buffer=0x%lX",
189                         r,(!Bcb ? -1 : (long)*Bcb),(!Buffer ? -1 : (long)*Buffer));
190
191         return r;
192 }
193
194
195 /**
196  * CcSetDirtyPinnedData:
197  * @Bcb: #PUBLIB_BCB to be unpinned from CcRepinBcb().
198  * %NULL value is forbidden.
199  * @Lsn: Optional LSN (Linear Sequence Number) to assign to @Bcb.
200  * %NULL pointer is permitted.
201  *
202  * This call will set the buffer as dirty - such buffer will be flushed automatically.
203  *
204  * You should call it only on CcPin*() buffers - not just CcMapData() buffers
205  * although libcaptive does not differentiate it.
206  */
207 VOID CcSetDirtyPinnedData(IN PVOID Bcb,IN PLARGE_INTEGER Lsn OPTIONAL)
208 {
209 CaptivePrivateBcbPinObject *captive_private_bcb_pin_object;
210
211         g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"enter: CcSetDirtyPinnedData: BcbVoid=0x%lX,Lsn=0x%lX",
212                         (long)Bcb,(!Lsn ? -1 : (long)Lsn->QuadPart));
213
214         g_return_if_fail(Bcb!=NULL);
215
216         captive_private_bcb_pin_object=CAPTIVE_PRIVATE_BCB_PIN_OBJECT(captive_PublicBcb_to_PrivateBcbObject(Bcb));
217
218         captive_private_bcb_pin_object_set_dirty(captive_private_bcb_pin_object);
219         if (Lsn)
220                 captive_private_bcb_pin_object_set_lsn(captive_private_bcb_pin_object,Lsn->QuadPart);
221
222         g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"leave: CcSetDirtyPinnedData");
223 }
224
225
226 /**
227  * CcPreparePinWrite:
228  * @FileObject: Initialized open #FileObject to map.
229  * %NULL value is forbidden.
230  * @FileOffset: The @FileObject file offset from where to map the region from.
231  * Negative value is forbidden.
232  * @Length: Requested length of the region to map from @FileObject.
233  * FIXME: Value %0 is currently forbidden by libcaptive; it should be allowed.
234  * @Zero: %TRUE if the area of @FileOffset...@FileOffset+@Length should be cleared.
235  * @Flags: %PIN_WAIT means whether disk waiting is permitted for this function.
236  * Value without %PIN_WAIT is currently permtted by libcaptive as the data must have been mapped by CcMapData() already anyway.
237  * %PIN_NO_READ is the same as %MAP_NO_READ - see CcMapData().
238  * FIXME: %PIN_EXCLUSIVE for exclusive @Bcb access is now ignored by libcaptive.
239  * %PIN_IF_BCB if @Bcb should never be created; function is successful only if @Bcb already exists.
240  * @Bcb: Returns initialized #PUBLIC_BCB to refer to the mapped region.
241  * The memory region can be larger than requested as it is %PAGE_SIZE aligned.
242  * %NULL pointer is forbidden.
243  * @Buffer: Returns the mapped memory region start address.
244  * This address may not be %PAGE_SIZE aligned.
245  * %NULL pointer is forbidden.
246  *
247  * Wrapper for a pair of CcPinRead() and CcSetDirtyPinnedData().
248  * The mapped range can be also optionally cleared if @Zero is specified.
249  * See CcPinRead() for a more detailed documentation.
250  *
251  * This call will set the buffer as dirty - such buffer will be flushed automatically.
252  *
253  * Returns: %TRUE if the mapping was successful.
254  */
255 BOOLEAN CcPreparePinWrite(IN PFILE_OBJECT FileObject,
256                 IN PLARGE_INTEGER FileOffset,IN ULONG Length,IN BOOLEAN Zero,IN ULONG Flags,OUT PVOID *Bcb,OUT PVOID *Buffer)
257 {
258 CaptiveSharedCacheMapObject *SharedCacheMap;
259 CaptivePrivateBcbPinObject *captive_private_bcb_pin_object;
260 BOOLEAN r;
261
262         g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"enter: CcPreparePinWrite: FileObject=0x%lX,FileOffset=0x%lX,Length=0x%lX,Zero=%d,Flags=0x%lX",
263                         (long)FileObject,(!FileOffset ? -1 : (long)FileOffset->QuadPart),Length,Zero,Flags);
264
265         g_return_val_if_fail(FileObject!=NULL,FALSE);
266         g_return_val_if_fail(FileOffset!=NULL,FALSE);
267         g_return_val_if_fail(FileOffset->QuadPart>=0,FALSE);
268         g_return_val_if_fail(Length>0,FALSE);   /* FIXME: not handled below; 0 should be allowed */
269         g_return_val_if_fail(Flags==PIN_WAIT,FALSE);    /* FIXME */
270         g_return_val_if_fail(Bcb!=NULL,FALSE);
271         g_return_val_if_fail(Buffer!=NULL,FALSE);
272
273         g_assert(0==CAPTIVE_ROUND_DOWN_EXCEEDING64(FileOffset->QuadPart,PAGE_SIZE));    /* NOT YET IMPLEMENTED */
274         g_assert(Length==PAGE_SIZE);    /* NOT YET IMPLEMENTED */
275
276         SharedCacheMap=captive_FileObject_to_SharedCacheMap(FileObject);
277         captive_private_bcb_pin_object=captive_private_bcb_pin_object_get_ref(SharedCacheMap,
278                         CAPTIVE_ROUND_DOWN64(FileOffset->QuadPart,PAGE_SIZE),
279                         FALSE); /* invalidate_new: FIXME: Is it compatible? */
280
281         captive_shared_cache_map_set_data_valid(SharedCacheMap,FileOffset->QuadPart,FileOffset->QuadPart+Length);
282         if (Zero)
283                 memset(captive_shared_cache_map_get_buffer(SharedCacheMap)+FileOffset->QuadPart,0,Length);
284         captive_shared_cache_map_set_dirty(SharedCacheMap,FileOffset->QuadPart,FileOffset->QuadPart+Length);
285
286         *Bcb=captive_private_bcb_object_get_PublicBcb(CAPTIVE_PRIVATE_BCB_OBJECT(captive_private_bcb_pin_object));
287         *Buffer=captive_shared_cache_map_get_buffer(SharedCacheMap)+FileOffset->QuadPart;
288         r=TRUE;
289
290         g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"leave: CcPreparePinWrite: r=%d,Bcb=0x%lX,Buffer=0x%lX",
291                         r,(!Bcb ? -1 : (long)*Bcb),(!Buffer ? -1 : (long)*Buffer));
292
293         return r;
294 }