Windows: hold locks during non-cached writes
[openafs.git] / src / WINNT / afsrdr / kernel / lib / AFSWrite.cpp
1 /*
2  * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3  * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * - Redistributions of source code must retain the above copyright notice,
11  *   this list of conditions and the following disclaimer.
12  * - Redistributions in binary form must reproduce the above copyright
13  *   notice,
14  *   this list of conditions and the following disclaimer in the
15  *   documentation
16  *   and/or other materials provided with the distribution.
17  * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
18  *   nor the names of their contributors may be used to endorse or promote
19  *   products derived from this software without specific prior written
20  *   permission from Kernel Drivers, LLC and Your File System, Inc.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
26  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34
35 //
36 // File: AFSWrite.cpp
37 //
38
39 #include "AFSCommon.h"
40
41 static
42 NTSTATUS
43 AFSCachedWrite( IN PDEVICE_OBJECT DeviceObject,
44                 IN PIRP Irp,
45                 IN LARGE_INTEGER StartingByte,
46                 IN ULONG ByteCount,
47                 IN BOOLEAN ForceFlush);
48 static
49 NTSTATUS
50 AFSNonCachedWrite( IN PDEVICE_OBJECT DeviceObject,
51                    IN PIRP Irp,
52                    IN LARGE_INTEGER StartingByte,
53                    IN ULONG ByteCount);
54
55 static
56 NTSTATUS
57 AFSNonCachedWriteDirect( IN PDEVICE_OBJECT DeviceObject,
58                          IN PIRP Irp,
59                          IN LARGE_INTEGER StartingByte,
60                          IN ULONG ByteCount);
61
62 static
63 NTSTATUS
64 AFSExtendingWrite( IN AFSFcb *Fcb,
65                    IN PFILE_OBJECT FileObject,
66                    IN LONGLONG NewLength);
67
68 //
69 // Function: AFSWrite
70 //
71 // Description:
72 //
73 //      This is the dispatch handler for the IRP_MJ_WRITE request
74 //
75 // Return:
76 //
77 //      A status is returned for the function
78 //
79 NTSTATUS
80 AFSWrite( IN PDEVICE_OBJECT LibDeviceObject,
81           IN PIRP Irp)
82 {
83
84     UNREFERENCED_PARAMETER(LibDeviceObject);
85     NTSTATUS ntStatus = STATUS_SUCCESS;
86
87     __try
88     {
89
90         ntStatus = AFSCommonWrite( AFSRDRDeviceObject, Irp, NULL, FALSE);
91     }
92     __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
93     {
94
95         ntStatus = STATUS_INSUFFICIENT_RESOURCES;
96     }
97
98     return ntStatus;
99 }
100
101 NTSTATUS
102 AFSCommonWrite( IN PDEVICE_OBJECT DeviceObject,
103                 IN PIRP Irp,
104                 IN HANDLE OnBehalfOf,
105                 IN BOOLEAN bRetry)
106 {
107
108     NTSTATUS           ntStatus = STATUS_SUCCESS;
109     AFSDeviceExt      *pDeviceExt = (AFSDeviceExt *)DeviceObject->DeviceExtension;
110     IO_STACK_LOCATION *pIrpSp;
111     AFSFcb            *pFcb = NULL;
112     AFSCcb            *pCcb = NULL;
113     AFSNonPagedFcb    *pNPFcb = NULL;
114     ULONG              ulByteCount = 0;
115     LARGE_INTEGER      liStartingByte;
116     PFILE_OBJECT       pFileObject;
117     BOOLEAN            bPagingIo = FALSE;
118     BOOLEAN            bNonCachedIo = FALSE;
119     BOOLEAN            bReleaseMain = FALSE;
120     BOOLEAN            bReleaseSectionObject = FALSE;
121     BOOLEAN            bReleasePaging = FALSE;
122     BOOLEAN            bExtendingWrite = FALSE;
123     BOOLEAN            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             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
673                           AFS_TRACE_LEVEL_VERBOSE,
674                           "AFSCommonWrite (%p) Processing NON-CACHED request Offset %0I64X Len %08lX%s\n",
675                           Irp,
676                           liStartingByte.QuadPart,
677                           ulByteCount,
678                           bRetry ? " RETRY" : ""));
679
680             if( BooleanFlagOn( pRDRDevExt->DeviceFlags, AFS_DEVICE_FLAG_DIRECT_SERVICE_IO))
681             {
682
683                 ntStatus = AFSNonCachedWriteDirect( DeviceObject, Irp,  liStartingByte, ulByteCount);
684             }
685             else
686             {
687                 ntStatus = AFSNonCachedWrite( DeviceObject, Irp,  liStartingByte, ulByteCount);
688             }
689         }
690
691 try_exit:
692
693         AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
694                       AFS_TRACE_LEVEL_VERBOSE,
695                       "AFSCommonWrite (%p) Process complete Status %08lX\n",
696                       Irp,
697                       ntStatus));
698
699         ObDereferenceObject(pFileObject);
700
701         if( bReleaseSectionObject)
702         {
703
704             AFSReleaseResource( &pNPFcb->SectionObjectResource);
705         }
706
707         if( bReleasePaging)
708         {
709
710             AFSReleaseResource( &pNPFcb->PagingResource);
711         }
712
713         if( bReleaseMain)
714         {
715
716             AFSReleaseResource( &pNPFcb->Resource);
717         }
718
719         if( bCompleteIrp)
720         {
721
722             AFSCompleteRequest( Irp,
723                                 ntStatus);
724         }
725     }
726
727     return ntStatus;
728 }
729
730 NTSTATUS
731 AFSIOCtlWrite( IN PDEVICE_OBJECT DeviceObject,
732                IN PIRP Irp)
733 {
734
735     UNREFERENCED_PARAMETER(DeviceObject);
736     NTSTATUS ntStatus = STATUS_SUCCESS;
737     AFSPIOCtlIORequestCB stIORequestCB;
738     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
739     AFSFcb *pFcb = NULL;
740     AFSCcb *pCcb = NULL;
741     AFSPIOCtlIOResultCB stIOResultCB;
742     ULONG ulBytesReturned = 0;
743     AFSFileID stParentFID;
744
745     __Enter
746     {
747
748         Irp->IoStatus.Information = 0;
749
750         RtlZeroMemory( &stIORequestCB,
751                        sizeof( AFSPIOCtlIORequestCB));
752
753         if( pIrpSp->Parameters.Write.Length == 0)
754         {
755
756             //
757             // Nothing to do in this case
758             //
759
760             try_return( ntStatus);
761         }
762
763         pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
764
765         pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
766
767         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
768                       AFS_TRACE_LEVEL_VERBOSE,
769                       "AFSIOCtlWrite Acquiring Fcb lock %p SHARED %08lX\n",
770                       &pFcb->NPFcb->Resource,
771                       PsGetCurrentThread()));
772
773         AFSAcquireShared( &pFcb->NPFcb->Resource,
774                           TRUE);
775
776         //
777         // Get the parent fid to pass to the cm
778         //
779
780         RtlZeroMemory( &stParentFID,
781                        sizeof( AFSFileID));
782
783         if( BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
784         {
785
786             //
787             // The parent directory FID of the node
788             //
789
790             stParentFID = pFcb->ObjectInformation->ParentFileId;
791         }
792
793         //
794         // Set the control block up
795         //
796
797         stIORequestCB.RequestId = pCcb->RequestID;
798
799         if( pFcb->ObjectInformation->VolumeCB != NULL)
800         {
801             stIORequestCB.RootId = pFcb->ObjectInformation->VolumeCB->ObjectInformation.FileId;
802         }
803
804         //
805         // Lock down the buffer
806         //
807
808         stIORequestCB.MappedBuffer = AFSMapToService( Irp,
809                                                       pIrpSp->Parameters.Write.Length);
810
811         if( stIORequestCB.MappedBuffer == NULL)
812         {
813
814             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
815         }
816
817         stIORequestCB.BufferLength = pIrpSp->Parameters.Write.Length;
818
819         stIOResultCB.BytesProcessed = 0;
820
821         ulBytesReturned = sizeof( AFSPIOCtlIOResultCB);
822
823         //
824         // Issue the request to the service
825         //
826
827         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIOCTL_WRITE,
828                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
829                                       &pCcb->AuthGroup,
830                                       NULL,
831                                       &stParentFID,
832                                       NULL,
833                                       0,
834                                       (void *)&stIORequestCB,
835                                       sizeof( AFSPIOCtlIORequestCB),
836                                       &stIOResultCB,
837                                       &ulBytesReturned);
838
839         if( !NT_SUCCESS( ntStatus))
840         {
841
842             try_return( ntStatus);
843         }
844
845         //
846         // Update the length written
847         //
848
849         Irp->IoStatus.Information = stIOResultCB.BytesProcessed;
850
851 try_exit:
852
853         if( stIORequestCB.MappedBuffer != NULL)
854         {
855
856             AFSUnmapServiceMappedBuffer( stIORequestCB.MappedBuffer,
857                                          Irp->MdlAddress);
858         }
859
860         if( pFcb != NULL)
861         {
862
863             AFSReleaseResource( &pFcb->NPFcb->Resource);
864         }
865     }
866
867     return ntStatus;
868 }
869
870 //
871 // This function is called when we know we have to read from the AFS Cache.
872 //
873 // It ensures that we have exents for the entirety of the write and
874 // then pins the extents into memory (meaning that although we may
875 // add we will not remove).  Then it creates a scatter gather write
876 // and fires off the IRPs
877 //
878 static
879 NTSTATUS
880 AFSNonCachedWrite( IN PDEVICE_OBJECT DeviceObject,
881                    IN PIRP Irp,
882                    IN LARGE_INTEGER StartingByte,
883                    IN ULONG ByteCount)
884 {
885     NTSTATUS           ntStatus = STATUS_UNSUCCESSFUL;
886     VOID              *pSystemBuffer = NULL;
887     BOOLEAN            bPagingIo = BooleanFlagOn( Irp->Flags, IRP_PAGING_IO);
888     BOOLEAN            bLocked = FALSE;
889     BOOLEAN            bCompleteIrp = TRUE;
890     AFSGatherIo       *pGatherIo = NULL;
891     AFSIoRun          *pIoRuns = NULL;
892     AFSIoRun           stIoRuns[AFS_MAX_STACK_IO_RUNS];
893     ULONG              extentsCount = 0, runCount = 0;
894     AFSExtent         *pStartExtent = NULL;
895     AFSExtent         *pIgnoreExtent = NULL;
896     IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
897     PFILE_OBJECT       pFileObject = pIrpSp->FileObject;
898     AFSFcb            *pFcb = (AFSFcb *)pFileObject->FsContext;
899     AFSCcb            *pCcb = (AFSCcb *)pFileObject->FsContext2;
900     BOOLEAN            bSynchronousFo = BooleanFlagOn( pFileObject->Flags, FO_SYNCHRONOUS_IO);
901     AFSDeviceExt      *pDevExt = (AFSDeviceExt *)DeviceObject->DeviceExtension;
902     LARGE_INTEGER      liCurrentTime, liLastRequestTime;
903     AFSDeviceExt      *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
904     PFILE_OBJECT       pCacheFileObject = NULL;
905     BOOLEAN            bDerefExtents = FALSE;
906
907     __Enter
908     {
909
910         AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
911                       AFS_TRACE_LEVEL_VERBOSE,
912                       "AFSNonCachedWrite (FO: %p) StartingByte %08lX:%08lX Length %08lX\n",
913                       pFileObject,
914                       StartingByte.HighPart,
915                       StartingByte.LowPart,
916                       ByteCount));
917
918         if (ByteCount > pDevExt->Specific.RDR.MaxIo.QuadPart)
919         {
920
921             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
922                           AFS_TRACE_LEVEL_ERROR,
923                           "AFSNonCachedWrite (%p) Request %08lX Actual %08lX larger than MaxIO %I64X\n",
924                           Irp,
925                           ByteCount,
926                           pIrpSp->Parameters.Write.Length,
927                           pDevExt->Specific.RDR.MaxIo.QuadPart));
928
929             try_return( ntStatus = STATUS_UNSUCCESSFUL);
930         }
931
932         //
933         // Get the mapping for the buffer
934         //
935         pSystemBuffer = AFSLockSystemBuffer( Irp,
936                                              ByteCount);
937
938         if( pSystemBuffer == NULL)
939         {
940
941             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
942                           AFS_TRACE_LEVEL_ERROR,
943                           "AFSNonCachedWrite (%p) Failed to map system buffer\n",
944                           Irp));
945
946             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
947         }
948
949
950         //
951         // Provoke a get of the extents - if we need to.
952         //
953
954         AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
955                       AFS_TRACE_LEVEL_VERBOSE,
956                       "AFSNonCachedWrite Requesting extents for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX\n",
957                       pFcb->ObjectInformation->FileId.Cell,
958                       pFcb->ObjectInformation->FileId.Volume,
959                       pFcb->ObjectInformation->FileId.Vnode,
960                       pFcb->ObjectInformation->FileId.Unique,
961                       StartingByte.QuadPart,
962                       ByteCount));
963
964         ntStatus = AFSRequestExtentsAsync( pFcb,
965                                            pCcb,
966                                            &StartingByte,
967                                            ByteCount);
968
969         if (!NT_SUCCESS(ntStatus))
970         {
971
972             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
973                           AFS_TRACE_LEVEL_ERROR,
974                           "AFSNonCachedWrite (%p) Failed to request extents Status %08lX\n",
975                           Irp,
976                           ntStatus));
977
978             try_return( ntStatus);
979         }
980
981         KeQueryTickCount( &liLastRequestTime);
982
983         while (TRUE)
984         {
985
986             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
987                           AFS_TRACE_LEVEL_VERBOSE,
988                           "AFSNonCachedWrite Acquiring Fcb extents lock %p SHARED %08lX\n",
989                           &pFcb->NPFcb->Specific.File.ExtentsResource,
990                           PsGetCurrentThread()));
991
992             ASSERT( !ExIsResourceAcquiredLite( &pFcb->NPFcb->Specific.File.ExtentsResource ));
993
994             AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource, TRUE );
995             bLocked = TRUE;
996
997             pStartExtent = NULL;
998             pIgnoreExtent = NULL;
999
1000             if ( AFSDoExtentsMapRegion( pFcb, &StartingByte, ByteCount, &pStartExtent, &pIgnoreExtent ))
1001             {
1002                 break;
1003             }
1004
1005             KeClearEvent( &pFcb->NPFcb->Specific.File.ExtentsRequestComplete );
1006
1007             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1008                           AFS_TRACE_LEVEL_VERBOSE,
1009                           "AFSNonCachedWrite Releasing(1) Fcb extents lock %p SHARED %08lX\n",
1010                           &pFcb->NPFcb->Specific.File.ExtentsResource,
1011                           PsGetCurrentThread()));
1012
1013             AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
1014             bLocked= FALSE;
1015
1016             //
1017             // We will re-request the extents after waiting for them
1018             //
1019
1020             KeQueryTickCount( &liCurrentTime);
1021
1022             if( liCurrentTime.QuadPart - liLastRequestTime.QuadPart >= pControlDevExt->Specific.Control.ExtentRequestTimeCount.QuadPart)
1023             {
1024
1025                 AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1026                               AFS_TRACE_LEVEL_VERBOSE,
1027                               "AFSNonCachedWrite Requesting extents, again, for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX\n",
1028                               pFcb->ObjectInformation->FileId.Cell,
1029                               pFcb->ObjectInformation->FileId.Volume,
1030                               pFcb->ObjectInformation->FileId.Vnode,
1031                               pFcb->ObjectInformation->FileId.Unique,
1032                               StartingByte.QuadPart,
1033                               ByteCount));
1034
1035                 ntStatus = AFSRequestExtentsAsync( pFcb,
1036                                                    pCcb,
1037                                                    &StartingByte,
1038                                                    ByteCount);
1039
1040                 if (!NT_SUCCESS(ntStatus))
1041                 {
1042
1043                     AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1044                                   AFS_TRACE_LEVEL_ERROR,
1045                                   "AFSNonCachedWrite (%p) Failed to request extents Status %08lX\n",
1046                                   Irp,
1047                                   ntStatus));
1048
1049                     try_return( ntStatus);
1050                 }
1051
1052                 KeQueryTickCount( &liLastRequestTime);
1053             }
1054
1055
1056             AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1057                           AFS_TRACE_LEVEL_VERBOSE,
1058                           "AFSNonCachedWrite Waiting for extents for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX\n",
1059                           pFcb->ObjectInformation->FileId.Cell,
1060                           pFcb->ObjectInformation->FileId.Volume,
1061                           pFcb->ObjectInformation->FileId.Vnode,
1062                           pFcb->ObjectInformation->FileId.Unique,
1063                           StartingByte.QuadPart,
1064                           ByteCount));
1065
1066             //
1067             // Wait for it
1068             //
1069
1070             ntStatus =  AFSWaitForExtentMapping ( pFcb, pCcb);
1071
1072             if (!NT_SUCCESS(ntStatus))
1073             {
1074
1075                 AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1076                               AFS_TRACE_LEVEL_ERROR,
1077                               "AFSNonCachedWrite Failed wait for extents for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX Status %08lX\n",
1078                               pFcb->ObjectInformation->FileId.Cell,
1079                               pFcb->ObjectInformation->FileId.Volume,
1080                               pFcb->ObjectInformation->FileId.Vnode,
1081                               pFcb->ObjectInformation->FileId.Unique,
1082                               StartingByte.QuadPart,
1083                               ByteCount,
1084                               ntStatus));
1085
1086                 try_return( ntStatus);
1087             }
1088         }
1089
1090         //
1091         // As per the read path -
1092         //
1093
1094         AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1095                       AFS_TRACE_LEVEL_VERBOSE,
1096                       "AFSNonCachedWrite Extents located for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX\n",
1097                       pFcb->ObjectInformation->FileId.Cell,
1098                       pFcb->ObjectInformation->FileId.Volume,
1099                       pFcb->ObjectInformation->FileId.Vnode,
1100                       pFcb->ObjectInformation->FileId.Unique,
1101                       StartingByte.QuadPart,
1102                       ByteCount));
1103
1104         ntStatus = AFSGetExtents( pFcb,
1105                                   &StartingByte,
1106                                   ByteCount,
1107                                   pStartExtent,
1108                                   &extentsCount,
1109                                   &runCount);
1110
1111         if (!NT_SUCCESS(ntStatus))
1112         {
1113
1114             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1115                           AFS_TRACE_LEVEL_ERROR,
1116                           "AFSNonCachedWrite (%p) Failed to retrieve mapped extents Status %08lX\n",
1117                           Irp,
1118                           ntStatus));
1119
1120             try_return( ntStatus );
1121         }
1122
1123         AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1124                       AFS_TRACE_LEVEL_VERBOSE,
1125                       "AFSNonCachedWrite (%p) Successfully retrieved map extents count %d run count %d\n",
1126                       Irp,
1127                       extentsCount,
1128                       runCount));
1129
1130         if( BooleanFlagOn( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE))
1131         {
1132
1133             Irp->IoStatus.Information = ByteCount;
1134
1135 #if GEN_MD5
1136             //
1137             // Setup the MD5 for each extent
1138             //
1139
1140             AFSSetupMD5Hash( pFcb,
1141                              pStartExtent,
1142                              extentsCount,
1143                              pSystemBuffer,
1144                              &StartingByte,
1145                              ByteCount);
1146 #endif
1147
1148             ntStatus = AFSProcessExtentRun( pSystemBuffer,
1149                                             &StartingByte,
1150                                             ByteCount,
1151                                             pStartExtent,
1152                                             TRUE);
1153
1154             if (!NT_SUCCESS(ntStatus))
1155             {
1156
1157                 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1158                               AFS_TRACE_LEVEL_ERROR,
1159                               "AFSNonCachedWrite (%p) Failed to process extent run for non-persistent cache Status %08lX\n",
1160                               Irp,
1161                               ntStatus));
1162             }
1163
1164             try_return( ntStatus);
1165         }
1166
1167         //
1168         // Retrieve the cache file object
1169         //
1170
1171         pCacheFileObject = AFSReferenceCacheFileObject();
1172
1173         if( pCacheFileObject == NULL)
1174         {
1175
1176             ntStatus = STATUS_DEVICE_NOT_READY;
1177
1178             AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1179                           AFS_TRACE_LEVEL_ERROR,
1180                           "AFSNonCachedWrite Failed to retrieve cache fileobject for fid %08lX-%08lX-%08lX-%08lX Offset %0I64X Length %08lX Status %08lX\n",
1181                           pFcb->ObjectInformation->FileId.Cell,
1182                           pFcb->ObjectInformation->FileId.Volume,
1183                           pFcb->ObjectInformation->FileId.Vnode,
1184                           pFcb->ObjectInformation->FileId.Unique,
1185                           StartingByte.QuadPart,
1186                           ByteCount,
1187                           ntStatus));
1188
1189             try_return( ntStatus);
1190         }
1191
1192         if (runCount > AFS_MAX_STACK_IO_RUNS)
1193         {
1194
1195             pIoRuns = (AFSIoRun*) AFSExAllocatePoolWithTag( PagedPool,
1196                                                             runCount * sizeof( AFSIoRun ),
1197                                                             AFS_IO_RUN_TAG );
1198             if (NULL == pIoRuns)
1199             {
1200
1201                 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1202                               AFS_TRACE_LEVEL_ERROR,
1203                               "AFSNonCachedWrite (%p) Failed to allocate IO run block\n",
1204                               Irp));
1205
1206                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
1207             }
1208         }
1209         else
1210         {
1211
1212             pIoRuns = stIoRuns;
1213         }
1214
1215         RtlZeroMemory( pIoRuns, runCount * sizeof( AFSIoRun ));
1216
1217         ntStatus = AFSSetupIoRun( IoGetRelatedDeviceObject( pCacheFileObject),
1218                                   Irp,
1219                                   pSystemBuffer,
1220                                   pIoRuns,
1221                                   &StartingByte,
1222                                   ByteCount,
1223                                   pStartExtent,
1224                                   &runCount );
1225
1226         if (!NT_SUCCESS(ntStatus))
1227         {
1228
1229             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1230                           AFS_TRACE_LEVEL_ERROR,
1231                           "AFSNonCachedWrite (%p) Failed to initialize IO run block Status %08lX\n",
1232                           Irp,
1233                           ntStatus));
1234
1235             try_return( ntStatus );
1236         }
1237
1238         AFSReferenceActiveExtents( pStartExtent,
1239                                    extentsCount);
1240
1241         bDerefExtents = TRUE;
1242
1243         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1244                       AFS_TRACE_LEVEL_VERBOSE,
1245                       "AFSNonCachedWrite Releasing(2) Fcb extents lock %p SHARED %08lX\n",
1246                       &pFcb->NPFcb->Specific.File.ExtentsResource,
1247                       PsGetCurrentThread()));
1248
1249         AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
1250         bLocked = FALSE;
1251
1252         pGatherIo = (AFSGatherIo*) AFSExAllocatePoolWithTag( NonPagedPool,
1253                                                              sizeof( AFSGatherIo),
1254                                                              AFS_GATHER_TAG);
1255
1256         if (NULL == pGatherIo)
1257         {
1258
1259             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1260                           AFS_TRACE_LEVEL_ERROR,
1261                           "AFSNonCachedWrite (%p) Failed to allocate IO gather block\n",
1262                           Irp));
1263
1264             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1265                           AFS_TRACE_LEVEL_VERBOSE,
1266                           "AFSNonCachedWrite Acquiring(1) Fcb extents lock %p SHARED %08lX\n",
1267                           &pFcb->NPFcb->Specific.File.ExtentsResource,
1268                           PsGetCurrentThread()));
1269
1270             AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
1271                               TRUE);
1272             bLocked = TRUE;
1273
1274             AFSDereferenceActiveExtents( pStartExtent,
1275                                          extentsCount);
1276
1277             try_return (ntStatus = STATUS_INSUFFICIENT_RESOURCES );
1278         }
1279
1280         RtlZeroMemory( pGatherIo, sizeof( AFSGatherIo ));
1281
1282         //
1283         // Initialize count to 1, that was we won't get an early
1284         // completion if the first irp completes before the second is
1285         // queued.
1286         //
1287         pGatherIo->Count = 1;
1288         pGatherIo->Status = STATUS_SUCCESS;
1289         pGatherIo->MasterIrp = Irp;
1290         pGatherIo->Synchronous = TRUE;
1291         pGatherIo->CompleteMasterIrp = FALSE;
1292
1293         bCompleteIrp = TRUE;
1294
1295         if( pGatherIo->Synchronous)
1296         {
1297             KeInitializeEvent( &pGatherIo->Event, NotificationEvent, FALSE );
1298         }
1299
1300 #if GEN_MD5
1301         //
1302         // Setup the MD5 for each extent
1303         //
1304
1305         AFSSetupMD5Hash( pFcb,
1306                          pStartExtent,
1307                          extentsCount,
1308                          pSystemBuffer,
1309                          &StartingByte,
1310                          ByteCount);
1311 #endif
1312
1313         //
1314         // Pre-emptively set up the count
1315         //
1316
1317         Irp->IoStatus.Information = ByteCount;
1318
1319         ntStatus = AFSQueueStartIos( pCacheFileObject,
1320                                      IRP_MJ_WRITE,
1321                                      IRP_WRITE_OPERATION | IRP_SYNCHRONOUS_API,
1322                                      pIoRuns,
1323                                      runCount,
1324                                      pGatherIo);
1325
1326         AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1327                       AFS_TRACE_LEVEL_VERBOSE,
1328                       "AFSNonCachedWrite (%p) AFSStartIos completed Status %08lX\n",
1329                       Irp,
1330                       ntStatus));
1331
1332         if( !NT_SUCCESS( ntStatus))
1333         {
1334
1335             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1336                           AFS_TRACE_LEVEL_VERBOSE,
1337                           "AFSNonCachedWrite Acquiring(2) Fcb extents lock %p SHARED %08lX\n",
1338                           &pFcb->NPFcb->Specific.File.ExtentsResource,
1339                           PsGetCurrentThread()));
1340
1341             AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
1342                               TRUE);
1343             bLocked = TRUE;
1344
1345             AFSDereferenceActiveExtents( pStartExtent,
1346                                          extentsCount);
1347
1348             try_return( ntStatus);
1349         }
1350
1351         //
1352         // Wait for completion of All IOs we started.
1353         //
1354
1355         ntStatus = KeWaitForSingleObject( &pGatherIo->Event,
1356                                           Executive,
1357                                           KernelMode,
1358                                           FALSE,
1359                                           NULL);
1360
1361         if( NT_SUCCESS( ntStatus))
1362         {
1363
1364             ntStatus = pGatherIo->Status;
1365         }
1366
1367         if( !NT_SUCCESS( ntStatus))
1368         {
1369
1370             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1371                           AFS_TRACE_LEVEL_VERBOSE,
1372                           "AFSNonCachedWrite Acquiring(3) Fcb extents lock %p SHARED %08lX\n",
1373                           &pFcb->NPFcb->Specific.File.ExtentsResource,
1374                           PsGetCurrentThread()));
1375
1376             AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
1377                               TRUE);
1378             bLocked = TRUE;
1379
1380             AFSDereferenceActiveExtents( pStartExtent,
1381                                          extentsCount);
1382
1383             try_return( ntStatus);
1384         }
1385
1386 try_exit:
1387
1388         if( NT_SUCCESS( ntStatus) &&
1389             pStartExtent != NULL &&
1390             Irp->IoStatus.Information > 0)
1391         {
1392
1393             if ( !bLocked)
1394             {
1395
1396                 AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
1397                                   TRUE);
1398                 bLocked = TRUE;
1399             }
1400
1401             //
1402             // Since this is dirty we can mark the extents dirty now.
1403             // AFSMarkDirty will dereference the extents.  Do not call
1404             // AFSDereferenceActiveExtents() in this code path.
1405             //
1406
1407             AFSMarkDirty( pFcb,
1408                           pStartExtent,
1409                           extentsCount,
1410                           &StartingByte,
1411                           bDerefExtents);
1412
1413             if (!bPagingIo)
1414             {
1415                 //
1416                 // This was an uncached user write - tell the server to do
1417                 // the flush when the worker thread next wakes up
1418                 //
1419                 pFcb->Specific.File.LastServerFlush.QuadPart = 0;
1420             }
1421         }
1422
1423         if( pCacheFileObject != NULL)
1424         {
1425             AFSReleaseCacheFileObject( pCacheFileObject);
1426         }
1427
1428         AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1429                       AFS_TRACE_LEVEL_VERBOSE,
1430                       "AFSNonCachedWrite (FO: %p) StartingByte %08lX:%08lX Length %08lX Status %08lX\n",
1431                       pFileObject,
1432                       StartingByte.HighPart,
1433                       StartingByte.LowPart,
1434                       ByteCount,
1435                       ntStatus));
1436
1437         if (NT_SUCCESS(ntStatus) &&
1438             !bPagingIo &&
1439             bSynchronousFo)
1440         {
1441
1442             pFileObject->CurrentByteOffset.QuadPart = StartingByte.QuadPart + ByteCount;
1443         }
1444
1445         if( bLocked)
1446         {
1447
1448             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1449                           AFS_TRACE_LEVEL_VERBOSE,
1450                           "AFSNonCachedWrite Releasing Fcb extents lock %p SHARED %08lX\n",
1451                           &pFcb->NPFcb->Specific.File.ExtentsResource,
1452                           PsGetCurrentThread()));
1453
1454             AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
1455         }
1456
1457         if( pGatherIo)
1458         {
1459             AFSExFreePoolWithTag(pGatherIo, AFS_GATHER_TAG);
1460         }
1461
1462         if( NULL != pIoRuns &&
1463             stIoRuns != pIoRuns)
1464         {
1465             AFSExFreePoolWithTag(pIoRuns, AFS_IO_RUN_TAG);
1466         }
1467
1468         if( bCompleteIrp)
1469         {
1470
1471             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1472                           AFS_TRACE_LEVEL_VERBOSE,
1473                           "AFSNonCachedWrite Completing Irp %p Status %08lX Info %08lX\n",
1474                           Irp,
1475                           ntStatus,
1476                           Irp->IoStatus.Information));
1477
1478             AFSCompleteRequest( Irp, ntStatus);
1479         }
1480     }
1481
1482     return ntStatus;
1483 }
1484
1485 static
1486 NTSTATUS
1487 AFSNonCachedWriteDirect( IN PDEVICE_OBJECT DeviceObject,
1488                          IN PIRP Irp,
1489                          IN LARGE_INTEGER StartingByte,
1490                          IN ULONG ByteCount)
1491 {
1492     NTSTATUS           ntStatus = STATUS_UNSUCCESSFUL;
1493     VOID              *pSystemBuffer = NULL;
1494     BOOLEAN            bPagingIo = BooleanFlagOn( Irp->Flags, IRP_PAGING_IO);
1495     IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1496     PFILE_OBJECT       pFileObject = pIrpSp->FileObject;
1497     AFSFcb            *pFcb = (AFSFcb *)pFileObject->FsContext;
1498     AFSCcb            *pCcb = (AFSCcb *)pFileObject->FsContext2;
1499     BOOLEAN            bSynchronousFo = BooleanFlagOn( pFileObject->Flags, FO_SYNCHRONOUS_IO);
1500     BOOLEAN            bNoIntermediateBuffering = BooleanFlagOn( pFileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING);
1501     AFSDeviceExt      *pDevExt = (AFSDeviceExt *)DeviceObject->DeviceExtension;
1502     AFSFileIOCB        stFileIORequest;
1503     AFSFileIOResultCB  stFileIOResult;
1504     ULONG              ulResultLen = 0;
1505     ULONG              ulFlags;
1506
1507     __Enter
1508     {
1509         Irp->IoStatus.Information = 0;
1510
1511         AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1512                       AFS_TRACE_LEVEL_VERBOSE,
1513                       "AFSNonCachedWriteDirect (FO: %p) StartingByte %08lX:%08lX Length %08lX\n",
1514                       pFileObject,
1515                       StartingByte.HighPart,
1516                       StartingByte.LowPart,
1517                       ByteCount));
1518
1519         if (ByteCount > pDevExt->Specific.RDR.MaxIo.QuadPart)
1520         {
1521
1522             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1523                           AFS_TRACE_LEVEL_ERROR,
1524                           "AFSNonCachedWriteDirect (%p) Request %08lX Actual %08lX larger than MaxIO %I64X\n",
1525                           Irp,
1526                           ByteCount,
1527                           pIrpSp->Parameters.Write.Length,
1528                           pDevExt->Specific.RDR.MaxIo.QuadPart));
1529
1530             try_return( ntStatus = STATUS_UNSUCCESSFUL);
1531         }
1532
1533         //
1534         // Get the mapping for the buffer
1535         //
1536         pSystemBuffer = AFSLockSystemBuffer( Irp,
1537                                              ByteCount);
1538
1539         if( pSystemBuffer == NULL)
1540         {
1541
1542             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1543                           AFS_TRACE_LEVEL_ERROR,
1544                           "AFSNonCachedWriteDirect (%p) Failed to map system buffer\n",
1545                           Irp));
1546
1547             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1548         }
1549
1550         //
1551         // Issue the request at the service for processing
1552         //
1553
1554         ulResultLen = sizeof( AFSFileIOResultCB);
1555
1556         RtlZeroMemory( &stFileIORequest,
1557                        sizeof( AFSFileIOCB));
1558
1559         RtlZeroMemory( &stFileIOResult,
1560                        sizeof( AFSFileIOResultCB));
1561
1562         stFileIORequest.SystemIOBuffer = pSystemBuffer;
1563
1564         stFileIORequest.SystemIOBufferMdl = Irp->MdlAddress;
1565
1566         stFileIORequest.IOLength = ByteCount;
1567
1568         stFileIORequest.IOOffset = StartingByte;
1569
1570         ulFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
1571
1572         if ( bNoIntermediateBuffering)
1573         {
1574
1575             ulFlags |= AFS_REQUEST_FLAG_CACHE_BYPASS;
1576         }
1577
1578         //
1579         // Update file metadata
1580         //
1581
1582         stFileIORequest.EndOfFile = pFcb->ObjectInformation->EndOfFile;
1583
1584         stFileIORequest.CreateTime = pFcb->ObjectInformation->CreationTime;
1585
1586         stFileIORequest.ChangeTime = pFcb->ObjectInformation->ChangeTime;
1587
1588         stFileIORequest.LastAccessTime = pFcb->ObjectInformation->LastAccessTime;
1589
1590         stFileIORequest.LastWriteTime = pFcb->ObjectInformation->LastWriteTime;
1591
1592         //
1593         // Write the data to the service
1594         //
1595
1596         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PROCESS_WRITE_FILE,
1597                                       ulFlags,
1598                                       &pCcb->AuthGroup,
1599                                       &pCcb->DirectoryCB->NameInformation.FileName,
1600                                       &pFcb->ObjectInformation->FileId,
1601                                       pFcb->ObjectInformation->VolumeCB->VolumeInformation.Cell,
1602                                       pFcb->ObjectInformation->VolumeCB->VolumeInformation.CellLength,
1603                                       &stFileIORequest,
1604                                       sizeof( AFSFileIOCB),
1605                                       &stFileIOResult,
1606                                       &ulResultLen);
1607
1608         if( NT_SUCCESS( ntStatus))
1609         {
1610
1611             Irp->IoStatus.Information = (ULONG_PTR)stFileIOResult.Length;
1612         }
1613         else
1614         {
1615
1616             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1617                           AFS_TRACE_LEVEL_ERROR,
1618                           "AFSNonCachedWriteDirect (%p) Failed to send write to service Status %08lX\n",
1619                           Irp,
1620                           ntStatus));
1621         }
1622
1623 try_exit:
1624
1625         AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1626                       AFS_TRACE_LEVEL_VERBOSE,
1627                       "AFSNonCachedWriteDirect (FO: %p) StartingByte %08lX:%08lX Length %08lX Status %08lX\n",
1628                       pFileObject,
1629                       StartingByte.HighPart,
1630                       StartingByte.LowPart,
1631                       ByteCount,
1632                       ntStatus));
1633
1634         if (NT_SUCCESS(ntStatus) &&
1635             !bPagingIo &&
1636             bSynchronousFo)
1637         {
1638
1639             pFileObject->CurrentByteOffset.QuadPart = StartingByte.QuadPart + ByteCount;
1640         }
1641
1642         AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1643                       AFS_TRACE_LEVEL_VERBOSE,
1644                       "AFSNonCachedWriteDirect Completing Irp %p Status %08lX Info %08lX\n",
1645                       Irp,
1646                       ntStatus,
1647                       Irp->IoStatus.Information));
1648
1649         AFSCompleteRequest( Irp, ntStatus);
1650     }
1651
1652     return ntStatus;
1653 }
1654
1655 static
1656 NTSTATUS
1657 AFSCachedWrite( IN PDEVICE_OBJECT DeviceObject,
1658                 IN PIRP Irp,
1659                 IN LARGE_INTEGER StartingByte,
1660                 IN ULONG ByteCount,
1661                 IN BOOLEAN ForceFlush)
1662 {
1663     UNREFERENCED_PARAMETER(DeviceObject);
1664     PVOID              pSystemBuffer = NULL;
1665     NTSTATUS           ntStatus = STATUS_SUCCESS;
1666     IO_STATUS_BLOCK    iosbFlush;
1667     IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1668     PFILE_OBJECT       pFileObject = pIrpSp->FileObject;
1669     AFSFcb            *pFcb = (AFSFcb *)pFileObject->FsContext;
1670     BOOLEAN            bSynchronousFo = BooleanFlagOn( pFileObject->Flags, FO_SYNCHRONOUS_IO);
1671     ULONG              ulCurrentIO = 0, ulTotalLen = ByteCount;
1672     PMDL               pCurrentMdl = Irp->MdlAddress;
1673     LARGE_INTEGER      liCurrentOffset;
1674
1675     __Enter
1676     {
1677
1678         Irp->IoStatus.Information = 0;
1679
1680         if( BooleanFlagOn( pIrpSp->MinorFunction, IRP_MN_MDL))
1681         {
1682
1683             __try
1684             {
1685
1686                 CcPrepareMdlWrite( pFileObject,
1687                                    &StartingByte,
1688                                    ByteCount,
1689                                    &Irp->MdlAddress,
1690                                    &Irp->IoStatus);
1691
1692                 ntStatus = Irp->IoStatus.Status;
1693             }
1694             __except( EXCEPTION_EXECUTE_HANDLER)
1695             {
1696                 ntStatus = GetExceptionCode();
1697
1698                 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1699                               AFS_TRACE_LEVEL_ERROR,
1700                               "AFSCachedWrite (%p) Exception thrown while preparing mdl write Status %08lX\n",
1701                               Irp,
1702                               ntStatus));
1703             }
1704
1705             if( !NT_SUCCESS( ntStatus))
1706             {
1707
1708                 //
1709                 // Free up any potentially allocated mdl's
1710                 //
1711
1712                 CcMdlWriteComplete( pFileObject,
1713                                     &StartingByte,
1714                                     Irp->MdlAddress);
1715
1716                 Irp->MdlAddress = NULL;
1717
1718                 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1719                               AFS_TRACE_LEVEL_ERROR,
1720                               "AFSCachedWrite (%p) Failed to process MDL write Status %08lX\n",
1721                               Irp,
1722                               ntStatus));
1723             }
1724
1725             try_return( ntStatus);
1726         }
1727
1728         liCurrentOffset.QuadPart = StartingByte.QuadPart;
1729
1730         while( ulTotalLen > 0)
1731         {
1732
1733             ntStatus = STATUS_SUCCESS;
1734
1735             if( pCurrentMdl != NULL)
1736             {
1737
1738                 pSystemBuffer = MmGetSystemAddressForMdlSafe( pCurrentMdl,
1739                                                               NormalPagePriority);
1740
1741                 ulCurrentIO = MmGetMdlByteCount( pCurrentMdl);
1742
1743                 if( ulCurrentIO > ulTotalLen)
1744                 {
1745                     ulCurrentIO = ulTotalLen;
1746                 }
1747             }
1748             else
1749             {
1750
1751                 pSystemBuffer = AFSLockSystemBuffer( Irp,
1752                                                      ulTotalLen);
1753
1754                 ulCurrentIO = ulTotalLen;
1755             }
1756
1757             if( pSystemBuffer == NULL)
1758             {
1759
1760                 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1761                               AFS_TRACE_LEVEL_ERROR,
1762                               "AFSCachedWrite (%p) Failed to lock system buffer\n",
1763                               Irp));
1764
1765                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1766             }
1767
1768             __try
1769             {
1770
1771                 if( !CcCopyWrite( pFileObject,
1772                                   &liCurrentOffset,
1773                                   ulCurrentIO,
1774                                   TRUE,
1775                                   pSystemBuffer))
1776                 {
1777                     //
1778                     // Failed to process request.
1779                     //
1780
1781                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1782                                   AFS_TRACE_LEVEL_ERROR,
1783                                   "AFSCachedWrite (%p) Failed to issue CcCopyWrite %wZ @ %0I64X Status %08lX\n",
1784                                   Irp,
1785                                   &pFileObject->FileName,
1786                                   liCurrentOffset.QuadPart,
1787                                   Irp->IoStatus.Status));
1788
1789                     try_return( ntStatus = STATUS_UNSUCCESSFUL);
1790                 }
1791             }
1792             __except( EXCEPTION_EXECUTE_HANDLER)
1793             {
1794
1795                 ntStatus = GetExceptionCode();
1796
1797                 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1798                               AFS_TRACE_LEVEL_ERROR,
1799                               "AFSCachedWrite (%p) CcCopyWrite Threw exception %wZ @ %0I64X Status %08lX\n",
1800                               Irp,
1801                               &pFileObject->FileName,
1802                               liCurrentOffset.QuadPart,
1803                               ntStatus));
1804             }
1805
1806             if( !NT_SUCCESS( ntStatus))
1807             {
1808                 try_return( ntStatus);
1809             }
1810
1811             if( ForceFlush ||
1812                 BooleanFlagOn(pFileObject->Flags, (FO_NO_INTERMEDIATE_BUFFERING + FO_WRITE_THROUGH)))
1813             {
1814
1815                 //
1816                 // We have detected a file we do a write through with.
1817                 //
1818
1819                 CcFlushCache(&pFcb->NPFcb->SectionObjectPointers,
1820                              &liCurrentOffset,
1821                              ulCurrentIO,
1822                              &iosbFlush);
1823
1824                 if( !NT_SUCCESS( iosbFlush.Status))
1825                 {
1826
1827                     AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1828                                   AFS_TRACE_LEVEL_ERROR,
1829                                   "AFSCachedWrite (%p) CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
1830                                   Irp,
1831                                   &pFileObject->FileName,
1832                                   pFcb->ObjectInformation->FileId.Cell,
1833                                   pFcb->ObjectInformation->FileId.Volume,
1834                                   pFcb->ObjectInformation->FileId.Vnode,
1835                                   pFcb->ObjectInformation->FileId.Unique,
1836                                   iosbFlush.Status,
1837                                   iosbFlush.Information));
1838
1839                     try_return( ntStatus = iosbFlush.Status);
1840                 }
1841             }
1842
1843             if( ulTotalLen <= ulCurrentIO)
1844             {
1845                 break;
1846             }
1847
1848             liCurrentOffset.QuadPart += ulCurrentIO;
1849
1850             ulTotalLen -= ulCurrentIO;
1851
1852             pCurrentMdl = pCurrentMdl->Next;
1853         }
1854
1855 try_exit:
1856
1857         if( NT_SUCCESS( ntStatus))
1858         {
1859
1860             Irp->IoStatus.Information = ByteCount;
1861
1862             if( bSynchronousFo)
1863             {
1864
1865                 pFileObject->CurrentByteOffset.QuadPart = StartingByte.QuadPart + ByteCount;
1866             }
1867
1868             //
1869             // If this extended the Vdl, then update it accordingly
1870             //
1871
1872             if( StartingByte.QuadPart + ByteCount > pFcb->Header.ValidDataLength.QuadPart)
1873             {
1874
1875                 pFcb->Header.ValidDataLength.QuadPart = StartingByte.QuadPart + ByteCount;
1876             }
1877
1878             if ( ForceFlush ||
1879                  BooleanFlagOn(pFileObject->Flags, (FO_NO_INTERMEDIATE_BUFFERING + FO_WRITE_THROUGH)))
1880             {
1881                 //
1882                 // Write through asked for... Set things so that we get
1883                 // flush when the worker thread next wakes up
1884                 //
1885                 pFcb->Specific.File.LastServerFlush.QuadPart = 0;
1886             }
1887
1888             if( !BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME))
1889             {
1890
1891                 SetFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_WRITE_TIME);
1892
1893                 KeQuerySystemTime( &pFcb->ObjectInformation->LastWriteTime);
1894             }
1895         }
1896
1897         AFSCompleteRequest( Irp,
1898                             ntStatus);
1899     }
1900
1901     return ntStatus;
1902 }
1903
1904 static
1905 NTSTATUS
1906 AFSExtendingWrite( IN AFSFcb *Fcb,
1907                    IN PFILE_OBJECT FileObject,
1908                    IN LONGLONG NewLength)
1909 {
1910     LARGE_INTEGER liSaveFileSize = Fcb->Header.FileSize;
1911     LARGE_INTEGER liSaveAllocation = Fcb->Header.AllocationSize;
1912     NTSTATUS      ntStatus = STATUS_SUCCESS;
1913     AFSCcb       *pCcb = (AFSCcb *)FileObject->FsContext2;
1914
1915     if( NewLength > Fcb->Header.AllocationSize.QuadPart)
1916     {
1917
1918         Fcb->Header.AllocationSize.QuadPart = NewLength;
1919
1920         Fcb->ObjectInformation->AllocationSize = Fcb->Header.AllocationSize;
1921     }
1922
1923     if( NewLength > Fcb->Header.FileSize.QuadPart)
1924     {
1925
1926         Fcb->Header.FileSize.QuadPart = NewLength;
1927
1928         Fcb->ObjectInformation->EndOfFile = Fcb->Header.FileSize;
1929     }
1930
1931     //
1932     // Tell the server
1933     //
1934
1935     ntStatus = AFSUpdateFileInformation( &Fcb->ObjectInformation->ParentFileId,
1936                                          Fcb->ObjectInformation,
1937                                          &pCcb->AuthGroup);
1938
1939     if (NT_SUCCESS(ntStatus))
1940     {
1941
1942         KeQuerySystemTime( &Fcb->ObjectInformation->ChangeTime);
1943
1944         SetFlag( Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
1945
1946         //
1947         // If the file is currently cached, then let the MM know about the extension
1948         //
1949
1950         if( CcIsFileCached( FileObject))
1951         {
1952             CcSetFileSizes( FileObject,
1953                             (PCC_FILE_SIZES)&Fcb->Header.AllocationSize);
1954         }
1955     }
1956     else
1957     {
1958         Fcb->Header.FileSize = liSaveFileSize;
1959         Fcb->Header.AllocationSize = liSaveAllocation;
1960     }
1961
1962     //
1963     // DownConvert file resource to shared
1964     //
1965     ExConvertExclusiveToSharedLite( &Fcb->NPFcb->Resource);
1966
1967     return ntStatus;
1968 }
1969
1970 NTSTATUS
1971 AFSShareWrite( IN PDEVICE_OBJECT DeviceObject,
1972                IN PIRP Irp)
1973 {
1974
1975     UNREFERENCED_PARAMETER(DeviceObject);
1976     NTSTATUS ntStatus = STATUS_SUCCESS;
1977     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1978     AFSFcb *pFcb = NULL;
1979     AFSCcb *pCcb = NULL;
1980     AFSPipeIORequestCB *pIoRequest = NULL;
1981     void *pBuffer = NULL;
1982     AFSPipeIOResultCB stIoResult;
1983     ULONG ulBytesReturned = 0;
1984
1985     __Enter
1986     {
1987
1988         pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
1989
1990         pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
1991
1992         AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
1993                       AFS_TRACE_LEVEL_VERBOSE,
1994                       "AFSShareWrite On pipe %wZ Length %08lX\n",
1995                       &pCcb->DirectoryCB->NameInformation.FileName,
1996                       pIrpSp->Parameters.Write.Length));
1997
1998         if( pIrpSp->Parameters.Write.Length == 0)
1999         {
2000
2001             //
2002             // Nothing to do in this case
2003             //
2004
2005             try_return( ntStatus);
2006         }
2007
2008         //
2009         // Retrieve the buffer for the read request
2010         //
2011
2012         pBuffer = AFSLockSystemBuffer( Irp,
2013                                        pIrpSp->Parameters.Write.Length);
2014
2015         if( pBuffer == NULL)
2016         {
2017
2018             AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
2019                           AFS_TRACE_LEVEL_ERROR,
2020                           "AFSShareWrite Failed to map buffer on pipe %wZ\n",
2021                           &pCcb->DirectoryCB->NameInformation.FileName));
2022
2023             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2024         }
2025
2026         AFSAcquireShared( &pFcb->NPFcb->Resource,
2027                           TRUE);
2028
2029         pIoRequest = (AFSPipeIORequestCB *)AFSExAllocatePoolWithTag( PagedPool,
2030                                                                      sizeof( AFSPipeIORequestCB) +
2031                                                                                 pIrpSp->Parameters.Write.Length,
2032                                                                      AFS_GENERIC_MEMORY_14_TAG);
2033
2034         if( pIoRequest == NULL)
2035         {
2036
2037             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2038         }
2039
2040         RtlZeroMemory( pIoRequest,
2041                        sizeof( AFSPipeIORequestCB) + pIrpSp->Parameters.Write.Length);
2042
2043         pIoRequest->RequestId = pCcb->RequestID;
2044
2045         pIoRequest->RootId = pFcb->ObjectInformation->VolumeCB->ObjectInformation.FileId;
2046
2047         pIoRequest->BufferLength = pIrpSp->Parameters.Write.Length;
2048
2049         RtlCopyMemory( (void *)((char *)pIoRequest + sizeof( AFSPipeIORequestCB)),
2050                        pBuffer,
2051                        pIrpSp->Parameters.Write.Length);
2052
2053         stIoResult.BytesProcessed = 0;
2054
2055         ulBytesReturned = sizeof( AFSPipeIOResultCB);
2056
2057         //
2058         // Issue the open request to the service
2059         //
2060
2061         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_WRITE,
2062                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
2063                                       &pCcb->AuthGroup,
2064                                       &pCcb->DirectoryCB->NameInformation.FileName,
2065                                       NULL,
2066                                       NULL,
2067                                       0,
2068                                       pIoRequest,
2069                                       sizeof( AFSPipeIORequestCB) +
2070                                                 pIrpSp->Parameters.Write.Length,
2071                                       &stIoResult,
2072                                       &ulBytesReturned);
2073
2074         if( !NT_SUCCESS( ntStatus))
2075         {
2076
2077             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2078                           AFS_TRACE_LEVEL_ERROR,
2079                           "AFSShareWrite (%p) Failed service write Status %08lX\n",
2080                           Irp,
2081                           ntStatus));
2082
2083             try_return( ntStatus);
2084         }
2085
2086         AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
2087                       AFS_TRACE_LEVEL_VERBOSE,
2088                       "AFSShareWrite Completed on pipe %wZ Length read %08lX\n",
2089                       &pCcb->DirectoryCB->NameInformation.FileName,
2090                       stIoResult.BytesProcessed));
2091
2092         Irp->IoStatus.Information = stIoResult.BytesProcessed;
2093
2094 try_exit:
2095
2096         if( pFcb != NULL)
2097         {
2098
2099             AFSReleaseResource( &pFcb->NPFcb->Resource);
2100         }
2101
2102         if( pIoRequest != NULL)
2103         {
2104
2105             AFSExFreePoolWithTag( pIoRequest, AFS_GENERIC_MEMORY_14_TAG);
2106         }
2107     }
2108
2109     return ntStatus;
2110 }