Windows: AFSCommonWrite STATUS_PENDING is Success
[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( EXCEPTION_EXECUTE_HANDLER)
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              ntStatus != STATUS_PENDING)
757         {
758             if ( !bPagingIo)
759             {
760
761                 if( bSynchronousFo)
762                 {
763
764                     pFileObject->CurrentByteOffset.QuadPart = liStartingByte.QuadPart + ulByteCount;
765                 }
766
767                 //
768                 // If this extended the VDL, then update it accordingly.
769                 // Increasing the VDL does not require a call to CcSetFileSizes.
770                 //
771
772                 if( liStartingByte.QuadPart + ulByteCount > pFcb->Header.ValidDataLength.QuadPart)
773                 {
774
775                     pFcb->Header.ValidDataLength.QuadPart = liStartingByte.QuadPart + ulByteCount;
776                 }
777
778                 if( !BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME))
779                 {
780
781                     SetFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_WRITE_TIME);
782
783                     KeQuerySystemTime( &pFcb->ObjectInformation->LastWriteTime);
784                 }
785             }
786         }
787
788         if ( ntStatus != STATUS_PENDING &&
789              !bPagingIo && bNonCachedIo && CcIsFileCached( pFileObject) &&
790              pNPFcb->SectionObjectPointers.DataSectionObject != NULL &&
791              bReleaseSectionObject)
792         {
793             //
794             // Regardless of whether or not the a non-paging non-cached write
795             // succeeds or fails, if the file is cached the contents of the
796             // cache are no longer up to date.  A CcPurgeCacheSection must be
797             // performed to force subsequent cached reads to obtain the data
798             // from the service.
799             //
800             // The Fcb Resource is dropped in order to permit filters that perform
801             // an open via a worker thread in response to a purge to do so without
802             // deadlocking.  The SectionObjectResource is held across the purge to
803             // prevent racing with other cache operations.
804             //
805
806             if( bReleaseMain)
807             {
808
809                 AFSReleaseResource( &pNPFcb->Resource);
810
811                 bReleaseMain = FALSE;
812             }
813
814             __try
815             {
816
817                 if ( !CcPurgeCacheSection( &pNPFcb->SectionObjectPointers,
818                                            &liStartingByte,
819                                            ulByteCount,
820                                            FALSE))
821                 {
822
823                     AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
824                                   AFS_TRACE_LEVEL_WARNING,
825                                   "AFSCommonWrite CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
826                                   pFcb->ObjectInformation->FileId.Cell,
827                                   pFcb->ObjectInformation->FileId.Volume,
828                                   pFcb->ObjectInformation->FileId.Vnode,
829                                   pFcb->ObjectInformation->FileId.Unique));
830
831                     SetFlag( pFcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
832                 }
833             }
834             __except( EXCEPTION_EXECUTE_HANDLER)
835             {
836
837                 DWORD ntStatus2 = GetExceptionCode();
838
839                 AFSDbgTrace(( 0,
840                               0,
841                               "EXCEPTION - AFSCommonWrite CcPurgeCacheSection failed FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
842                               pFcb->ObjectInformation->FileId.Cell,
843                               pFcb->ObjectInformation->FileId.Volume,
844                               pFcb->ObjectInformation->FileId.Vnode,
845                               pFcb->ObjectInformation->FileId.Unique,
846                               ntStatus2));
847
848                 SetFlag( pFcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
849             }
850         }
851
852         ObDereferenceObject(pFileObject);
853
854         if( bReleaseSectionObject)
855         {
856
857             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
858                           AFS_TRACE_LEVEL_VERBOSE,
859                           "AFSCommonWrite Releasing Fcb SectionObject lock %p EXCL/SHARED %08lX\n",
860                           &pNPFcb->SectionObjectResource,
861                           PsGetCurrentThread()));
862
863             AFSReleaseResource( &pNPFcb->SectionObjectResource);
864         }
865
866         if( bReleasePaging)
867         {
868
869             AFSReleaseResource( &pNPFcb->PagingResource);
870         }
871
872         if( bReleaseMain)
873         {
874
875             AFSReleaseResource( &pNPFcb->Resource);
876         }
877
878         if( bCompleteIrp)
879         {
880
881             AFSCompleteRequest( Irp,
882                                 ntStatus);
883         }
884     }
885
886     return ntStatus;
887 }
888
889 NTSTATUS
890 AFSIOCtlWrite( IN PDEVICE_OBJECT DeviceObject,
891                IN PIRP Irp)
892 {
893
894     UNREFERENCED_PARAMETER(DeviceObject);
895     NTSTATUS ntStatus = STATUS_SUCCESS;
896     AFSPIOCtlIORequestCB stIORequestCB;
897     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
898     AFSFcb *pFcb = NULL;
899     AFSCcb *pCcb = NULL;
900     AFSPIOCtlIOResultCB stIOResultCB;
901     ULONG ulBytesReturned = 0;
902     AFSFileID stParentFID;
903
904     __Enter
905     {
906
907         Irp->IoStatus.Information = 0;
908
909         RtlZeroMemory( &stIORequestCB,
910                        sizeof( AFSPIOCtlIORequestCB));
911
912         if( pIrpSp->Parameters.Write.Length == 0)
913         {
914
915             //
916             // Nothing to do in this case
917             //
918
919             try_return( ntStatus);
920         }
921
922         pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
923
924         pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
925
926         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
927                       AFS_TRACE_LEVEL_VERBOSE,
928                       "AFSIOCtlWrite Acquiring Fcb lock %p SHARED %08lX\n",
929                       &pFcb->NPFcb->Resource,
930                       PsGetCurrentThread()));
931
932         AFSAcquireShared( &pFcb->NPFcb->Resource,
933                           TRUE);
934
935         //
936         // Get the parent fid to pass to the cm
937         //
938
939         RtlZeroMemory( &stParentFID,
940                        sizeof( AFSFileID));
941
942         if( BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
943         {
944
945             //
946             // The parent directory FID of the node
947             //
948
949             stParentFID = pFcb->ObjectInformation->ParentFileId;
950         }
951
952         //
953         // Set the control block up
954         //
955
956         stIORequestCB.RequestId = pCcb->RequestID;
957
958         if( pFcb->ObjectInformation->VolumeCB != NULL)
959         {
960             stIORequestCB.RootId = pFcb->ObjectInformation->VolumeCB->ObjectInformation.FileId;
961         }
962
963         //
964         // Lock down the buffer
965         //
966
967         stIORequestCB.MappedBuffer = AFSMapToService( Irp,
968                                                       pIrpSp->Parameters.Write.Length);
969
970         if( stIORequestCB.MappedBuffer == NULL)
971         {
972
973             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
974         }
975
976         stIORequestCB.BufferLength = pIrpSp->Parameters.Write.Length;
977
978         stIOResultCB.BytesProcessed = 0;
979
980         ulBytesReturned = sizeof( AFSPIOCtlIOResultCB);
981
982         //
983         // Issue the request to the service
984         //
985
986         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIOCTL_WRITE,
987                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
988                                       &pCcb->AuthGroup,
989                                       NULL,
990                                       &stParentFID,
991                                       NULL,
992                                       0,
993                                       (void *)&stIORequestCB,
994                                       sizeof( AFSPIOCtlIORequestCB),
995                                       &stIOResultCB,
996                                       &ulBytesReturned);
997
998         if( !NT_SUCCESS( ntStatus))
999         {
1000
1001             try_return( ntStatus);
1002         }
1003
1004         //
1005         // Update the length written
1006         //
1007
1008         Irp->IoStatus.Information = stIOResultCB.BytesProcessed;
1009
1010 try_exit:
1011
1012         if( stIORequestCB.MappedBuffer != NULL)
1013         {
1014
1015             AFSUnmapServiceMappedBuffer( stIORequestCB.MappedBuffer,
1016                                          Irp->MdlAddress);
1017         }
1018
1019         if( pFcb != NULL)
1020         {
1021
1022             AFSReleaseResource( &pFcb->NPFcb->Resource);
1023         }
1024     }
1025
1026     return ntStatus;
1027 }
1028
1029 //
1030 // This function is called when we know we have to read from the AFS Cache.
1031 //
1032 // It ensures that we have exents for the entirety of the write and
1033 // then pins the extents into memory (meaning that although we may
1034 // add we will not remove).  Then it creates a scatter gather write
1035 // and fires off the IRPs
1036 //
1037 static
1038 NTSTATUS
1039 AFSNonCachedWrite( IN PDEVICE_OBJECT DeviceObject,
1040                    IN PIRP Irp,
1041                    IN LARGE_INTEGER StartingByte,
1042                    IN ULONG ByteCount)
1043 {
1044     NTSTATUS           ntStatus = STATUS_UNSUCCESSFUL;
1045     VOID              *pSystemBuffer = NULL;
1046     BOOLEAN            bPagingIo = BooleanFlagOn( Irp->Flags, IRP_PAGING_IO);
1047     BOOLEAN            bLocked = FALSE;
1048     BOOLEAN            bCompleteIrp = TRUE;
1049     AFSGatherIo       *pGatherIo = NULL;
1050     AFSIoRun          *pIoRuns = NULL;
1051     AFSIoRun           stIoRuns[AFS_MAX_STACK_IO_RUNS];
1052     ULONG              extentsCount = 0, runCount = 0;
1053     AFSExtent         *pStartExtent = NULL;
1054     AFSExtent         *pIgnoreExtent = NULL;
1055     IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1056     PFILE_OBJECT       pFileObject = pIrpSp->FileObject;
1057     AFSFcb            *pFcb = (AFSFcb *)pFileObject->FsContext;
1058     AFSCcb            *pCcb = (AFSCcb *)pFileObject->FsContext2;
1059     BOOLEAN            bSynchronousFo = BooleanFlagOn( pFileObject->Flags, FO_SYNCHRONOUS_IO);
1060     AFSDeviceExt      *pDevExt = (AFSDeviceExt *)DeviceObject->DeviceExtension;
1061     LARGE_INTEGER      liCurrentTime, liLastRequestTime;
1062     AFSDeviceExt      *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1063     PFILE_OBJECT       pCacheFileObject = NULL;
1064     BOOLEAN            bDerefExtents = FALSE;
1065
1066     __Enter
1067     {
1068
1069         AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1070                       AFS_TRACE_LEVEL_VERBOSE,
1071                       "AFSNonCachedWrite (FO: %p) StartingByte %08lX:%08lX Length %08lX\n",
1072                       pFileObject,
1073                       StartingByte.HighPart,
1074                       StartingByte.LowPart,
1075                       ByteCount));
1076
1077         if (ByteCount > pDevExt->Specific.RDR.MaxIo.QuadPart)
1078         {
1079
1080             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1081                           AFS_TRACE_LEVEL_ERROR,
1082                           "AFSNonCachedWrite (%p) Request %08lX Actual %08lX larger than MaxIO %I64X\n",
1083                           Irp,
1084                           ByteCount,
1085                           pIrpSp->Parameters.Write.Length,
1086                           pDevExt->Specific.RDR.MaxIo.QuadPart));
1087
1088             try_return( ntStatus = STATUS_UNSUCCESSFUL);
1089         }
1090
1091         //
1092         // Get the mapping for the buffer
1093         //
1094         pSystemBuffer = AFSLockSystemBuffer( Irp,
1095                                              ByteCount);
1096
1097         if( pSystemBuffer == NULL)
1098         {
1099
1100             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1101                           AFS_TRACE_LEVEL_ERROR,
1102                           "AFSNonCachedWrite (%p) Failed to map system buffer\n",
1103                           Irp));
1104
1105             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1106         }
1107
1108
1109         //
1110         // Provoke a get of the extents - if we need to.
1111         //
1112
1113         AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1114                       AFS_TRACE_LEVEL_VERBOSE,
1115                       "AFSNonCachedWrite Requesting extents for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX\n",
1116                       pFcb->ObjectInformation->FileId.Cell,
1117                       pFcb->ObjectInformation->FileId.Volume,
1118                       pFcb->ObjectInformation->FileId.Vnode,
1119                       pFcb->ObjectInformation->FileId.Unique,
1120                       StartingByte.QuadPart,
1121                       ByteCount));
1122
1123         ntStatus = AFSRequestExtentsAsync( pFcb,
1124                                            pCcb,
1125                                            &StartingByte,
1126                                            ByteCount);
1127
1128         if (!NT_SUCCESS(ntStatus))
1129         {
1130
1131             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1132                           AFS_TRACE_LEVEL_ERROR,
1133                           "AFSNonCachedWrite (%p) Failed to request extents Status %08lX\n",
1134                           Irp,
1135                           ntStatus));
1136
1137             try_return( ntStatus);
1138         }
1139
1140         KeQueryTickCount( &liLastRequestTime);
1141
1142         while (TRUE)
1143         {
1144
1145             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1146                           AFS_TRACE_LEVEL_VERBOSE,
1147                           "AFSNonCachedWrite Acquiring Fcb extents lock %p SHARED %08lX\n",
1148                           &pFcb->NPFcb->Specific.File.ExtentsResource,
1149                           PsGetCurrentThread()));
1150
1151             ASSERT( !ExIsResourceAcquiredLite( &pFcb->NPFcb->Specific.File.ExtentsResource ));
1152
1153             AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource, TRUE );
1154             bLocked = TRUE;
1155
1156             pStartExtent = NULL;
1157             pIgnoreExtent = NULL;
1158
1159             if ( AFSDoExtentsMapRegion( pFcb, &StartingByte, ByteCount, &pStartExtent, &pIgnoreExtent ))
1160             {
1161                 break;
1162             }
1163
1164             KeClearEvent( &pFcb->NPFcb->Specific.File.ExtentsRequestComplete );
1165
1166             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1167                           AFS_TRACE_LEVEL_VERBOSE,
1168                           "AFSNonCachedWrite Releasing(1) Fcb extents lock %p SHARED %08lX\n",
1169                           &pFcb->NPFcb->Specific.File.ExtentsResource,
1170                           PsGetCurrentThread()));
1171
1172             AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
1173             bLocked= FALSE;
1174
1175             //
1176             // We will re-request the extents after waiting for them
1177             //
1178
1179             KeQueryTickCount( &liCurrentTime);
1180
1181             if( liCurrentTime.QuadPart - liLastRequestTime.QuadPart >= pControlDevExt->Specific.Control.ExtentRequestTimeCount.QuadPart)
1182             {
1183
1184                 AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1185                               AFS_TRACE_LEVEL_VERBOSE,
1186                               "AFSNonCachedWrite Requesting extents, again, for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX\n",
1187                               pFcb->ObjectInformation->FileId.Cell,
1188                               pFcb->ObjectInformation->FileId.Volume,
1189                               pFcb->ObjectInformation->FileId.Vnode,
1190                               pFcb->ObjectInformation->FileId.Unique,
1191                               StartingByte.QuadPart,
1192                               ByteCount));
1193
1194                 ntStatus = AFSRequestExtentsAsync( pFcb,
1195                                                    pCcb,
1196                                                    &StartingByte,
1197                                                    ByteCount);
1198
1199                 if (!NT_SUCCESS(ntStatus))
1200                 {
1201
1202                     AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1203                                   AFS_TRACE_LEVEL_ERROR,
1204                                   "AFSNonCachedWrite (%p) Failed to request extents Status %08lX\n",
1205                                   Irp,
1206                                   ntStatus));
1207
1208                     try_return( ntStatus);
1209                 }
1210
1211                 KeQueryTickCount( &liLastRequestTime);
1212             }
1213
1214
1215             AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1216                           AFS_TRACE_LEVEL_VERBOSE,
1217                           "AFSNonCachedWrite Waiting for extents for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX\n",
1218                           pFcb->ObjectInformation->FileId.Cell,
1219                           pFcb->ObjectInformation->FileId.Volume,
1220                           pFcb->ObjectInformation->FileId.Vnode,
1221                           pFcb->ObjectInformation->FileId.Unique,
1222                           StartingByte.QuadPart,
1223                           ByteCount));
1224
1225             //
1226             // Wait for it
1227             //
1228
1229             ntStatus =  AFSWaitForExtentMapping ( pFcb, pCcb);
1230
1231             if (!NT_SUCCESS(ntStatus))
1232             {
1233
1234                 AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1235                               AFS_TRACE_LEVEL_ERROR,
1236                               "AFSNonCachedWrite Failed wait for extents for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX Status %08lX\n",
1237                               pFcb->ObjectInformation->FileId.Cell,
1238                               pFcb->ObjectInformation->FileId.Volume,
1239                               pFcb->ObjectInformation->FileId.Vnode,
1240                               pFcb->ObjectInformation->FileId.Unique,
1241                               StartingByte.QuadPart,
1242                               ByteCount,
1243                               ntStatus));
1244
1245                 try_return( ntStatus);
1246             }
1247         }
1248
1249         //
1250         // As per the read path -
1251         //
1252
1253         AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1254                       AFS_TRACE_LEVEL_VERBOSE,
1255                       "AFSNonCachedWrite Extents located for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX\n",
1256                       pFcb->ObjectInformation->FileId.Cell,
1257                       pFcb->ObjectInformation->FileId.Volume,
1258                       pFcb->ObjectInformation->FileId.Vnode,
1259                       pFcb->ObjectInformation->FileId.Unique,
1260                       StartingByte.QuadPart,
1261                       ByteCount));
1262
1263         ntStatus = AFSGetExtents( pFcb,
1264                                   &StartingByte,
1265                                   ByteCount,
1266                                   pStartExtent,
1267                                   &extentsCount,
1268                                   &runCount);
1269
1270         if (!NT_SUCCESS(ntStatus))
1271         {
1272
1273             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1274                           AFS_TRACE_LEVEL_ERROR,
1275                           "AFSNonCachedWrite (%p) Failed to retrieve mapped extents Status %08lX\n",
1276                           Irp,
1277                           ntStatus));
1278
1279             try_return( ntStatus );
1280         }
1281
1282         AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1283                       AFS_TRACE_LEVEL_VERBOSE,
1284                       "AFSNonCachedWrite (%p) Successfully retrieved map extents count %d run count %d\n",
1285                       Irp,
1286                       extentsCount,
1287                       runCount));
1288
1289         if( BooleanFlagOn( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE))
1290         {
1291
1292             Irp->IoStatus.Information = ByteCount;
1293
1294 #if GEN_MD5
1295             //
1296             // Setup the MD5 for each extent
1297             //
1298
1299             AFSSetupMD5Hash( pFcb,
1300                              pStartExtent,
1301                              extentsCount,
1302                              pSystemBuffer,
1303                              &StartingByte,
1304                              ByteCount);
1305 #endif
1306
1307             ntStatus = AFSProcessExtentRun( pSystemBuffer,
1308                                             &StartingByte,
1309                                             ByteCount,
1310                                             pStartExtent,
1311                                             TRUE);
1312
1313             if (!NT_SUCCESS(ntStatus))
1314             {
1315
1316                 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1317                               AFS_TRACE_LEVEL_ERROR,
1318                               "AFSNonCachedWrite (%p) Failed to process extent run for non-persistent cache Status %08lX\n",
1319                               Irp,
1320                               ntStatus));
1321             }
1322
1323             try_return( ntStatus);
1324         }
1325
1326         //
1327         // Retrieve the cache file object
1328         //
1329
1330         pCacheFileObject = AFSReferenceCacheFileObject();
1331
1332         if( pCacheFileObject == NULL)
1333         {
1334
1335             ntStatus = STATUS_DEVICE_NOT_READY;
1336
1337             AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1338                           AFS_TRACE_LEVEL_ERROR,
1339                           "AFSNonCachedWrite Failed to retrieve cache fileobject for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX Status %08lX\n",
1340                           pFcb->ObjectInformation->FileId.Cell,
1341                           pFcb->ObjectInformation->FileId.Volume,
1342                           pFcb->ObjectInformation->FileId.Vnode,
1343                           pFcb->ObjectInformation->FileId.Unique,
1344                           StartingByte.QuadPart,
1345                           ByteCount,
1346                           ntStatus));
1347
1348             try_return( ntStatus);
1349         }
1350
1351         if (runCount > AFS_MAX_STACK_IO_RUNS)
1352         {
1353
1354             pIoRuns = (AFSIoRun*) AFSExAllocatePoolWithTag( PagedPool,
1355                                                             runCount * sizeof( AFSIoRun ),
1356                                                             AFS_IO_RUN_TAG );
1357             if (NULL == pIoRuns)
1358             {
1359
1360                 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1361                               AFS_TRACE_LEVEL_ERROR,
1362                               "AFSNonCachedWrite (%p) Failed to allocate IO run block\n",
1363                               Irp));
1364
1365                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
1366             }
1367         }
1368         else
1369         {
1370
1371             pIoRuns = stIoRuns;
1372         }
1373
1374         RtlZeroMemory( pIoRuns, runCount * sizeof( AFSIoRun ));
1375
1376         ntStatus = AFSSetupIoRun( IoGetRelatedDeviceObject( pCacheFileObject),
1377                                   Irp,
1378                                   pSystemBuffer,
1379                                   pIoRuns,
1380                                   &StartingByte,
1381                                   ByteCount,
1382                                   pStartExtent,
1383                                   &runCount );
1384
1385         if (!NT_SUCCESS(ntStatus))
1386         {
1387
1388             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1389                           AFS_TRACE_LEVEL_ERROR,
1390                           "AFSNonCachedWrite (%p) Failed to initialize IO run block Status %08lX\n",
1391                           Irp,
1392                           ntStatus));
1393
1394             try_return( ntStatus );
1395         }
1396
1397         AFSReferenceActiveExtents( pStartExtent,
1398                                    extentsCount);
1399
1400         bDerefExtents = TRUE;
1401
1402         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1403                       AFS_TRACE_LEVEL_VERBOSE,
1404                       "AFSNonCachedWrite Releasing(2) Fcb extents lock %p SHARED %08lX\n",
1405                       &pFcb->NPFcb->Specific.File.ExtentsResource,
1406                       PsGetCurrentThread()));
1407
1408         AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
1409         bLocked = FALSE;
1410
1411         pGatherIo = (AFSGatherIo*) AFSExAllocatePoolWithTag( NonPagedPool,
1412                                                              sizeof( AFSGatherIo),
1413                                                              AFS_GATHER_TAG);
1414
1415         if (NULL == pGatherIo)
1416         {
1417
1418             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1419                           AFS_TRACE_LEVEL_ERROR,
1420                           "AFSNonCachedWrite (%p) Failed to allocate IO gather block\n",
1421                           Irp));
1422
1423             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1424                           AFS_TRACE_LEVEL_VERBOSE,
1425                           "AFSNonCachedWrite Acquiring(1) Fcb extents lock %p SHARED %08lX\n",
1426                           &pFcb->NPFcb->Specific.File.ExtentsResource,
1427                           PsGetCurrentThread()));
1428
1429             AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
1430                               TRUE);
1431             bLocked = TRUE;
1432
1433             AFSDereferenceActiveExtents( pStartExtent,
1434                                          extentsCount);
1435
1436             try_return (ntStatus = STATUS_INSUFFICIENT_RESOURCES );
1437         }
1438
1439         RtlZeroMemory( pGatherIo, sizeof( AFSGatherIo ));
1440
1441         //
1442         // Initialize count to 1, that was we won't get an early
1443         // completion if the first irp completes before the second is
1444         // queued.
1445         //
1446         pGatherIo->Count = 1;
1447         pGatherIo->Status = STATUS_SUCCESS;
1448         pGatherIo->MasterIrp = Irp;
1449         pGatherIo->Synchronous = TRUE;
1450         pGatherIo->CompleteMasterIrp = FALSE;
1451
1452         bCompleteIrp = TRUE;
1453
1454         if( pGatherIo->Synchronous)
1455         {
1456             KeInitializeEvent( &pGatherIo->Event, NotificationEvent, FALSE );
1457         }
1458
1459 #if GEN_MD5
1460         //
1461         // Setup the MD5 for each extent
1462         //
1463
1464         AFSSetupMD5Hash( pFcb,
1465                          pStartExtent,
1466                          extentsCount,
1467                          pSystemBuffer,
1468                          &StartingByte,
1469                          ByteCount);
1470 #endif
1471
1472         //
1473         // Pre-emptively set up the count
1474         //
1475
1476         Irp->IoStatus.Information = ByteCount;
1477
1478         ntStatus = AFSQueueStartIos( pCacheFileObject,
1479                                      IRP_MJ_WRITE,
1480                                      IRP_WRITE_OPERATION | IRP_SYNCHRONOUS_API,
1481                                      pIoRuns,
1482                                      runCount,
1483                                      pGatherIo);
1484
1485         AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1486                       AFS_TRACE_LEVEL_VERBOSE,
1487                       "AFSNonCachedWrite (%p) AFSStartIos completed Status %08lX\n",
1488                       Irp,
1489                       ntStatus));
1490
1491         if( !NT_SUCCESS( ntStatus))
1492         {
1493
1494             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1495                           AFS_TRACE_LEVEL_VERBOSE,
1496                           "AFSNonCachedWrite Acquiring(2) Fcb extents lock %p SHARED %08lX\n",
1497                           &pFcb->NPFcb->Specific.File.ExtentsResource,
1498                           PsGetCurrentThread()));
1499
1500             AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
1501                               TRUE);
1502             bLocked = TRUE;
1503
1504             AFSDereferenceActiveExtents( pStartExtent,
1505                                          extentsCount);
1506
1507             try_return( ntStatus);
1508         }
1509
1510         //
1511         // Wait for completion of All IOs we started.
1512         //
1513
1514         ntStatus = KeWaitForSingleObject( &pGatherIo->Event,
1515                                           Executive,
1516                                           KernelMode,
1517                                           FALSE,
1518                                           NULL);
1519
1520         if( NT_SUCCESS( ntStatus))
1521         {
1522
1523             ntStatus = pGatherIo->Status;
1524         }
1525
1526         if( !NT_SUCCESS( ntStatus))
1527         {
1528
1529             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1530                           AFS_TRACE_LEVEL_VERBOSE,
1531                           "AFSNonCachedWrite Acquiring(3) Fcb extents lock %p SHARED %08lX\n",
1532                           &pFcb->NPFcb->Specific.File.ExtentsResource,
1533                           PsGetCurrentThread()));
1534
1535             AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
1536                               TRUE);
1537             bLocked = TRUE;
1538
1539             AFSDereferenceActiveExtents( pStartExtent,
1540                                          extentsCount);
1541
1542             try_return( ntStatus);
1543         }
1544
1545 try_exit:
1546
1547         if( NT_SUCCESS( ntStatus) &&
1548             pStartExtent != NULL &&
1549             Irp->IoStatus.Information > 0)
1550         {
1551
1552             if ( !bLocked)
1553             {
1554
1555                 AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
1556                                   TRUE);
1557                 bLocked = TRUE;
1558             }
1559
1560             //
1561             // Since this is dirty we can mark the extents dirty now.
1562             // AFSMarkDirty will dereference the extents.  Do not call
1563             // AFSDereferenceActiveExtents() in this code path.
1564             //
1565
1566             AFSMarkDirty( pFcb,
1567                           pStartExtent,
1568                           extentsCount,
1569                           &StartingByte,
1570                           bDerefExtents);
1571
1572             if (!bPagingIo)
1573             {
1574                 //
1575                 // This was an uncached user write - tell the server to do
1576                 // the flush when the worker thread next wakes up
1577                 //
1578                 pFcb->Specific.File.LastServerFlush.QuadPart = 0;
1579             }
1580         }
1581
1582         if( pCacheFileObject != NULL)
1583         {
1584             AFSReleaseCacheFileObject( pCacheFileObject);
1585         }
1586
1587         AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1588                       AFS_TRACE_LEVEL_VERBOSE,
1589                       "AFSNonCachedWrite (FO: %p) StartingByte %08lX:%08lX Length %08lX Status %08lX\n",
1590                       pFileObject,
1591                       StartingByte.HighPart,
1592                       StartingByte.LowPart,
1593                       ByteCount,
1594                       ntStatus));
1595
1596         if (NT_SUCCESS(ntStatus) &&
1597             !bPagingIo &&
1598             bSynchronousFo)
1599         {
1600
1601             pFileObject->CurrentByteOffset.QuadPart = StartingByte.QuadPart + ByteCount;
1602         }
1603
1604         if( bLocked)
1605         {
1606
1607             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1608                           AFS_TRACE_LEVEL_VERBOSE,
1609                           "AFSNonCachedWrite Releasing Fcb extents lock %p SHARED %08lX\n",
1610                           &pFcb->NPFcb->Specific.File.ExtentsResource,
1611                           PsGetCurrentThread()));
1612
1613             AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
1614         }
1615
1616         if( pGatherIo)
1617         {
1618             AFSExFreePoolWithTag(pGatherIo, AFS_GATHER_TAG);
1619         }
1620
1621         if( NULL != pIoRuns &&
1622             stIoRuns != pIoRuns)
1623         {
1624             AFSExFreePoolWithTag(pIoRuns, AFS_IO_RUN_TAG);
1625         }
1626
1627         if( bCompleteIrp)
1628         {
1629
1630             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1631                           AFS_TRACE_LEVEL_VERBOSE,
1632                           "AFSNonCachedWrite Completing Irp %p Status %08lX Info %08lX\n",
1633                           Irp,
1634                           ntStatus,
1635                           Irp->IoStatus.Information));
1636
1637             AFSCompleteRequest( Irp, ntStatus);
1638         }
1639     }
1640
1641     return ntStatus;
1642 }
1643
1644 static
1645 NTSTATUS
1646 AFSNonCachedWriteDirect( IN PDEVICE_OBJECT DeviceObject,
1647                          IN PIRP Irp,
1648                          IN LARGE_INTEGER StartingByte,
1649                          IN ULONG ByteCount)
1650 {
1651     NTSTATUS           ntStatus = STATUS_UNSUCCESSFUL;
1652     VOID              *pSystemBuffer = NULL;
1653     BOOLEAN            bPagingIo = BooleanFlagOn( Irp->Flags, IRP_PAGING_IO);
1654     IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1655     PFILE_OBJECT       pFileObject = pIrpSp->FileObject;
1656     AFSFcb            *pFcb = (AFSFcb *)pFileObject->FsContext;
1657     AFSCcb            *pCcb = (AFSCcb *)pFileObject->FsContext2;
1658     BOOLEAN            bSynchronousFo = BooleanFlagOn( pFileObject->Flags, FO_SYNCHRONOUS_IO);
1659     BOOLEAN            bNoIntermediateBuffering = BooleanFlagOn( pFileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING);
1660     AFSDeviceExt      *pDevExt = (AFSDeviceExt *)DeviceObject->DeviceExtension;
1661     AFSFileIOCB        stFileIORequest;
1662     AFSFileIOResultCB  stFileIOResult;
1663     ULONG              ulResultLen = 0;
1664     ULONG              ulFlags;
1665
1666     __Enter
1667     {
1668         Irp->IoStatus.Information = 0;
1669
1670         AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1671                       AFS_TRACE_LEVEL_VERBOSE,
1672                       "AFSNonCachedWriteDirect (FO: %p) StartingByte %08lX:%08lX Length %08lX\n",
1673                       pFileObject,
1674                       StartingByte.HighPart,
1675                       StartingByte.LowPart,
1676                       ByteCount));
1677
1678         if (ByteCount > pDevExt->Specific.RDR.MaxIo.QuadPart)
1679         {
1680
1681             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1682                           AFS_TRACE_LEVEL_ERROR,
1683                           "AFSNonCachedWriteDirect (%p) Request %08lX Actual %08lX larger than MaxIO %I64X\n",
1684                           Irp,
1685                           ByteCount,
1686                           pIrpSp->Parameters.Write.Length,
1687                           pDevExt->Specific.RDR.MaxIo.QuadPart));
1688
1689             try_return( ntStatus = STATUS_UNSUCCESSFUL);
1690         }
1691
1692         //
1693         // Get the mapping for the buffer
1694         //
1695         pSystemBuffer = AFSLockSystemBuffer( Irp,
1696                                              ByteCount);
1697
1698         if( pSystemBuffer == NULL)
1699         {
1700
1701             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1702                           AFS_TRACE_LEVEL_ERROR,
1703                           "AFSNonCachedWriteDirect (%p) Failed to map system buffer\n",
1704                           Irp));
1705
1706             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1707         }
1708
1709         //
1710         // Issue the request at the service for processing
1711         //
1712
1713         ulResultLen = sizeof( AFSFileIOResultCB);
1714
1715         RtlZeroMemory( &stFileIORequest,
1716                        sizeof( AFSFileIOCB));
1717
1718         RtlZeroMemory( &stFileIOResult,
1719                        sizeof( AFSFileIOResultCB));
1720
1721         stFileIORequest.SystemIOBuffer = pSystemBuffer;
1722
1723         stFileIORequest.SystemIOBufferMdl = Irp->MdlAddress;
1724
1725         stFileIORequest.IOLength = ByteCount;
1726
1727         stFileIORequest.IOOffset = StartingByte;
1728
1729         ulFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
1730
1731         if ( bNoIntermediateBuffering)
1732         {
1733
1734             ulFlags |= AFS_REQUEST_FLAG_CACHE_BYPASS;
1735         }
1736
1737         //
1738         // Update file metadata
1739         //
1740
1741         stFileIORequest.EndOfFile = pFcb->ObjectInformation->EndOfFile;
1742
1743         stFileIORequest.CreateTime = pFcb->ObjectInformation->CreationTime;
1744
1745         stFileIORequest.ChangeTime = pFcb->ObjectInformation->ChangeTime;
1746
1747         stFileIORequest.LastAccessTime = pFcb->ObjectInformation->LastAccessTime;
1748
1749         stFileIORequest.LastWriteTime = pFcb->ObjectInformation->LastWriteTime;
1750
1751         //
1752         // Write the data to the service
1753         //
1754
1755         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PROCESS_WRITE_FILE,
1756                                       ulFlags,
1757                                       &pCcb->AuthGroup,
1758                                       &pCcb->DirectoryCB->NameInformation.FileName,
1759                                       &pFcb->ObjectInformation->FileId,
1760                                       pFcb->ObjectInformation->VolumeCB->VolumeInformation.Cell,
1761                                       pFcb->ObjectInformation->VolumeCB->VolumeInformation.CellLength,
1762                                       &stFileIORequest,
1763                                       sizeof( AFSFileIOCB),
1764                                       &stFileIOResult,
1765                                       &ulResultLen);
1766
1767         if( NT_SUCCESS( ntStatus))
1768         {
1769
1770             Irp->IoStatus.Information = (ULONG_PTR)stFileIOResult.Length;
1771         }
1772         else
1773         {
1774
1775             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1776                           AFS_TRACE_LEVEL_ERROR,
1777                           "AFSNonCachedWriteDirect (%p) Failed to send write to service Status %08lX\n",
1778                           Irp,
1779                           ntStatus));
1780         }
1781
1782 try_exit:
1783
1784         AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1785                       AFS_TRACE_LEVEL_VERBOSE,
1786                       "AFSNonCachedWriteDirect (FO: %p) StartingByte %08lX:%08lX Length %08lX Status %08lX\n",
1787                       pFileObject,
1788                       StartingByte.HighPart,
1789                       StartingByte.LowPart,
1790                       ByteCount,
1791                       ntStatus));
1792
1793         if (NT_SUCCESS(ntStatus) &&
1794             !bPagingIo &&
1795             bSynchronousFo)
1796         {
1797
1798             pFileObject->CurrentByteOffset.QuadPart = StartingByte.QuadPart + ByteCount;
1799         }
1800
1801         AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1802                       AFS_TRACE_LEVEL_VERBOSE,
1803                       "AFSNonCachedWriteDirect Completing Irp %p Status %08lX Info %08lX\n",
1804                       Irp,
1805                       ntStatus,
1806                       Irp->IoStatus.Information));
1807
1808         AFSCompleteRequest( Irp, ntStatus);
1809     }
1810
1811     return ntStatus;
1812 }
1813
1814 static
1815 NTSTATUS
1816 AFSCachedWrite( IN PDEVICE_OBJECT DeviceObject,
1817                 IN PIRP Irp,
1818                 IN LARGE_INTEGER StartingByte,
1819                 IN ULONG ByteCount,
1820                 IN BOOLEAN ForceFlush)
1821 {
1822     UNREFERENCED_PARAMETER(DeviceObject);
1823     PVOID              pSystemBuffer = NULL;
1824     NTSTATUS           ntStatus = STATUS_SUCCESS;
1825     IO_STATUS_BLOCK    iosbFlush;
1826     IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1827     PFILE_OBJECT       pFileObject = pIrpSp->FileObject;
1828     AFSFcb            *pFcb = (AFSFcb *)pFileObject->FsContext;
1829     BOOLEAN            bSynchronousFo = BooleanFlagOn( pFileObject->Flags, FO_SYNCHRONOUS_IO);
1830     ULONG              ulCurrentIO = 0, ulTotalLen = ByteCount;
1831     PMDL               pCurrentMdl = Irp->MdlAddress;
1832     LARGE_INTEGER      liCurrentOffset;
1833
1834     __Enter
1835     {
1836
1837         Irp->IoStatus.Information = 0;
1838
1839         if( BooleanFlagOn( pIrpSp->MinorFunction, IRP_MN_MDL))
1840         {
1841
1842             __try
1843             {
1844
1845                 CcPrepareMdlWrite( pFileObject,
1846                                    &StartingByte,
1847                                    ByteCount,
1848                                    &Irp->MdlAddress,
1849                                    &Irp->IoStatus);
1850
1851                 ntStatus = Irp->IoStatus.Status;
1852             }
1853             __except( EXCEPTION_EXECUTE_HANDLER)
1854             {
1855                 ntStatus = GetExceptionCode();
1856
1857                 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1858                               AFS_TRACE_LEVEL_ERROR,
1859                               "AFSCachedWrite (%p) Exception thrown while preparing mdl write Status %08lX\n",
1860                               Irp,
1861                               ntStatus));
1862             }
1863
1864             if( !NT_SUCCESS( ntStatus))
1865             {
1866
1867                 //
1868                 // Free up any potentially allocated mdl's
1869                 //
1870
1871                 CcMdlWriteComplete( pFileObject,
1872                                     &StartingByte,
1873                                     Irp->MdlAddress);
1874
1875                 Irp->MdlAddress = NULL;
1876
1877                 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1878                               AFS_TRACE_LEVEL_ERROR,
1879                               "AFSCachedWrite (%p) Failed to process MDL write Status %08lX\n",
1880                               Irp,
1881                               ntStatus));
1882             }
1883
1884             try_return( ntStatus);
1885         }
1886
1887         liCurrentOffset.QuadPart = StartingByte.QuadPart;
1888
1889         while( ulTotalLen > 0)
1890         {
1891
1892             ntStatus = STATUS_SUCCESS;
1893
1894             if( pCurrentMdl != NULL)
1895             {
1896
1897                 pSystemBuffer = MmGetSystemAddressForMdlSafe( pCurrentMdl,
1898                                                               NormalPagePriority);
1899
1900                 ulCurrentIO = MmGetMdlByteCount( pCurrentMdl);
1901
1902                 if( ulCurrentIO > ulTotalLen)
1903                 {
1904                     ulCurrentIO = ulTotalLen;
1905                 }
1906             }
1907             else
1908             {
1909
1910                 pSystemBuffer = AFSLockSystemBuffer( Irp,
1911                                                      ulTotalLen);
1912
1913                 ulCurrentIO = ulTotalLen;
1914             }
1915
1916             if( pSystemBuffer == NULL)
1917             {
1918
1919                 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1920                               AFS_TRACE_LEVEL_ERROR,
1921                               "AFSCachedWrite (%p) Failed to lock system buffer\n",
1922                               Irp));
1923
1924                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1925             }
1926
1927             __try
1928             {
1929
1930                 if( !CcCopyWrite( pFileObject,
1931                                   &liCurrentOffset,
1932                                   ulCurrentIO,
1933                                   TRUE,
1934                                   pSystemBuffer))
1935                 {
1936                     //
1937                     // Failed to process request.
1938                     //
1939
1940                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1941                                   AFS_TRACE_LEVEL_ERROR,
1942                                   "AFSCachedWrite (%p) Failed to issue CcCopyWrite %wZ @ %0I64X Status %08lX\n",
1943                                   Irp,
1944                                   &pFileObject->FileName,
1945                                   liCurrentOffset.QuadPart,
1946                                   Irp->IoStatus.Status));
1947
1948                     try_return( ntStatus = STATUS_UNSUCCESSFUL);
1949                 }
1950             }
1951             __except( EXCEPTION_EXECUTE_HANDLER)
1952             {
1953
1954                 ntStatus = GetExceptionCode();
1955
1956                 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1957                               AFS_TRACE_LEVEL_ERROR,
1958                               "AFSCachedWrite (%p) CcCopyWrite Threw exception %wZ @ %0I64X Status %08lX\n",
1959                               Irp,
1960                               &pFileObject->FileName,
1961                               liCurrentOffset.QuadPart,
1962                               ntStatus));
1963             }
1964
1965             if( !NT_SUCCESS( ntStatus))
1966             {
1967                 try_return( ntStatus);
1968             }
1969
1970             if( ForceFlush ||
1971                 BooleanFlagOn(pFileObject->Flags, (FO_NO_INTERMEDIATE_BUFFERING + FO_WRITE_THROUGH)))
1972             {
1973
1974                 __try
1975                 {
1976                     //
1977                     // We have detected a file we do a write through with.
1978                     //
1979
1980                     CcFlushCache(&pFcb->NPFcb->SectionObjectPointers,
1981                                   &liCurrentOffset,
1982                                   ulCurrentIO,
1983                                   &iosbFlush);
1984
1985                     if( !NT_SUCCESS( iosbFlush.Status))
1986                     {
1987
1988                         AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1989                                       AFS_TRACE_LEVEL_ERROR,
1990                                       "AFSCachedWrite (%p) CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
1991                                       Irp,
1992                                       &pFileObject->FileName,
1993                                       pFcb->ObjectInformation->FileId.Cell,
1994                                       pFcb->ObjectInformation->FileId.Volume,
1995                                       pFcb->ObjectInformation->FileId.Vnode,
1996                                       pFcb->ObjectInformation->FileId.Unique,
1997                                       iosbFlush.Status,
1998                                       iosbFlush.Information));
1999
2000                         try_return( ntStatus = iosbFlush.Status);
2001                     }
2002                 }
2003                 __except( EXCEPTION_EXECUTE_HANDLER)
2004                 {
2005
2006                     ntStatus = GetExceptionCode();
2007
2008                     AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
2009                                   AFS_TRACE_LEVEL_ERROR,
2010                                   "AFSCachedWrite (%p) CcFlushCache Threw exception %wZ @ %0I64X Status %08lX\n",
2011                                   Irp,
2012                                   &pFileObject->FileName,
2013                                   liCurrentOffset.QuadPart,
2014                                   ntStatus));
2015
2016                     try_return( ntStatus);
2017                 }
2018             }
2019
2020             if( ulTotalLen <= ulCurrentIO)
2021             {
2022                 break;
2023             }
2024
2025             liCurrentOffset.QuadPart += ulCurrentIO;
2026
2027             ulTotalLen -= ulCurrentIO;
2028
2029             pCurrentMdl = pCurrentMdl->Next;
2030         }
2031
2032 try_exit:
2033
2034         if( NT_SUCCESS( ntStatus))
2035         {
2036
2037             Irp->IoStatus.Information = ByteCount;
2038
2039             if ( ForceFlush ||
2040                  BooleanFlagOn(pFileObject->Flags, (FO_NO_INTERMEDIATE_BUFFERING + FO_WRITE_THROUGH)))
2041             {
2042                 //
2043                 // Write through asked for... Set things so that we get
2044                 // flush when the worker thread next wakes up
2045                 //
2046                 pFcb->Specific.File.LastServerFlush.QuadPart = 0;
2047             }
2048         }
2049
2050         AFSCompleteRequest( Irp,
2051                             ntStatus);
2052     }
2053
2054     return ntStatus;
2055 }
2056
2057 //
2058 // Called with Fcb->NPFcb->SectionObjectResource and Fcb->NPFcb->Resource held
2059 //
2060
2061 static
2062 NTSTATUS
2063 AFSExtendingWrite( IN AFSFcb *Fcb,
2064                    IN PFILE_OBJECT FileObject,
2065                    IN LONGLONG NewLength)
2066 {
2067     LARGE_INTEGER liSaveFileSize = Fcb->Header.FileSize;
2068     LARGE_INTEGER liSaveAllocation = Fcb->Header.AllocationSize;
2069     NTSTATUS      ntStatus = STATUS_SUCCESS;
2070     AFSCcb       *pCcb = (AFSCcb *)FileObject->FsContext2;
2071
2072     if( NewLength > Fcb->Header.AllocationSize.QuadPart)
2073     {
2074
2075         Fcb->Header.AllocationSize.QuadPart = NewLength;
2076
2077         Fcb->ObjectInformation->AllocationSize = Fcb->Header.AllocationSize;
2078     }
2079
2080     if( NewLength > Fcb->Header.FileSize.QuadPart)
2081     {
2082
2083         Fcb->Header.FileSize.QuadPart = NewLength;
2084
2085         Fcb->ObjectInformation->EndOfFile = Fcb->Header.FileSize;
2086     }
2087
2088     //
2089     // Tell the server
2090     //
2091
2092     ntStatus = AFSUpdateFileInformation( &Fcb->ObjectInformation->ParentFileId,
2093                                          Fcb->ObjectInformation,
2094                                          &pCcb->AuthGroup);
2095
2096     if (NT_SUCCESS(ntStatus))
2097     {
2098
2099         KeQuerySystemTime( &Fcb->ObjectInformation->ChangeTime);
2100
2101         SetFlag( Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
2102
2103         //
2104         // If the file is currently cached, then let the MM know about the extension
2105         //
2106         // The CcSetFileSizes call should be made with only the PagingResource held
2107         // which we are currently not holding.
2108         //
2109
2110         if( CcIsFileCached( FileObject))
2111         {
2112             CcSetFileSizes( FileObject,
2113                             (PCC_FILE_SIZES)&Fcb->Header.AllocationSize);
2114         }
2115     }
2116     else
2117     {
2118         Fcb->Header.FileSize = liSaveFileSize;
2119         Fcb->Header.AllocationSize = liSaveAllocation;
2120     }
2121
2122     //
2123     // DownConvert file resource to shared
2124     //
2125     ExConvertExclusiveToSharedLite( &Fcb->NPFcb->Resource);
2126
2127     return ntStatus;
2128 }
2129
2130 NTSTATUS
2131 AFSShareWrite( IN PDEVICE_OBJECT DeviceObject,
2132                IN PIRP Irp)
2133 {
2134
2135     UNREFERENCED_PARAMETER(DeviceObject);
2136     NTSTATUS ntStatus = STATUS_SUCCESS;
2137     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2138     AFSFcb *pFcb = NULL;
2139     AFSCcb *pCcb = NULL;
2140     AFSPipeIORequestCB *pIoRequest = NULL;
2141     void *pBuffer = NULL;
2142     AFSPipeIOResultCB stIoResult;
2143     ULONG ulBytesReturned = 0;
2144
2145     __Enter
2146     {
2147
2148         pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
2149
2150         pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
2151
2152         AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
2153                       AFS_TRACE_LEVEL_VERBOSE,
2154                       "AFSShareWrite On pipe %wZ Length %08lX\n",
2155                       &pCcb->DirectoryCB->NameInformation.FileName,
2156                       pIrpSp->Parameters.Write.Length));
2157
2158         if( pIrpSp->Parameters.Write.Length == 0)
2159         {
2160
2161             //
2162             // Nothing to do in this case
2163             //
2164
2165             try_return( ntStatus);
2166         }
2167
2168         //
2169         // Retrieve the buffer for the read request
2170         //
2171
2172         pBuffer = AFSLockSystemBuffer( Irp,
2173                                        pIrpSp->Parameters.Write.Length);
2174
2175         if( pBuffer == NULL)
2176         {
2177
2178             AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
2179                           AFS_TRACE_LEVEL_ERROR,
2180                           "AFSShareWrite Failed to map buffer on pipe %wZ\n",
2181                           &pCcb->DirectoryCB->NameInformation.FileName));
2182
2183             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2184         }
2185
2186         AFSAcquireShared( &pFcb->NPFcb->Resource,
2187                           TRUE);
2188
2189         pIoRequest = (AFSPipeIORequestCB *)AFSExAllocatePoolWithTag( PagedPool,
2190                                                                      sizeof( AFSPipeIORequestCB) +
2191                                                                                 pIrpSp->Parameters.Write.Length,
2192                                                                      AFS_GENERIC_MEMORY_14_TAG);
2193
2194         if( pIoRequest == NULL)
2195         {
2196
2197             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2198         }
2199
2200         RtlZeroMemory( pIoRequest,
2201                        sizeof( AFSPipeIORequestCB) + pIrpSp->Parameters.Write.Length);
2202
2203         pIoRequest->RequestId = pCcb->RequestID;
2204
2205         pIoRequest->RootId = pFcb->ObjectInformation->VolumeCB->ObjectInformation.FileId;
2206
2207         pIoRequest->BufferLength = pIrpSp->Parameters.Write.Length;
2208
2209         RtlCopyMemory( (void *)((char *)pIoRequest + sizeof( AFSPipeIORequestCB)),
2210                        pBuffer,
2211                        pIrpSp->Parameters.Write.Length);
2212
2213         stIoResult.BytesProcessed = 0;
2214
2215         ulBytesReturned = sizeof( AFSPipeIOResultCB);
2216
2217         //
2218         // Issue the open request to the service
2219         //
2220
2221         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_WRITE,
2222                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
2223                                       &pCcb->AuthGroup,
2224                                       &pCcb->DirectoryCB->NameInformation.FileName,
2225                                       NULL,
2226                                       NULL,
2227                                       0,
2228                                       pIoRequest,
2229                                       sizeof( AFSPipeIORequestCB) +
2230                                                 pIrpSp->Parameters.Write.Length,
2231                                       &stIoResult,
2232                                       &ulBytesReturned);
2233
2234         if( !NT_SUCCESS( ntStatus))
2235         {
2236
2237             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2238                           AFS_TRACE_LEVEL_ERROR,
2239                           "AFSShareWrite (%p) Failed service write Status %08lX\n",
2240                           Irp,
2241                           ntStatus));
2242
2243             try_return( ntStatus);
2244         }
2245
2246         AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
2247                       AFS_TRACE_LEVEL_VERBOSE,
2248                       "AFSShareWrite Completed on pipe %wZ Length read %08lX\n",
2249                       &pCcb->DirectoryCB->NameInformation.FileName,
2250                       stIoResult.BytesProcessed));
2251
2252         Irp->IoStatus.Information = stIoResult.BytesProcessed;
2253
2254 try_exit:
2255
2256         if( pFcb != NULL)
2257         {
2258
2259             AFSReleaseResource( &pFcb->NPFcb->Resource);
2260         }
2261
2262         if( pIoRequest != NULL)
2263         {
2264
2265             AFSExFreePoolWithTag( pIoRequest, AFS_GENERIC_MEMORY_14_TAG);
2266         }
2267     }
2268
2269     return ntStatus;
2270 }