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