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