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