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