Windows: EOF for Synchronous Deferred Writes on XP/2003
[openafs.git] / src / WINNT / afsrdr / kernel / lib / AFSWrite.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: AFSWrite.cpp
37 //
38
39 #include "AFSCommon.h"
40
41 static
42 NTSTATUS
43 AFSCachedWrite( IN PDEVICE_OBJECT DeviceObject,
44                 IN PIRP Irp,
45                 IN LARGE_INTEGER StartingByte,
46                 IN ULONG ByteCount,
47                 IN BOOLEAN ForceFlush);
48 static
49 NTSTATUS
50 AFSNonCachedWrite( IN PDEVICE_OBJECT DeviceObject,
51                    IN PIRP Irp,
52                    IN LARGE_INTEGER StartingByte,
53                    IN ULONG ByteCount);
54
55 static
56 NTSTATUS
57 AFSNonCachedWriteDirect( IN PDEVICE_OBJECT DeviceObject,
58                          IN PIRP Irp,
59                          IN LARGE_INTEGER StartingByte,
60                          IN ULONG ByteCount);
61
62 static
63 NTSTATUS
64 AFSExtendingWrite( IN AFSFcb *Fcb,
65                    IN PFILE_OBJECT FileObject,
66                    IN LONGLONG NewLength);
67
68 //
69 // Function: AFSWrite
70 //
71 // Description:
72 //
73 //      This is the dispatch handler for the IRP_MJ_WRITE request
74 //
75 // Return:
76 //
77 //      A status is returned for the function
78 //
79 NTSTATUS
80 AFSWrite( IN PDEVICE_OBJECT LibDeviceObject,
81           IN PIRP Irp)
82 {
83
84     UNREFERENCED_PARAMETER(LibDeviceObject);
85     NTSTATUS ntStatus = STATUS_SUCCESS;
86
87     __try
88     {
89
90         ntStatus = AFSCommonWrite( AFSRDRDeviceObject, Irp, NULL, FALSE);
91     }
92     __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
93     {
94
95         ntStatus = STATUS_INSUFFICIENT_RESOURCES;
96     }
97
98     return ntStatus;
99 }
100
101 NTSTATUS
102 AFSCommonWrite( IN PDEVICE_OBJECT DeviceObject,
103                 IN PIRP Irp,
104                 IN HANDLE OnBehalfOf,
105                 IN BOOLEAN bRetry)
106 {
107
108     NTSTATUS           ntStatus = STATUS_SUCCESS;
109     AFSDeviceExt      *pDeviceExt = (AFSDeviceExt *)DeviceObject->DeviceExtension;
110     IO_STACK_LOCATION *pIrpSp;
111     AFSFcb            *pFcb = NULL;
112     AFSCcb            *pCcb = NULL;
113     AFSNonPagedFcb    *pNPFcb = NULL;
114     ULONG              ulByteCount = 0;
115     LARGE_INTEGER      liStartingByte;
116     PFILE_OBJECT       pFileObject;
117     BOOLEAN            bPagingIo = FALSE;
118     BOOLEAN            bNonCachedIo = FALSE;
119     BOOLEAN            bReleaseMain = FALSE;
120     BOOLEAN            bReleaseSectionObject = FALSE;
121     BOOLEAN            bReleasePaging = FALSE;
122     BOOLEAN            bExtendingWrite = FALSE;
123     BOOLEAN            bSynchronousFo = FALSE;
124     BOOLEAN            bCompleteIrp = TRUE;
125     BOOLEAN            bForceFlush = FALSE;
126     BOOLEAN            bLockOK;
127     HANDLE             hCallingUser = OnBehalfOf;
128     ULONGLONG          ullProcessId = (ULONGLONG)PsGetCurrentProcessId();
129     AFSDeviceExt       *pRDRDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
130
131     pIrpSp = IoGetCurrentIrpStackLocation( Irp);
132
133     __Enter
134     {
135
136         Irp->IoStatus.Information = 0;
137
138         pFileObject = pIrpSp->FileObject;
139
140         //
141         // Extract the fileobject references
142         //
143
144         pFcb = (AFSFcb *)pFileObject->FsContext;
145         pCcb = (AFSCcb *)pFileObject->FsContext2;
146
147         ObReferenceObject( pFileObject);
148
149         if( pFcb == NULL)
150         {
151
152             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
153                           AFS_TRACE_LEVEL_ERROR,
154                           "AFSCommonWrite Attempted write (%p) when pFcb == NULL\n",
155                           Irp));
156
157             try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
158         }
159
160         pNPFcb = pFcb->NPFcb;
161
162         //
163         // If we are in shutdown mode then fail the request
164         //
165
166         if( BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
167         {
168
169             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
170                           AFS_TRACE_LEVEL_WARNING,
171                           "AFSCommonWrite (%p) Open request after shutdown\n",
172                           Irp));
173
174             try_return( ntStatus = STATUS_TOO_LATE);
175         }
176
177         liStartingByte = pIrpSp->Parameters.Write.ByteOffset;
178         bPagingIo      = BooleanFlagOn( Irp->Flags, IRP_PAGING_IO);
179         bNonCachedIo   = BooleanFlagOn( Irp->Flags, IRP_NOCACHE);
180         ulByteCount    = pIrpSp->Parameters.Write.Length;
181         bSynchronousFo = BooleanFlagOn( pFileObject->Flags, FO_SYNCHRONOUS_IO);
182
183         if( pFcb->Header.NodeTypeCode != AFS_IOCTL_FCB &&
184             pFcb->Header.NodeTypeCode != AFS_FILE_FCB  &&
185             pFcb->Header.NodeTypeCode != AFS_SPECIAL_SHARE_FCB)
186         {
187
188             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
189                           AFS_TRACE_LEVEL_ERROR,
190                           "AFSCommonWrite Attempted write (%p) on an invalid node type %08lX\n",
191                           Irp,
192                           pFcb->Header.NodeTypeCode));
193
194             try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
195         }
196
197         //
198         // If this is a write against an IOCtl node then handle it
199         // in a different pathway
200         //
201
202         if( pFcb->Header.NodeTypeCode == AFS_IOCTL_FCB)
203         {
204
205             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
206                           AFS_TRACE_LEVEL_VERBOSE,
207                           "AFSCommonWrite (%p) Processing file (PIOCTL) Offset %0I64X Length %08lX Irp Flags %08lX\n",
208                           Irp,
209                           liStartingByte.QuadPart,
210                           ulByteCount,
211                           Irp->Flags));
212
213             ntStatus = AFSIOCtlWrite( DeviceObject,
214                                       Irp);
215
216             try_return( ntStatus);
217         }
218         else if( pFcb->Header.NodeTypeCode == AFS_SPECIAL_SHARE_FCB)
219         {
220
221             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
222                           AFS_TRACE_LEVEL_VERBOSE,
223                           "AFSCommonWrite (%p) Processing file (SHARE) Offset %0I64X Length %08lX Irp Flags %08lX\n",
224                           Irp,
225                           liStartingByte.QuadPart,
226                           ulByteCount,
227                           Irp->Flags));
228
229             ntStatus = AFSShareWrite( DeviceObject,
230                                       Irp);
231
232             try_return( ntStatus);
233         }
234
235         //
236         // Is the Cache not there yet?  Exit.
237         //
238         if( !BooleanFlagOn( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE) &&
239             !BooleanFlagOn( pRDRDevExt->DeviceFlags, AFS_REDIR_INIT_PERFORM_SERVICE_IO) &&
240             NULL == pDeviceExt->Specific.RDR.CacheFileObject)
241         {
242
243             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
244                           AFS_TRACE_LEVEL_ERROR,
245                           "AFSCommonWrite (%p) Request failed due to AFS cache closed\n",
246                           Irp));
247
248             try_return( ntStatus = STATUS_TOO_LATE );
249         }
250
251         if( pFcb->ObjectInformation->VolumeCB != NULL &&
252             BooleanFlagOn( pFcb->ObjectInformation->VolumeCB->VolumeInformation.FileSystemAttributes, FILE_READ_ONLY_VOLUME))
253         {
254
255             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
256                           AFS_TRACE_LEVEL_ERROR,
257                           "AFSCommonWrite (%p) Request failed due to read only volume\n",
258                           Irp));
259
260             try_return( ntStatus = STATUS_ACCESS_DENIED);
261         }
262
263         //
264         // We need to know on whose behalf we have been called (which
265         // we will eventually tell to the server - for non paging
266         // writes).  If we were posted then we were told.  If this is
267         // the first time we saw the irp then we grab it now.
268         //
269         if( NULL == OnBehalfOf )
270         {
271
272             hCallingUser = PsGetCurrentProcessId();
273         }
274         else
275         {
276
277             hCallingUser = OnBehalfOf;
278         }
279
280         //
281         // Check for zero length write
282         //
283
284         if( ulByteCount == 0)
285         {
286
287             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
288                           AFS_TRACE_LEVEL_VERBOSE,
289                           "AFSCommonWrite (%p) Request completed due to zero length\n",
290                           Irp));
291
292             try_return( ntStatus);
293         }
294
295         //
296         // Is this Fcb valid???
297         //
298
299         if( BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID))
300         {
301
302             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
303                           AFS_TRACE_LEVEL_ERROR,
304                           "AFSCommonWrite (%p) Failing request due to INVALID fcb\n",
305                           Irp));
306
307             try_return( ntStatus = STATUS_FILE_DELETED);
308         }
309
310         if( BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED) ||
311             BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
312         {
313
314             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
315                           AFS_TRACE_LEVEL_ERROR,
316                           "AFSCommonWrite (%p) Request failed due to file deleted\n",
317                           Irp));
318
319             try_return( ntStatus = STATUS_FILE_DELETED);
320         }
321
322         if( FlagOn( pIrpSp->MinorFunction, IRP_MN_COMPLETE))
323         {
324
325             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
326                           AFS_TRACE_LEVEL_VERBOSE,
327                           "AFSCommonWrite (%p) IRP_MN_COMPLETE being processed\n",
328                           Irp));
329
330             CcMdlWriteComplete(pFileObject, &pIrpSp->Parameters.Write.ByteOffset, Irp->MdlAddress);
331
332             //
333             // Mdl is now Deallocated
334             //
335
336             Irp->MdlAddress = NULL;
337
338             try_return( ntStatus = STATUS_SUCCESS );
339         }
340
341         //
342         // If we get a non cached IO for a cached file we should do a purge.
343         // For now we will just promote to cached
344         //
345         if( NULL != pFileObject->SectionObjectPointer->DataSectionObject && !bPagingIo && bNonCachedIo)
346         {
347             bNonCachedIo = FALSE;
348             bForceFlush = TRUE;
349         }
350
351         if ( !bNonCachedIo && !bPagingIo)
352         {
353
354             if( pFileObject->PrivateCacheMap == NULL)
355             {
356
357                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
358                               AFS_TRACE_LEVEL_VERBOSE,
359                               "AFSCommonWrite Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
360                               &pNPFcb->SectionObjectResource,
361                               PsGetCurrentThread()));
362
363                 AFSAcquireExcl( &pNPFcb->SectionObjectResource,
364                                 TRUE);
365
366                 bReleaseSectionObject = TRUE;
367
368                 __try
369                 {
370
371                     AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
372                                   AFS_TRACE_LEVEL_VERBOSE,
373                                   "AFSCommonWrite Initialize caching on Fcb %p FileObject %p\n",
374                                   pFcb,
375                                   pFileObject));
376
377                     CcInitializeCacheMap( pFileObject,
378                                           (PCC_FILE_SIZES)&pFcb->Header.AllocationSize,
379                                           FALSE,
380                                           AFSLibCacheManagerCallbacks,
381                                           pFcb);
382
383                     CcSetReadAheadGranularity( pFileObject,
384                                                pDeviceExt->Specific.RDR.MaximumRPCLength);
385
386                     CcSetDirtyPageThreshold( pFileObject,
387                                              AFS_DIRTY_CHUNK_THRESHOLD * pDeviceExt->Specific.RDR.MaximumRPCLength / 4096);
388                 }
389                 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()))
390                 {
391
392                     ntStatus = GetExceptionCode();
393
394                     AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
395                                   AFS_TRACE_LEVEL_ERROR,
396                                   "AFSCommonWrite (%p) Exception thrown while initializing cache map Status %08lX\n",
397                                   Irp,
398                                   ntStatus));
399                 }
400
401                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
402                               AFS_TRACE_LEVEL_VERBOSE,
403                               "AFSCommonWrite Releasing Fcb SectionObject lock %p EXCL %08lX\n",
404                               &pNPFcb->SectionObjectResource,
405                               PsGetCurrentThread()));
406
407                 AFSReleaseResource( &pNPFcb->SectionObjectResource);
408
409                 bReleaseSectionObject = FALSE;
410
411                 if( !NT_SUCCESS( ntStatus))
412                 {
413
414                     try_return( ntStatus);
415                 }
416             }
417
418             //
419             // On versions of Microsoft Windows older than Vista the IO Manager
420             // will issue multiple outstanding writes on a synchronous file object
421             // if one of the cached writes completes with STATUS_PENDING.  This can
422             // result in the writes being completed out of order which can corrupt
423             // the end of file marker.  On OS versions older than Vista use a spin
424             // loop instead of deferring the write.
425             //
426
427             if ( bSynchronousFo &&
428                  AFSRtlSysVersion.dwMajorVersion < 6)
429             {
430
431                 while (!CcCanIWrite( pFileObject,
432                                      ulByteCount,
433                                      FALSE,
434                                      bRetry))
435                 {
436                     static const LONGLONG llWriteDelay = (LONGLONG)-100000;
437                     bRetry = TRUE;
438
439                     AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
440                                   AFS_TRACE_LEVEL_WARNING,
441                                   "AFSCommonWrite (FO: %p) CcCanIWrite says No room for %u bytes! Retry in 10ms\n",
442                                   pFileObject,
443                                   ulByteCount);
444
445                     KeDelayExecutionThread(KernelMode, FALSE, (PLARGE_INTEGER)&llWriteDelay);
446                 }
447             }
448             else
449             {
450
451                 if (!CcCanIWrite( pFileObject,
452                                   ulByteCount,
453                                   FALSE,
454                                   bRetry))
455                 {
456
457                     AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
458                                   AFS_TRACE_LEVEL_WARNING,
459                                   "AFSCommonWrite (FO: %p) CcCanIWrite says No room for Offset %0I64X Length %08lX bytes! Deferring%s\n",
460                                   pFileObject,
461                                   liStartingByte.QuadPart,
462                                   ulByteCount,
463                                   bRetry ? " RETRY" : ""));
464
465                     ntStatus = AFSDeferWrite( DeviceObject, pFileObject, hCallingUser, Irp, ulByteCount, bRetry);
466
467                     if ( STATUS_PENDING == ntStatus)
468                     {
469
470                         bCompleteIrp = FALSE;
471                     }
472                     else
473                     {
474
475                         AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
476                                       AFS_TRACE_LEVEL_ERROR,
477                                       "AFSCommonWrite (FO: %p) AFSDeferWrite failure Status %08lX\n",
478                                       pFileObject,
479                                       ntStatus));
480                     }
481
482                     try_return( ntStatus);
483                 }
484             }
485         }
486
487         //
488         // Save off the PID if this is not a paging IO
489         //
490
491         if( !bPagingIo &&
492             ( pFcb->Specific.File.ExtentRequestProcessId == 0 ||
493               ( ullProcessId != (ULONGLONG)AFSSysProcess &&
494                 pFcb->Specific.File.ExtentRequestProcessId != ullProcessId)))
495         {
496
497             pFcb->Specific.File.ExtentRequestProcessId = ullProcessId;
498
499             if( ullProcessId == (ULONGLONG)AFSSysProcess)
500             {
501                 AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
502                               AFS_TRACE_LEVEL_WARNING,
503                               "%s Setting LastWriterExtentProcessId to system process for Fcb %p\n",
504                               __FUNCTION__,
505                               pFcb));
506             }
507         }
508
509         //
510         // Take locks
511         //
512         //   - if Paging then we need to do nothing (the precalls will
513         //     have acquired the paging resource), for clarity we will collect
514         //     the paging resource
515         //   - If extending Write then take the fileresource EX (EOF will change, Allocation will only move out)
516         //   - Otherwise we collect the file shared, check against extending and
517         //
518
519         bLockOK = FALSE;
520
521         do
522         {
523
524             if( bPagingIo)
525             {
526
527                 //ASSERT( NULL != OnBehalfOf || ExIsResourceAcquiredLite( &pNPFcb->Resource ));
528
529                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
530                               AFS_TRACE_LEVEL_VERBOSE,
531                               "AFSCommonWrite Acquiring Fcb PagingIo lock %p SHARED %08lX\n",
532                               &pNPFcb->PagingResource,
533                               PsGetCurrentThread()));
534
535                 AFSAcquireShared( &pNPFcb->PagingResource,
536                                   TRUE);
537
538                 bReleasePaging = TRUE;
539
540                 //
541                 // We have the correct lock - we cannot have the wrong one
542                 //
543                 bLockOK = TRUE;
544             }
545             else
546             {
547
548                 bExtendingWrite = (((liStartingByte.QuadPart + ulByteCount) >=
549                                      pFcb->Header.FileSize.QuadPart) ||
550                                     (liStartingByte.LowPart == FILE_WRITE_TO_END_OF_FILE &&
551                                       liStartingByte.HighPart == -1)) ;
552
553                 if( bExtendingWrite || bNonCachedIo)
554                 {
555                     //
556                     // Check for lock inversion
557                     //
558
559                     //
560                     // For bExtendingWrite the PagingResource is needed to protect
561                     // the CcSetFileSizes call in AFSExtendingWrite
562                     //
563
564                     ASSERT( !ExIsResourceAcquiredLite( &pNPFcb->PagingResource ));
565
566                     AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
567                                   AFS_TRACE_LEVEL_VERBOSE,
568                                   "AFSCommonWrite Acquiring Fcb lock %p EXCL %08lX\n",
569                                   &pNPFcb->Resource,
570                                   PsGetCurrentThread()));
571
572                     AFSAcquireExcl( &pNPFcb->Resource,
573                                     TRUE);
574
575                     bReleaseMain = TRUE;
576
577                     AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
578                                   AFS_TRACE_LEVEL_VERBOSE,
579                                   "AFSCommonWrite Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
580                                   &pNPFcb->SectionObjectResource,
581                                   PsGetCurrentThread()));
582
583                     AFSAcquireExcl( &pNPFcb->SectionObjectResource,
584                                     TRUE);
585
586                     bReleaseSectionObject = TRUE;
587
588                     if (liStartingByte.LowPart == FILE_WRITE_TO_END_OF_FILE &&
589                          liStartingByte.HighPart == -1)
590                     {
591                         if (pFcb->Header.ValidDataLength.QuadPart > pFcb->Header.FileSize.QuadPart)
592                         {
593                             liStartingByte = pFcb->Header.ValidDataLength;
594                         }
595                         else
596                         {
597                             liStartingByte = pFcb->Header.FileSize;
598                         }
599                     }
600
601                     //
602                     // We have the correct lock - even if we don't end up truncating
603                     //
604                     bLockOK = TRUE;
605                 }
606                 else
607                 {
608                     ASSERT( !ExIsResourceAcquiredLite( &pNPFcb->PagingResource ));
609
610                     AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
611                                   AFS_TRACE_LEVEL_VERBOSE,
612                                   "AFSCommonWrite Acquiring Fcb lock %p SHARED %08lX\n",
613                                   &pNPFcb->Resource,
614                                   PsGetCurrentThread()));
615
616                     AFSAcquireShared( &pNPFcb->Resource,
617                                       TRUE);
618
619                     bReleaseMain = TRUE;
620
621                     AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
622                                   AFS_TRACE_LEVEL_VERBOSE,
623                                   "AFSCommonWrite Acquiring Fcb SectionObject lock %p SHARED %08lX\n",
624                                   &pNPFcb->SectionObjectResource,
625                                   PsGetCurrentThread()));
626
627                     AFSAcquireShared( &pNPFcb->SectionObjectResource,
628                                       TRUE);
629
630                     bReleaseSectionObject = TRUE;
631
632                     //
633                     // Have things moved?  Are we extending? If so, the the lock isn't OK
634                     //
635                     bLockOK = (liStartingByte.QuadPart + ulByteCount) < pFcb->Header.FileSize.QuadPart;
636
637                     if (!bLockOK)
638                     {
639
640                         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
641                                       AFS_TRACE_LEVEL_VERBOSE,
642                                       "AFSCommonWrite Releasing Fcb SectionObject lock %p SHARED %08lX\n",
643                                       &pNPFcb->SectionObjectResource,
644                                       PsGetCurrentThread()));
645
646                         AFSReleaseResource( &pNPFcb->SectionObjectResource);
647
648                         bReleaseSectionObject = FALSE;
649
650                         AFSReleaseResource( &pNPFcb->Resource);
651
652                         bReleaseMain = FALSE;
653                     }
654                 }
655             }
656         }
657         while (!bLockOK);
658
659         if( !bPagingIo)
660         {
661
662             //
663             // Check the BR locks on the file.
664             //
665
666             if ( !FsRtlCheckLockForWriteAccess( &pFcb->Specific.File.FileLock,
667                                                 Irp))
668             {
669
670                 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
671                               AFS_TRACE_LEVEL_ERROR,
672                               "AFSCommonWrite (%p) Request failed due to lock conflict\n",
673                               Irp));
674
675                 try_return( ntStatus = STATUS_FILE_LOCK_CONFLICT);
676             }
677
678             if( bExtendingWrite)
679             {
680
681                 ntStatus = AFSExtendingWrite( pFcb, pFileObject, (liStartingByte.QuadPart + ulByteCount));
682
683                 //
684                 // Fcb->NPFcb->Resource is now held SHARED
685                 //
686
687                 if( !NT_SUCCESS(ntStatus))
688                 {
689
690                     AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
691                                   AFS_TRACE_LEVEL_ERROR,
692                                   "AFSCommonWrite (%p) Failed extending write request Status %08lX\n",
693                                   Irp,
694                                   ntStatus));
695
696                     try_return( ntStatus );
697                 }
698             }
699         }
700
701         //
702         // Fire off the request as appropriate
703         //
704         bCompleteIrp = FALSE;
705
706         if( !bPagingIo &&
707             !bNonCachedIo)
708         {
709
710             //
711             // Main resource held Shared
712             // SectionObject resource held exclusive if extending write
713             //
714
715             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
716                           AFS_TRACE_LEVEL_VERBOSE,
717                           "AFSCommonWrite (%p) Processing CACHED request Offset %0I64X Len %08lX%s\n",
718                           Irp,
719                           liStartingByte.QuadPart,
720                           ulByteCount,
721                           bRetry ? " RETRY" : ""));
722
723             ntStatus = AFSCachedWrite( DeviceObject, Irp, liStartingByte, ulByteCount, bForceFlush);
724         }
725         else
726         {
727
728             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
729                           AFS_TRACE_LEVEL_VERBOSE,
730                           "AFSCommonWrite (%p) Processing NON-CACHED request Offset %0I64X Len %08lX%s\n",
731                           Irp,
732                           liStartingByte.QuadPart,
733                           ulByteCount,
734                           bRetry ? " RETRY" : ""));
735
736             if( BooleanFlagOn( pRDRDevExt->DeviceFlags, AFS_DEVICE_FLAG_DIRECT_SERVICE_IO))
737             {
738
739                 ntStatus = AFSNonCachedWriteDirect( DeviceObject, Irp,  liStartingByte, ulByteCount);
740             }
741             else
742             {
743                 ntStatus = AFSNonCachedWrite( DeviceObject, Irp,  liStartingByte, ulByteCount);
744             }
745         }
746
747 try_exit:
748
749         AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
750                       AFS_TRACE_LEVEL_VERBOSE,
751                       "AFSCommonWrite (%p) Process complete Status %08lX\n",
752                       Irp,
753                       ntStatus));
754
755         if ( NT_SUCCESS( ntStatus))
756         {
757             if ( !bPagingIo)
758             {
759
760                 if( bSynchronousFo)
761                 {
762
763                     pFileObject->CurrentByteOffset.QuadPart = liStartingByte.QuadPart + ulByteCount;
764                 }
765
766                 //
767                 // If this extended the VDL, then update it accordingly.
768                 // Increasing the VDL does not require a call to CcSetFileSizes.
769                 //
770
771                 if( liStartingByte.QuadPart + ulByteCount > pFcb->Header.ValidDataLength.QuadPart)
772                 {
773
774                     pFcb->Header.ValidDataLength.QuadPart = liStartingByte.QuadPart + ulByteCount;
775                 }
776
777                 if( !BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME))
778                 {
779
780                     SetFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_WRITE_TIME);
781
782                     KeQuerySystemTime( &pFcb->ObjectInformation->LastWriteTime);
783                 }
784             }
785         }
786
787         if ( !bPagingIo && bNonCachedIo && CcIsFileCached( pFileObject) &&
788              pNPFcb->SectionObjectPointers.DataSectionObject != NULL &&
789              bReleaseSectionObject)
790         {
791             //
792             // Regardless of whether or not the a non-paging non-cached write
793             // succeeds or fails, if the file is cached the contents of the
794             // cache are no longer up to date.  A CcPurgeCacheSection must be
795             // performed to force subsequent cached reads to obtain the data
796             // from the service.
797             //
798             // The Fcb Resource is dropped in order to permit filters that perform
799             // an open via a worker thread in response to a purge to do so without
800             // deadlocking.  The SectionObjectResource is held across the purge to
801             // prevent racing with other cache operations.
802             //
803
804             if( bReleaseMain)
805             {
806
807                 AFSReleaseResource( &pNPFcb->Resource);
808
809                 bReleaseMain = FALSE;
810             }
811
812             __try
813             {
814
815                 if ( !CcPurgeCacheSection( &pNPFcb->SectionObjectPointers,
816                                            &liStartingByte,
817                                            ulByteCount,
818                                            FALSE))
819                 {
820
821                     AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
822                                   AFS_TRACE_LEVEL_WARNING,
823                                   "AFSCommonWrite CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
824                                   pFcb->ObjectInformation->FileId.Cell,
825                                   pFcb->ObjectInformation->FileId.Volume,
826                                   pFcb->ObjectInformation->FileId.Vnode,
827                                   pFcb->ObjectInformation->FileId.Unique));
828
829                     SetFlag( pFcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
830                 }
831             }
832             __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()))
833             {
834
835                 DWORD ntStatus2 = GetExceptionCode();
836
837                 AFSDbgTrace(( 0,
838                               0,
839                               "EXCEPTION - AFSCommonWrite CcPurgeCacheSection failed FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
840                               pFcb->ObjectInformation->FileId.Cell,
841                               pFcb->ObjectInformation->FileId.Volume,
842                               pFcb->ObjectInformation->FileId.Vnode,
843                               pFcb->ObjectInformation->FileId.Unique,
844                               ntStatus2));
845
846                 SetFlag( pFcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
847             }
848         }
849
850         ObDereferenceObject(pFileObject);
851
852         if( bReleaseSectionObject)
853         {
854
855             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
856                           AFS_TRACE_LEVEL_VERBOSE,
857                           "AFSCommonWrite Releasing Fcb SectionObject lock %p EXCL/SHARED %08lX\n",
858                           &pNPFcb->SectionObjectResource,
859                           PsGetCurrentThread()));
860
861             AFSReleaseResource( &pNPFcb->SectionObjectResource);
862         }
863
864         if( bReleasePaging)
865         {
866
867             AFSReleaseResource( &pNPFcb->PagingResource);
868         }
869
870         if( bReleaseMain)
871         {
872
873             AFSReleaseResource( &pNPFcb->Resource);
874         }
875
876         if( bCompleteIrp)
877         {
878
879             AFSCompleteRequest( Irp,
880                                 ntStatus);
881         }
882     }
883
884     return ntStatus;
885 }
886
887 NTSTATUS
888 AFSIOCtlWrite( IN PDEVICE_OBJECT DeviceObject,
889                IN PIRP Irp)
890 {
891
892     UNREFERENCED_PARAMETER(DeviceObject);
893     NTSTATUS ntStatus = STATUS_SUCCESS;
894     AFSPIOCtlIORequestCB stIORequestCB;
895     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
896     AFSFcb *pFcb = NULL;
897     AFSCcb *pCcb = NULL;
898     AFSPIOCtlIOResultCB stIOResultCB;
899     ULONG ulBytesReturned = 0;
900     AFSFileID stParentFID;
901
902     __Enter
903     {
904
905         Irp->IoStatus.Information = 0;
906
907         RtlZeroMemory( &stIORequestCB,
908                        sizeof( AFSPIOCtlIORequestCB));
909
910         if( pIrpSp->Parameters.Write.Length == 0)
911         {
912
913             //
914             // Nothing to do in this case
915             //
916
917             try_return( ntStatus);
918         }
919
920         pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
921
922         pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
923
924         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
925                       AFS_TRACE_LEVEL_VERBOSE,
926                       "AFSIOCtlWrite Acquiring Fcb lock %p SHARED %08lX\n",
927                       &pFcb->NPFcb->Resource,
928                       PsGetCurrentThread()));
929
930         AFSAcquireShared( &pFcb->NPFcb->Resource,
931                           TRUE);
932
933         //
934         // Get the parent fid to pass to the cm
935         //
936
937         RtlZeroMemory( &stParentFID,
938                        sizeof( AFSFileID));
939
940         if( BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
941         {
942
943             //
944             // The parent directory FID of the node
945             //
946
947             stParentFID = pFcb->ObjectInformation->ParentFileId;
948         }
949
950         //
951         // Set the control block up
952         //
953
954         stIORequestCB.RequestId = pCcb->RequestID;
955
956         if( pFcb->ObjectInformation->VolumeCB != NULL)
957         {
958             stIORequestCB.RootId = pFcb->ObjectInformation->VolumeCB->ObjectInformation.FileId;
959         }
960
961         //
962         // Lock down the buffer
963         //
964
965         stIORequestCB.MappedBuffer = AFSMapToService( Irp,
966                                                       pIrpSp->Parameters.Write.Length);
967
968         if( stIORequestCB.MappedBuffer == NULL)
969         {
970
971             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
972         }
973
974         stIORequestCB.BufferLength = pIrpSp->Parameters.Write.Length;
975
976         stIOResultCB.BytesProcessed = 0;
977
978         ulBytesReturned = sizeof( AFSPIOCtlIOResultCB);
979
980         //
981         // Issue the request to the service
982         //
983
984         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIOCTL_WRITE,
985                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
986                                       &pCcb->AuthGroup,
987                                       NULL,
988                                       &stParentFID,
989                                       NULL,
990                                       0,
991                                       (void *)&stIORequestCB,
992                                       sizeof( AFSPIOCtlIORequestCB),
993                                       &stIOResultCB,
994                                       &ulBytesReturned);
995
996         if( !NT_SUCCESS( ntStatus))
997         {
998
999             try_return( ntStatus);
1000         }
1001
1002         //
1003         // Update the length written
1004         //
1005
1006         Irp->IoStatus.Information = stIOResultCB.BytesProcessed;
1007
1008 try_exit:
1009
1010         if( stIORequestCB.MappedBuffer != NULL)
1011         {
1012
1013             AFSUnmapServiceMappedBuffer( stIORequestCB.MappedBuffer,
1014                                          Irp->MdlAddress);
1015         }
1016
1017         if( pFcb != NULL)
1018         {
1019
1020             AFSReleaseResource( &pFcb->NPFcb->Resource);
1021         }
1022     }
1023
1024     return ntStatus;
1025 }
1026
1027 //
1028 // This function is called when we know we have to read from the AFS Cache.
1029 //
1030 // It ensures that we have exents for the entirety of the write and
1031 // then pins the extents into memory (meaning that although we may
1032 // add we will not remove).  Then it creates a scatter gather write
1033 // and fires off the IRPs
1034 //
1035 static
1036 NTSTATUS
1037 AFSNonCachedWrite( IN PDEVICE_OBJECT DeviceObject,
1038                    IN PIRP Irp,
1039                    IN LARGE_INTEGER StartingByte,
1040                    IN ULONG ByteCount)
1041 {
1042     NTSTATUS           ntStatus = STATUS_UNSUCCESSFUL;
1043     VOID              *pSystemBuffer = NULL;
1044     BOOLEAN            bPagingIo = BooleanFlagOn( Irp->Flags, IRP_PAGING_IO);
1045     BOOLEAN            bLocked = FALSE;
1046     BOOLEAN            bCompleteIrp = TRUE;
1047     AFSGatherIo       *pGatherIo = NULL;
1048     AFSIoRun          *pIoRuns = NULL;
1049     AFSIoRun           stIoRuns[AFS_MAX_STACK_IO_RUNS];
1050     ULONG              extentsCount = 0, runCount = 0;
1051     AFSExtent         *pStartExtent = NULL;
1052     AFSExtent         *pIgnoreExtent = NULL;
1053     IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1054     PFILE_OBJECT       pFileObject = pIrpSp->FileObject;
1055     AFSFcb            *pFcb = (AFSFcb *)pFileObject->FsContext;
1056     AFSCcb            *pCcb = (AFSCcb *)pFileObject->FsContext2;
1057     BOOLEAN            bSynchronousFo = BooleanFlagOn( pFileObject->Flags, FO_SYNCHRONOUS_IO);
1058     AFSDeviceExt      *pDevExt = (AFSDeviceExt *)DeviceObject->DeviceExtension;
1059     LARGE_INTEGER      liCurrentTime, liLastRequestTime;
1060     AFSDeviceExt      *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1061     PFILE_OBJECT       pCacheFileObject = NULL;
1062     BOOLEAN            bDerefExtents = FALSE;
1063
1064     __Enter
1065     {
1066
1067         AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1068                       AFS_TRACE_LEVEL_VERBOSE,
1069                       "AFSNonCachedWrite (FO: %p) StartingByte %08lX:%08lX Length %08lX\n",
1070                       pFileObject,
1071                       StartingByte.HighPart,
1072                       StartingByte.LowPart,
1073                       ByteCount));
1074
1075         if (ByteCount > pDevExt->Specific.RDR.MaxIo.QuadPart)
1076         {
1077
1078             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1079                           AFS_TRACE_LEVEL_ERROR,
1080                           "AFSNonCachedWrite (%p) Request %08lX Actual %08lX larger than MaxIO %I64X\n",
1081                           Irp,
1082                           ByteCount,
1083                           pIrpSp->Parameters.Write.Length,
1084                           pDevExt->Specific.RDR.MaxIo.QuadPart));
1085
1086             try_return( ntStatus = STATUS_UNSUCCESSFUL);
1087         }
1088
1089         //
1090         // Get the mapping for the buffer
1091         //
1092         pSystemBuffer = AFSLockSystemBuffer( Irp,
1093                                              ByteCount);
1094
1095         if( pSystemBuffer == NULL)
1096         {
1097
1098             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1099                           AFS_TRACE_LEVEL_ERROR,
1100                           "AFSNonCachedWrite (%p) Failed to map system buffer\n",
1101                           Irp));
1102
1103             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1104         }
1105
1106
1107         //
1108         // Provoke a get of the extents - if we need to.
1109         //
1110
1111         AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1112                       AFS_TRACE_LEVEL_VERBOSE,
1113                       "AFSNonCachedWrite Requesting extents for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX\n",
1114                       pFcb->ObjectInformation->FileId.Cell,
1115                       pFcb->ObjectInformation->FileId.Volume,
1116                       pFcb->ObjectInformation->FileId.Vnode,
1117                       pFcb->ObjectInformation->FileId.Unique,
1118                       StartingByte.QuadPart,
1119                       ByteCount));
1120
1121         ntStatus = AFSRequestExtentsAsync( pFcb,
1122                                            pCcb,
1123                                            &StartingByte,
1124                                            ByteCount);
1125
1126         if (!NT_SUCCESS(ntStatus))
1127         {
1128
1129             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1130                           AFS_TRACE_LEVEL_ERROR,
1131                           "AFSNonCachedWrite (%p) Failed to request extents Status %08lX\n",
1132                           Irp,
1133                           ntStatus));
1134
1135             try_return( ntStatus);
1136         }
1137
1138         KeQueryTickCount( &liLastRequestTime);
1139
1140         while (TRUE)
1141         {
1142
1143             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1144                           AFS_TRACE_LEVEL_VERBOSE,
1145                           "AFSNonCachedWrite Acquiring Fcb extents lock %p SHARED %08lX\n",
1146                           &pFcb->NPFcb->Specific.File.ExtentsResource,
1147                           PsGetCurrentThread()));
1148
1149             ASSERT( !ExIsResourceAcquiredLite( &pFcb->NPFcb->Specific.File.ExtentsResource ));
1150
1151             AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource, TRUE );
1152             bLocked = TRUE;
1153
1154             pStartExtent = NULL;
1155             pIgnoreExtent = NULL;
1156
1157             if ( AFSDoExtentsMapRegion( pFcb, &StartingByte, ByteCount, &pStartExtent, &pIgnoreExtent ))
1158             {
1159                 break;
1160             }
1161
1162             KeClearEvent( &pFcb->NPFcb->Specific.File.ExtentsRequestComplete );
1163
1164             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1165                           AFS_TRACE_LEVEL_VERBOSE,
1166                           "AFSNonCachedWrite Releasing(1) Fcb extents lock %p SHARED %08lX\n",
1167                           &pFcb->NPFcb->Specific.File.ExtentsResource,
1168                           PsGetCurrentThread()));
1169
1170             AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
1171             bLocked= FALSE;
1172
1173             //
1174             // We will re-request the extents after waiting for them
1175             //
1176
1177             KeQueryTickCount( &liCurrentTime);
1178
1179             if( liCurrentTime.QuadPart - liLastRequestTime.QuadPart >= pControlDevExt->Specific.Control.ExtentRequestTimeCount.QuadPart)
1180             {
1181
1182                 AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1183                               AFS_TRACE_LEVEL_VERBOSE,
1184                               "AFSNonCachedWrite Requesting extents, again, for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX\n",
1185                               pFcb->ObjectInformation->FileId.Cell,
1186                               pFcb->ObjectInformation->FileId.Volume,
1187                               pFcb->ObjectInformation->FileId.Vnode,
1188                               pFcb->ObjectInformation->FileId.Unique,
1189                               StartingByte.QuadPart,
1190                               ByteCount));
1191
1192                 ntStatus = AFSRequestExtentsAsync( pFcb,
1193                                                    pCcb,
1194                                                    &StartingByte,
1195                                                    ByteCount);
1196
1197                 if (!NT_SUCCESS(ntStatus))
1198                 {
1199
1200                     AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1201                                   AFS_TRACE_LEVEL_ERROR,
1202                                   "AFSNonCachedWrite (%p) Failed to request extents Status %08lX\n",
1203                                   Irp,
1204                                   ntStatus));
1205
1206                     try_return( ntStatus);
1207                 }
1208
1209                 KeQueryTickCount( &liLastRequestTime);
1210             }
1211
1212
1213             AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1214                           AFS_TRACE_LEVEL_VERBOSE,
1215                           "AFSNonCachedWrite Waiting for extents for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX\n",
1216                           pFcb->ObjectInformation->FileId.Cell,
1217                           pFcb->ObjectInformation->FileId.Volume,
1218                           pFcb->ObjectInformation->FileId.Vnode,
1219                           pFcb->ObjectInformation->FileId.Unique,
1220                           StartingByte.QuadPart,
1221                           ByteCount));
1222
1223             //
1224             // Wait for it
1225             //
1226
1227             ntStatus =  AFSWaitForExtentMapping ( pFcb, pCcb);
1228
1229             if (!NT_SUCCESS(ntStatus))
1230             {
1231
1232                 AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1233                               AFS_TRACE_LEVEL_ERROR,
1234                               "AFSNonCachedWrite Failed wait for extents for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX Status %08lX\n",
1235                               pFcb->ObjectInformation->FileId.Cell,
1236                               pFcb->ObjectInformation->FileId.Volume,
1237                               pFcb->ObjectInformation->FileId.Vnode,
1238                               pFcb->ObjectInformation->FileId.Unique,
1239                               StartingByte.QuadPart,
1240                               ByteCount,
1241                               ntStatus));
1242
1243                 try_return( ntStatus);
1244             }
1245         }
1246
1247         //
1248         // As per the read path -
1249         //
1250
1251         AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1252                       AFS_TRACE_LEVEL_VERBOSE,
1253                       "AFSNonCachedWrite Extents located for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX\n",
1254                       pFcb->ObjectInformation->FileId.Cell,
1255                       pFcb->ObjectInformation->FileId.Volume,
1256                       pFcb->ObjectInformation->FileId.Vnode,
1257                       pFcb->ObjectInformation->FileId.Unique,
1258                       StartingByte.QuadPart,
1259                       ByteCount));
1260
1261         ntStatus = AFSGetExtents( pFcb,
1262                                   &StartingByte,
1263                                   ByteCount,
1264                                   pStartExtent,
1265                                   &extentsCount,
1266                                   &runCount);
1267
1268         if (!NT_SUCCESS(ntStatus))
1269         {
1270
1271             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1272                           AFS_TRACE_LEVEL_ERROR,
1273                           "AFSNonCachedWrite (%p) Failed to retrieve mapped extents Status %08lX\n",
1274                           Irp,
1275                           ntStatus));
1276
1277             try_return( ntStatus );
1278         }
1279
1280         AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1281                       AFS_TRACE_LEVEL_VERBOSE,
1282                       "AFSNonCachedWrite (%p) Successfully retrieved map extents count %d run count %d\n",
1283                       Irp,
1284                       extentsCount,
1285                       runCount));
1286
1287         if( BooleanFlagOn( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE))
1288         {
1289
1290             Irp->IoStatus.Information = ByteCount;
1291
1292 #if GEN_MD5
1293             //
1294             // Setup the MD5 for each extent
1295             //
1296
1297             AFSSetupMD5Hash( pFcb,
1298                              pStartExtent,
1299                              extentsCount,
1300                              pSystemBuffer,
1301                              &StartingByte,
1302                              ByteCount);
1303 #endif
1304
1305             ntStatus = AFSProcessExtentRun( pSystemBuffer,
1306                                             &StartingByte,
1307                                             ByteCount,
1308                                             pStartExtent,
1309                                             TRUE);
1310
1311             if (!NT_SUCCESS(ntStatus))
1312             {
1313
1314                 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1315                               AFS_TRACE_LEVEL_ERROR,
1316                               "AFSNonCachedWrite (%p) Failed to process extent run for non-persistent cache Status %08lX\n",
1317                               Irp,
1318                               ntStatus));
1319             }
1320
1321             try_return( ntStatus);
1322         }
1323
1324         //
1325         // Retrieve the cache file object
1326         //
1327
1328         pCacheFileObject = AFSReferenceCacheFileObject();
1329
1330         if( pCacheFileObject == NULL)
1331         {
1332
1333             ntStatus = STATUS_DEVICE_NOT_READY;
1334
1335             AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1336                           AFS_TRACE_LEVEL_ERROR,
1337                           "AFSNonCachedWrite Failed to retrieve cache fileobject for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX Status %08lX\n",
1338                           pFcb->ObjectInformation->FileId.Cell,
1339                           pFcb->ObjectInformation->FileId.Volume,
1340                           pFcb->ObjectInformation->FileId.Vnode,
1341                           pFcb->ObjectInformation->FileId.Unique,
1342                           StartingByte.QuadPart,
1343                           ByteCount,
1344                           ntStatus));
1345
1346             try_return( ntStatus);
1347         }
1348
1349         if (runCount > AFS_MAX_STACK_IO_RUNS)
1350         {
1351
1352             pIoRuns = (AFSIoRun*) AFSExAllocatePoolWithTag( PagedPool,
1353                                                             runCount * sizeof( AFSIoRun ),
1354                                                             AFS_IO_RUN_TAG );
1355             if (NULL == pIoRuns)
1356             {
1357
1358                 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1359                               AFS_TRACE_LEVEL_ERROR,
1360                               "AFSNonCachedWrite (%p) Failed to allocate IO run block\n",
1361                               Irp));
1362
1363                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
1364             }
1365         }
1366         else
1367         {
1368
1369             pIoRuns = stIoRuns;
1370         }
1371
1372         RtlZeroMemory( pIoRuns, runCount * sizeof( AFSIoRun ));
1373
1374         ntStatus = AFSSetupIoRun( IoGetRelatedDeviceObject( pCacheFileObject),
1375                                   Irp,
1376                                   pSystemBuffer,
1377                                   pIoRuns,
1378                                   &StartingByte,
1379                                   ByteCount,
1380                                   pStartExtent,
1381                                   &runCount );
1382
1383         if (!NT_SUCCESS(ntStatus))
1384         {
1385
1386             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1387                           AFS_TRACE_LEVEL_ERROR,
1388                           "AFSNonCachedWrite (%p) Failed to initialize IO run block Status %08lX\n",
1389                           Irp,
1390                           ntStatus));
1391
1392             try_return( ntStatus );
1393         }
1394
1395         AFSReferenceActiveExtents( pStartExtent,
1396                                    extentsCount);
1397
1398         bDerefExtents = TRUE;
1399
1400         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1401                       AFS_TRACE_LEVEL_VERBOSE,
1402                       "AFSNonCachedWrite Releasing(2) Fcb extents lock %p SHARED %08lX\n",
1403                       &pFcb->NPFcb->Specific.File.ExtentsResource,
1404                       PsGetCurrentThread()));
1405
1406         AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
1407         bLocked = FALSE;
1408
1409         pGatherIo = (AFSGatherIo*) AFSExAllocatePoolWithTag( NonPagedPool,
1410                                                              sizeof( AFSGatherIo),
1411                                                              AFS_GATHER_TAG);
1412
1413         if (NULL == pGatherIo)
1414         {
1415
1416             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1417                           AFS_TRACE_LEVEL_ERROR,
1418                           "AFSNonCachedWrite (%p) Failed to allocate IO gather block\n",
1419                           Irp));
1420
1421             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1422                           AFS_TRACE_LEVEL_VERBOSE,
1423                           "AFSNonCachedWrite Acquiring(1) Fcb extents lock %p SHARED %08lX\n",
1424                           &pFcb->NPFcb->Specific.File.ExtentsResource,
1425                           PsGetCurrentThread()));
1426
1427             AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
1428                               TRUE);
1429             bLocked = TRUE;
1430
1431             AFSDereferenceActiveExtents( pStartExtent,
1432                                          extentsCount);
1433
1434             try_return (ntStatus = STATUS_INSUFFICIENT_RESOURCES );
1435         }
1436
1437         RtlZeroMemory( pGatherIo, sizeof( AFSGatherIo ));
1438
1439         //
1440         // Initialize count to 1, that was we won't get an early
1441         // completion if the first irp completes before the second is
1442         // queued.
1443         //
1444         pGatherIo->Count = 1;
1445         pGatherIo->Status = STATUS_SUCCESS;
1446         pGatherIo->MasterIrp = Irp;
1447         pGatherIo->Synchronous = TRUE;
1448         pGatherIo->CompleteMasterIrp = FALSE;
1449
1450         bCompleteIrp = TRUE;
1451
1452         if( pGatherIo->Synchronous)
1453         {
1454             KeInitializeEvent( &pGatherIo->Event, NotificationEvent, FALSE );
1455         }
1456
1457 #if GEN_MD5
1458         //
1459         // Setup the MD5 for each extent
1460         //
1461
1462         AFSSetupMD5Hash( pFcb,
1463                          pStartExtent,
1464                          extentsCount,
1465                          pSystemBuffer,
1466                          &StartingByte,
1467                          ByteCount);
1468 #endif
1469
1470         //
1471         // Pre-emptively set up the count
1472         //
1473
1474         Irp->IoStatus.Information = ByteCount;
1475
1476         ntStatus = AFSQueueStartIos( pCacheFileObject,
1477                                      IRP_MJ_WRITE,
1478                                      IRP_WRITE_OPERATION | IRP_SYNCHRONOUS_API,
1479                                      pIoRuns,
1480                                      runCount,
1481                                      pGatherIo);
1482
1483         AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1484                       AFS_TRACE_LEVEL_VERBOSE,
1485                       "AFSNonCachedWrite (%p) AFSStartIos completed Status %08lX\n",
1486                       Irp,
1487                       ntStatus));
1488
1489         if( !NT_SUCCESS( ntStatus))
1490         {
1491
1492             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1493                           AFS_TRACE_LEVEL_VERBOSE,
1494                           "AFSNonCachedWrite Acquiring(2) Fcb extents lock %p SHARED %08lX\n",
1495                           &pFcb->NPFcb->Specific.File.ExtentsResource,
1496                           PsGetCurrentThread()));
1497
1498             AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
1499                               TRUE);
1500             bLocked = TRUE;
1501
1502             AFSDereferenceActiveExtents( pStartExtent,
1503                                          extentsCount);
1504
1505             try_return( ntStatus);
1506         }
1507
1508         //
1509         // Wait for completion of All IOs we started.
1510         //
1511
1512         ntStatus = KeWaitForSingleObject( &pGatherIo->Event,
1513                                           Executive,
1514                                           KernelMode,
1515                                           FALSE,
1516                                           NULL);
1517
1518         if( NT_SUCCESS( ntStatus))
1519         {
1520
1521             ntStatus = pGatherIo->Status;
1522         }
1523
1524         if( !NT_SUCCESS( ntStatus))
1525         {
1526
1527             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1528                           AFS_TRACE_LEVEL_VERBOSE,
1529                           "AFSNonCachedWrite Acquiring(3) Fcb extents lock %p SHARED %08lX\n",
1530                           &pFcb->NPFcb->Specific.File.ExtentsResource,
1531                           PsGetCurrentThread()));
1532
1533             AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
1534                               TRUE);
1535             bLocked = TRUE;
1536
1537             AFSDereferenceActiveExtents( pStartExtent,
1538                                          extentsCount);
1539
1540             try_return( ntStatus);
1541         }
1542
1543 try_exit:
1544
1545         if( NT_SUCCESS( ntStatus) &&
1546             pStartExtent != NULL &&
1547             Irp->IoStatus.Information > 0)
1548         {
1549
1550             if ( !bLocked)
1551             {
1552
1553                 AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
1554                                   TRUE);
1555                 bLocked = TRUE;
1556             }
1557
1558             //
1559             // Since this is dirty we can mark the extents dirty now.
1560             // AFSMarkDirty will dereference the extents.  Do not call
1561             // AFSDereferenceActiveExtents() in this code path.
1562             //
1563
1564             AFSMarkDirty( pFcb,
1565                           pStartExtent,
1566                           extentsCount,
1567                           &StartingByte,
1568                           bDerefExtents);
1569
1570             if (!bPagingIo)
1571             {
1572                 //
1573                 // This was an uncached user write - tell the server to do
1574                 // the flush when the worker thread next wakes up
1575                 //
1576                 pFcb->Specific.File.LastServerFlush.QuadPart = 0;
1577             }
1578         }
1579
1580         if( pCacheFileObject != NULL)
1581         {
1582             AFSReleaseCacheFileObject( pCacheFileObject);
1583         }
1584
1585         AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1586                       AFS_TRACE_LEVEL_VERBOSE,
1587                       "AFSNonCachedWrite (FO: %p) StartingByte %08lX:%08lX Length %08lX Status %08lX\n",
1588                       pFileObject,
1589                       StartingByte.HighPart,
1590                       StartingByte.LowPart,
1591                       ByteCount,
1592                       ntStatus));
1593
1594         if (NT_SUCCESS(ntStatus) &&
1595             !bPagingIo &&
1596             bSynchronousFo)
1597         {
1598
1599             pFileObject->CurrentByteOffset.QuadPart = StartingByte.QuadPart + ByteCount;
1600         }
1601
1602         if( bLocked)
1603         {
1604
1605             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1606                           AFS_TRACE_LEVEL_VERBOSE,
1607                           "AFSNonCachedWrite Releasing Fcb extents lock %p SHARED %08lX\n",
1608                           &pFcb->NPFcb->Specific.File.ExtentsResource,
1609                           PsGetCurrentThread()));
1610
1611             AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
1612         }
1613
1614         if( pGatherIo)
1615         {
1616             AFSExFreePoolWithTag(pGatherIo, AFS_GATHER_TAG);
1617         }
1618
1619         if( NULL != pIoRuns &&
1620             stIoRuns != pIoRuns)
1621         {
1622             AFSExFreePoolWithTag(pIoRuns, AFS_IO_RUN_TAG);
1623         }
1624
1625         if( bCompleteIrp)
1626         {
1627
1628             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1629                           AFS_TRACE_LEVEL_VERBOSE,
1630                           "AFSNonCachedWrite Completing Irp %p Status %08lX Info %08lX\n",
1631                           Irp,
1632                           ntStatus,
1633                           Irp->IoStatus.Information));
1634
1635             AFSCompleteRequest( Irp, ntStatus);
1636         }
1637     }
1638
1639     return ntStatus;
1640 }
1641
1642 static
1643 NTSTATUS
1644 AFSNonCachedWriteDirect( IN PDEVICE_OBJECT DeviceObject,
1645                          IN PIRP Irp,
1646                          IN LARGE_INTEGER StartingByte,
1647                          IN ULONG ByteCount)
1648 {
1649     NTSTATUS           ntStatus = STATUS_UNSUCCESSFUL;
1650     VOID              *pSystemBuffer = NULL;
1651     BOOLEAN            bPagingIo = BooleanFlagOn( Irp->Flags, IRP_PAGING_IO);
1652     IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1653     PFILE_OBJECT       pFileObject = pIrpSp->FileObject;
1654     AFSFcb            *pFcb = (AFSFcb *)pFileObject->FsContext;
1655     AFSCcb            *pCcb = (AFSCcb *)pFileObject->FsContext2;
1656     BOOLEAN            bSynchronousFo = BooleanFlagOn( pFileObject->Flags, FO_SYNCHRONOUS_IO);
1657     BOOLEAN            bNoIntermediateBuffering = BooleanFlagOn( pFileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING);
1658     AFSDeviceExt      *pDevExt = (AFSDeviceExt *)DeviceObject->DeviceExtension;
1659     AFSFileIOCB        stFileIORequest;
1660     AFSFileIOResultCB  stFileIOResult;
1661     ULONG              ulResultLen = 0;
1662     ULONG              ulFlags;
1663
1664     __Enter
1665     {
1666         Irp->IoStatus.Information = 0;
1667
1668         AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1669                       AFS_TRACE_LEVEL_VERBOSE,
1670                       "AFSNonCachedWriteDirect (FO: %p) StartingByte %08lX:%08lX Length %08lX\n",
1671                       pFileObject,
1672                       StartingByte.HighPart,
1673                       StartingByte.LowPart,
1674                       ByteCount));
1675
1676         if (ByteCount > pDevExt->Specific.RDR.MaxIo.QuadPart)
1677         {
1678
1679             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1680                           AFS_TRACE_LEVEL_ERROR,
1681                           "AFSNonCachedWriteDirect (%p) Request %08lX Actual %08lX larger than MaxIO %I64X\n",
1682                           Irp,
1683                           ByteCount,
1684                           pIrpSp->Parameters.Write.Length,
1685                           pDevExt->Specific.RDR.MaxIo.QuadPart));
1686
1687             try_return( ntStatus = STATUS_UNSUCCESSFUL);
1688         }
1689
1690         //
1691         // Get the mapping for the buffer
1692         //
1693         pSystemBuffer = AFSLockSystemBuffer( Irp,
1694                                              ByteCount);
1695
1696         if( pSystemBuffer == NULL)
1697         {
1698
1699             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1700                           AFS_TRACE_LEVEL_ERROR,
1701                           "AFSNonCachedWriteDirect (%p) Failed to map system buffer\n",
1702                           Irp));
1703
1704             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1705         }
1706
1707         //
1708         // Issue the request at the service for processing
1709         //
1710
1711         ulResultLen = sizeof( AFSFileIOResultCB);
1712
1713         RtlZeroMemory( &stFileIORequest,
1714                        sizeof( AFSFileIOCB));
1715
1716         RtlZeroMemory( &stFileIOResult,
1717                        sizeof( AFSFileIOResultCB));
1718
1719         stFileIORequest.SystemIOBuffer = pSystemBuffer;
1720
1721         stFileIORequest.SystemIOBufferMdl = Irp->MdlAddress;
1722
1723         stFileIORequest.IOLength = ByteCount;
1724
1725         stFileIORequest.IOOffset = StartingByte;
1726
1727         ulFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
1728
1729         if ( bNoIntermediateBuffering)
1730         {
1731
1732             ulFlags |= AFS_REQUEST_FLAG_CACHE_BYPASS;
1733         }
1734
1735         //
1736         // Update file metadata
1737         //
1738
1739         stFileIORequest.EndOfFile = pFcb->ObjectInformation->EndOfFile;
1740
1741         stFileIORequest.CreateTime = pFcb->ObjectInformation->CreationTime;
1742
1743         stFileIORequest.ChangeTime = pFcb->ObjectInformation->ChangeTime;
1744
1745         stFileIORequest.LastAccessTime = pFcb->ObjectInformation->LastAccessTime;
1746
1747         stFileIORequest.LastWriteTime = pFcb->ObjectInformation->LastWriteTime;
1748
1749         //
1750         // Write the data to the service
1751         //
1752
1753         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PROCESS_WRITE_FILE,
1754                                       ulFlags,
1755                                       &pCcb->AuthGroup,
1756                                       &pCcb->DirectoryCB->NameInformation.FileName,
1757                                       &pFcb->ObjectInformation->FileId,
1758                                       pFcb->ObjectInformation->VolumeCB->VolumeInformation.Cell,
1759                                       pFcb->ObjectInformation->VolumeCB->VolumeInformation.CellLength,
1760                                       &stFileIORequest,
1761                                       sizeof( AFSFileIOCB),
1762                                       &stFileIOResult,
1763                                       &ulResultLen);
1764
1765         if( NT_SUCCESS( ntStatus))
1766         {
1767
1768             Irp->IoStatus.Information = (ULONG_PTR)stFileIOResult.Length;
1769         }
1770         else
1771         {
1772
1773             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1774                           AFS_TRACE_LEVEL_ERROR,
1775                           "AFSNonCachedWriteDirect (%p) Failed to send write to service Status %08lX\n",
1776                           Irp,
1777                           ntStatus));
1778         }
1779
1780 try_exit:
1781
1782         AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1783                       AFS_TRACE_LEVEL_VERBOSE,
1784                       "AFSNonCachedWriteDirect (FO: %p) StartingByte %08lX:%08lX Length %08lX Status %08lX\n",
1785                       pFileObject,
1786                       StartingByte.HighPart,
1787                       StartingByte.LowPart,
1788                       ByteCount,
1789                       ntStatus));
1790
1791         if (NT_SUCCESS(ntStatus) &&
1792             !bPagingIo &&
1793             bSynchronousFo)
1794         {
1795
1796             pFileObject->CurrentByteOffset.QuadPart = StartingByte.QuadPart + ByteCount;
1797         }
1798
1799         AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1800                       AFS_TRACE_LEVEL_VERBOSE,
1801                       "AFSNonCachedWriteDirect Completing Irp %p Status %08lX Info %08lX\n",
1802                       Irp,
1803                       ntStatus,
1804                       Irp->IoStatus.Information));
1805
1806         AFSCompleteRequest( Irp, ntStatus);
1807     }
1808
1809     return ntStatus;
1810 }
1811
1812 static
1813 NTSTATUS
1814 AFSCachedWrite( IN PDEVICE_OBJECT DeviceObject,
1815                 IN PIRP Irp,
1816                 IN LARGE_INTEGER StartingByte,
1817                 IN ULONG ByteCount,
1818                 IN BOOLEAN ForceFlush)
1819 {
1820     UNREFERENCED_PARAMETER(DeviceObject);
1821     PVOID              pSystemBuffer = NULL;
1822     NTSTATUS           ntStatus = STATUS_SUCCESS;
1823     IO_STATUS_BLOCK    iosbFlush;
1824     IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1825     PFILE_OBJECT       pFileObject = pIrpSp->FileObject;
1826     AFSFcb            *pFcb = (AFSFcb *)pFileObject->FsContext;
1827     BOOLEAN            bSynchronousFo = BooleanFlagOn( pFileObject->Flags, FO_SYNCHRONOUS_IO);
1828     ULONG              ulCurrentIO = 0, ulTotalLen = ByteCount;
1829     PMDL               pCurrentMdl = Irp->MdlAddress;
1830     LARGE_INTEGER      liCurrentOffset;
1831
1832     __Enter
1833     {
1834
1835         Irp->IoStatus.Information = 0;
1836
1837         if( BooleanFlagOn( pIrpSp->MinorFunction, IRP_MN_MDL))
1838         {
1839
1840             __try
1841             {
1842
1843                 CcPrepareMdlWrite( pFileObject,
1844                                    &StartingByte,
1845                                    ByteCount,
1846                                    &Irp->MdlAddress,
1847                                    &Irp->IoStatus);
1848
1849                 ntStatus = Irp->IoStatus.Status;
1850             }
1851             __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()))
1852             {
1853                 ntStatus = GetExceptionCode();
1854
1855                 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1856                               AFS_TRACE_LEVEL_ERROR,
1857                               "AFSCachedWrite (%p) Exception thrown while preparing mdl write Status %08lX\n",
1858                               Irp,
1859                               ntStatus));
1860             }
1861
1862             if( !NT_SUCCESS( ntStatus))
1863             {
1864
1865                 //
1866                 // Free up any potentially allocated mdl's
1867                 //
1868
1869                 CcMdlWriteComplete( pFileObject,
1870                                     &StartingByte,
1871                                     Irp->MdlAddress);
1872
1873                 Irp->MdlAddress = NULL;
1874
1875                 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1876                               AFS_TRACE_LEVEL_ERROR,
1877                               "AFSCachedWrite (%p) Failed to process MDL write Status %08lX\n",
1878                               Irp,
1879                               ntStatus));
1880             }
1881
1882             try_return( ntStatus);
1883         }
1884
1885         liCurrentOffset.QuadPart = StartingByte.QuadPart;
1886
1887         while( ulTotalLen > 0)
1888         {
1889
1890             ntStatus = STATUS_SUCCESS;
1891
1892             if( pCurrentMdl != NULL)
1893             {
1894
1895                 pSystemBuffer = MmGetSystemAddressForMdlSafe( pCurrentMdl,
1896                                                               NormalPagePriority);
1897
1898                 ulCurrentIO = MmGetMdlByteCount( pCurrentMdl);
1899
1900                 if( ulCurrentIO > ulTotalLen)
1901                 {
1902                     ulCurrentIO = ulTotalLen;
1903                 }
1904             }
1905             else
1906             {
1907
1908                 pSystemBuffer = AFSLockSystemBuffer( Irp,
1909                                                      ulTotalLen);
1910
1911                 ulCurrentIO = ulTotalLen;
1912             }
1913
1914             if( pSystemBuffer == NULL)
1915             {
1916
1917                 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1918                               AFS_TRACE_LEVEL_ERROR,
1919                               "AFSCachedWrite (%p) Failed to lock system buffer\n",
1920                               Irp));
1921
1922                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1923             }
1924
1925             __try
1926             {
1927
1928                 if( !CcCopyWrite( pFileObject,
1929                                   &liCurrentOffset,
1930                                   ulCurrentIO,
1931                                   TRUE,
1932                                   pSystemBuffer))
1933                 {
1934                     //
1935                     // Failed to process request.
1936                     //
1937
1938                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1939                                   AFS_TRACE_LEVEL_ERROR,
1940                                   "AFSCachedWrite (%p) Failed to issue CcCopyWrite %wZ @ %0I64X Status %08lX\n",
1941                                   Irp,
1942                                   &pFileObject->FileName,
1943                                   liCurrentOffset.QuadPart,
1944                                   Irp->IoStatus.Status));
1945
1946                     try_return( ntStatus = STATUS_UNSUCCESSFUL);
1947                 }
1948             }
1949             __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()))
1950             {
1951
1952                 ntStatus = GetExceptionCode();
1953
1954                 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1955                               AFS_TRACE_LEVEL_ERROR,
1956                               "AFSCachedWrite (%p) CcCopyWrite Threw exception %wZ @ %0I64X Status %08lX\n",
1957                               Irp,
1958                               &pFileObject->FileName,
1959                               liCurrentOffset.QuadPart,
1960                               ntStatus));
1961             }
1962
1963             if( !NT_SUCCESS( ntStatus))
1964             {
1965                 try_return( ntStatus);
1966             }
1967
1968             if( ForceFlush ||
1969                 BooleanFlagOn(pFileObject->Flags, (FO_NO_INTERMEDIATE_BUFFERING + FO_WRITE_THROUGH)))
1970             {
1971
1972                 __try
1973                 {
1974                     //
1975                     // We have detected a file we do a write through with.
1976                     //
1977
1978                     CcFlushCache(&pFcb->NPFcb->SectionObjectPointers,
1979                                   &liCurrentOffset,
1980                                   ulCurrentIO,
1981                                   &iosbFlush);
1982
1983                     if( !NT_SUCCESS( iosbFlush.Status))
1984                     {
1985
1986                         AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1987                                       AFS_TRACE_LEVEL_ERROR,
1988                                       "AFSCachedWrite (%p) CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
1989                                       Irp,
1990                                       &pFileObject->FileName,
1991                                       pFcb->ObjectInformation->FileId.Cell,
1992                                       pFcb->ObjectInformation->FileId.Volume,
1993                                       pFcb->ObjectInformation->FileId.Vnode,
1994                                       pFcb->ObjectInformation->FileId.Unique,
1995                                       iosbFlush.Status,
1996                                       iosbFlush.Information));
1997
1998                         try_return( ntStatus = iosbFlush.Status);
1999                     }
2000                 }
2001                 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()))
2002                 {
2003
2004                     ntStatus = GetExceptionCode();
2005
2006                     AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
2007                                   AFS_TRACE_LEVEL_ERROR,
2008                                   "AFSCachedWrite (%p) CcFlushCache Threw exception %wZ @ %0I64X Status %08lX\n",
2009                                   Irp,
2010                                   &pFileObject->FileName,
2011                                   liCurrentOffset.QuadPart,
2012                                   ntStatus));
2013
2014                     try_return( ntStatus);
2015                 }
2016             }
2017
2018             if( ulTotalLen <= ulCurrentIO)
2019             {
2020                 break;
2021             }
2022
2023             liCurrentOffset.QuadPart += ulCurrentIO;
2024
2025             ulTotalLen -= ulCurrentIO;
2026
2027             pCurrentMdl = pCurrentMdl->Next;
2028         }
2029
2030 try_exit:
2031
2032         if( NT_SUCCESS( ntStatus))
2033         {
2034
2035             Irp->IoStatus.Information = ByteCount;
2036
2037             if ( ForceFlush ||
2038                  BooleanFlagOn(pFileObject->Flags, (FO_NO_INTERMEDIATE_BUFFERING + FO_WRITE_THROUGH)))
2039             {
2040                 //
2041                 // Write through asked for... Set things so that we get
2042                 // flush when the worker thread next wakes up
2043                 //
2044                 pFcb->Specific.File.LastServerFlush.QuadPart = 0;
2045             }
2046         }
2047
2048         AFSCompleteRequest( Irp,
2049                             ntStatus);
2050     }
2051
2052     return ntStatus;
2053 }
2054
2055 //
2056 // Called with Fcb->NPFcb->SectionObjectResource and Fcb->NPFcb->Resource held
2057 //
2058
2059 static
2060 NTSTATUS
2061 AFSExtendingWrite( IN AFSFcb *Fcb,
2062                    IN PFILE_OBJECT FileObject,
2063                    IN LONGLONG NewLength)
2064 {
2065     LARGE_INTEGER liSaveFileSize = Fcb->Header.FileSize;
2066     LARGE_INTEGER liSaveAllocation = Fcb->Header.AllocationSize;
2067     NTSTATUS      ntStatus = STATUS_SUCCESS;
2068     AFSCcb       *pCcb = (AFSCcb *)FileObject->FsContext2;
2069
2070     if( NewLength > Fcb->Header.AllocationSize.QuadPart)
2071     {
2072
2073         Fcb->Header.AllocationSize.QuadPart = NewLength;
2074
2075         Fcb->ObjectInformation->AllocationSize = Fcb->Header.AllocationSize;
2076     }
2077
2078     if( NewLength > Fcb->Header.FileSize.QuadPart)
2079     {
2080
2081         Fcb->Header.FileSize.QuadPart = NewLength;
2082
2083         Fcb->ObjectInformation->EndOfFile = Fcb->Header.FileSize;
2084     }
2085
2086     //
2087     // Tell the server
2088     //
2089
2090     ntStatus = AFSUpdateFileInformation( &Fcb->ObjectInformation->ParentFileId,
2091                                          Fcb->ObjectInformation,
2092                                          &pCcb->AuthGroup);
2093
2094     if (NT_SUCCESS(ntStatus))
2095     {
2096
2097         KeQuerySystemTime( &Fcb->ObjectInformation->ChangeTime);
2098
2099         SetFlag( Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
2100
2101         //
2102         // If the file is currently cached, then let the MM know about the extension
2103         //
2104         // The CcSetFileSizes call should be made with only the PagingResource held
2105         // which we are currently not holding.
2106         //
2107
2108         if( CcIsFileCached( FileObject))
2109         {
2110             CcSetFileSizes( FileObject,
2111                             (PCC_FILE_SIZES)&Fcb->Header.AllocationSize);
2112         }
2113     }
2114     else
2115     {
2116         Fcb->Header.FileSize = liSaveFileSize;
2117         Fcb->Header.AllocationSize = liSaveAllocation;
2118     }
2119
2120     //
2121     // DownConvert file resource to shared
2122     //
2123     ExConvertExclusiveToSharedLite( &Fcb->NPFcb->Resource);
2124
2125     return ntStatus;
2126 }
2127
2128 NTSTATUS
2129 AFSShareWrite( IN PDEVICE_OBJECT DeviceObject,
2130                IN PIRP Irp)
2131 {
2132
2133     UNREFERENCED_PARAMETER(DeviceObject);
2134     NTSTATUS ntStatus = STATUS_SUCCESS;
2135     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2136     AFSFcb *pFcb = NULL;
2137     AFSCcb *pCcb = NULL;
2138     AFSPipeIORequestCB *pIoRequest = NULL;
2139     void *pBuffer = NULL;
2140     AFSPipeIOResultCB stIoResult;
2141     ULONG ulBytesReturned = 0;
2142
2143     __Enter
2144     {
2145
2146         pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
2147
2148         pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
2149
2150         AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
2151                       AFS_TRACE_LEVEL_VERBOSE,
2152                       "AFSShareWrite On pipe %wZ Length %08lX\n",
2153                       &pCcb->DirectoryCB->NameInformation.FileName,
2154                       pIrpSp->Parameters.Write.Length));
2155
2156         if( pIrpSp->Parameters.Write.Length == 0)
2157         {
2158
2159             //
2160             // Nothing to do in this case
2161             //
2162
2163             try_return( ntStatus);
2164         }
2165
2166         //
2167         // Retrieve the buffer for the read request
2168         //
2169
2170         pBuffer = AFSLockSystemBuffer( Irp,
2171                                        pIrpSp->Parameters.Write.Length);
2172
2173         if( pBuffer == NULL)
2174         {
2175
2176             AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
2177                           AFS_TRACE_LEVEL_ERROR,
2178                           "AFSShareWrite Failed to map buffer on pipe %wZ\n",
2179                           &pCcb->DirectoryCB->NameInformation.FileName));
2180
2181             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2182         }
2183
2184         AFSAcquireShared( &pFcb->NPFcb->Resource,
2185                           TRUE);
2186
2187         pIoRequest = (AFSPipeIORequestCB *)AFSExAllocatePoolWithTag( PagedPool,
2188                                                                      sizeof( AFSPipeIORequestCB) +
2189                                                                                 pIrpSp->Parameters.Write.Length,
2190                                                                      AFS_GENERIC_MEMORY_14_TAG);
2191
2192         if( pIoRequest == NULL)
2193         {
2194
2195             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2196         }
2197
2198         RtlZeroMemory( pIoRequest,
2199                        sizeof( AFSPipeIORequestCB) + pIrpSp->Parameters.Write.Length);
2200
2201         pIoRequest->RequestId = pCcb->RequestID;
2202
2203         pIoRequest->RootId = pFcb->ObjectInformation->VolumeCB->ObjectInformation.FileId;
2204
2205         pIoRequest->BufferLength = pIrpSp->Parameters.Write.Length;
2206
2207         RtlCopyMemory( (void *)((char *)pIoRequest + sizeof( AFSPipeIORequestCB)),
2208                        pBuffer,
2209                        pIrpSp->Parameters.Write.Length);
2210
2211         stIoResult.BytesProcessed = 0;
2212
2213         ulBytesReturned = sizeof( AFSPipeIOResultCB);
2214
2215         //
2216         // Issue the open request to the service
2217         //
2218
2219         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_WRITE,
2220                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
2221                                       &pCcb->AuthGroup,
2222                                       &pCcb->DirectoryCB->NameInformation.FileName,
2223                                       NULL,
2224                                       NULL,
2225                                       0,
2226                                       pIoRequest,
2227                                       sizeof( AFSPipeIORequestCB) +
2228                                                 pIrpSp->Parameters.Write.Length,
2229                                       &stIoResult,
2230                                       &ulBytesReturned);
2231
2232         if( !NT_SUCCESS( ntStatus))
2233         {
2234
2235             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2236                           AFS_TRACE_LEVEL_ERROR,
2237                           "AFSShareWrite (%p) Failed service write Status %08lX\n",
2238                           Irp,
2239                           ntStatus));
2240
2241             try_return( ntStatus);
2242         }
2243
2244         AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
2245                       AFS_TRACE_LEVEL_VERBOSE,
2246                       "AFSShareWrite Completed on pipe %wZ Length read %08lX\n",
2247                       &pCcb->DirectoryCB->NameInformation.FileName,
2248                       stIoResult.BytesProcessed));
2249
2250         Irp->IoStatus.Information = stIoResult.BytesProcessed;
2251
2252 try_exit:
2253
2254         if( pFcb != NULL)
2255         {
2256
2257             AFSReleaseResource( &pFcb->NPFcb->Resource);
2258         }
2259
2260         if( pIoRequest != NULL)
2261         {
2262
2263             AFSExFreePoolWithTag( pIoRequest, AFS_GENERIC_MEMORY_14_TAG);
2264         }
2265     }
2266
2267     return ntStatus;
2268 }