c6e6b7d3a0a8f4d48a3e96b231dbd428b3be9d93
[openafs.git] / src / WINNT / afsrdr / kernel / lib / AFSLockControl.cpp
1 /*
2  * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3  * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * - Redistributions of source code must retain the above copyright notice,
11  *   this list of conditions and the following disclaimer.
12  * - Redistributions in binary form must reproduce the above copyright
13  *   notice,
14  *   this list of conditions and the following disclaimer in the
15  *   documentation
16  *   and/or other materials provided with the distribution.
17  * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
18  *   nor the names of their contributors may be used to endorse or promote
19  *   products derived from this software without specific prior written
20  *   permission from Kernel Drivers, LLC and Your File System, Inc.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
26  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34
35 //
36 // File: AFSLockControl.cpp
37 //
38
39 #include "AFSCommon.h"
40
41 NTSTATUS
42 AFSLockControl( IN PDEVICE_OBJECT LibDeviceObject,
43                   IN PIRP Irp)
44 {
45
46     NTSTATUS ntStatus = STATUS_SUCCESS;
47     ULONG ulRequestType = 0;
48     IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
49     AFSFcb *pFcb = NULL;
50     AFSCcb *pCcb = NULL;
51     BOOLEAN bCompleteRequest = TRUE;
52     AFSByteRangeLockRequestCB  stLockRequestCB;
53     AFSByteRangeLockResultCB  stLockResultCB;
54     AFSByteRangeUnlockRequestCB stUnlockRequestCB;
55     AFSByteRangeUnlockResultCB stUnlockResultCB;
56     ULONG           ulResultLen = 0;
57     BOOLEAN         bReleaseResource = FALSE;
58     IO_STATUS_BLOCK stIoStatus;
59
60     __try
61     {
62
63         pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
64
65         pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
66
67         if( pFcb == NULL)
68         {
69
70             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
71                           AFS_TRACE_LEVEL_ERROR,
72                           "AFSLockControl Attempted access (%08lX) when pFcb == NULL\n",
73                           Irp);
74
75             try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
76         }
77
78         //
79         // Acquire the main shared for adding the lock control to the list
80         //
81
82         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
83                       AFS_TRACE_LEVEL_VERBOSE,
84                       "AFSLockControl Acquiring Fcb lock %08lX SHARED %08lX\n",
85                       &pFcb->NPFcb->Resource,
86                       PsGetCurrentThread());
87
88         AFSAcquireShared( &pFcb->NPFcb->Resource,
89                           TRUE);
90
91         bReleaseResource = TRUE;
92
93         if( pFcb->Header.NodeTypeCode == AFS_IOCTL_FCB)
94         {
95
96             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
97                           AFS_TRACE_LEVEL_ERROR,
98                           "AFSLockControl Failing request against PIOCtl Fcb\n");
99
100             try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
101         }
102         else if( pFcb->Header.NodeTypeCode == AFS_SPECIAL_SHARE_FCB)
103         {
104
105             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
106                           AFS_TRACE_LEVEL_ERROR,
107                           "AFSLockControl Failing request against SpecialShare Fcb\n");
108
109             try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
110         }
111
112         //
113         // Post the request to the service for checks
114         //
115
116         switch( pIrpSp->MinorFunction)
117         {
118
119             case IRP_MN_LOCK:
120             {
121
122                 stLockRequestCB.Count = 1;
123
124                 stLockRequestCB.ProcessId = (ULONGLONG)PsGetCurrentProcessId();
125
126                 stLockRequestCB.Request[ 0].LockType = AFS_BYTE_RANGE_LOCK_TYPE_EXCL;
127
128                 stLockRequestCB.Request[ 0].Offset = pIrpSp->Parameters.LockControl.ByteOffset;
129
130                 stLockRequestCB.Request[ 0].Length.QuadPart = pIrpSp->Parameters.LockControl.Length->QuadPart;
131
132                 ulResultLen = sizeof( AFSByteRangeLockResultCB);
133
134                 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_BYTE_RANGE_LOCK,
135                                               AFS_REQUEST_FLAG_SYNCHRONOUS,
136                                               &pCcb->AuthGroup,
137                                               &pCcb->DirectoryCB->NameInformation.FileName,
138                                               &pFcb->ObjectInformation->FileId,
139                                               &stLockRequestCB,
140                                               sizeof( AFSByteRangeLockRequestCB),
141                                               &stLockResultCB,
142                                               &ulResultLen);
143
144                 if( !NT_SUCCESS( ntStatus))
145                 {
146
147                     try_return( ntStatus);
148                 }
149
150                 break;
151             }
152
153             case IRP_MN_UNLOCK_ALL:
154             case IRP_MN_UNLOCK_ALL_BY_KEY:
155             {
156
157                 RtlZeroMemory( &stUnlockRequestCB,
158                                sizeof( AFSByteRangeUnlockRequestCB));
159
160                 stUnlockRequestCB.ProcessId = (ULONGLONG)PsGetCurrentProcessId();
161
162                 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_BYTE_RANGE_UNLOCK_ALL,
163                                               AFS_REQUEST_FLAG_SYNCHRONOUS,
164                                               &pCcb->AuthGroup,
165                                               &pCcb->DirectoryCB->NameInformation.FileName,
166                                               &pFcb->ObjectInformation->FileId,
167                                               (void *)&stUnlockRequestCB,
168                                               sizeof( AFSByteRangeUnlockRequestCB),
169                                               NULL,
170                                               NULL);
171
172                 if( NT_SUCCESS( ntStatus))
173                 {
174                     CcFlushCache( &pFcb->NPFcb->SectionObjectPointers,
175                                   NULL,
176                                   0,
177                                   &stIoStatus);
178
179                     if( !NT_SUCCESS( stIoStatus.Status))
180                     {
181
182                         AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
183                                       AFS_TRACE_LEVEL_ERROR,
184                                       "AFSLockControl CcFlushCache [1] failure FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
185                                       pFcb->ObjectInformation->FileId.Cell,
186                                       pFcb->ObjectInformation->FileId.Volume,
187                                       pFcb->ObjectInformation->FileId.Vnode,
188                                       pFcb->ObjectInformation->FileId.Unique,
189                                       stIoStatus.Status,
190                                       stIoStatus.Information);
191
192                         ntStatus = stIoStatus.Status;
193                     }
194                 }
195
196                 //
197                 // Even on a failure we need to notify the rtl package of the unlock
198                 //
199
200                 break;
201             }
202
203             case IRP_MN_UNLOCK_SINGLE:
204             {
205
206                 stUnlockRequestCB.Count = 1;
207
208                 stUnlockRequestCB.ProcessId = (ULONGLONG)PsGetCurrentProcessId();
209
210                 stUnlockRequestCB.Request[ 0].LockType = AFS_BYTE_RANGE_LOCK_TYPE_EXCL;
211
212                 stUnlockRequestCB.Request[ 0].Offset = pIrpSp->Parameters.LockControl.ByteOffset;
213
214                 stUnlockRequestCB.Request[ 0].Length.QuadPart = pIrpSp->Parameters.LockControl.Length->QuadPart;
215
216                 ulResultLen = sizeof( AFSByteRangeUnlockResultCB);
217
218                 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_BYTE_RANGE_UNLOCK,
219                                               AFS_REQUEST_FLAG_SYNCHRONOUS,
220                                               &pCcb->AuthGroup,
221                                               &pCcb->DirectoryCB->NameInformation.FileName,
222                                               &pFcb->ObjectInformation->FileId,
223                                               (void *)&stUnlockRequestCB,
224                                               sizeof( AFSByteRangeUnlockRequestCB),
225                                               (void *)&stUnlockResultCB,
226                                               &ulResultLen);
227
228                 if( NT_SUCCESS( ntStatus))
229                 {
230                     CcFlushCache( &pFcb->NPFcb->SectionObjectPointers,
231                                   &pIrpSp->Parameters.LockControl.ByteOffset,
232                                   pIrpSp->Parameters.LockControl.Length->LowPart,
233                                   &stIoStatus);
234
235                     if( !NT_SUCCESS( stIoStatus.Status))
236                     {
237
238                         AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
239                                       AFS_TRACE_LEVEL_ERROR,
240                                       "AFSLockControl CcFlushCache [2] failure FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
241                                       pFcb->ObjectInformation->FileId.Cell,
242                                       pFcb->ObjectInformation->FileId.Volume,
243                                       pFcb->ObjectInformation->FileId.Vnode,
244                                       pFcb->ObjectInformation->FileId.Unique,
245                                       stIoStatus.Status,
246                                       stIoStatus.Information);
247
248                         ntStatus = stIoStatus.Status;
249                     }
250                 }
251
252                 break;
253             }
254
255             default:
256
257                 break;
258         }
259
260         //
261         // Below here we won't complete the request, it is handled by the lock package
262         //
263
264         bCompleteRequest = FALSE;
265
266         //
267         //  Now call the system package for actually processing the lock request
268         //
269
270         ntStatus = FsRtlProcessFileLock( &pFcb->Specific.File.FileLock,
271                                          Irp,
272                                          NULL);
273
274 try_exit:
275
276         if( bReleaseResource)
277         {
278
279             //
280             // And drop it
281             //
282
283             AFSReleaseResource( &pFcb->NPFcb->Resource);
284         }
285
286         if( bCompleteRequest)
287         {
288
289             AFSCompleteRequest( Irp,
290                                 ntStatus);
291         }
292     }
293     __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()))
294     {
295
296         AFSDbgLogMsg( 0,
297                       0,
298                       "EXCEPTION - AFSLockControl\n");
299
300         //
301         // Again, there is little point in failing this request but pass back some type of failure status
302         //
303
304         ntStatus = STATUS_UNSUCCESSFUL;
305
306         AFSCompleteRequest( Irp,
307                             ntStatus);
308     }
309
310     return ntStatus;
311 }