317406b1616777d4c845965e37d224ee17b64054
[openafs.git] / src / WINNT / afsrdr / kernel / lib / AFSRead.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: AFSRead.cpp
37 //
38
39 #include "AFSCommon.h"
40
41 static
42 NTSTATUS
43 AFSCachedRead( IN PDEVICE_OBJECT DeviceObject,
44                IN PIRP Irp,
45                IN LARGE_INTEGER StartingByte,
46                IN ULONG ByteCount)
47 {
48     UNREFERENCED_PARAMETER(DeviceObject);
49     NTSTATUS           ntStatus = STATUS_SUCCESS;
50     IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
51     PFILE_OBJECT       pFileObject = pIrpSp->FileObject;
52     BOOLEAN            bSynchronousIo = BooleanFlagOn( pFileObject->Flags, FO_SYNCHRONOUS_IO);
53     VOID              *pSystemBuffer = NULL;
54     ULONG              ulCurrentIO = 0, ulTotalLen = ByteCount;
55     PMDL               pCurrentMdl = Irp->MdlAddress;
56     LARGE_INTEGER      liCurrentOffset;
57
58     __Enter
59     {
60
61         Irp->IoStatus.Information = 0;
62
63         liCurrentOffset.QuadPart = StartingByte.QuadPart;
64
65         while( ulTotalLen > 0)
66         {
67
68             ntStatus = STATUS_SUCCESS;
69
70             if( pCurrentMdl != NULL)
71             {
72
73                 ASSERT( pCurrentMdl != NULL);
74
75                 pSystemBuffer = MmGetSystemAddressForMdlSafe( pCurrentMdl,
76                                                               NormalPagePriority);
77
78                 ulCurrentIO = MmGetMdlByteCount( pCurrentMdl);
79
80                 if( ulCurrentIO > ulTotalLen)
81                 {
82                     ulCurrentIO = ulTotalLen;
83                 }
84             }
85             else
86             {
87
88                 pSystemBuffer = AFSLockSystemBuffer( Irp,
89                                                      ulTotalLen);
90
91                 ulCurrentIO = ulTotalLen;
92             }
93
94             if( pSystemBuffer == NULL)
95             {
96
97                 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
98                               AFS_TRACE_LEVEL_ERROR,
99                               "AFSCachedRead (%p) Failed to lock system buffer\n",
100                               Irp));
101
102                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
103             }
104
105             __try
106             {
107
108                 if( !CcCopyRead( pFileObject,
109                                  &liCurrentOffset,
110                                  ulCurrentIO,
111                                  TRUE,
112                                  pSystemBuffer,
113                                  &Irp->IoStatus))
114                 {
115
116                     //
117                     // Failed to process request.
118                     //
119
120                     AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
121                                   AFS_TRACE_LEVEL_ERROR,
122                                   "AFSCachedRead (%p) Failed CcCopyRead() %wZ @ %0I64X Status %08lX\n",
123                                   Irp,
124                                   &pFileObject->FileName,
125                                   liCurrentOffset.QuadPart,
126                                   Irp->IoStatus.Status));
127
128                     try_return( ntStatus = Irp->IoStatus.Status);
129                 }
130             }
131             __except( EXCEPTION_EXECUTE_HANDLER)
132             {
133                 ntStatus = GetExceptionCode();
134
135                 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
136                               AFS_TRACE_LEVEL_ERROR,
137                               "AFSCachedRead (%p) CcCopyRead() Threw exception %wZ @ %0I64X Status %08lX\n",
138                               Irp,
139                               &pFileObject->FileName,
140                               liCurrentOffset.QuadPart,
141                               ntStatus));
142             }
143
144             if( !NT_SUCCESS( ntStatus))
145             {
146
147                 try_return( ntStatus);
148             }
149
150             if( ulTotalLen <= ulCurrentIO)
151             {
152                 break;
153             }
154
155             liCurrentOffset.QuadPart += ulCurrentIO;
156
157             ulTotalLen -= ulCurrentIO;
158
159             pCurrentMdl = pCurrentMdl->Next;
160         }
161
162 try_exit:
163
164         if( NT_SUCCESS( ntStatus))
165         {
166
167             Irp->IoStatus.Information = ByteCount;
168
169             //
170             // Update the CBO if this is a sync read
171             //
172
173             if( bSynchronousIo)
174             {
175
176                 pFileObject->CurrentByteOffset.QuadPart = StartingByte.QuadPart + ByteCount;
177             }
178         }
179
180         AFSCompleteRequest( Irp,
181                             ntStatus);
182     }
183
184     return ntStatus;
185 }
186
187 static
188 NTSTATUS
189 AFSNonCachedRead( IN PDEVICE_OBJECT DeviceObject,
190                   IN PIRP Irp,
191                   IN LARGE_INTEGER StartingByte)
192 {
193     NTSTATUS           ntStatus = STATUS_UNSUCCESSFUL;
194     IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
195     PFILE_OBJECT       pFileObject = pIrpSp->FileObject;
196     AFSFcb            *pFcb = (AFSFcb *)pFileObject->FsContext;
197     AFSCcb            *pCcb = (AFSCcb *)pFileObject->FsContext2;
198     VOID              *pSystemBuffer = NULL;
199     BOOLEAN            bPagingIo = BooleanFlagOn( Irp->Flags, IRP_PAGING_IO);
200     BOOLEAN            bLocked = FALSE;
201     AFSGatherIo       *pGatherIo = NULL;
202     AFSIoRun          *pIoRuns = NULL;
203     AFSIoRun           stIoRuns[AFS_MAX_STACK_IO_RUNS];
204     ULONG              extentsCount = 0, runCount = 0;
205     AFSExtent         *pStartExtent = NULL;
206     AFSExtent         *pIgnoreExtent = NULL;
207     BOOLEAN            bCompleteIrp = TRUE;
208     ULONG              ulReadByteCount;
209     ULONG              ulByteCount;
210     AFSDeviceExt      *pDevExt = (AFSDeviceExt *)DeviceObject->DeviceExtension;
211     LARGE_INTEGER      liCurrentTime, liLastRequestTime;
212     AFSDeviceExt      *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
213     PFILE_OBJECT       pCacheFileObject = NULL;
214
215     __Enter
216     {
217
218         ulByteCount = pIrpSp->Parameters.Read.Length;
219
220         if (ulByteCount > pDevExt->Specific.RDR.MaxIo.QuadPart)
221         {
222
223             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
224                           AFS_TRACE_LEVEL_ERROR,
225                           "AFSNonCachedRead (%p) Request larger than MaxIO %I64X\n",
226                           Irp,
227                           pDevExt->Specific.RDR.MaxIo.QuadPart));
228
229             try_return( ntStatus = STATUS_UNSUCCESSFUL);
230         }
231
232         pSystemBuffer = AFSLockSystemBuffer( Irp,
233                                              ulByteCount);
234
235         if( pSystemBuffer == NULL)
236         {
237
238             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
239                           AFS_TRACE_LEVEL_ERROR,
240                           "AFSNonCachedRead (%p) Failed to map system buffer\n",
241                           Irp));
242
243             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
244         }
245
246         if( StartingByte.QuadPart + ulByteCount > pFcb->Header.FileSize.QuadPart)
247         {
248             ULONG zeroCount = (ULONG) (StartingByte.QuadPart + ulByteCount - pFcb->Header.FileSize.QuadPart);
249             ulReadByteCount = (ULONG)(pFcb->Header.FileSize.QuadPart - StartingByte.QuadPart);
250
251             //
252             // Clear up to EOF
253             //
254
255             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
256                           AFS_TRACE_LEVEL_VERBOSE,
257                           "AFSNonCachedRead (%p) Zeroing to EOF zero byte length %08lX\n",
258                           Irp,
259                           zeroCount));
260
261             RtlZeroMemory( ((PCHAR)pSystemBuffer) + ulReadByteCount, zeroCount);
262         }
263         else
264         {
265             ulReadByteCount = ulByteCount;
266         }
267
268         //
269         // Provoke a get of the extents - if we need to.
270         //
271
272         pStartExtent = NULL;
273
274         AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
275                       AFS_TRACE_LEVEL_VERBOSE,
276                       "AFSNonCachedRead Requesting extents for fid %08lX-%08lX-%08lX-%08lX Offset %I64X Length %08lX\n",
277                       pFcb->ObjectInformation->FileId.Cell,
278                       pFcb->ObjectInformation->FileId.Volume,
279                       pFcb->ObjectInformation->FileId.Vnode,
280                       pFcb->ObjectInformation->FileId.Unique,
281                       StartingByte.QuadPart,
282                       ulReadByteCount));
283
284         ntStatus = AFSRequestExtentsAsync( pFcb,
285                                            pCcb,
286                                            &StartingByte,
287                                            ulReadByteCount);
288
289         if (!NT_SUCCESS(ntStatus))
290         {
291
292             AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
293                           AFS_TRACE_LEVEL_ERROR,
294                           "AFSNonCachedRead (%p) Failed to request extents Status %08lX\n",
295                           Irp,
296                           ntStatus));
297
298             try_return( ntStatus);
299         }
300
301         KeQueryTickCount( &liLastRequestTime);
302
303         while (TRUE)
304         {
305
306             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
307                           AFS_TRACE_LEVEL_VERBOSE,
308                           "AFSNonCachedRead Acquiring Fcb extents lock %p SHARED %08lX\n",
309                           &pFcb->NPFcb->Specific.File.ExtentsResource,
310                           PsGetCurrentThread()));
311
312             AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource, TRUE );
313             bLocked = TRUE;
314
315             pStartExtent = NULL;
316             pIgnoreExtent = NULL;
317
318             if( AFSDoExtentsMapRegion( pFcb,
319                                        &StartingByte,
320                                        ulReadByteCount,
321                                        &pStartExtent,
322                                        &pIgnoreExtent ))
323             {
324                 break;
325             }
326
327             KeClearEvent( &pFcb->NPFcb->Specific.File.ExtentsRequestComplete);
328
329             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
330                           AFS_TRACE_LEVEL_VERBOSE,
331                           "AFSNonCachedRead Releasing Fcb extents lock %p SHARED %08lX\n",
332                           &pFcb->NPFcb->Specific.File.ExtentsResource,
333                           PsGetCurrentThread()));
334
335             AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
336             bLocked= FALSE;
337
338             //
339             // We will re-request the extents after 10 seconds of waiting for them
340             //
341
342             KeQueryTickCount( &liCurrentTime);
343
344             if( liCurrentTime.QuadPart - liLastRequestTime.QuadPart >= pControlDevExt->Specific.Control.ExtentRequestTimeCount.QuadPart)
345             {
346
347                 AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
348                               AFS_TRACE_LEVEL_VERBOSE,
349                               "AFSNonCachedRead Requesting extents, again, for fid %08lX-%08lX-%08lX-%08lX Offset %I64X Length %08lX\n",
350                               pFcb->ObjectInformation->FileId.Cell,
351                               pFcb->ObjectInformation->FileId.Volume,
352                               pFcb->ObjectInformation->FileId.Vnode,
353                               pFcb->ObjectInformation->FileId.Unique,
354                               StartingByte.QuadPart,
355                               ulReadByteCount));
356
357                 ntStatus = AFSRequestExtentsAsync( pFcb,
358                                                    pCcb,
359                                                    &StartingByte,
360                                                    ulReadByteCount);
361
362                 if (!NT_SUCCESS(ntStatus))
363                 {
364
365                     AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
366                                   AFS_TRACE_LEVEL_ERROR,
367                                   "AFSNonCachedRead (%p) Failed to request extents Status %08lX\n",
368                                   Irp,
369                                   ntStatus));
370
371                     try_return( ntStatus);
372                 }
373
374                 KeQueryTickCount( &liLastRequestTime);
375             }
376
377             AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
378                           AFS_TRACE_LEVEL_VERBOSE,
379                           "AFSNonCachedRead Waiting for extents for fid %08lX-%08lX-%08lX-%08lX Offset %I64X Length %08lX\n",
380                           pFcb->ObjectInformation->FileId.Cell,
381                           pFcb->ObjectInformation->FileId.Volume,
382                           pFcb->ObjectInformation->FileId.Vnode,
383                           pFcb->ObjectInformation->FileId.Unique,
384                           StartingByte.QuadPart,
385                           ulReadByteCount));
386
387             ntStatus =  AFSWaitForExtentMapping ( pFcb, pCcb);
388
389             if (!NT_SUCCESS(ntStatus))
390             {
391
392                 AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
393                               AFS_TRACE_LEVEL_ERROR,
394                               "AFSNonCachedRead Failed wait for extents for fid %08lX-%08lX-%08lX-%08lX Offset %I64X Length %08lX Status %08lX\n",
395                               pFcb->ObjectInformation->FileId.Cell,
396                               pFcb->ObjectInformation->FileId.Volume,
397                               pFcb->ObjectInformation->FileId.Vnode,
398                               pFcb->ObjectInformation->FileId.Unique,
399                               StartingByte.QuadPart,
400                               ulReadByteCount,
401                               ntStatus));
402
403                 try_return( ntStatus);
404             }
405         }
406
407         //
408         // At this stage we know that the extents are fully mapped and
409         // that, because we took a reference they won't be unmapped.
410         // Thus the list will not move between the start and end.
411         //
412
413         AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
414                       AFS_TRACE_LEVEL_VERBOSE,
415                       "AFSNonCachedRead Extents mapped for fid %08lX-%08lX-%08lX-%08lX Offset %I64X Length %08lX\n",
416                       pFcb->ObjectInformation->FileId.Cell,
417                       pFcb->ObjectInformation->FileId.Volume,
418                       pFcb->ObjectInformation->FileId.Vnode,
419                       pFcb->ObjectInformation->FileId.Unique,
420                       StartingByte.QuadPart,
421                       ulReadByteCount));
422
423         ntStatus = AFSGetExtents( pFcb,
424                                   &StartingByte,
425                                   ulReadByteCount,
426                                   pStartExtent,
427                                   &extentsCount,
428                                   &runCount);
429
430         if (!NT_SUCCESS(ntStatus))
431         {
432
433             AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
434                           AFS_TRACE_LEVEL_ERROR,
435                           "AFSNonCachedRead (%p) Failed to retrieve mapped extents Status %08lX\n",
436                           Irp,
437                           ntStatus));
438
439             try_return( ntStatus );
440         }
441
442         AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
443                       AFS_TRACE_LEVEL_VERBOSE,
444                       "AFSNonCachedRead (%p) Successfully retrieved map extents count %d run count %d\n",
445                       Irp,
446                       extentsCount,
447                       runCount));
448
449         if( BooleanFlagOn( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE))
450         {
451
452             Irp->IoStatus.Information = ulReadByteCount;
453
454             ntStatus = AFSProcessExtentRun( pSystemBuffer,
455                                             &StartingByte,
456                                             ulReadByteCount,
457                                             pStartExtent,
458                                             FALSE);
459
460             if (!NT_SUCCESS(ntStatus))
461             {
462
463                 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
464                               AFS_TRACE_LEVEL_ERROR,
465                               "AFSNonCachedRead (%p) Failed to process extent run for non-persistent cache Status %08lX\n",
466                               Irp,
467                               ntStatus));
468             }
469
470             try_return( ntStatus);
471         }
472
473         //
474         // Retrieve the cache file object
475         //
476
477         pCacheFileObject = AFSReferenceCacheFileObject();
478
479         if( pCacheFileObject == NULL)
480         {
481
482             ntStatus = STATUS_DEVICE_NOT_READY;
483
484             AFSDbgTrace(( AFS_SUBSYSTEM_EXTENT_PROCESSING,
485                           AFS_TRACE_LEVEL_ERROR,
486                           "AFSNonCachedRead Failed to retrieve cache fileobject for fid %08lX-%08lX-%08lX-%08lX Offset %I64X Length %08lX Status %08lX\n",
487                           pFcb->ObjectInformation->FileId.Cell,
488                           pFcb->ObjectInformation->FileId.Volume,
489                           pFcb->ObjectInformation->FileId.Vnode,
490                           pFcb->ObjectInformation->FileId.Unique,
491                           StartingByte.QuadPart,
492                           ulReadByteCount,
493                           ntStatus));
494
495             try_return( ntStatus);
496         }
497
498         if (runCount > AFS_MAX_STACK_IO_RUNS)
499         {
500
501             pIoRuns = (AFSIoRun*) AFSExAllocatePoolWithTag( PagedPool,
502                                                             runCount * sizeof( AFSIoRun ),
503                                                             AFS_IO_RUN_TAG );
504             if (NULL == pIoRuns)
505             {
506
507                 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
508                               AFS_TRACE_LEVEL_ERROR,
509                               "AFSNonCachedRead (%p) Failed to allocate IO run block\n",
510                               Irp));
511
512                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
513             }
514         }
515         else
516         {
517
518             pIoRuns = stIoRuns;
519         }
520
521         RtlZeroMemory( pIoRuns, runCount * sizeof( AFSIoRun ));
522
523         ntStatus = AFSSetupIoRun( IoGetRelatedDeviceObject( pCacheFileObject),
524                                   Irp,
525                                   pSystemBuffer,
526                                   pIoRuns,
527                                   &StartingByte,
528                                   ulReadByteCount,
529                                   pStartExtent,
530                                   &runCount );
531
532         if (!NT_SUCCESS(ntStatus))
533         {
534
535             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
536                           AFS_TRACE_LEVEL_ERROR,
537                           "AFSNonCachedRead (%p) Failed to initialize IO run block Status %08lX\n",
538                           Irp,
539                           ntStatus));
540
541             try_return( ntStatus );
542         }
543
544         AFSReferenceActiveExtents( pStartExtent,
545                                    extentsCount);
546
547         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
548                       AFS_TRACE_LEVEL_VERBOSE,
549                       "AFSNonCachedRead Releasing Fcb extents lock %p SHARED %08lX\n",
550                       &pFcb->NPFcb->Specific.File.ExtentsResource,
551                       PsGetCurrentThread()));
552
553         AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
554         bLocked = FALSE;
555
556         pGatherIo = (AFSGatherIo*) AFSExAllocatePoolWithTag( NonPagedPool,
557                                                              sizeof( AFSGatherIo ),
558                                                              AFS_GATHER_TAG );
559
560         if (NULL == pGatherIo)
561         {
562
563             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
564                           AFS_TRACE_LEVEL_ERROR,
565                           "AFSNonCachedRead (%p) Failed to allocate IO gather block\n",
566                           Irp));
567
568             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
569                           AFS_TRACE_LEVEL_VERBOSE,
570                           "AFSNonCachedRead Acquiring(2) Fcb extents lock %p SHARED %08lX\n",
571                           &pFcb->NPFcb->Specific.File.ExtentsResource,
572                           PsGetCurrentThread()));
573
574             AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
575                               TRUE);
576             bLocked = TRUE;
577
578             AFSDereferenceActiveExtents( pStartExtent,
579                                          extentsCount);
580
581             try_return (ntStatus = STATUS_INSUFFICIENT_RESOURCES );
582         }
583
584         RtlZeroMemory( pGatherIo, sizeof( AFSGatherIo ));
585
586         //
587         // Initialize count to 1, that was we won't get an early
588         // completion if the first irp completes before the second is
589         // queued.
590         //
591         pGatherIo->Count = 1;
592         pGatherIo->Status = STATUS_SUCCESS;
593         pGatherIo->MasterIrp = Irp;
594         pGatherIo->Synchronous = TRUE;
595         pGatherIo->Fcb = pFcb;
596         pGatherIo->CompleteMasterIrp = FALSE;
597
598         bCompleteIrp = TRUE;
599
600         if (pGatherIo->Synchronous)
601         {
602             KeInitializeEvent( &pGatherIo->Event, NotificationEvent, FALSE );
603         }
604         else
605         {
606             IoMarkIrpPending( Irp);
607         }
608
609         //
610         // Pre-emptively set up the count
611         //
612
613         Irp->IoStatus.Information = ulByteCount;
614
615         ntStatus = AFSQueueStartIos( pCacheFileObject,
616                                      IRP_MJ_READ,
617                                      IRP_READ_OPERATION | IRP_SYNCHRONOUS_API,
618                                      pIoRuns,
619                                      runCount,
620                                      pGatherIo);
621
622         AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
623                       AFS_TRACE_LEVEL_VERBOSE,
624                       "AFSNonCachedRead (%p) AFSStartIos completed Status %08lX\n",
625                       Irp,
626                       ntStatus));
627
628         if( !NT_SUCCESS( ntStatus))
629         {
630
631             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
632                           AFS_TRACE_LEVEL_VERBOSE,
633                           "AFSNonCachedRead Acquiring(3) Fcb extents lock %p SHARED %08lX\n",
634                           &pFcb->NPFcb->Specific.File.ExtentsResource,
635                           PsGetCurrentThread()));
636
637             AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
638                               TRUE);
639             bLocked = TRUE;
640
641             AFSDereferenceActiveExtents( pStartExtent,
642                                          extentsCount);
643
644             try_return( ntStatus);
645         }
646
647         //
648         // Wait for completion of all IOs we started.
649         //
650         (VOID) KeWaitForSingleObject( &pGatherIo->Event,
651                                       Executive,
652                                       KernelMode,
653                                       FALSE,
654                                       NULL);
655
656         ntStatus = pGatherIo->Status;
657
658         AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
659                       AFS_TRACE_LEVEL_VERBOSE,
660                       "AFSNonCachedRead (%p) AFSStartIos wait completed Status %08lX\n",
661                       Irp,
662                       ntStatus));
663
664         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
665                       AFS_TRACE_LEVEL_VERBOSE,
666                       "AFSNonCachedRead Acquiring(4) Fcb extents lock %p SHARED %08lX\n",
667                       &pFcb->NPFcb->Specific.File.ExtentsResource,
668                       PsGetCurrentThread()));
669
670         AFSAcquireShared( &pFcb->NPFcb->Specific.File.ExtentsResource,
671                           TRUE);
672         bLocked = TRUE;
673
674         AFSDereferenceActiveExtents( pStartExtent,
675                                      extentsCount);
676
677         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
678                       AFS_TRACE_LEVEL_VERBOSE,
679                       "AFSNonCachedRead Releasing Fcb extents lock %p SHARED %08lX\n",
680                       &pFcb->NPFcb->Specific.File.ExtentsResource,
681                       PsGetCurrentThread()));
682
683         AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
684         bLocked = FALSE;
685
686         //
687         // The data is there now.  Give back the extents now so the service
688         // has some in hand
689         //
690
691         if ( pFcb->Specific.File.ExtentLength > 4096)
692         {
693
694             (VOID) AFSReleaseExtentsWithFlush( pFcb,
695                                                &pCcb->AuthGroup,
696                                                FALSE);
697         }
698
699 try_exit:
700
701         if( pCacheFileObject != NULL)
702         {
703             AFSReleaseCacheFileObject( pCacheFileObject);
704         }
705
706         AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
707                       AFS_TRACE_LEVEL_VERBOSE,
708                       "AFSNonCachedRead (%p) Completed request Status %08lX\n",
709                       Irp,
710                       ntStatus));
711
712         if (NT_SUCCESS(ntStatus) &&
713             !bPagingIo &&
714             BooleanFlagOn( pFileObject->Flags, FO_SYNCHRONOUS_IO))
715         {
716             //
717             // Update the CBO if this is a sync, nopaging read
718             //
719             pFileObject->CurrentByteOffset.QuadPart = StartingByte.QuadPart + ulByteCount;
720         }
721
722         if (bLocked)
723         {
724
725             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
726                           AFS_TRACE_LEVEL_VERBOSE,
727                           "AFSNonCachedRead Releasing Fcb extents lock %p SHARED %08lX\n",
728                           &pFcb->NPFcb->Specific.File.ExtentsResource,
729                           PsGetCurrentThread()));
730
731             AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
732         }
733
734         if (pGatherIo)
735         {
736             AFSExFreePoolWithTag(pGatherIo, AFS_GATHER_TAG);
737         }
738
739         if (NULL != pIoRuns && stIoRuns != pIoRuns)
740         {
741             AFSExFreePoolWithTag(pIoRuns, AFS_IO_RUN_TAG);
742         }
743
744         if (bCompleteIrp)
745         {
746
747             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
748                           AFS_TRACE_LEVEL_VERBOSE,
749                           "AFSNonCachedRead Completing irp %08lX Status %08lX Info %08lX\n",
750                           Irp,
751                           ntStatus,
752                           Irp->IoStatus.Information));
753
754             AFSCompleteRequest( Irp, ntStatus );
755         }
756     }
757     return ntStatus;
758 }
759
760 static
761 NTSTATUS
762 AFSNonCachedReadDirect( IN PDEVICE_OBJECT DeviceObject,
763                         IN PIRP Irp,
764                         IN LARGE_INTEGER StartingByte)
765 {
766     NTSTATUS           ntStatus = STATUS_UNSUCCESSFUL;
767     IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
768     PFILE_OBJECT       pFileObject = pIrpSp->FileObject;
769     AFSFcb            *pFcb = (AFSFcb *)pFileObject->FsContext;
770     AFSCcb            *pCcb = (AFSCcb *)pFileObject->FsContext2;
771     VOID              *pSystemBuffer = NULL;
772     ULONG              ulByteCount = 0;
773     ULONG              ulReadByteCount = 0;
774     ULONG              ulFlags;
775     BOOLEAN            bNoIntermediateBuffering = BooleanFlagOn( pFileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING);
776     AFSDeviceExt      *pDevExt = (AFSDeviceExt *)DeviceObject->DeviceExtension;
777     AFSFileIOCB        stFileIORequest;
778     AFSFileIOResultCB  stFileIOResult;
779     ULONG              ulResultLen = 0;
780
781     __Enter
782     {
783
784         Irp->IoStatus.Information = 0;
785
786         ulByteCount = pIrpSp->Parameters.Read.Length;
787
788         if (ulByteCount > pDevExt->Specific.RDR.MaxIo.QuadPart)
789         {
790
791             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
792                           AFS_TRACE_LEVEL_ERROR,
793                           "AFSNonCachedReadDirect (%p) Request larger than MaxIO %I64X\n",
794                           Irp,
795                           pDevExt->Specific.RDR.MaxIo.QuadPart));
796
797             try_return( ntStatus = STATUS_UNSUCCESSFUL);
798         }
799
800         pSystemBuffer = AFSLockSystemBuffer( Irp,
801                                              ulByteCount);
802
803         if( pSystemBuffer == NULL)
804         {
805
806             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
807                           AFS_TRACE_LEVEL_ERROR,
808                           "AFSNonCachedReadDirect (%p) Failed to map system buffer\n",
809                           Irp));
810
811             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
812         }
813
814         if( StartingByte.QuadPart + ulByteCount > pFcb->Header.FileSize.QuadPart)
815         {
816             ULONG zeroCount = (ULONG) (StartingByte.QuadPart + ulByteCount - pFcb->Header.FileSize.QuadPart);
817             ulReadByteCount = (ULONG)(pFcb->Header.FileSize.QuadPart - StartingByte.QuadPart);
818
819             //
820             // Clear up to EOF
821             //
822
823             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
824                           AFS_TRACE_LEVEL_VERBOSE,
825                           "AFSNonCachedReadDirect (%p) Zeroing to EOF zero byte length %08lX\n",
826                           Irp,
827                           zeroCount));
828
829             RtlZeroMemory( ((PCHAR)pSystemBuffer) + ulReadByteCount, zeroCount);
830         }
831         else
832         {
833             ulReadByteCount = ulByteCount;
834         }
835
836         //
837         // Issue the request at the service for processing
838         //
839
840         ulResultLen = sizeof( AFSFileIOResultCB);
841
842         RtlZeroMemory( &stFileIORequest,
843                        sizeof( AFSFileIOCB));
844
845         RtlZeroMemory( &stFileIOResult,
846                        sizeof( AFSFileIOResultCB));
847
848         stFileIORequest.SystemIOBuffer = pSystemBuffer;
849
850         stFileIORequest.SystemIOBufferMdl = Irp->MdlAddress;
851
852         stFileIORequest.IOOffset = StartingByte;
853
854         stFileIORequest.IOLength = ulReadByteCount;
855
856         ulFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
857
858         if ( bNoIntermediateBuffering)
859         {
860
861             ulFlags |= AFS_REQUEST_FLAG_CACHE_BYPASS;
862         }
863
864         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PROCESS_READ_FILE,
865                                       ulFlags,
866                                       &pCcb->AuthGroup,
867                                       &pCcb->DirectoryCB->NameInformation.FileName,
868                                       &pFcb->ObjectInformation->FileId,
869                                       pFcb->ObjectInformation->VolumeCB->VolumeInformation.Cell,
870                                       pFcb->ObjectInformation->VolumeCB->VolumeInformation.CellLength,
871                                       &stFileIORequest,
872                                       sizeof( AFSFileIOCB),
873                                       &stFileIOResult,
874                                       &ulResultLen);
875
876         if( NT_SUCCESS( ntStatus))
877         {
878
879             Irp->IoStatus.Information = (ULONG_PTR)stFileIOResult.Length;
880         }
881         else
882         {
883
884             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
885                           AFS_TRACE_LEVEL_ERROR,
886                           "AFSNonCachedReadDirect (%p) Failed to send read to service Status %08lX\n",
887                           Irp,
888                           ntStatus));
889         }
890
891 try_exit:
892
893         AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
894                       AFS_TRACE_LEVEL_VERBOSE,
895                       "AFSNonCachedReadDirect (%p) Completed request Status %08lX\n",
896                       Irp,
897                       ntStatus));
898
899         if (NT_SUCCESS(ntStatus) &&
900             !BooleanFlagOn( Irp->Flags, IRP_PAGING_IO) &&
901             BooleanFlagOn( pFileObject->Flags, FO_SYNCHRONOUS_IO))
902         {
903             //
904             // Update the CBO if this is a sync, nopaging read
905             //
906             pFileObject->CurrentByteOffset.QuadPart = StartingByte.QuadPart + ulByteCount;
907         }
908
909         AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
910                       AFS_TRACE_LEVEL_VERBOSE,
911                       "AFSNonCachedReadDirect Completing irp %08lX Status %08lX Info %08lX\n",
912                       Irp,
913                       ntStatus,
914                       Irp->IoStatus.Information));
915
916         AFSCompleteRequest( Irp, ntStatus );
917     }
918
919     return ntStatus;
920 }
921
922 //
923 // Function: AFSDispatch
924 //
925 // Description:
926 //
927 // A shim around AFSCommonRead (qv)
928 //
929 NTSTATUS
930 AFSRead( IN PDEVICE_OBJECT LibDeviceObject,
931          IN PIRP Irp)
932 {
933
934     UNREFERENCED_PARAMETER(LibDeviceObject);
935     NTSTATUS ntStatus = STATUS_SUCCESS;
936
937     __try
938     {
939
940         ntStatus = AFSCommonRead( AFSRDRDeviceObject, Irp, NULL);
941     }
942     __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
943     {
944
945         ntStatus = STATUS_INSUFFICIENT_RESOURCES;
946
947         AFSDumpTraceFilesFnc();
948     }
949
950     return ntStatus;
951 }
952 //
953 // Function: AFSRead
954 //
955 // Description:
956 //
957 //      This function is a slightly widened Dispatch handler for the
958 //      AFS Read function.  The third parameter is NULL if we were called
959 //      at our dispatch point and a process handle if we have been posted.
960 //
961 //      After doing the obvious (completing MDL writes and so forth)
962 //      we then post, or not.
963 //
964 // Return:
965 //
966 //      A status is returned for the function
967 //
968
969 NTSTATUS
970 AFSCommonRead( IN PDEVICE_OBJECT DeviceObject,
971                IN PIRP Irp,
972                IN HANDLE OnBehalfOf)
973 {
974
975     UNREFERENCED_PARAMETER(OnBehalfOf);
976     NTSTATUS            ntStatus = STATUS_SUCCESS;
977     AFSDeviceExt       *pDeviceExt;
978     IO_STACK_LOCATION  *pIrpSp;
979     AFSFcb             *pFcb = NULL;
980     AFSCcb             *pCcb = NULL;
981     BOOLEAN             bReleaseMain = FALSE;
982     BOOLEAN             bReleaseSectionObject = FALSE;
983     BOOLEAN             bReleasePaging = FALSE;
984     BOOLEAN             bPagingIo = FALSE;
985     BOOLEAN             bNonCachedIo = FALSE;
986     BOOLEAN             bCompleteIrp = TRUE;
987     PFILE_OBJECT        pFileObject = NULL;
988     LARGE_INTEGER       liStartingByte;
989     ULONG               ulByteCount;
990     AFSDeviceExt       *pRDRDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
991
992     pIrpSp = IoGetCurrentIrpStackLocation( Irp);
993     pDeviceExt = (AFSDeviceExt *)DeviceObject->DeviceExtension;
994
995     __Enter
996     {
997         //
998         // Decode the fileobject
999         //
1000         pFileObject = pIrpSp->FileObject;
1001
1002         //
1003         // There is a risk (albeit infinitely small) that the Irp will
1004         // complete before this function exits, then a cleanup and
1005         // close will happen and the FCB will be torn down before we
1006         // get to the try_exit.  Pin the file Object which will pin the FCB
1007         //
1008
1009         ObReferenceObject( pFileObject);
1010
1011         //
1012         // If we are in shutdown mode then fail the request
1013         //
1014
1015         if( BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
1016         {
1017
1018             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1019                           AFS_TRACE_LEVEL_WARNING,
1020                           "AFSCommonRead (%p) Open request after shutdown\n",
1021                           Irp));
1022
1023             try_return( ntStatus = STATUS_TOO_LATE);
1024         }
1025
1026         pFcb = (AFSFcb *)pFileObject->FsContext;
1027
1028         pCcb = (AFSCcb *)pFileObject->FsContext2;
1029
1030         if( pFcb == NULL)
1031         {
1032
1033             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1034                           AFS_TRACE_LEVEL_ERROR,
1035                           "AFSCommonRead Attempted read (%p) when pFcb == NULL\n",
1036                           Irp));
1037
1038             try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
1039         }
1040
1041         bPagingIo = BooleanFlagOn( Irp->Flags, IRP_PAGING_IO);
1042         bNonCachedIo = BooleanFlagOn( Irp->Flags,IRP_NOCACHE);
1043
1044         liStartingByte = pIrpSp->Parameters.Read.ByteOffset;
1045         ulByteCount = pIrpSp->Parameters.Read.Length;
1046
1047         if( pFcb->Header.NodeTypeCode != AFS_IOCTL_FCB &&
1048             pFcb->Header.NodeTypeCode != AFS_FILE_FCB &&
1049             pFcb->Header.NodeTypeCode != AFS_SPECIAL_SHARE_FCB)
1050         {
1051
1052             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1053                           AFS_TRACE_LEVEL_ERROR,
1054                           "AFSCommonRead Attempted read (%p) on an invalid node type %08lX\n",
1055                           Irp,
1056                           pFcb->Header.NodeTypeCode));
1057
1058             try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
1059         }
1060
1061         //
1062         // If this is a read against an IOCtl node then handle it
1063         // in a different pathway
1064         //
1065
1066         if( pFcb->Header.NodeTypeCode == AFS_IOCTL_FCB)
1067         {
1068
1069             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1070                           AFS_TRACE_LEVEL_VERBOSE,
1071                           "AFSCommonRead (%p) Processing file (PIOCTL) Offset %I64X Length %08lX Irp Flags %08lX\n",
1072                           Irp,
1073                           liStartingByte.QuadPart,
1074                           ulByteCount,
1075                           Irp->Flags));
1076
1077             ntStatus = AFSIOCtlRead( DeviceObject,
1078                                      Irp);
1079
1080             try_return( ntStatus);
1081         }
1082         else if( pFcb->Header.NodeTypeCode == AFS_SPECIAL_SHARE_FCB)
1083         {
1084
1085             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1086                           AFS_TRACE_LEVEL_VERBOSE,
1087                           "AFSCommonRead (%p) Processing file (SHARE) Offset %I64X Length %08lX Irp Flags %08lX\n",
1088                           Irp,
1089                           liStartingByte.QuadPart,
1090                           ulByteCount,
1091                           Irp->Flags));
1092
1093             ntStatus = AFSShareRead( DeviceObject,
1094                                      Irp);
1095
1096             try_return( ntStatus);
1097         }
1098
1099         //
1100         // No fileobject yet?  Bail.
1101         //
1102         if( !BooleanFlagOn( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE) &&
1103             !BooleanFlagOn( pRDRDevExt->DeviceFlags, AFS_REDIR_INIT_PERFORM_SERVICE_IO) &&
1104             NULL == pDeviceExt->Specific.RDR.CacheFileObject)
1105         {
1106
1107             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1108                           AFS_TRACE_LEVEL_ERROR,
1109                           "AFSCommonRead (%p) Request failed due to AFS cache closed\n",
1110                           Irp));
1111
1112             try_return( ntStatus = STATUS_TOO_LATE );
1113         }
1114
1115         if( pIrpSp->Parameters.Read.Length == 0)
1116         {
1117
1118             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1119                           AFS_TRACE_LEVEL_VERBOSE,
1120                           "AFSCommonRead (%p) Request completed due to zero length\n",
1121                           Irp));
1122
1123             try_return( ntStatus);
1124         }
1125
1126         if ( FlagOn(pIrpSp->MinorFunction, IRP_MN_COMPLETE) )
1127         {
1128
1129             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1130                           AFS_TRACE_LEVEL_VERBOSE,
1131                           "AFSCommonRead Acquiring Fcb SectionObject lock %p SHARED %08lX\n",
1132                           &pFcb->NPFcb->SectionObjectResource,
1133                           PsGetCurrentThread()));
1134
1135             AFSAcquireShared( &pFcb->NPFcb->SectionObjectResource,
1136                               TRUE);
1137
1138             bReleaseSectionObject = TRUE;
1139
1140             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1141                           AFS_TRACE_LEVEL_VERBOSE,
1142                           "AFSCommonRead (%p) IRP_MN_COMPLETE being processed\n",
1143                           Irp));
1144
1145             CcMdlReadComplete(pIrpSp->FileObject, Irp->MdlAddress);
1146
1147             //
1148             // Mdl is now Deallocated
1149             //
1150
1151             Irp->MdlAddress = NULL;
1152
1153             try_return( ntStatus = STATUS_SUCCESS );
1154         }
1155
1156         //
1157         // If we get a non cached IO for a cached file we should do a purge.
1158         // For now we will just promote to cached
1159         //
1160         if (NULL != pFileObject->SectionObjectPointer->DataSectionObject && !bPagingIo)
1161         {
1162
1163             bNonCachedIo = FALSE;
1164         }
1165
1166         //
1167         // We acquire the main/paging resource first to synchronize
1168         // against size checks.
1169         //
1170
1171         if( bPagingIo)
1172         {
1173
1174             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1175                           AFS_TRACE_LEVEL_VERBOSE,
1176                           "AFSCommonRead Acquiring Fcb PagingIo lock %p SHARED %08lX\n",
1177                           &pFcb->NPFcb->PagingResource,
1178                           PsGetCurrentThread()));
1179
1180             AFSAcquireShared( &pFcb->NPFcb->PagingResource,
1181                               TRUE);
1182
1183             bReleasePaging = TRUE;
1184
1185             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1186                           AFS_TRACE_LEVEL_VERBOSE,
1187                           "AFSCommonRead Acquiring Fcb SectionObject lock %p SHARED %08lX\n",
1188                           &pFcb->NPFcb->SectionObjectResource,
1189                           PsGetCurrentThread()));
1190
1191             AFSAcquireShared( &pFcb->NPFcb->SectionObjectResource,
1192                               TRUE);
1193
1194             bReleaseSectionObject = TRUE;
1195
1196         }
1197         else
1198         {
1199
1200             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1201                           AFS_TRACE_LEVEL_VERBOSE,
1202                           "AFSCommonRead Acquiring Fcb SectionObject lock %p SHARED %08lX\n",
1203                           &pFcb->NPFcb->SectionObjectResource,
1204                           PsGetCurrentThread()));
1205
1206             AFSAcquireShared( &pFcb->NPFcb->SectionObjectResource,
1207                               TRUE);
1208
1209             bReleaseSectionObject = TRUE;
1210
1211             //
1212             // Check the BR locks
1213             //
1214
1215             if( !FsRtlCheckLockForReadAccess( &pFcb->Specific.File.FileLock,
1216                                               Irp))
1217             {
1218
1219                 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1220                               AFS_TRACE_LEVEL_ERROR,
1221                               "AFSCommonRead (%p) Request failed due to lock conflict\n",
1222                               Irp));
1223
1224                 try_return( ntStatus = STATUS_FILE_LOCK_CONFLICT);
1225             }
1226         }
1227
1228         if( BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED) ||
1229             BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
1230         {
1231
1232             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1233                           AFS_TRACE_LEVEL_ERROR,
1234                           "AFSCommonRead (%p) Request failed due to file deleted\n",
1235                           Irp));
1236
1237             try_return( ntStatus = STATUS_FILE_DELETED);
1238         }
1239
1240         //
1241         // If the read starts beyond End of File, return EOF.
1242         //
1243
1244         if( liStartingByte.QuadPart >= pFcb->Header.FileSize.QuadPart)
1245         {
1246
1247             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1248                           AFS_TRACE_LEVEL_VERBOSE,
1249                           "AFSCommonRead (%p) Request beyond EOF %I64X\n",
1250                           Irp,
1251                           pFcb->Header.FileSize.QuadPart));
1252
1253             try_return( ntStatus = STATUS_END_OF_FILE);
1254         }
1255
1256         //
1257         //
1258
1259         if( liStartingByte.QuadPart + ulByteCount > pFcb->Header.FileSize.QuadPart)
1260         {
1261
1262             ulByteCount = (ULONG)(pFcb->Header.FileSize.QuadPart - liStartingByte.QuadPart);
1263
1264             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1265                           AFS_TRACE_LEVEL_VERBOSE,
1266                           "AFSCommonRead (%p) Truncated read request to %08lX\n",
1267                           Irp,
1268                           ulByteCount));
1269         }
1270
1271         //
1272         // Is this Fcb valid???
1273         //
1274
1275         if( BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID))
1276         {
1277
1278             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1279                           AFS_TRACE_LEVEL_ERROR,
1280                           "AFSCommonRead (%p) Failing request due to INVALID fcb\n",
1281                           Irp));
1282
1283             Irp->IoStatus.Information = 0;
1284
1285             try_return( ntStatus = STATUS_FILE_DELETED);
1286         }
1287
1288         //
1289         // If this is an cached IO
1290         //
1291         if( (!bPagingIo && !bNonCachedIo))
1292         {
1293             //
1294             // This is a top level irp. Init the caching if it has not yet
1295             // been initialzed for this FO
1296             //
1297
1298             if( pFileObject->PrivateCacheMap == NULL)
1299             {
1300
1301                 __try
1302                 {
1303
1304                     AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1305                                   AFS_TRACE_LEVEL_VERBOSE,
1306                                   "AFSCommonRead Initialize caching on Fcb %p FO %p\n",
1307                                   pFcb,
1308                                   pFileObject));
1309
1310                     CcInitializeCacheMap( pFileObject,
1311                                           (PCC_FILE_SIZES)&pFcb->Header.AllocationSize,
1312                                           FALSE,
1313                                           AFSLibCacheManagerCallbacks,
1314                                           pFcb);
1315
1316                     CcSetReadAheadGranularity( pFileObject,
1317                                                pDeviceExt->Specific.RDR.MaximumRPCLength);
1318
1319                     CcSetDirtyPageThreshold( pFileObject,
1320                                              AFS_DIRTY_CHUNK_THRESHOLD * pDeviceExt->Specific.RDR.MaximumRPCLength / 4096);
1321                 }
1322                 __except( EXCEPTION_EXECUTE_HANDLER)
1323                 {
1324
1325                     ntStatus = GetExceptionCode();
1326
1327                     AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1328                                   AFS_TRACE_LEVEL_ERROR,
1329                                   "AFSCommonRead (%p) Exception thrown while initializing cache map Status %08lX\n",
1330                                   Irp,
1331                                   ntStatus));
1332                 }
1333
1334                 if( !NT_SUCCESS( ntStatus))
1335                 {
1336
1337                     try_return( ntStatus);
1338                 }
1339             }
1340
1341             //
1342             // And if this is MDL operation, deal with it now (yes we
1343             // could post, but we are almost certainly posted
1344             // already and we don't want to grow and SVA for it..)
1345             //
1346
1347             if( BooleanFlagOn( pIrpSp->MinorFunction, IRP_MN_MDL))
1348             {
1349                 __try
1350                 {
1351
1352                     CcMdlRead( pFileObject,
1353                                &liStartingByte,
1354                                ulByteCount,
1355                                &Irp->MdlAddress,
1356                                &Irp->IoStatus);
1357                     ntStatus = Irp->IoStatus.Status;
1358                 }
1359                 __except( EXCEPTION_EXECUTE_HANDLER)
1360                 {
1361                     ntStatus = GetExceptionCode();
1362
1363                     AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1364                                   AFS_TRACE_LEVEL_ERROR,
1365                                   "AFSCommonRead (%p) Exception thrown during mdl read Status %08lX\n",
1366                                   Irp,
1367                                   ntStatus));
1368                 }
1369
1370                 if( !NT_SUCCESS( ntStatus))
1371                 {
1372
1373                     AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1374                                   AFS_TRACE_LEVEL_ERROR,
1375                                   "AFSCommonRead (%p) Failed to process MDL read Status %08lX\n",
1376                                   Irp,
1377                                   ntStatus));
1378
1379                     try_return( ntStatus);
1380                 }
1381
1382                 //
1383                 // Update the CBO if this is a sync read
1384                 //
1385
1386                 if( BooleanFlagOn( pFileObject->Flags, FO_SYNCHRONOUS_IO))
1387                 {
1388
1389                     pFileObject->CurrentByteOffset.QuadPart = liStartingByte.QuadPart + ulByteCount;
1390                 }
1391
1392                 try_return( ntStatus);
1393             }
1394         }
1395
1396         //
1397         // The called request completes the IRP for us.
1398         //
1399
1400         bCompleteIrp = FALSE;
1401
1402         if( !bPagingIo &&
1403             !bNonCachedIo)
1404         {
1405
1406             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1407                           AFS_TRACE_LEVEL_VERBOSE,
1408                           "AFSCommonRead (%p) Processing CACHED request Offset %I64X Len %08lX\n",
1409                           Irp,
1410                           liStartingByte.QuadPart,
1411                           ulByteCount));
1412
1413             ntStatus = AFSCachedRead( DeviceObject, Irp, liStartingByte, ulByteCount);
1414         }
1415         else
1416         {
1417
1418             if( bReleasePaging)
1419             {
1420
1421                 AFSReleaseResource( &pFcb->NPFcb->PagingResource);
1422
1423                 bReleasePaging = FALSE;
1424             }
1425
1426             if( bReleaseSectionObject)
1427             {
1428
1429                 AFSReleaseResource( &pFcb->NPFcb->SectionObjectResource);
1430
1431                 bReleaseSectionObject = FALSE;
1432             }
1433
1434             if( bReleaseMain)
1435             {
1436
1437                 AFSReleaseResource( &pFcb->NPFcb->Resource);
1438
1439                 bReleaseMain = FALSE;
1440             }
1441
1442             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1443                           AFS_TRACE_LEVEL_VERBOSE,
1444                           "AFSCommonRead (%p) Processing NON-CACHED request Offset %I64X Len %08lX\n",
1445                           Irp,
1446                           liStartingByte.QuadPart,
1447                           ulByteCount));
1448
1449             if( BooleanFlagOn( pRDRDevExt->DeviceFlags, AFS_DEVICE_FLAG_DIRECT_SERVICE_IO))
1450             {
1451
1452                 ntStatus = AFSNonCachedReadDirect( DeviceObject, Irp,  liStartingByte);
1453             }
1454             else
1455             {
1456                 ntStatus = AFSNonCachedRead( DeviceObject, Irp,  liStartingByte);
1457             }
1458         }
1459
1460 try_exit:
1461
1462         AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1463                       AFS_TRACE_LEVEL_VERBOSE,
1464                       "AFSCommonRead (%p) Process complete Status %08lX\n",
1465                       Irp,
1466                       ntStatus));
1467
1468         if( bReleasePaging)
1469         {
1470
1471             AFSReleaseResource( &pFcb->NPFcb->PagingResource);
1472         }
1473
1474         if( bReleaseSectionObject)
1475         {
1476
1477             AFSReleaseResource( &pFcb->NPFcb->SectionObjectResource);
1478         }
1479
1480         if( bReleaseMain)
1481         {
1482
1483             AFSReleaseResource( &pFcb->NPFcb->Resource);
1484         }
1485
1486         if( bCompleteIrp)
1487         {
1488
1489             AFSCompleteRequest( Irp, ntStatus);
1490         }
1491
1492         ObDereferenceObject( pFileObject);
1493     }
1494
1495     return ntStatus;
1496 }
1497
1498 NTSTATUS
1499 AFSIOCtlRead( IN PDEVICE_OBJECT DeviceObject,
1500               IN PIRP Irp)
1501 {
1502
1503     UNREFERENCED_PARAMETER(DeviceObject);
1504     NTSTATUS ntStatus = STATUS_SUCCESS;
1505     AFSPIOCtlIORequestCB stIORequestCB;
1506     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1507     AFSFcb *pFcb = NULL;
1508     AFSCcb *pCcb = NULL;
1509     AFSPIOCtlIOResultCB stIOResultCB;
1510     ULONG ulBytesReturned = 0;
1511     AFSFileID   stParentFID;
1512
1513     __Enter
1514     {
1515
1516         RtlZeroMemory( &stIORequestCB,
1517                        sizeof( AFSPIOCtlIORequestCB));
1518
1519         if( pIrpSp->Parameters.Read.Length == 0)
1520         {
1521
1522             //
1523             // Nothing to do in this case
1524             //
1525
1526             try_return( ntStatus);
1527         }
1528
1529         pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
1530
1531         pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
1532
1533         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1534                       AFS_TRACE_LEVEL_VERBOSE,
1535                       "AFSIOCtlRead Acquiring Fcb lock %p SHARED %08lX\n",
1536                       &pFcb->NPFcb->Resource,
1537                       PsGetCurrentThread()));
1538
1539         AFSAcquireShared( &pFcb->NPFcb->Resource,
1540                           TRUE);
1541
1542         //
1543         // Get the parent fid to pass to the cm
1544         //
1545
1546         RtlZeroMemory( &stParentFID,
1547                        sizeof( AFSFileID));
1548
1549         if( BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
1550         {
1551
1552             //
1553             // The parent directory FID of the node
1554             //
1555
1556             stParentFID = pFcb->ObjectInformation->ParentFileId;
1557         }
1558
1559         //
1560         // Set the control block up
1561         //
1562
1563         stIORequestCB.RequestId = pCcb->RequestID;
1564
1565         if( pFcb->ObjectInformation->VolumeCB != NULL)
1566         {
1567             stIORequestCB.RootId = pFcb->ObjectInformation->VolumeCB->ObjectInformation.FileId;
1568         }
1569
1570         //
1571         // Lock down the buffer
1572         //
1573
1574         stIORequestCB.MappedBuffer = AFSMapToService( Irp,
1575                                                       pIrpSp->Parameters.Read.Length);
1576
1577         if( stIORequestCB.MappedBuffer == NULL)
1578         {
1579
1580             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1581         }
1582
1583         stIORequestCB.BufferLength = pIrpSp->Parameters.Read.Length;
1584
1585         stIOResultCB.BytesProcessed = 0;
1586
1587         ulBytesReturned = sizeof( AFSPIOCtlIOResultCB);
1588
1589         //
1590         // Issue the request to the service
1591         //
1592
1593         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIOCTL_READ,
1594                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
1595                                       &pCcb->AuthGroup,
1596                                       NULL,
1597                                       &stParentFID,
1598                                       NULL,
1599                                       0,
1600                                       (void *)&stIORequestCB,
1601                                       sizeof( AFSPIOCtlIORequestCB),
1602                                       &stIOResultCB,
1603                                       &ulBytesReturned);
1604
1605         if( !NT_SUCCESS( ntStatus))
1606         {
1607
1608             try_return( ntStatus);
1609         }
1610
1611         //
1612         // Update the length read
1613         //
1614
1615         Irp->IoStatus.Information = stIOResultCB.BytesProcessed;
1616
1617 try_exit:
1618
1619         if( stIORequestCB.MappedBuffer != NULL)
1620         {
1621
1622             AFSUnmapServiceMappedBuffer( stIORequestCB.MappedBuffer,
1623                                          Irp->MdlAddress);
1624         }
1625
1626         if( pFcb != NULL)
1627         {
1628
1629             AFSReleaseResource( &pFcb->NPFcb->Resource);
1630         }
1631     }
1632
1633     return ntStatus;
1634 }
1635
1636 NTSTATUS
1637 AFSShareRead( IN PDEVICE_OBJECT DeviceObject,
1638               IN PIRP Irp)
1639 {
1640
1641     UNREFERENCED_PARAMETER(DeviceObject);
1642     NTSTATUS ntStatus = STATUS_SUCCESS;
1643     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1644     AFSFcb *pFcb = NULL;
1645     AFSCcb *pCcb = NULL;
1646     ULONG ulBytesReturned = 0;
1647     void *pBuffer = NULL;
1648     AFSPipeIORequestCB stIoRequest;
1649
1650     __Enter
1651     {
1652
1653         pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
1654
1655         pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;
1656
1657         AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
1658                       AFS_TRACE_LEVEL_VERBOSE,
1659                       "AFSShareRead On pipe %wZ Length %08lX\n",
1660                       &pCcb->DirectoryCB->NameInformation.FileName,
1661                       pIrpSp->Parameters.Read.Length));
1662
1663         if( pIrpSp->Parameters.Read.Length == 0)
1664         {
1665
1666             //
1667             // Nothing to do in this case
1668             //
1669
1670             try_return( ntStatus);
1671         }
1672
1673         AFSAcquireShared( &pFcb->NPFcb->Resource,
1674                           TRUE);
1675
1676         //
1677         // Retrieve the buffer for the read request
1678         //
1679
1680         pBuffer = AFSLockSystemBuffer( Irp,
1681                                        pIrpSp->Parameters.Read.Length);
1682
1683         if( pBuffer == NULL)
1684         {
1685
1686             AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
1687                           AFS_TRACE_LEVEL_ERROR,
1688                           "AFSShareRead Failed to map buffer on pipe %wZ\n",
1689                           &pCcb->DirectoryCB->NameInformation.FileName));
1690
1691             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1692         }
1693
1694         RtlZeroMemory( &stIoRequest,
1695                        sizeof( AFSPipeIORequestCB));
1696
1697         stIoRequest.RequestId = pCcb->RequestID;
1698
1699         stIoRequest.RootId = pFcb->ObjectInformation->VolumeCB->ObjectInformation.FileId;
1700
1701         stIoRequest.BufferLength = pIrpSp->Parameters.Read.Length;
1702
1703         ulBytesReturned = pIrpSp->Parameters.Read.Length;
1704
1705         //
1706         // Issue the open request to the service
1707         //
1708
1709         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_READ,
1710                                       AFS_REQUEST_FLAG_SYNCHRONOUS,
1711                                       &pCcb->AuthGroup,
1712                                       &pCcb->DirectoryCB->NameInformation.FileName,
1713                                       NULL,
1714                                       NULL,
1715                                       0,
1716                                       (void *)&stIoRequest,
1717                                       sizeof( AFSPipeIORequestCB),
1718                                       pBuffer,
1719                                       &ulBytesReturned);
1720
1721         if( !NT_SUCCESS( ntStatus) &&
1722             ntStatus != STATUS_BUFFER_OVERFLOW)
1723         {
1724
1725             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1726                           AFS_TRACE_LEVEL_ERROR,
1727                           "AFSShareRead (%p) Failed service read Status %08lX\n",
1728                           Irp,
1729                           ntStatus));
1730
1731             try_return( ntStatus);
1732         }
1733
1734         AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
1735                       AFS_TRACE_LEVEL_VERBOSE,
1736                       "AFSShareRead Completed on pipe %wZ Length read %08lX Status %08lX\n",
1737                       &pCcb->DirectoryCB->NameInformation.FileName,
1738                       ulBytesReturned,
1739                       ntStatus));
1740
1741         Irp->IoStatus.Information = ulBytesReturned;
1742
1743 try_exit:
1744
1745         if( pFcb != NULL)
1746         {
1747
1748             AFSReleaseResource( &pFcb->NPFcb->Resource);
1749         }
1750     }
1751
1752     return ntStatus;
1753 }