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