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