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