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