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