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