[CDFS_NEW] Replace old driver with a Ms-PL licensed version straight out of the drive...
[reactos.git] / drivers / filesystems / cdfs_new / resrcsup.c
1 /*++
2
3 Copyright (c) 1989-2000 Microsoft Corporation
4
5 Module Name:
6
7 ResrcSup.c
8
9 Abstract:
10
11 This module implements the Cdfs Resource acquisition routines
12
13
14 --*/
15
16 #include "CdProcs.h"
17
18 //
19 // The Bug check file id for this module
20 //
21
22 #define BugCheckFileId (CDFS_BUG_CHECK_RESRCSUP)
23
24 #ifdef ALLOC_PRAGMA
25 #pragma alloc_text(PAGE, CdAcquireForCache)
26 #pragma alloc_text(PAGE, CdFilterCallbackAcquireForCreateSection)
27 #pragma alloc_text(PAGE, CdAcquireResource)
28 #pragma alloc_text(PAGE, CdNoopAcquire)
29 #pragma alloc_text(PAGE, CdNoopRelease)
30 #pragma alloc_text(PAGE, CdReleaseForCreateSection)
31 #pragma alloc_text(PAGE, CdReleaseFromCache)
32 #endif
33
34 \f
35
36 _Requires_lock_held_(_Global_critical_region_)
37 _When_(Type == AcquireExclusive && return != FALSE, _Acquires_exclusive_lock_(*Resource))
38 _When_(Type == AcquireShared && return != FALSE, _Acquires_shared_lock_(*Resource))
39 _When_(Type == AcquireSharedStarveExclusive && return != FALSE, _Acquires_shared_lock_(*Resource))
40 _When_(IgnoreWait == FALSE, _Post_satisfies_(return == TRUE))
41 BOOLEAN
42 CdAcquireResource (
43 _In_ PIRP_CONTEXT IrpContext,
44 _Inout_ PERESOURCE Resource,
45 _In_ BOOLEAN IgnoreWait,
46 _In_ TYPE_OF_ACQUIRE Type
47 )
48
49 /*++
50
51 Routine Description:
52
53 This is the single routine used to acquire file system resources. It
54 looks at the IgnoreWait flag to determine whether to try to acquire the
55 resource without waiting. Returning TRUE/FALSE to indicate success or
56 failure. Otherwise it is driven by the WAIT flag in the IrpContext and
57 will raise CANT_WAIT on a failure.
58
59 Arguments:
60
61 Resource - This is the resource to try and acquire.
62
63 IgnoreWait - If TRUE then this routine will not wait to acquire the
64 resource and will return a boolean indicating whether the resource was
65 acquired. Otherwise we use the flag in the IrpContext and raise
66 if the resource is not acquired.
67
68 Type - Indicates how we should try to get the resource.
69
70 Return Value:
71
72 BOOLEAN - TRUE if the resource is acquired. FALSE if not acquired and
73 IgnoreWait is specified. Otherwise we raise CANT_WAIT.
74
75 --*/
76
77 {
78 BOOLEAN Wait = FALSE;
79 BOOLEAN Acquired;
80 PAGED_CODE();
81
82 //
83 // We look first at the IgnoreWait flag, next at the flag in the Irp
84 // Context to decide how to acquire this resource.
85 //
86
87 if (!IgnoreWait && FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) {
88
89 Wait = TRUE;
90 }
91
92 //
93 // Attempt to acquire the resource either shared or exclusively.
94 //
95
96 switch (Type) {
97 case AcquireExclusive:
98
99 #pragma prefast( suppress:28137, "prefast believes Wait should be a constant, but this is ok for CDFS" )
100 Acquired = ExAcquireResourceExclusiveLite( Resource, Wait );
101 break;
102
103 case AcquireShared:
104
105 Acquired = ExAcquireResourceSharedLite( Resource, Wait );
106 break;
107
108 case AcquireSharedStarveExclusive:
109
110 Acquired = ExAcquireSharedStarveExclusive( Resource, Wait );
111 break;
112
113 default:
114 Acquired = FALSE;
115 NT_ASSERT( FALSE );
116 }
117
118 //
119 // If not acquired and the user didn't specifiy IgnoreWait then
120 // raise CANT_WAIT.
121 //
122
123 if (!Acquired && !IgnoreWait) {
124
125 CdRaiseStatus( IrpContext, STATUS_CANT_WAIT );
126 }
127
128 return Acquired;
129 }
130
131 \f
132
133 _Requires_lock_held_(_Global_critical_region_)
134 _When_(return!=0, _Acquires_shared_lock_(*Fcb->Resource))
135 BOOLEAN
136 CdAcquireForCache (
137 _Inout_ PFCB Fcb,
138 _In_ BOOLEAN Wait
139 )
140
141 /*++
142
143 Routine Description:
144
145 The address of this routine is specified when creating a CacheMap for
146 a file. It is subsequently called by the Lazy Writer for synchronization.
147
148 Arguments:
149
150 Fcb - The pointer supplied as context to the cache initialization
151 routine.
152
153 Wait - TRUE if the caller is willing to block.
154
155 Return Value:
156
157 None
158
159 --*/
160
161 {
162 PAGED_CODE();
163
164 NT_ASSERT(IoGetTopLevelIrp() == NULL);
165 IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
166
167 return ExAcquireResourceSharedLite( Fcb->Resource, Wait );
168 }
169
170 \f
171 _Requires_lock_held_(_Global_critical_region_)
172 _Releases_lock_(*Fcb->Resource)
173 VOID
174 CdReleaseFromCache (
175 _Inout_ PFCB Fcb
176 )
177
178 /*++
179
180 Routine Description:
181
182 The address of this routine is specified when creating a CacheMap for
183 a virtual file. It is subsequently called by the Lazy Writer to release
184 a resource acquired above.
185
186 Arguments:
187
188 Fcb - The pointer supplied as context to the cache initialization
189 routine.
190
191 Return Value:
192
193 None
194
195 --*/
196
197 {
198 PAGED_CODE();
199
200 NT_ASSERT(IoGetTopLevelIrp() == (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
201 IoSetTopLevelIrp( NULL );
202
203 ExReleaseResourceLite( Fcb->Resource );
204 }
205
206 \f
207 BOOLEAN
208 CdNoopAcquire (
209 _In_ PVOID Fcb,
210 _In_ BOOLEAN Wait
211 )
212
213 /*++
214
215 Routine Description:
216
217 This routine does nothing.
218
219 Arguments:
220
221 Fcb - The Fcb/Vcb which was specified as a context parameter for this
222 routine.
223
224 Wait - TRUE if the caller is willing to block.
225
226 Return Value:
227
228 TRUE
229
230 --*/
231
232 {
233 PAGED_CODE();
234
235 UNREFERENCED_PARAMETER( Fcb );
236 UNREFERENCED_PARAMETER( Wait );
237
238 return TRUE;
239 }
240
241 \f
242 VOID
243 CdNoopRelease (
244 _In_ PVOID Fcb
245 )
246
247 /*++
248
249 Routine Description:
250
251 This routine does nothing.
252
253 Arguments:
254
255 Fcb - The Fcb/Vcb which was specified as a context parameter for this
256 routine.
257
258 Return Value:
259
260 None
261
262 --*/
263
264 {
265 PAGED_CODE();
266
267 UNREFERENCED_PARAMETER( Fcb );
268 }
269
270 \f
271
272 _Requires_lock_held_(_Global_critical_region_)
273 NTSTATUS
274 CdFilterCallbackAcquireForCreateSection (
275 _In_ PFS_FILTER_CALLBACK_DATA CallbackData,
276 _Unreferenced_parameter_ PVOID *CompletionContext
277 )
278
279 /*++
280
281 Routine Description:
282
283 This is the callback routine for MM to use to acquire the file exclusively.
284
285 Arguments:
286
287 FS_FILTER_CALLBACK_DATA - Filter based callback data that provides the file object we
288 want to acquire.
289
290 CompletionContext - Ignored.
291
292 Return Value:
293
294 On success we return STATUS_FSFILTER_OP_COMPLETED_SUCCESSFULLY.
295
296 If SyncType is SyncTypeCreateSection, we return a status that indicates there are no
297 writers to this file.
298
299 --*/
300
301 {
302 PFILE_OBJECT FileObject;
303
304
305 PAGED_CODE();
306
307 NT_ASSERT( CallbackData->Operation == FS_FILTER_ACQUIRE_FOR_SECTION_SYNCHRONIZATION );
308 NT_ASSERT( CallbackData->SizeOfFsFilterCallbackData == sizeof(FS_FILTER_CALLBACK_DATA) );
309
310 //
311 // Get the file object from the callback data.
312 //
313
314 FileObject = CallbackData->FileObject;
315
316 //
317 // Get the Fcb resource exclusively.
318 //
319
320 ExAcquireResourceExclusiveLite( &((PFCB) FileObject->FsContext)->FcbNonpaged->FcbResource,
321 TRUE );
322
323 //
324 // Take the File resource shared. We need this later on when MM calls
325 // QueryStandardInfo to get the file size.
326 //
327 // If we don't use StarveExclusive, then we can get wedged behind an
328 // exclusive waiter who is waiting on someone else holding it shared in the
329 // read->initializecachemap path (which calls createsection) who is in turn
330 // waiting on us to finish the create section.
331 //
332
333 ExAcquireSharedStarveExclusive( ((PFCB) FileObject->FsContext)->Resource,
334 TRUE );
335
336 //
337 // CDFS is a read-only file system, so we can always indicate no writers.
338 // We only do this for create section synchronization. For others we
339 // return the generic success STATUS_FSFILTER_OP_COMPLETED_SUCCESSFULLY.
340 //
341
342 if (CallbackData->Parameters.AcquireForSectionSynchronization.SyncType == SyncTypeCreateSection) {
343
344 return STATUS_FILE_LOCKED_WITH_ONLY_READERS;
345
346 } else {
347
348 return STATUS_FSFILTER_OP_COMPLETED_SUCCESSFULLY;
349 }
350
351 UNREFERENCED_PARAMETER( CompletionContext );
352 }
353
354 \f
355 _Function_class_(FAST_IO_RELEASE_FILE)
356 _Requires_lock_held_(_Global_critical_region_)
357 VOID
358 CdReleaseForCreateSection (
359 _In_ PFILE_OBJECT FileObject
360 )
361
362 /*++
363
364 Routine Description:
365
366 This is the callback routine for MM to use to release a file acquired with
367 the AcquireForCreateSection call above.
368
369 Arguments:
370
371 FileObject - File object for a Cdfs stream.
372
373 Return Value:
374
375 None
376
377 --*/
378
379 {
380 PAGED_CODE();
381
382 //
383 // Release the resources.
384 //
385
386 ExReleaseResourceLite( &((PFCB) FileObject->FsContext)->FcbNonpaged->FcbResource );
387 ExReleaseResourceLite( ((PFCB) FileObject->FsContext)->Resource);
388 }
389