Windows: Skip Extent operations if Direct IO
[openafs.git] / src / WINNT / afsrdr / kernel / lib / AFSFlushBuffers.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: AFSFlushBuffers.cpp
37 //
38
39 #include "AFSCommon.h"
40
41 NTSTATUS
42 AFSFlushBuffers( IN PDEVICE_OBJECT LibDeviceObject,
43                  IN PIRP Irp)
44 {
45
46     UNREFERENCED_PARAMETER(LibDeviceObject);
47     AFSDeviceExt *pRDRDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
48     NTSTATUS           ntStatus = STATUS_SUCCESS;
49     IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
50     PFILE_OBJECT       pFileObject = pIrpSp->FileObject;
51     AFSFcb            *pFcb = (AFSFcb *)pFileObject->FsContext;
52     AFSCcb            *pCcb = (AFSCcb *)pFileObject->FsContext2;
53     IO_STATUS_BLOCK    iosb = {0};
54     BOOLEAN            bReleaseSectionObject = FALSE;
55
56     pIrpSp = IoGetCurrentIrpStackLocation( Irp);
57
58     __Enter
59     {
60
61         if( pFcb == NULL)
62         {
63
64             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
65                           AFS_TRACE_LEVEL_ERROR,
66                           "AFSFlushBuffers Attempted access (%p) when pFcb == NULL\n",
67                           Irp));
68
69             try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
70         }
71
72         if( pFcb->Header.NodeTypeCode == AFS_ROOT_FCB ||
73             pFcb->Header.NodeTypeCode == AFS_ROOT_ALL )
74         {
75
76             //
77             // Once we support ADS's on directories we need to perform a flush ehre
78             //
79
80             try_return( ntStatus = STATUS_SUCCESS);
81
82         }
83         else if (pFcb->Header.NodeTypeCode != AFS_FILE_FCB)
84         {
85             //
86             // Nothing to flush Everything but files are write through
87             //
88             try_return( ntStatus = STATUS_INVALID_PARAMETER);
89         }
90
91         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
92                       AFS_TRACE_LEVEL_VERBOSE,
93                       "AFSFlushBuffers Acquiring Fcb SectionObject lock %p SHARED %08lX\n",
94                       &pFcb->NPFcb->SectionObjectResource,
95                       PsGetCurrentThread()));
96
97         AFSAcquireShared( &pFcb->NPFcb->SectionObjectResource,
98                           TRUE);
99
100         bReleaseSectionObject = TRUE;
101
102         //
103         // The flush consists of two parts.  We firstly flush our
104         // cache (if we have one), then we tell the service to write
105         // to the remote server
106         //
107         __try
108         {
109
110             CcFlushCache( &pFcb->NPFcb->SectionObjectPointers, NULL, 0, &iosb);
111
112             if (!NT_SUCCESS( iosb.Status ))
113             {
114
115                 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
116                               AFS_TRACE_LEVEL_ERROR,
117                               "AFSFlushBuffers CcFlushCache [1] failure FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
118                               pFcb->ObjectInformation->FileId.Cell,
119                               pFcb->ObjectInformation->FileId.Volume,
120                               pFcb->ObjectInformation->FileId.Vnode,
121                               pFcb->ObjectInformation->FileId.Unique,
122                               iosb.Status,
123                               iosb.Information));
124
125                 try_return( ntStatus = iosb.Status );
126             }
127         }
128         __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()))
129         {
130
131             try_return( ntStatus = GetExceptionCode());
132         }
133
134         if( !BooleanFlagOn( pRDRDevExt->DeviceFlags, AFS_DEVICE_FLAG_DIRECT_SERVICE_IO))
135         {
136
137             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
138                           AFS_TRACE_LEVEL_VERBOSE,
139                           "AFSFlushBuffers Releasing Fcb SectionObject lock %p SHARED %08lX\n",
140                           &pFcb->NPFcb->SectionObjectResource,
141                           PsGetCurrentThread()));
142
143             AFSReleaseResource( &pFcb->NPFcb->SectionObjectResource);
144
145             bReleaseSectionObject = FALSE;
146
147             //
148             // Now, flush to the server - if there is stuff to do
149             //
150
151             ntStatus = AFSFlushExtents( pFcb,
152                                         &pCcb->AuthGroup);
153
154             if( !NT_SUCCESS( ntStatus))
155             {
156
157                 AFSReleaseExtentsWithFlush( pFcb,
158                                             &pCcb->AuthGroup,
159                                             TRUE);
160
161                 ntStatus = STATUS_SUCCESS;
162             }
163         }
164
165 try_exit:
166
167         if ( bReleaseSectionObject)
168         {
169
170             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
171                           AFS_TRACE_LEVEL_VERBOSE,
172                           "AFSFlushBuffers Releasing Fcb SectionObject lock %p SHARED %08lX\n",
173                           &pFcb->NPFcb->SectionObjectResource,
174                           PsGetCurrentThread()));
175
176             AFSReleaseResource( &pFcb->NPFcb->SectionObjectResource);
177         }
178
179         AFSCompleteRequest( Irp, ntStatus);
180     }
181
182     return ntStatus;
183 }