2 * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3 * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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
14 * this list of conditions and the following disclaimer in the
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.
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.
36 // File: AFSCommSupport.cpp
38 #include "AFSCommon.h"
40 #define AFS_MAX_FCBS_TO_DROP 10
42 static AFSExtent *ExtentFor( PLIST_ENTRY le, ULONG SkipList );
43 static AFSExtent *NextExtent( AFSExtent *Extent, ULONG SkipList );
44 static ULONG ExtentsMasks[AFS_NUM_EXTENT_LISTS] = AFS_EXTENTS_MASKS;
45 static VOID VerifyExtentsLists(AFSFcb *Fcb);
46 static AFSExtent *DirtyExtentFor(PLIST_ENTRY le);
49 AFSEntryForOffset( IN AFSFcb *Fcb,
50 IN PLARGE_INTEGER Offset);
54 // Returns with Extents lock EX and no one using them.
58 AFSLockForExtentsTrim( IN AFSFcb *Fcb)
61 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
63 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
64 AFS_TRACE_LEVEL_VERBOSE,
65 "AFSLockForExtentsTrim Acuiring Fcb extents lock %08lX EXCL %08lX\n",
66 &pNPFcb->Specific.File.ExtentsResource,
67 PsGetCurrentThread());
69 AFSAcquireExcl( &pNPFcb->Specific.File.ExtentsResource, TRUE );
75 // return FALSE *or* with Extents lock EX and noone using them
78 AFSLockForExtentsTrimNoWait( IN AFSFcb *Fcb)
80 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
82 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
83 AFS_TRACE_LEVEL_VERBOSE,
84 "AFSLockForExtentsTrimNoWait Attempting to acquiring Fcb extent lock %08lX EXCL %08lX\n",
85 &pNPFcb->Specific.File.ExtentsResource,
86 PsGetCurrentThread());
88 if (!AFSAcquireExcl( &pNPFcb->Specific.File.ExtentsResource, FALSE ))
91 // Couldn't lock immediately
94 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
95 AFS_TRACE_LEVEL_VERBOSE,
96 "AFSLockForExtentsTrimNoWait Refused to wait for Fcb extent lock %08lX EXCL %08lX\n",
97 &pNPFcb->Specific.File.ExtentsResource,
98 PsGetCurrentThread());
106 // Pull all the extents away from the FCB.
109 AFSTearDownFcbExtents( IN AFSFcb *Fcb )
111 BOOLEAN bFoundExtents = FALSE;
112 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
115 ULONG ulCount = 0, ulReleaseCount = 0, ulProcessCount = 0;
117 AFSReleaseExtentsCB *pRelease = NULL;
118 BOOLEAN locked = FALSE;
120 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
126 // Ensure that no one is working with the extents and grab the
130 AFSLockForExtentsTrim( Fcb );
134 if (0 == Fcb->Specific.File.ExtentCount)
136 try_return ( ntStatus = STATUS_SUCCESS);
140 // Release a max of 100 extents at a time
143 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
145 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
147 AFS_EXTENT_RELEASE_TAG);
148 if (NULL == pRelease)
151 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
154 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
156 ulCount = Fcb->Specific.File.ExtentCount;
158 while( ulReleaseCount < ulCount)
161 bFoundExtents = TRUE;
163 RtlZeroMemory( pRelease,
164 sizeof( AFSReleaseExtentsCB ) +
165 (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB )));
167 if( ulCount - ulReleaseCount <= AFS_MAXIMUM_EXTENT_RELEASE_COUNT)
169 ulProcessCount = ulCount - ulReleaseCount;
173 ulProcessCount = AFS_MAXIMUM_EXTENT_RELEASE_COUNT;
176 pRelease->Flags = AFS_EXTENT_FLAG_RELEASE;
177 pRelease->ExtentCount = ulProcessCount;
180 // Update the metadata for this call
183 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
184 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
185 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
186 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
187 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
191 while (ulProcessCount < pRelease->ExtentCount)
193 pEntry = ExtentFor( le, AFS_EXTENTS_LIST );
195 pRelease->FileExtents[ulProcessCount].Flags = AFS_EXTENT_FLAG_RELEASE;
198 RtlCopyMemory( pRelease->FileExtents[ulProcessCount].MD5,
200 sizeof(pEntry->MD5));
202 pRelease->FileExtents[ulProcessCount].Flags |= AFS_EXTENT_FLAG_MD5_SET;
205 if( BooleanFlagOn( pEntry->Flags, AFS_EXTENT_DIRTY))
208 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
211 if( BooleanFlagOn( pEntry->Flags, AFS_EXTENT_DIRTY))
216 AFSRemoveEntryDirtyList( Fcb,
219 pRelease->FileExtents[ulProcessCount].Flags |= AFS_EXTENT_FLAG_DIRTY;
221 dirtyCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
223 ASSERT( dirtyCount >= 0);
226 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
229 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
230 AFS_TRACE_LEVEL_VERBOSE,
231 "AFSTearDownFcbExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %08lX-%08lX Len %08lX\n",
233 Fcb->ObjectInformation->FileId.Cell,
234 Fcb->ObjectInformation->FileId.Volume,
235 Fcb->ObjectInformation->FileId.Vnode,
236 Fcb->ObjectInformation->FileId.Unique,
237 pEntry->FileOffset.HighPart,
238 pEntry->FileOffset.LowPart,
241 pRelease->FileExtents[ulProcessCount].Length = pEntry->Size;
242 pRelease->FileExtents[ulProcessCount].DirtyLength = pEntry->Size;
243 pRelease->FileExtents[ulProcessCount].DirtyOffset = 0;
244 pRelease->FileExtents[ulProcessCount].CacheOffset = pEntry->CacheOffset;
245 pRelease->FileExtents[ulProcessCount].FileOffset = pEntry->FileOffset;
247 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pEntry->Size/1024)));
249 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pEntry->Size/1024)));
251 ASSERT( pEntry->ActiveCount == 0);
255 AFSExFreePool( pEntry);
257 InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
259 if( InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount) == 0)
262 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
269 // Send the request down. We cannot send this down
270 // asynchronously - if we did that we could request them
271 // back before the service got this request and then this
272 // request would be a corruption.
275 sz = sizeof( AFSReleaseExtentsCB ) + (ulProcessCount * sizeof ( AFSFileExtentCB ));
277 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
278 AFS_REQUEST_FLAG_SYNCHRONOUS,
281 &Fcb->ObjectInformation->FileId,
287 if( !NT_SUCCESS(ntStatus))
291 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
292 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
295 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
296 AFS_TRACE_LEVEL_ERROR,
297 "AFSTearDownFcbExtents AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
298 Fcb->ObjectInformation->FileId.Cell,
299 Fcb->ObjectInformation->FileId.Volume,
300 Fcb->ObjectInformation->FileId.Vnode,
301 Fcb->ObjectInformation->FileId.Unique,
306 ulReleaseCount += ulProcessCount;
310 // Reinitialize the skip lists
313 ASSERT( Fcb->Specific.File.ExtentCount == 0);
315 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i++)
317 InitializeListHead(&Fcb->Specific.File.ExtentsLists[i]);
321 // Reinitialize the dirty list as well
324 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
327 ASSERT( Fcb->Specific.File.ExtentsDirtyCount == 0);
329 Fcb->NPFcb->Specific.File.DirtyListHead = NULL;
330 Fcb->NPFcb->Specific.File.DirtyListTail = NULL;
332 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
334 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
341 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
342 AFS_TRACE_LEVEL_VERBOSE,
343 "AFSTearDownFcbExtents Releasing Fcb extent lock %08lX thread %08lX\n",
344 &Fcb->NPFcb->Specific.File.ExtentsResource,
345 PsGetCurrentThread());
347 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
351 AFSExFreePool( pRelease);
355 return bFoundExtents;
359 ExtentForOffsetInList( IN AFSFcb *Fcb,
362 IN PLARGE_INTEGER Offset)
365 // Return the extent that maps the offset, that
366 // - Contains the offset
367 // - or is immediately ahead of the offset (in this list)
368 // - otherwise return NULL.
371 PLIST_ENTRY pLe = List;
372 AFSExtent *pPrevious = NULL;
374 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
376 while (pLe != &Fcb->Specific.File.ExtentsLists[ListNumber])
380 entry = ExtentFor( pLe, ListNumber );
387 if (Offset->QuadPart < entry->FileOffset.QuadPart)
390 // Offset is ahead of entry. Return previous
395 if (Offset->QuadPart >= (entry->FileOffset.QuadPart + entry->Size))
398 // We start after this extent - carry on round
406 // Otherwise its a match
413 // Got to the end. Return Previous
419 AFSExtentContains( IN AFSExtent *Extent, IN PLARGE_INTEGER Offset)
425 return (Extent->FileOffset.QuadPart <= Offset->QuadPart &&
426 (Extent->FileOffset.QuadPart + Extent->Size) > Offset->QuadPart);
431 // Return the extent that contains the offset
434 AFSExtentForOffsetHint( IN AFSFcb *Fcb,
435 IN PLARGE_INTEGER Offset,
436 IN BOOLEAN ReturnPrevious,
439 AFSExtent *pPrevious = Hint;
443 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
445 #if AFS_VALIDATE_EXTENTS
446 VerifyExtentsLists(Fcb);
450 // So we will go across the skip lists until we find an
451 // appropriate entry (previous or direct match). If it's a match
452 // we are done, other wise we start on the next layer down
454 for (i = AFS_NUM_EXTENT_LISTS-1; i >= AFS_EXTENTS_LIST; i--)
456 if (NULL == pPrevious)
459 // We haven't found anything in the previous layers
461 pLe = Fcb->Specific.File.ExtentsLists[i].Flink;
463 else if (NULL == pPrevious->Lists[i].Flink)
465 ASSERT(AFS_EXTENTS_LIST != i);
467 // The hint doesn't exist at this level, next one down
474 // take the previous into the next
476 pLe = &pPrevious->Lists[i];
479 pPrevious = ExtentForOffsetInList( Fcb, pLe, i, Offset);
481 if (NULL != pPrevious && AFSExtentContains(pPrevious, Offset))
484 // Found it immediately. Stop here
490 if (NULL == pPrevious || ReturnPrevious )
495 ASSERT( !AFSExtentContains(pPrevious, Offset) );
501 AFSEntryForOffset( IN AFSFcb *Fcb,
502 IN PLARGE_INTEGER Offset)
504 AFSExtent *pPrevious = NULL;
508 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
510 #if AFS_VALIDATE_EXTENTS
511 VerifyExtentsLists(Fcb);
515 // So we will go across the skip lists until we find an
516 // appropriate entry (previous or direct match). If it's a match
517 // we are done, other wise we start on the next layer down
519 for (i = AFS_NUM_EXTENT_LISTS-1; i >= AFS_EXTENTS_LIST; i--)
521 if (NULL == pPrevious)
524 // We haven't found anything in the previous layers
526 pLe = Fcb->Specific.File.ExtentsLists[i].Flink;
528 else if (NULL == pPrevious->Lists[i].Flink)
530 ASSERT(AFS_EXTENTS_LIST != i);
532 // The hint doesn't exist at this level, next one down
539 // take the previous into the next
541 pLe = &pPrevious->Lists[i];
544 pPrevious = ExtentForOffsetInList( Fcb, pLe, i, Offset);
546 if (NULL != pPrevious && AFSExtentContains(pPrevious, Offset))
549 // Found it immediately. Stop here
559 AFSExtentForOffset( IN AFSFcb *Fcb,
560 IN PLARGE_INTEGER Offset,
561 IN BOOLEAN ReturnPrevious)
563 return AFSExtentForOffsetHint(Fcb, Offset, ReturnPrevious, NULL);
567 BOOLEAN AFSDoExtentsMapRegion(IN AFSFcb *Fcb,
568 IN PLARGE_INTEGER Offset,
570 IN OUT AFSExtent **FirstExtent,
571 OUT AFSExtent **LastExtent)
574 // Return TRUE region is completely mapped. FALSE
575 // otherwise. If the region isn't mapped then the last
576 // extent to map part of the region is returned.
578 // *LastExtent as input is where to start looking.
579 // *LastExtent as output is either the extent which
580 // contains the Offset, or the last one which doesn't
584 BOOLEAN retVal = FALSE;
589 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
590 AFS_TRACE_LEVEL_VERBOSE,
591 "AFSDoExtentsMapRegion Acquiring Fcb extent lock %08lX SHARED %08lX\n",
592 &Fcb->NPFcb->Specific.File.ExtentsResource,
593 PsGetCurrentThread());
595 AFSAcquireShared( &Fcb->NPFcb->Specific.File.ExtentsResource, TRUE );
597 entry = AFSExtentForOffsetHint(Fcb, Offset, TRUE, *FirstExtent);
598 *FirstExtent = entry;
600 if (NULL == entry || !AFSExtentContains(entry, Offset))
602 try_return (retVal = FALSE);
605 ASSERT(Offset->QuadPart >= entry->FileOffset.QuadPart);
609 if ((entry->FileOffset.QuadPart + entry->Size) >=
610 (Offset->QuadPart + Size))
613 // The end is inside the extent
615 try_return (retVal = TRUE);
618 if (entry->Lists[AFS_EXTENTS_LIST].Flink == &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
621 // Run out of extents
623 try_return (retVal = FALSE);
626 newEntry = NextExtent( entry, AFS_EXTENTS_LIST );
628 if (newEntry->FileOffset.QuadPart !=
629 (entry->FileOffset.QuadPart + entry->Size))
634 try_return (retVal = FALSE);
642 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
643 AFS_TRACE_LEVEL_VERBOSE,
644 "AFSDoExtentsMapRegion Releasing Fcb extent lock %08lX SHARED %08lX\n",
645 &Fcb->NPFcb->Specific.File.ExtentsResource,
646 PsGetCurrentThread());
648 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
657 // Given an FCB and an Offset we look to see whether there extents to
658 // Map them all. If there are then we return TRUE to fullymapped
659 // and *FirstExtent points to the first extent to map the extent.
660 // If not then we return FALSE, but we request the extents to be mapped.
661 // Further *FirstExtent (if non null) is the last extent which doesn't
664 // Finally on the way *in* if *FirstExtent is non null it is where we start looking
668 AFSRequestExtents( IN AFSFcb *Fcb,
669 IN PLARGE_INTEGER Offset,
671 OUT BOOLEAN *FullyMapped)
674 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
675 NTSTATUS ntStatus = STATUS_SUCCESS;
677 AFSRequestExtentsCB request;
678 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
679 AFSExtent *pFirstExtent;
680 LARGE_INTEGER liAlignedOffset;
681 ULONG ulAlignedLength = 0;
682 LARGE_INTEGER liTimeOut;
685 // Check our extents, then fire off a request if we need to.
686 // We start off knowing nothing about where we will go.
691 *FullyMapped = AFSDoExtentsMapRegion( Fcb, Offset, Size, &pFirstExtent, &pExtent );
696 ASSERT(AFSExtentContains(pFirstExtent, Offset));
697 LARGE_INTEGER end = *Offset;
698 end.QuadPart += (Size-1);
699 ASSERT(AFSExtentContains(pExtent, &end));
701 return STATUS_SUCCESS;
705 // So we need to queue a request. Since we will be clearing the
706 // ExtentsRequestComplete event we need to do with with the lock
710 liTimeOut.QuadPart = -(50000000);
714 if (!NT_SUCCESS( pNPFcb->Specific.File.ExtentsRequestStatus))
718 // If this isn't the same process which caused the failure then try to request them again
721 if( Fcb->Specific.File.ExtentRequestProcessId == (ULONGLONG)PsGetCurrentProcessId())
723 ntStatus = pNPFcb->Specific.File.ExtentsRequestStatus;
728 pNPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
731 ntStatus = KeWaitForSingleObject( &pNPFcb->Specific.File.ExtentsRequestComplete,
736 if (!NT_SUCCESS(ntStatus))
747 // Lock resource EX and look again
750 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
751 AFS_TRACE_LEVEL_VERBOSE,
752 "AFSRequestExtents Acquiring Fcb extent lock %08lX EXCL %08lX\n",
753 &pNPFcb->Specific.File.ExtentsResource,
754 PsGetCurrentThread());
756 AFSAcquireExcl( &pNPFcb->Specific.File.ExtentsResource, TRUE );
758 if (!NT_SUCCESS( pNPFcb->Specific.File.ExtentsRequestStatus))
762 // If this isn't the same process which caused the failure then try to request them again
765 if( Fcb->Specific.File.ExtentRequestProcessId == (ULONGLONG)PsGetCurrentProcessId())
767 ntStatus = pNPFcb->Specific.File.ExtentsRequestStatus;
769 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
770 AFS_TRACE_LEVEL_VERBOSE,
771 "AFSRequestExtents Releasing Fcb extent lock %08lX EXCL %08lX\n",
772 &pNPFcb->Specific.File.ExtentsResource,
773 PsGetCurrentThread());
775 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
780 pNPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
783 if( KeReadStateEvent( &pNPFcb->Specific.File.ExtentsRequestComplete) ||
784 ntStatus == STATUS_TIMEOUT)
787 ntStatus = pNPFcb->Specific.File.ExtentsRequestStatus;
789 if( !NT_SUCCESS( ntStatus))
793 // If this isn't the same process which caused the failure then try to request them again
796 if( Fcb->Specific.File.ExtentRequestProcessId == (ULONGLONG)PsGetCurrentProcessId())
798 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
799 AFS_TRACE_LEVEL_VERBOSE,
800 "AFSRequestExtents Releasing Fcb extent lock %08lX EXCL %08lX\n",
801 &pNPFcb->Specific.File.ExtentsResource,
802 PsGetCurrentThread());
804 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
809 pNPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
811 ntStatus = STATUS_SUCCESS;
818 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
819 AFS_TRACE_LEVEL_VERBOSE,
820 "AFSRequestExtents Releasing Fcb extent lock %08lX EXCL %08lX\n",
821 &pNPFcb->Specific.File.ExtentsResource,
822 PsGetCurrentThread());
824 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
827 if (!NT_SUCCESS(ntStatus))
836 // We have the lock Ex and there is no filling going on.
837 // Check again to see whether things have moved since we last
838 // checked. Since we haven't locked against pinning, we will
844 *FullyMapped = AFSDoExtentsMapRegion(Fcb, Offset, Size, &pFirstExtent, &pExtent);
849 ASSERT(AFSExtentContains(pFirstExtent, Offset));
850 LARGE_INTEGER end = *Offset;
851 end.QuadPart += (Size-1);
852 ASSERT(AFSExtentContains(pExtent, &end));
854 try_return (ntStatus = STATUS_SUCCESS);
857 RtlZeroMemory( &request,
858 sizeof( AFSRequestExtentsCB));
864 ulAlignedLength = Size;
866 liAlignedOffset = *Offset;
868 if( liAlignedOffset.QuadPart % pDevExt->Specific.RDR.CacheBlockSize != 0)
871 liAlignedOffset.QuadPart = (ULONGLONG)( (ULONGLONG)(liAlignedOffset.QuadPart / pDevExt->Specific.RDR.CacheBlockSize) * (ULONGLONG)pDevExt->Specific.RDR.CacheBlockSize);
873 ulAlignedLength += (ULONG)(Offset->QuadPart - liAlignedOffset.QuadPart);
876 if( ulAlignedLength % pDevExt->Specific.RDR.CacheBlockSize != 0)
879 ulAlignedLength = (ULONG)(((ulAlignedLength / pDevExt->Specific.RDR.CacheBlockSize) + 1) * pDevExt->Specific.RDR.CacheBlockSize);
882 request.ByteOffset = liAlignedOffset;
883 request.Length = ulAlignedLength;
885 if( !AFSIsExtentRequestQueued( &Fcb->ObjectInformation->FileId,
890 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
891 AFS_TRACE_LEVEL_VERBOSE,
892 "AFSRequestExtents Request extents for fid %08lX-%08lX-%08lX-%08lX Offset %08lX Len %08lX Thread %08lX\n",
893 Fcb->ObjectInformation->FileId.Cell,
894 Fcb->ObjectInformation->FileId.Volume,
895 Fcb->ObjectInformation->FileId.Vnode,
896 Fcb->ObjectInformation->FileId.Unique,
897 request.ByteOffset.LowPart,
899 PsGetCurrentThread());
901 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS,
905 &Fcb->ObjectInformation->FileId,
907 sizeof( AFSRequestExtentsCB ),
911 if( NT_SUCCESS( ntStatus))
913 KeClearEvent( &pNPFcb->Specific.File.ExtentsRequestComplete );
919 KeClearEvent( &pNPFcb->Specific.File.ExtentsRequestComplete );
924 if (NT_SUCCESS( ntStatus ))
926 KeQueryTickCount( &Fcb->Specific.File.LastExtentAccess );
929 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
930 AFS_TRACE_LEVEL_VERBOSE,
931 "AFSRequestExtents Releasing Fcb extent lock %08lX EXCL %08lX\n",
932 &pNPFcb->Specific.File.ExtentsResource,
933 PsGetCurrentThread());
935 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
942 AFSRequestExtentsAsync( IN AFSFcb *Fcb,
943 IN PLARGE_INTEGER Offset,
947 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
948 NTSTATUS ntStatus = STATUS_SUCCESS;
949 AFSExtent *pExtent = NULL;
950 AFSRequestExtentsCB request;
951 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
952 AFSExtent *pFirstExtent = NULL;
953 LARGE_INTEGER liAlignedOffset;
954 ULONG ulAlignedLength = 0;
955 BOOLEAN bRegionMapped = FALSE;
960 ASSERT( !ExIsResourceAcquiredLite( &pNPFcb->Specific.File.ExtentsResource ));
963 // If the service set a failure on the file since the last
964 // CreateFile was issued, return it now.
967 if (!NT_SUCCESS( pNPFcb->Specific.File.ExtentsRequestStatus))
971 // If this isn't the same process which caused the failure then try to request them again
974 if( Fcb->Specific.File.ExtentRequestProcessId == (ULONGLONG)PsGetCurrentProcessId())
976 try_return( ntStatus = pNPFcb->Specific.File.ExtentsRequestStatus);
979 pNPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
983 // Check if we are already mapped
986 bRegionMapped = AFSDoExtentsMapRegion( Fcb, Offset, Size, &pFirstExtent, &pExtent);
991 try_return( ntStatus = STATUS_SUCCESS);
995 // Align our request on extent size boundary
998 ulAlignedLength = Size;
1000 liAlignedOffset = *Offset;
1002 if( liAlignedOffset.QuadPart % pDevExt->Specific.RDR.CacheBlockSize != 0)
1005 liAlignedOffset.QuadPart = (ULONGLONG)( (ULONGLONG)(liAlignedOffset.QuadPart / pDevExt->Specific.RDR.CacheBlockSize) * (ULONGLONG)pDevExt->Specific.RDR.CacheBlockSize);
1007 ulAlignedLength += (ULONG)(Offset->QuadPart - liAlignedOffset.QuadPart);
1010 if( ulAlignedLength % pDevExt->Specific.RDR.CacheBlockSize != 0)
1013 ulAlignedLength = (ULONG)(((ulAlignedLength / pDevExt->Specific.RDR.CacheBlockSize) + 1) * pDevExt->Specific.RDR.CacheBlockSize);
1016 RtlZeroMemory( &request,
1017 sizeof( AFSRequestExtentsCB));
1019 request.ByteOffset = liAlignedOffset;
1020 request.Length = ulAlignedLength;
1022 if( !AFSIsExtentRequestQueued( &Fcb->ObjectInformation->FileId,
1023 &request.ByteOffset,
1027 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1028 AFS_TRACE_LEVEL_VERBOSE,
1029 "AFSRequestExtentsAsync Request extents for fid %08lX-%08lX-%08lX-%08lX Offset %08lX Len %08lX Thread %08lX\n",
1030 Fcb->ObjectInformation->FileId.Cell,
1031 Fcb->ObjectInformation->FileId.Volume,
1032 Fcb->ObjectInformation->FileId.Vnode,
1033 Fcb->ObjectInformation->FileId.Unique,
1034 request.ByteOffset.LowPart,
1036 PsGetCurrentThread());
1038 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS,
1042 &Fcb->ObjectInformation->FileId,
1044 sizeof( AFSRequestExtentsCB ),
1048 if( NT_SUCCESS( ntStatus))
1051 KeClearEvent( &pNPFcb->Specific.File.ExtentsRequestComplete );
1057 KeClearEvent( &pNPFcb->Specific.File.ExtentsRequestComplete );
1069 AFSProcessExtentsResult( IN AFSFcb *Fcb,
1071 IN AFSFileExtentCB *Result)
1073 NTSTATUS ntStatus = STATUS_SUCCESS;
1074 AFSFileExtentCB *pFileExtents = Result;
1077 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
1078 ULONG fileExtentsUsed = 0;
1079 BOOLEAN bFoundExtent = FALSE;
1080 LIST_ENTRY *pSkipEntries[AFS_NUM_EXTENT_LISTS] = { 0 };
1081 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1084 // Grab the extents exclusive for the duration
1087 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1088 AFS_TRACE_LEVEL_VERBOSE,
1089 "AFSProcessExtentsResult Acquiring Fcb extent lock %08lX EXCL %08lX\n",
1090 &pNPFcb->Specific.File.ExtentsResource,
1091 PsGetCurrentThread());
1093 AFSAcquireExcl( &pNPFcb->Specific.File.ExtentsResource, TRUE );
1099 // Find where to put the extents
1101 for (ULONG i = AFS_EXTENTS_LIST; i < AFS_NUM_EXTENT_LISTS; i++)
1104 pSkipEntries[i] = Fcb->Specific.File.ExtentsLists[i].Flink;
1107 le = pSkipEntries[AFS_EXTENTS_LIST];
1109 if (le == &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
1112 // No extents. Insert at head of list (which is where the skip lists point!)
1116 else if (0 != pFileExtents->FileOffset.QuadPart)
1119 // We want to find the best extents immediately *behind* this offset
1121 LARGE_INTEGER offset = pFileExtents->FileOffset;
1124 // Ask in the top skip list first, then work down
1126 for (LONG i = AFS_NUM_EXTENT_LISTS-1; i >= AFS_EXTENTS_LIST; i--)
1128 pExtent = ExtentForOffsetInList( Fcb,
1133 if (NULL == pExtent)
1136 // No dice. Header has to become the head of the list
1138 pSkipEntries[i] = &Fcb->Specific.File.ExtentsLists[i];
1140 // And as a loop invariant we should never have found an extent
1142 ASSERT(!bFoundExtent);
1147 // pExtent is where to start to insert at this level
1149 pSkipEntries[i] = &pExtent->Lists[i];
1152 // And also where to start to look at the next level
1155 if (i > AFS_EXTENTS_LIST)
1157 pSkipEntries[i-1] = &pExtent->Lists[i-1];
1159 bFoundExtent = TRUE;
1163 if (NULL == pExtent)
1165 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
1170 le = pExtent->Lists[AFS_EXTENTS_LIST].Blink;
1176 // Looking at offset 0, so we must start at the beginning
1179 pExtent = ExtentFor(le, AFS_EXTENTS_LIST);
1183 // And set up the skip lists
1186 for (ULONG i = AFS_EXTENTS_LIST; i < AFS_NUM_EXTENT_LISTS; i++)
1188 pSkipEntries[i] = &Fcb->Specific.File.ExtentsLists[i];
1192 while (fileExtentsUsed < Count)
1196 // Loop invariant - le points to where to insert after and
1197 // pExtent points to le->fLink
1200 ASSERT (NULL == pExtent ||
1201 le->Flink == &pExtent->Lists[AFS_EXTENTS_LIST]);
1203 if (NULL == pExtent ||
1204 pExtent->FileOffset.QuadPart > pFileExtents->FileOffset.QuadPart)
1207 // We need to insert a new extent at le. Start with
1208 // some sanity check on spanning
1210 if (NULL != pExtent &&
1211 ((pFileExtents->FileOffset.QuadPart + pFileExtents->Length) >
1212 pExtent->FileOffset.QuadPart))
1215 // File Extents overlaps pExtent
1217 ASSERT( (pFileExtents->FileOffset.QuadPart + pFileExtents->Length) <=
1218 pExtent->FileOffset.QuadPart);
1220 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1224 // File offset is entirely in front of this extent. Create
1225 // a new one (remember le is the previous list entry)
1227 pExtent = (AFSExtent *) AFSExAllocatePoolWithTag( NonPagedPool,
1230 if (NULL == pExtent)
1235 try_return (ntStatus = STATUS_INSUFFICIENT_RESOURCES );
1238 RtlZeroMemory( pExtent, sizeof( AFSExtent ));
1240 pExtent->FileOffset = pFileExtents->FileOffset;
1241 pExtent->CacheOffset = pFileExtents->CacheOffset;
1242 pExtent->Size = pFileExtents->Length;
1244 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1245 AFS_TRACE_LEVEL_VERBOSE,
1246 "AFSProcessExtentsResult Received extent for fid %08lX-%08lX-%08lX-%08lX File Offset %I64X Cache Offset %I64X Len %08lX\n",
1247 Fcb->ObjectInformation->FileId.Cell,
1248 Fcb->ObjectInformation->FileId.Volume,
1249 Fcb->ObjectInformation->FileId.Vnode,
1250 Fcb->ObjectInformation->FileId.Unique,
1251 pFileExtents->FileOffset.QuadPart,
1252 pFileExtents->CacheOffset.QuadPart,
1253 pFileExtents->Length);
1255 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, (LONG)(pExtent->Size/1024));
1257 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, (LONG)(pExtent->Size/1024));
1259 InterlockedIncrement( &Fcb->Specific.File.ExtentCount);
1261 if( InterlockedIncrement( &pControlDevExt->Specific.Control.ExtentCount) == 1)
1264 KeClearEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent);
1270 InsertHeadList(le, &pExtent->Lists[AFS_EXTENTS_LIST]);
1271 ASSERT(le->Flink == &pExtent->Lists[AFS_EXTENTS_LIST]);
1272 ASSERT(0 == (pExtent->FileOffset.LowPart & ExtentsMasks[AFS_EXTENTS_LIST]));
1275 // Do not move the cursor - we will do it next time
1279 // And into the (upper) skip lists - Again, do not move the cursor
1281 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1283 if (0 == (pExtent->FileOffset.LowPart & ExtentsMasks[i]))
1285 InsertHeadList(pSkipEntries[i], &pExtent->Lists[i]);
1286 #if AFS_VALIDATE_EXTENTS
1287 VerifyExtentsLists(Fcb);
1292 else if (pExtent->FileOffset.QuadPart == pFileExtents->FileOffset.QuadPart)
1295 if (pExtent->Size != pFileExtents->Length)
1298 ASSERT (pExtent->Size == pFileExtents->Length);
1300 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1304 // Move both cursors forward.
1306 // First the extent pointer
1309 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1312 // Then the skip lists cursors forward if needed
1314 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1316 if (0 == (pExtent->FileOffset.LowPart & ExtentsMasks[i]))
1319 // Check sanity before
1321 #if AFS_VALIDATE_EXTENTS
1322 VerifyExtentsLists(Fcb);
1326 // Skip list should point to us
1328 //ASSERT(pSkipEntries[i] == &pExtent->Lists[i]);
1330 // Move forward cursor
1332 pSkipEntries[i] = pSkipEntries[i]->Flink;
1334 // Check sanity before
1336 #if AFS_VALIDATE_EXTENTS
1337 VerifyExtentsLists(Fcb);
1343 // And then the cursor in the supplied array
1349 // setup pExtent if there is one
1351 if (le->Flink != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
1353 pExtent = NextExtent( pExtent, AFS_EXTENTS_LIST ) ;
1363 ASSERT( pExtent->FileOffset.QuadPart < pFileExtents->FileOffset.QuadPart );
1366 // Sanity check on spanning
1368 if ((pExtent->FileOffset.QuadPart + pExtent->Size) >
1369 pFileExtents->FileOffset.QuadPart)
1372 ASSERT( (pExtent->FileOffset.QuadPart + pExtent->Size) <=
1373 pFileExtents->FileOffset.QuadPart);
1375 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1379 // Move le and pExtent forward
1381 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1385 // Then the check the skip lists cursors
1387 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1389 if (0 == (pFileExtents->FileOffset.LowPart & ExtentsMasks[i]))
1393 // - empty list (pSkipEntries[i]->Flink == pSkipEntries[i]->Flink == fcb->lists[i]
1394 // - We are the last on the list (pSkipEntries[i]->Flink == fcb->lists[i])
1395 // - We are not the last on the list. In that case we have to be strictly less than
1397 if (pSkipEntries[i]->Flink != &Fcb->Specific.File.ExtentsLists[i]) {
1399 AFSExtent *otherExtent = ExtentFor(pSkipEntries[i]->Flink, i);
1400 ASSERT(pFileExtents->FileOffset.QuadPart < otherExtent->FileOffset.QuadPart);
1407 // setup pExtent if there is one
1410 if (le->Flink != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
1412 pExtent = NextExtent( pExtent, AFS_EXTENTS_LIST ) ;
1422 // All done, signal that we are done drop the lock, exit
1427 if( !NT_SUCCESS( ntStatus))
1431 // If we failed the service is going to drop all extents so trim away the
1435 AFSTrimSpecifiedExtents( Fcb,
1440 #if AFS_VALIDATE_EXTENTS
1441 VerifyExtentsLists(Fcb);
1444 KeSetEvent( &pNPFcb->Specific.File.ExtentsRequestComplete,
1448 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1449 AFS_TRACE_LEVEL_VERBOSE,
1450 "AFSProcessExtentsResult Releasing Fcb extent lock %08lX EXCL %08lX\n",
1451 &pNPFcb->Specific.File.ExtentsResource,
1452 PsGetCurrentThread());
1454 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
1461 AFSProcessSetFileExtents( IN AFSSetFileExtentsCB *SetExtents )
1463 AFSFcb *pFcb = NULL;
1464 AFSVolumeCB *pVolumeCB = NULL;
1465 NTSTATUS ntStatus = STATUS_SUCCESS;
1466 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1467 ULONGLONG ullIndex = 0;
1468 AFSObjectInfoCB *pObjectInfo = NULL;
1473 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1474 AFS_TRACE_LEVEL_VERBOSE,
1475 "AFSProcessSetFileExtents Acquiring RDR VolumeTreeLock lock %08lX SHARED %08lX\n",
1476 &pDevExt->Specific.RDR.VolumeTreeLock,
1477 PsGetCurrentThread());
1479 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
1481 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1482 AFS_TRACE_LEVEL_VERBOSE,
1483 "AFSProcessSetFileExtents Set extents for fid %08lX-%08lX-%08lX-%08lX\n",
1484 SetExtents->FileId.Cell,
1485 SetExtents->FileId.Volume,
1486 SetExtents->FileId.Vnode,
1487 SetExtents->FileId.Unique);
1490 // Locate the volume node
1493 ullIndex = AFSCreateHighIndex( &SetExtents->FileId);
1495 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
1497 (AFSBTreeEntry **)&pVolumeCB);
1499 if( pVolumeCB != NULL)
1502 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1503 AFS_TRACE_LEVEL_VERBOSE,
1504 "AFSProcessSetFileExtents Acquiring VolumeRoot FileIDTree.TreeLock lock %08lX SHARED %08lX\n",
1505 pVolumeCB->ObjectInfoTree.TreeLock,
1506 PsGetCurrentThread());
1508 InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1511 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
1513 if( !NT_SUCCESS( ntStatus) ||
1517 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1518 AFS_TRACE_LEVEL_ERROR,
1519 "AFSProcessSetFileExtents Set extents for fid %08lX-%08lX-%08lX-%08lX Failed to locate volume Status %08lX\n",
1520 SetExtents->FileId.Cell,
1521 SetExtents->FileId.Volume,
1522 SetExtents->FileId.Vnode,
1523 SetExtents->FileId.Unique,
1526 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1529 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1532 InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1535 // Now locate the Object in this volume
1538 ullIndex = AFSCreateLowIndex( &SetExtents->FileId);
1540 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
1542 (AFSBTreeEntry **)&pObjectInfo);
1544 if( pObjectInfo != NULL)
1548 // Reference the node so it won't be torn down
1551 InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
1553 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1554 AFS_TRACE_LEVEL_VERBOSE,
1555 "AFSProcessSetFileExtents Increment count on object %08lX Cnt %d\n",
1557 pObjectInfo->ObjectReferenceCount);
1560 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1562 if( !NT_SUCCESS( ntStatus) ||
1563 pObjectInfo == NULL)
1566 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1567 AFS_TRACE_LEVEL_ERROR,
1568 "AFSProcessSetFileExtents Set extents for hash %I64X fid %08lX-%08lX-%08lX-%08lX Failed to locate file in volume %08lX\n",
1570 SetExtents->FileId.Cell,
1571 SetExtents->FileId.Volume,
1572 SetExtents->FileId.Vnode,
1573 SetExtents->FileId.Unique,
1576 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1579 pFcb = pObjectInfo->Fcb;
1582 // If we have a result failure then don't bother trying to set the extents
1585 if( SetExtents->ResultStatus != STATUS_SUCCESS)
1588 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1589 AFS_TRACE_LEVEL_ERROR,
1590 "AFSProcessSetFileExtents Set extents failure fid %08lX-%08lX-%08lX-%08lX ResultStatus %08lX\n",
1591 SetExtents->FileId.Cell,
1592 SetExtents->FileId.Volume,
1593 SetExtents->FileId.Vnode,
1594 SetExtents->FileId.Unique,
1595 SetExtents->ResultStatus);
1597 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1598 AFS_TRACE_LEVEL_VERBOSE,
1599 "AFSProcessSetFileExtents Acquiring Fcb extents lock %08lX EXCL %08lX\n",
1600 &pFcb->NPFcb->Specific.File.ExtentsResource,
1601 PsGetCurrentThread());
1603 AFSAcquireExcl( &pFcb->NPFcb->Specific.File.ExtentsResource,
1606 pFcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_CANCELLED;
1608 KeSetEvent( &pFcb->NPFcb->Specific.File.ExtentsRequestComplete,
1612 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1613 AFS_TRACE_LEVEL_VERBOSE,
1614 "AFSProcessSetFileExtents Releasing Fcb extent lock %08lX EXCL %08lX\n",
1615 &pFcb->NPFcb->Specific.File.ExtentsResource,
1616 PsGetCurrentThread());
1618 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
1620 try_return( ntStatus);
1623 ntStatus = AFSProcessExtentsResult ( pFcb,
1624 SetExtents->ExtentCount,
1625 SetExtents->FileExtents );
1629 if( pObjectInfo != NULL)
1632 InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
1634 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1635 AFS_TRACE_LEVEL_VERBOSE,
1636 "AFSProcessSetFileExtents Decrement count on object %08lX Cnt %d\n",
1638 pObjectInfo->ObjectReferenceCount);
1646 // Helper fuctions for Usermode initiation of release of extents
1649 AFSReleaseSpecifiedExtents( IN AFSReleaseFileExtentsCB *Extents,
1651 OUT AFSFileExtentCB *FileExtents,
1652 IN ULONG BufferSize,
1653 OUT ULONG *ExtentCount,
1654 OUT BOOLEAN *DirtyExtents)
1659 ULONG ulExtentCount = 0;
1660 NTSTATUS ntStatus = STATUS_SUCCESS;
1661 BOOLEAN bReleaseAll = FALSE;
1662 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1666 ASSERT( ExIsResourceAcquiredExclusiveLite( &Fcb->NPFcb->Specific.File.ExtentsResource));
1668 if (BufferSize < (Extents->ExtentCount * sizeof( AFSFileExtentCB)))
1671 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1672 AFS_TRACE_LEVEL_VERBOSE,
1673 "AFSReleaseSpecifiedExtents Buffer too small\n");
1675 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL);
1678 RtlZeroMemory( FileExtents, BufferSize);
1681 *DirtyExtents = FALSE;
1684 // iterate until we have dealt with all we were asked for or
1685 // are at the end of the list. Note that this deals (albeit
1686 // badly) with out of order extents
1689 pExtent = AFSExtentForOffset( Fcb,
1690 &Extents->FileExtents[0].FileOffset,
1693 if (NULL == pExtent)
1695 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1699 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1703 if( BooleanFlagOn( Extents->Flags, AFS_RELEASE_EXTENTS_FLAGS_RELEASE_ALL) ||
1704 ( Extents->FileId.Cell == 0 &&
1705 Extents->FileId.Volume == 0 &&
1706 Extents->FileId.Vnode == 0 &&
1707 Extents->FileId.Unique == 0))
1713 while( le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST] &&
1714 ulExtentCount < Extents->ExtentCount)
1718 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
1723 if( pExtent->FileOffset.QuadPart < Extents->FileExtents[ulExtentCount].FileOffset.QuadPart)
1726 // Skip forward through the extent list until we get
1727 // to the one we want
1733 else if (pExtent->FileOffset.QuadPart > Extents->FileExtents[ulExtentCount].FileOffset.QuadPart)
1736 // We don't have the extent asked for so return UNKNOWN
1739 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1740 AFS_TRACE_LEVEL_VERBOSE,
1741 "AFSReleaseSpecifiedExtents Located UNKNOWN extent Offset %I64X Len %08lX\n",
1742 Extents->FileExtents[ulExtentCount].FileOffset.QuadPart,
1743 Extents->FileExtents[ulExtentCount].Length);
1745 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_UNKNOWN;
1747 FileExtents[*ExtentCount].Length = 0;
1748 FileExtents[*ExtentCount].CacheOffset.QuadPart = 0;
1749 FileExtents[*ExtentCount].FileOffset = Extents->FileExtents[ulExtentCount].FileOffset;
1751 *ExtentCount = (*ExtentCount) + 1;
1756 // Reset where we are looking
1759 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1763 else if( pExtent->ActiveCount > 0)
1766 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1767 AFS_TRACE_LEVEL_VERBOSE,
1768 "AFSReleaseSpecifiedExtents Located IN_USE extent Offset %I64X Len %08lX\n",
1769 Extents->FileExtents[ulExtentCount].FileOffset.QuadPart,
1770 Extents->FileExtents[ulExtentCount].Length);
1772 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_IN_USE;
1774 FileExtents[*ExtentCount].Length = 0;
1775 FileExtents[*ExtentCount].CacheOffset.QuadPart = 0;
1776 FileExtents[*ExtentCount].FileOffset = Extents->FileExtents[ulExtentCount].FileOffset;
1778 *ExtentCount = (*ExtentCount) + 1;
1783 // Reset where we are looking
1786 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1795 // If the extent is currently active then skip it
1798 if( pExtent->ActiveCount > 0)
1807 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_RELEASE;
1809 FileExtents[*ExtentCount].Length = pExtent->Size;
1810 FileExtents[*ExtentCount].DirtyLength = pExtent->Size;
1811 FileExtents[*ExtentCount].DirtyOffset = 0;
1812 FileExtents[*ExtentCount].CacheOffset = pExtent->CacheOffset;
1813 FileExtents[*ExtentCount].FileOffset = pExtent->FileOffset;
1815 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1816 AFS_TRACE_LEVEL_VERBOSE,
1817 "AFSReleaseSpecifiedExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
1819 Fcb->ObjectInformation->FileId.Cell,
1820 Fcb->ObjectInformation->FileId.Volume,
1821 Fcb->ObjectInformation->FileId.Vnode,
1822 Fcb->ObjectInformation->FileId.Unique,
1823 FileExtents[*ExtentCount].FileOffset.QuadPart,
1824 FileExtents[*ExtentCount].Length);
1826 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
1829 AFSAcquireExcl( &Fcb->NPFcb->Specific.File.DirtyExtentsListLock,
1832 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
1835 AFSRemoveEntryDirtyList( Fcb,
1838 FileExtents[*ExtentCount].Flags |= AFS_EXTENT_FLAG_DIRTY;
1840 InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
1842 *DirtyExtents = TRUE;
1845 AFSReleaseResource( &Fcb->NPFcb->Specific.File.DirtyExtentsListLock);
1849 // move forward all three cursors
1853 *ExtentCount = (*ExtentCount) + 1;
1858 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
1860 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
1862 RemoveEntryList( &pExtent->Lists[i] );
1866 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
1868 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
1873 AFSExFreePool( pExtent);
1875 InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
1877 if( InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount) == 0)
1880 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
1895 AFSFindFcbToClean(ULONG IgnoreTime, AFSFcb *LastFcb, BOOLEAN Block)
1898 AFSFcb *pFcb = NULL;
1899 AFSVolumeCB *pVolumeCB = NULL;
1900 AFSDeviceExt *pRDRDeviceExt = NULL;
1901 AFSDeviceExt *pControlDeviceExt = NULL;
1902 BOOLEAN bLocatedEntry = FALSE;
1903 AFSObjectInfoCB *pCurrentObject = NULL;
1904 BOOLEAN bReleaseVolumeListLock = FALSE;
1906 pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1907 pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1909 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1910 AFS_TRACE_LEVEL_VERBOSE,
1911 "AFSFindFcbToClean Acquiring RDR VolumeListLock lock %08lX SHARED %08lX\n",
1912 &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1913 PsGetCurrentThread());
1915 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1918 bReleaseVolumeListLock = TRUE;
1920 pVolumeCB = pRDRDeviceExt->Specific.RDR.VolumeListHead;
1922 while( pVolumeCB != NULL)
1926 // The Volume list may move under our feet. Lock it.
1929 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1930 AFS_TRACE_LEVEL_VERBOSE,
1931 "AFSFindFcbToClean Acquiring VolumeRoot ObjectInfoTree lock %08lX SHARED %08lX\n",
1932 pVolumeCB->ObjectInfoTree.TreeLock,
1933 PsGetCurrentThread());
1935 InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1937 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1939 bReleaseVolumeListLock = FALSE;
1941 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1944 InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1946 if( NULL == LastFcb)
1949 pCurrentObject = pVolumeCB->ObjectInfoListHead;
1954 pCurrentObject = (AFSObjectInfoCB *)LastFcb->ObjectInformation->ListEntry.fLink;
1959 while( pCurrentObject != NULL)
1962 pFcb = (AFSFcb *)pCurrentObject->Fcb;
1965 // If the FCB is a candidate we try to lock it (but without waiting - which
1966 // means we are deadlock free
1970 pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
1976 AFSLockForExtentsTrim( pFcb);
1981 if( !AFSLockForExtentsTrimNoWait( pFcb))
1984 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1993 // Need to be sure there are no current flushes in the queue
1996 if( pFcb->Specific.File.ExtentCount == 0)
1999 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2000 AFS_TRACE_LEVEL_VERBOSE,
2001 "AFSFindFcbToClean Releasing Fcb extent lock %08lX thread %08lX\n",
2002 &pFcb->NPFcb->Specific.File.ExtentsResource,
2003 PsGetCurrentThread());
2005 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
2007 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
2014 if( pFcb->Specific.File.QueuedFlushCount > 0)
2017 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2018 AFS_TRACE_LEVEL_VERBOSE,
2019 "AFSFindFcbToClean Releasing Fcb extent lock %08lX thread %08lX\n",
2020 &pFcb->NPFcb->Specific.File.ExtentsResource,
2021 PsGetCurrentThread());
2023 AFSReleaseResource(&pFcb->NPFcb->Specific.File.ExtentsResource);
2027 AFSWaitOnQueuedFlushes( pFcb);
2032 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
2040 if( pFcb->OpenHandleCount > 0)
2043 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2044 AFS_TRACE_LEVEL_VERBOSE,
2045 "AFSFindFcbToClean Releasing Fcb extent lock %08lX thread %08lX\n",
2046 &pFcb->NPFcb->Specific.File.ExtentsResource,
2047 PsGetCurrentThread());
2049 AFSReleaseResource(&pFcb->NPFcb->Specific.File.ExtentsResource);
2051 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
2059 // A hit a very palpable hit. Pin it
2062 InterlockedIncrement( &pCurrentObject->ObjectReferenceCount);
2064 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2065 AFS_TRACE_LEVEL_VERBOSE,
2066 "AFSFindFcbToClean Increment count on Fcb %08lX Cnt %d\n",
2068 pCurrentObject->ObjectReferenceCount);
2070 bLocatedEntry = TRUE;
2075 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
2080 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2087 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
2090 bReleaseVolumeListLock = TRUE;
2092 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
2095 if( bReleaseVolumeListLock)
2098 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
2105 AFSProcessExtentFailure( PIRP Irp)
2107 AFSExtentFailureCB *pFailureCB = NULL;
2108 NTSTATUS ntStatus = STATUS_SUCCESS;
2109 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2110 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2111 AFSVolumeCB *pVolumeCB = NULL;
2112 ULONGLONG ullIndex = 0;
2113 AFSObjectInfoCB *pObjectInfo = NULL;
2117 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSExtentFailureCB))
2120 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2121 AFS_TRACE_LEVEL_ERROR,
2122 "AFSProcessExtentFailure Input buffer too small\n");
2124 try_return( ntStatus = STATUS_INVALID_PARAMETER);
2127 pFailureCB = (AFSExtentFailureCB *)Irp->AssociatedIrp.SystemBuffer;
2129 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2130 AFS_TRACE_LEVEL_ERROR,
2131 "AFSProcessExtentFailure Service Reports Failure fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2132 pFailureCB->FileId.Cell,
2133 pFailureCB->FileId.Volume,
2134 pFailureCB->FileId.Vnode,
2135 pFailureCB->FileId.Unique,
2136 pFailureCB->FailureStatus);
2138 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
2141 // Locate the volume node
2144 ullIndex = AFSCreateHighIndex( &pFailureCB->FileId);
2146 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
2148 (AFSBTreeEntry **)&pVolumeCB);
2150 if( pVolumeCB != NULL)
2153 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2154 AFS_TRACE_LEVEL_VERBOSE,
2155 "AFSProcessExtentFailure Acquiring VolumeRoot FileIDTree.TreeLock lock %08lX SHARED %08lX\n",
2156 pVolumeCB->ObjectInfoTree.TreeLock,
2157 PsGetCurrentThread());
2159 InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
2162 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
2164 if( !NT_SUCCESS( ntStatus) ||
2168 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2169 AFS_TRACE_LEVEL_ERROR,
2170 "AFSProcessExtentFailure Invalid volume index %I64X status %08X\n",
2171 ullIndex, ntStatus);
2173 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2176 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
2179 InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
2182 // Now locate the Object in this volume
2185 ullIndex = AFSCreateLowIndex( &pFailureCB->FileId);
2187 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
2189 (AFSBTreeEntry **)&pObjectInfo);
2191 if( pObjectInfo != NULL &&
2192 pObjectInfo->Fcb != NULL)
2196 // Reference the node so it won't be torn down
2199 InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
2201 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2202 AFS_TRACE_LEVEL_VERBOSE,
2203 "AFSProcessExtentFailure Increment count on object %08lX Cnt %d\n",
2205 pObjectInfo->ObjectReferenceCount);
2208 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2210 if( !NT_SUCCESS( ntStatus) ||
2211 pObjectInfo == NULL ||
2212 pObjectInfo->Fcb == NULL)
2215 if( pObjectInfo == NULL)
2217 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2218 AFS_TRACE_LEVEL_ERROR,
2219 "AFSProcessExtentFailure Invalid file index %I64X\n",
2224 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2225 AFS_TRACE_LEVEL_ERROR,
2226 "AFSProcessExtentFailure Fcb dealocated for %I64X\n",
2230 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2233 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2234 AFS_TRACE_LEVEL_VERBOSE,
2235 "AFSProcessExtentFailure Acquiring Fcb extent lock %08lX EXCL %08lX\n",
2236 &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2237 PsGetCurrentThread());
2239 AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2242 pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestStatus = pFailureCB->FailureStatus;
2244 KeSetEvent( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
2248 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2249 AFS_TRACE_LEVEL_VERBOSE,
2250 "AFSProcessExtentFailure Releasing Fcb extent lock %08lX EXCL %08lX\n",
2251 &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2252 PsGetCurrentThread());
2254 AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource);
2256 InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
2258 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2259 AFS_TRACE_LEVEL_VERBOSE,
2260 "AFSProcessExtentFailure Decrement count on object %08lX Cnt %d\n",
2262 pObjectInfo->ObjectReferenceCount);
2273 AFSProcessReleaseFileExtents( IN PIRP Irp)
2275 NTSTATUS ntStatus = STATUS_SUCCESS;
2276 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2277 PFILE_OBJECT pFileObject = pIrpSp->FileObject;
2278 AFSFcb *pFcb = NULL;
2279 AFSVolumeCB *pVolumeCB = NULL;
2280 AFSDeviceExt *pDevExt;
2281 AFSReleaseFileExtentsCB *pExtents;
2282 AFSReleaseFileExtentsResultCB *pResult = NULL;
2283 AFSReleaseFileExtentsResultFileCB *pFile = NULL;
2285 ULONGLONG ullIndex = 0;
2286 AFSObjectInfoCB *pObjectInfo = NULL;
2287 BOOLEAN bLocked = FALSE;
2288 BOOLEAN bDirtyExtents = FALSE;
2293 pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2295 pExtents = (AFSReleaseFileExtentsCB*) Irp->AssociatedIrp.SystemBuffer;
2297 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2298 sizeof( AFSReleaseFileExtentsCB))
2301 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2302 AFS_TRACE_LEVEL_ERROR,
2303 "AFSProcessReleaseFileExtents INPUT Buffer too small\n");
2305 try_return( ntStatus = STATUS_INVALID_PARAMETER );
2308 if ( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength <
2309 sizeof(AFSReleaseFileExtentsResultCB))
2312 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2313 AFS_TRACE_LEVEL_ERROR,
2314 "AFSProcessReleaseFileExtents OUTPUT Buffer too small [1]\n");
2317 // Must have space for one extent in one file
2320 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL);
2323 if (pExtents->ExtentCount == 0)
2326 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2327 AFS_TRACE_LEVEL_ERROR,
2328 "AFSProcessReleaseFileExtents Extent count zero\n");
2330 try_return( ntStatus = STATUS_INVALID_PARAMETER);
2333 if (pExtents->FileId.Cell != 0 ||
2334 pExtents->FileId.Volume != 0 ||
2335 pExtents->FileId.Vnode != 0 ||
2336 pExtents->FileId.Unique != 0)
2339 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2340 AFS_TRACE_LEVEL_VERBOSE,
2341 "AFSProcessReleaseFileExtents Processing FID %08lX:%08lX:%08lX:%08lX\n",
2342 pExtents->FileId.Cell,
2343 pExtents->FileId.Volume,
2344 pExtents->FileId.Vnode,
2345 pExtents->FileId.Unique);
2347 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2348 ( FIELD_OFFSET( AFSReleaseFileExtentsCB, ExtentCount) + sizeof(ULONG)) ||
2349 pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2350 ( FIELD_OFFSET( AFSReleaseFileExtentsCB, ExtentCount) + sizeof(ULONG) +
2351 sizeof (AFSFileExtentCB) * pExtents->ExtentCount))
2354 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2355 AFS_TRACE_LEVEL_ERROR,
2356 "AFSProcessReleaseFileExtents Buffer too small for FID %08lX:%08lx:%08lX:%08lX\n",
2357 pExtents->FileId.Cell,
2358 pExtents->FileId.Volume,
2359 pExtents->FileId.Vnode,
2360 pExtents->FileId.Unique);
2362 try_return( ntStatus = STATUS_INVALID_PARAMETER );
2365 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2366 AFS_TRACE_LEVEL_VERBOSE,
2367 "AFSProcessReleaseFileExtents Acquiring RDR VolumeTreeLock lock %08lX SHARED %08lX\n",
2368 &pDevExt->Specific.RDR.VolumeTreeLock,
2369 PsGetCurrentThread());
2371 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
2374 // Locate the volume node
2377 ullIndex = AFSCreateHighIndex( &pExtents->FileId);
2379 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
2381 (AFSBTreeEntry **)&pVolumeCB);
2383 if( pVolumeCB != NULL)
2386 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2387 AFS_TRACE_LEVEL_VERBOSE,
2388 "AFSProcessReleaseFileExtents Acquiring VolumeRoot FileIDTree.TreeLock lock %08lX SHARED %08lX\n",
2389 pVolumeCB->ObjectInfoTree.TreeLock,
2390 PsGetCurrentThread());
2392 InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
2395 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
2397 if( !NT_SUCCESS( ntStatus) ||
2401 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2402 AFS_TRACE_LEVEL_ERROR,
2403 "AFSProcessReleaseFileExtents Invalid volume index %I64X status %08X\n",
2404 ullIndex, ntStatus);
2406 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2409 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
2412 InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
2415 // Now locate the Object in this volume
2418 ullIndex = AFSCreateLowIndex( &pExtents->FileId);
2420 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
2422 (AFSBTreeEntry **)&pObjectInfo);
2424 if( pObjectInfo != NULL)
2428 // Reference the node so it won't be torn down
2431 InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
2433 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2434 AFS_TRACE_LEVEL_VERBOSE,
2435 "AFSProcessReleaseFileExtents Increment count on object %08lX Cnt %d\n",
2437 pObjectInfo->ObjectReferenceCount);
2440 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2442 if( !NT_SUCCESS( ntStatus) ||
2443 pObjectInfo == NULL)
2446 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2447 AFS_TRACE_LEVEL_ERROR,
2448 "AFSProcessReleaseFileExtents Invalid file index %I64X\n",
2451 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2454 pFcb = pObjectInfo->Fcb;
2459 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2460 AFS_TRACE_LEVEL_ERROR,
2461 "AFSProcessReleaseFileExtents Fcb not initialied (NO EXTENTS) for FID %08lX:%08lx:%08lX:%08lX\n",
2462 pExtents->FileId.Cell,
2463 pExtents->FileId.Volume,
2464 pExtents->FileId.Vnode,
2465 pExtents->FileId.Unique);
2467 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2470 AFSLockForExtentsTrim( pFcb );
2478 // Locate an Fcb to trim down
2481 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2482 AFS_TRACE_LEVEL_VERBOSE,
2483 "AFSProcessReleaseFileExtents Searching for a Fcb to Trim Down\n");
2485 pFcb = AFSFindFcbToClean( 0, NULL, FALSE);
2490 pFcb = AFSFindFcbToClean( 0, NULL, TRUE);
2496 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2497 AFS_TRACE_LEVEL_ERROR,
2498 "AFSProcessReleaseFileExtents Failed to locate Fcb for release ...\n");
2500 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2503 pObjectInfo = pFcb->ObjectInformation;
2509 // Allocate a scratch buffer to move in the extent information
2512 ulSz = (pExtents->ExtentCount-1) * sizeof(AFSFileExtentCB);
2513 ulSz += sizeof(AFSReleaseFileExtentsResultCB);
2515 if (ulSz > pIrpSp->Parameters.DeviceIoControl.OutputBufferLength)
2517 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2518 AFS_TRACE_LEVEL_ERROR,
2519 "AFSProcessReleaseFileExtents OUTPUT Buffer too small [2]\n");
2521 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL );
2524 pResult = (AFSReleaseFileExtentsResultCB*) AFSExAllocatePoolWithTag( PagedPool,
2526 AFS_EXTENTS_RESULT_TAG);
2527 if (NULL == pResult)
2530 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2531 AFS_TRACE_LEVEL_ERROR,
2532 "AFSProcessReleaseFileExtents Failed to allocate result block\n");
2534 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2538 // Set up the header (for an array of one)
2540 pResult->FileCount = 1;
2541 pResult->Flags = AFS_EXTENT_FLAG_RELEASE;
2542 ulSz -= FIELD_OFFSET(AFSReleaseFileExtentsResultCB, Files);
2545 // Setup the first (and only) file
2547 pFile = pResult->Files;
2548 pFile->FileId = pObjectInfo->FileId;
2549 pFile->Flags = AFS_EXTENT_FLAG_RELEASE;
2552 // Stash away the auth group
2555 RtlCopyMemory( &pFile->AuthGroup,
2560 // Update the metadata for this call
2563 pFile->AllocationSize = pFcb->ObjectInformation->EndOfFile;
2564 pFile->CreateTime = pFcb->ObjectInformation->CreationTime;
2565 pFile->ChangeTime = pFcb->ObjectInformation->ChangeTime;
2566 pFile->LastAccessTime = pFcb->ObjectInformation->LastAccessTime;
2567 pFile->LastWriteTime = pFcb->ObjectInformation->LastWriteTime;
2569 ulSz -= FIELD_OFFSET(AFSReleaseFileExtentsResultFileCB, FileExtents);
2571 ntStatus = AFSReleaseSpecifiedExtents( pExtents,
2575 &pFile->ExtentCount,
2578 if (!NT_SUCCESS(ntStatus))
2581 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2582 AFS_TRACE_LEVEL_ERROR,
2583 "AFSProcessReleaseFileExtents Failed to release extents Status %08lX\n",
2586 try_return( ntStatus );
2589 if( pExtents->ExtentCount == 0)
2592 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2593 AFS_TRACE_LEVEL_WARNING,
2594 "AFSProcessReleaseFileExtents Failed to release ANY extents\n");
2597 ulSz = sizeof(AFSReleaseFileExtentsResultCB);
2599 if( pExtents->ExtentCount > 0)
2601 ulSz += ((pExtents->ExtentCount-1) * sizeof(AFSFileExtentCB));
2604 RtlCopyMemory( Irp->AssociatedIrp.SystemBuffer,
2613 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2614 AFS_TRACE_LEVEL_VERBOSE,
2615 "AFSProcessReleaseFileExtents Releasing Fcb extent lock %08lX thread %08lX\n",
2616 &pFcb->NPFcb->Specific.File.ExtentsResource,
2617 PsGetCurrentThread());
2619 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
2622 if( NULL != pResult &&
2623 Irp->AssociatedIrp.SystemBuffer != pResult)
2626 AFSExFreePool(pResult);
2629 if (NT_SUCCESS(ntStatus))
2631 Irp->IoStatus.Information = ulSz;
2635 Irp->IoStatus.Information = 0;
2638 Irp->IoStatus.Status = ntStatus;
2640 if( pObjectInfo != NULL)
2643 InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
2645 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2646 AFS_TRACE_LEVEL_VERBOSE,
2647 "AFSProcessReleaseFileExtents Decrement count on object %08lX Cnt %d\n",
2649 pObjectInfo->ObjectReferenceCount);
2657 AFSWaitForExtentMapping( AFSFcb *Fcb )
2659 NTSTATUS ntStatus = STATUS_SUCCESS;
2660 LARGE_INTEGER liTimeOut;
2665 ASSERT( !ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
2667 if (!NT_SUCCESS( Fcb->NPFcb->Specific.File.ExtentsRequestStatus))
2671 // If this isn't the same process which caused the failure then try to request them again
2674 if( Fcb->Specific.File.ExtentRequestProcessId == (ULONGLONG)PsGetCurrentProcessId())
2676 try_return( ntStatus = Fcb->NPFcb->Specific.File.ExtentsRequestStatus);
2679 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
2682 liTimeOut.QuadPart = -(50000000);
2684 ntStatus = KeWaitForSingleObject( &Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
2690 if (!NT_SUCCESS( Fcb->NPFcb->Specific.File.ExtentsRequestStatus))
2694 // If this isn't the same process which caused the failure then try to request them again
2697 if( Fcb->Specific.File.ExtentRequestProcessId == (ULONGLONG)PsGetCurrentProcessId())
2699 try_return( ntStatus = Fcb->NPFcb->Specific.File.ExtentsRequestStatus);
2702 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
2705 if( ntStatus == STATUS_TIMEOUT)
2708 ntStatus = STATUS_SUCCESS;
2720 AFSFlushExtents( IN AFSFcb *Fcb)
2722 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
2723 AFSExtent *pExtent, *pNextExtent;
2725 AFSReleaseExtentsCB *pRelease = NULL;
2727 ULONG initialDirtyCount = 0;
2728 BOOLEAN bExtentsLocked = FALSE;
2731 NTSTATUS ntStatus = STATUS_SUCCESS;
2732 LARGE_INTEGER liLastFlush;
2733 AFSExtent *pDirtyListHead = NULL, *pDirtyListTail = NULL;
2734 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2736 ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
2739 // Save, then reset the flush time
2742 liLastFlush = Fcb->Specific.File.LastServerFlush;
2744 KeQueryTickCount( &Fcb->Specific.File.LastServerFlush);
2750 // Lock extents while we count and set up the array to send to
2754 AFSLockForExtentsTrim( Fcb);
2756 bExtentsLocked = TRUE;
2758 InterlockedIncrement( &Fcb->Specific.File.QueuedFlushCount);
2761 // Clear our queued flush event
2764 KeClearEvent( &Fcb->NPFcb->Specific.File.QueuedFlushEvent);
2767 // Look for a start in the list to flush entries
2772 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
2774 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
2776 AFS_EXTENT_RELEASE_TAG);
2777 if( NULL == pRelease)
2780 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2783 initialDirtyCount = Fcb->Specific.File.ExtentsDirtyCount;
2785 while( Fcb->Specific.File.ExtentsDirtyCount > 0)
2788 pRelease->Flags = AFS_EXTENT_FLAG_DIRTY;
2790 if( BooleanFlagOn( Fcb->Flags, AFS_FCB_FILE_CLOSED))
2793 pRelease->Flags |= AFS_EXTENT_FLAG_FLUSH;
2797 // Update the metadata for this call
2800 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
2801 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
2802 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
2803 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
2804 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
2808 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
2811 pExtent = (AFSExtent *)pNPFcb->Specific.File.DirtyListHead;
2813 while( count < AFS_MAXIMUM_EXTENT_RELEASE_COUNT)
2816 if ( pExtent == NULL)
2822 pNextExtent = (AFSExtent *)pExtent->DirtyList.fLink;
2824 if ( pExtent->ActiveCount > 0)
2826 pExtent = pNextExtent;
2830 AFSRemoveEntryDirtyList( Fcb, pExtent);
2832 pExtent->DirtyList.fLink = NULL;
2833 pExtent->DirtyList.bLink = NULL;
2835 InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
2838 // Clear the flag in advance of the write. If we do
2839 // things this was we know that the clear is
2840 // pessimistic (any write which happens from now on
2841 // will set the flag dirty again).
2844 pExtent->Flags &= ~AFS_EXTENT_DIRTY;
2846 pRelease->FileExtents[count].Flags = AFS_EXTENT_FLAG_DIRTY;
2848 pRelease->FileExtents[count].Length = pExtent->Size;
2849 pRelease->FileExtents[count].DirtyLength = pExtent->Size;
2850 pRelease->FileExtents[count].DirtyOffset = 0;
2851 pRelease->FileExtents[count].CacheOffset = pExtent->CacheOffset;
2852 pRelease->FileExtents[count].FileOffset = pExtent->FileOffset;
2855 RtlCopyMemory( pRelease->FileExtents[count].MD5,
2857 sizeof(pExtent->MD5));
2859 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_MD5_SET;
2862 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2863 AFS_TRACE_LEVEL_VERBOSE,
2864 "AFSFlushExtents Releasing DIRTY extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
2866 Fcb->ObjectInformation->FileId.Cell,
2867 Fcb->ObjectInformation->FileId.Volume,
2868 Fcb->ObjectInformation->FileId.Vnode,
2869 Fcb->ObjectInformation->FileId.Unique,
2870 pExtent->FileOffset.QuadPart,
2873 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_RELEASE;
2876 // Need to pull this extent from the main list as well
2879 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
2881 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
2883 RemoveEntryList( &pExtent->Lists[i] );
2887 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
2889 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
2891 AFSExFreePool( pExtent);
2893 InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
2895 if( InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount) == 0)
2898 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
2905 pExtent = pNextExtent;
2908 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
2911 // If we are done then get out
2917 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2918 AFS_TRACE_LEVEL_VERBOSE,
2919 "AFSFlushExtents No more dirty extents found\n");
2925 // Fire off the request synchronously
2928 sz = sizeof( AFSReleaseExtentsCB ) + (count * sizeof ( AFSFileExtentCB ));
2930 pRelease->ExtentCount = count;
2932 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2933 AFS_TRACE_LEVEL_VERBOSE,
2934 "AFSFlushExtents Releasing(1) Fcb extents lock %08lX SHARED %08lX\n",
2935 &pNPFcb->Specific.File.ExtentsResource,
2936 PsGetCurrentThread());
2938 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource);
2939 bExtentsLocked = FALSE;
2941 KeSetEvent( &pNPFcb->Specific.File.FlushEvent,
2945 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
2946 AFS_REQUEST_FLAG_SYNCHRONOUS,
2949 &Fcb->ObjectInformation->FileId,
2955 if( !NT_SUCCESS(ntStatus))
2959 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
2960 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
2963 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2964 AFS_TRACE_LEVEL_ERROR,
2965 "AFSFlushExtents AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2966 Fcb->ObjectInformation->FileId.Cell,
2967 Fcb->ObjectInformation->FileId.Volume,
2968 Fcb->ObjectInformation->FileId.Vnode,
2969 Fcb->ObjectInformation->FileId.Unique,
2973 AFSLockForExtentsTrim( Fcb);
2975 bExtentsLocked = TRUE;
2980 if( InterlockedDecrement( &Fcb->Specific.File.QueuedFlushCount) == 0)
2983 KeSetEvent( &pNPFcb->Specific.File.QueuedFlushEvent,
2988 KeSetEvent( &pNPFcb->Specific.File.FlushEvent,
2995 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2996 AFS_TRACE_LEVEL_VERBOSE,
2997 "AFSFlushExtents Releasing(2) Fcb extents lock %08lX SHARED %08lX\n",
2998 &pNPFcb->Specific.File.ExtentsResource,
2999 PsGetCurrentThread());
3001 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
3006 AFSExFreePool( pRelease);
3014 AFSReleaseExtentsWithFlush( IN AFSFcb *Fcb)
3016 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3019 AFSReleaseExtentsCB *pRelease = NULL;
3021 ULONG initialDirtyCount = 0;
3022 BOOLEAN bExtentsLocked = FALSE;
3025 NTSTATUS ntStatus = STATUS_SUCCESS;
3026 LARGE_INTEGER liLastFlush;
3027 ULONG ulRemainingExtentLength = 0;
3028 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3030 ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
3033 // Save, then reset the flush time
3036 liLastFlush = Fcb->Specific.File.LastServerFlush;
3038 KeQueryTickCount( &Fcb->Specific.File.LastServerFlush);
3044 // Look for a start in the list to flush entries
3049 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
3051 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
3053 AFS_EXTENT_RELEASE_TAG);
3054 if( NULL == pRelease)
3057 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
3060 if( Fcb->OpenHandleCount > 0)
3064 // Don't release everything ...
3068 // For now release everything
3071 //ulRemainingExtentLength = 1500;
3074 while( Fcb->Specific.File.ExtentLength > (LONG)ulRemainingExtentLength)
3077 AFSLockForExtentsTrim( Fcb);
3079 bExtentsLocked = TRUE;
3081 pRelease->Flags = AFS_EXTENT_FLAG_RELEASE;
3084 // Update the metadata for this call
3087 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
3088 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
3089 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
3090 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
3091 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
3095 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3097 while( count < AFS_MAXIMUM_EXTENT_RELEASE_COUNT &&
3098 le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
3101 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3105 if( pExtent->ActiveCount > 0)
3111 pRelease->FileExtents[count].Flags = AFS_EXTENT_FLAG_RELEASE;
3113 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3114 AFS_TRACE_LEVEL_VERBOSE,
3115 "AFSReleaseExtentsWithFlush Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3117 Fcb->ObjectInformation->FileId.Cell,
3118 Fcb->ObjectInformation->FileId.Volume,
3119 Fcb->ObjectInformation->FileId.Vnode,
3120 Fcb->ObjectInformation->FileId.Unique,
3121 pExtent->FileOffset.QuadPart,
3124 pRelease->FileExtents[count].Length = pExtent->Size;
3125 pRelease->FileExtents[count].DirtyLength = pExtent->Size;
3126 pRelease->FileExtents[count].DirtyOffset = 0;
3127 pRelease->FileExtents[count].CacheOffset = pExtent->CacheOffset;
3128 pRelease->FileExtents[count].FileOffset = pExtent->FileOffset;
3131 RtlCopyMemory( pRelease->FileExtents[count].MD5,
3133 sizeof(pExtent->MD5));
3135 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_MD5_SET;
3138 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3141 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3144 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3147 AFSRemoveEntryDirtyList( Fcb,
3150 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_DIRTY;
3152 InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
3155 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3159 // Need to pull this extent from the main list as well
3162 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
3164 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
3166 RemoveEntryList( &pExtent->Lists[i] );
3170 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
3172 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
3174 AFSExFreePool( pExtent);
3176 InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
3178 if( InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount) == 0)
3181 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
3190 // If we are done then get out
3196 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3197 AFS_TRACE_LEVEL_VERBOSE,
3198 "AFSReleaseExtentsWithFlush No more dirty extents found\n");
3204 // Fire off the request synchronously
3207 sz = sizeof( AFSReleaseExtentsCB ) + (count * sizeof ( AFSFileExtentCB ));
3209 pRelease->ExtentCount = count;
3212 // Drop the extents lock for the duration of the call to
3213 // the network. We have pinned the extents so, even
3214 // though we might get extents added during this period,
3215 // but none will be removed. Hence we can carry on from
3219 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3220 AFS_TRACE_LEVEL_VERBOSE,
3221 "AFSReleaseExtentsWithFlush Releasing Fcb extents lock %08lX thread %08lX\n",
3222 &pNPFcb->Specific.File.ExtentsResource,
3223 PsGetCurrentThread());
3225 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource);
3226 bExtentsLocked = FALSE;
3228 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
3229 AFS_REQUEST_FLAG_SYNCHRONOUS,
3232 &Fcb->ObjectInformation->FileId,
3238 if( !NT_SUCCESS(ntStatus))
3242 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
3243 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
3246 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3247 AFS_TRACE_LEVEL_ERROR,
3248 "AFSReleaseExtentsWithFlush AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3249 Fcb->ObjectInformation->FileId.Cell,
3250 Fcb->ObjectInformation->FileId.Volume,
3251 Fcb->ObjectInformation->FileId.Vnode,
3252 Fcb->ObjectInformation->FileId.Unique,
3262 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3263 AFS_TRACE_LEVEL_VERBOSE,
3264 "AFSReleaseExtentsWithFlush Releasing Fcb extents lock %08lX thread %08lX\n",
3265 &pNPFcb->Specific.File.ExtentsResource,
3266 PsGetCurrentThread());
3268 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
3273 AFSExFreePool( pRelease);
3281 AFSMarkDirty( IN AFSFcb *Fcb,
3282 IN AFSExtent *StartExtent,
3283 IN ULONG ExtentsCount,
3284 IN LARGE_INTEGER *StartingByte)
3287 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3288 AFSExtent *pExtent = StartExtent;
3289 AFSExtent *pNextExtent, *pCurrentExtent = NULL;
3291 BOOLEAN bInsertTail = FALSE, bInsertHead = FALSE;
3293 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3294 AFS_TRACE_LEVEL_VERBOSE,
3295 "AFSMarkDirty Acquiring Fcb extents lock %08lX SHARED %08lX\n",
3296 &Fcb->NPFcb->Specific.File.ExtentsResource,
3297 PsGetCurrentThread());
3299 AFSAcquireShared( &Fcb->NPFcb->Specific.File.ExtentsResource, TRUE);
3301 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3305 // Find the insertion point
3308 if( pNPFcb->Specific.File.DirtyListHead == NULL)
3313 else if( StartingByte->QuadPart == 0)
3321 pCurrentExtent = pNPFcb->Specific.File.DirtyListHead;
3323 while( pCurrentExtent != NULL)
3326 if( pCurrentExtent->FileOffset.QuadPart + pCurrentExtent->Size >= StartingByte->QuadPart ||
3327 pCurrentExtent->DirtyList.fLink == NULL)
3333 pCurrentExtent = (AFSExtent *)pCurrentExtent->DirtyList.fLink;
3337 while( ulCount < ExtentsCount)
3340 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
3342 if( !BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3345 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3346 AFS_TRACE_LEVEL_VERBOSE,
3347 "AFSMarkDirty Marking extent offset %I64X Length %08lX DIRTY\n",
3348 pExtent->FileOffset.QuadPart,
3351 pExtent->DirtyList.fLink = NULL;
3352 pExtent->DirtyList.bLink = NULL;
3357 pExtent->DirtyList.fLink = (void *)pNPFcb->Specific.File.DirtyListHead;
3359 pExtent->DirtyList.bLink = NULL;
3361 pNPFcb->Specific.File.DirtyListHead->DirtyList.bLink = (void *)pExtent;
3363 pNPFcb->Specific.File.DirtyListHead = pExtent;
3365 pCurrentExtent = pExtent;
3367 bInsertHead = FALSE;
3369 else if( bInsertTail)
3372 if( pNPFcb->Specific.File.DirtyListHead == NULL)
3375 pNPFcb->Specific.File.DirtyListHead = pExtent;
3380 pNPFcb->Specific.File.DirtyListTail->DirtyList.fLink = (void *)pExtent;
3382 pExtent->DirtyList.bLink = (void *)pNPFcb->Specific.File.DirtyListTail;
3385 pNPFcb->Specific.File.DirtyListTail = pExtent;
3390 pExtent->DirtyList.fLink = pCurrentExtent->DirtyList.fLink;
3391 pExtent->DirtyList.bLink = (void *)pCurrentExtent;
3393 if( pExtent->DirtyList.fLink == NULL)
3396 pNPFcb->Specific.File.DirtyListTail = pExtent;
3401 ((AFSExtent *)pExtent->DirtyList.fLink)->DirtyList.bLink = (void *)pExtent;
3404 pCurrentExtent->DirtyList.fLink = (void *)pExtent;
3406 pCurrentExtent = pExtent;
3409 pExtent->Flags |= AFS_EXTENT_DIRTY;
3412 // Up the dirty count
3415 InterlockedIncrement( &Fcb->Specific.File.ExtentsDirtyCount);
3420 pCurrentExtent = pExtent;
3423 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_ACTIVE_COUNTING,
3424 AFS_TRACE_LEVEL_VERBOSE,
3425 "AFSMarkDirty Decrement count on extent %08lX Cnt %d\n",
3427 pExtent->ActiveCount);
3429 ASSERT( pExtent->ActiveCount > 0);
3431 InterlockedDecrement( &pExtent->ActiveCount);
3433 pExtent = pNextExtent;
3438 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3440 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3441 AFS_TRACE_LEVEL_VERBOSE,
3442 "AFSMarkDirty Releasing Fcb extents lock %08lX SHARED %08lX\n",
3443 &Fcb->NPFcb->Specific.File.ExtentsResource,
3444 PsGetCurrentThread());
3446 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
3455 static AFSExtent *ExtentFor(PLIST_ENTRY le, ULONG SkipList)
3457 return CONTAINING_RECORD( le, AFSExtent, Lists[SkipList] );
3460 static AFSExtent *NextExtent(AFSExtent *Extent, ULONG SkipList)
3462 return ExtentFor(Extent->Lists[SkipList].Flink, SkipList);
3465 static AFSExtent *DirtyExtentFor(PLIST_ENTRY le)
3467 return CONTAINING_RECORD( le, AFSExtent, DirtyList );
3470 static VOID VerifyExtentsLists(AFSFcb *Fcb)
3474 // Check the ordering of the extents lists
3476 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
3478 ASSERT(Fcb->Specific.File.ExtentsLists[0].Flink != &Fcb->Specific.File.ExtentsLists[1]);
3480 for (ULONG listNo = 0; listNo < AFS_NUM_EXTENT_LISTS; listNo ++)
3482 LARGE_INTEGER lastOffset;
3484 lastOffset.QuadPart = 0;
3486 for (PLIST_ENTRY pLe = Fcb->Specific.File.ExtentsLists[listNo].Flink;
3487 pLe != &Fcb->Specific.File.ExtentsLists[listNo];
3492 pExtent = ExtentFor(pLe, listNo);
3495 ASSERT(pLe != &Fcb->Specific.File.ExtentsLists[1] &&
3496 pLe->Flink !=&Fcb->Specific.File.ExtentsLists[1] &&
3497 pLe->Blink !=&Fcb->Specific.File.ExtentsLists[1]);
3500 ASSERT(pLe->Flink->Blink == pLe);
3501 ASSERT(pLe->Blink->Flink == pLe);
3504 // Should follow on from previous
3506 ASSERT(pExtent->FileOffset.QuadPart >= lastOffset.QuadPart);
3507 lastOffset.QuadPart = pExtent->FileOffset.QuadPart + pExtent->Size;
3510 // Should match alignment criteria
3512 ASSERT( 0 == (pExtent->FileOffset.LowPart & ExtentsMasks[listNo]) );
3515 // "lower" lists should be populated
3517 for (LONG subListNo = listNo-1; subListNo > 0; subListNo --)
3519 ASSERT( !IsListEmpty(&pExtent->Lists[subListNo]));
3527 AFSTrimExtents( IN AFSFcb *Fcb,
3528 IN PLARGE_INTEGER FileSize)
3531 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3534 BOOLEAN locked = FALSE;
3535 NTSTATUS ntStatus = STATUS_SUCCESS;
3536 LARGE_INTEGER liAlignedOffset = {0,0};
3537 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
3538 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3544 // Get an aligned offset
3547 if( FileSize != NULL)
3550 liAlignedOffset = *FileSize;
3553 if( liAlignedOffset.QuadPart > 0 &&
3554 liAlignedOffset.QuadPart % pDevExt->Specific.RDR.CacheBlockSize != 0)
3558 // Align UP to the next cache block size
3561 liAlignedOffset.QuadPart = (ULONGLONG)( (ULONGLONG)((liAlignedOffset.QuadPart / pDevExt->Specific.RDR.CacheBlockSize) + 1) * (ULONGLONG)pDevExt->Specific.RDR.CacheBlockSize);
3565 // Ensure that no one is working with the extents and grab the
3569 AFSLockForExtentsTrim( Fcb);
3573 if( 0 == Fcb->Specific.File.ExtentCount)
3577 // Update the request extent status
3580 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
3582 try_return( ntStatus = STATUS_SUCCESS);
3586 // We are truncating from a specific length in the file. If the offset
3587 // is non-zero then go find the first extent to remove
3590 if( 0 == FileSize->QuadPart)
3593 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3598 pExtent = AFSExtentForOffset( Fcb,
3602 if( NULL == pExtent)
3605 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3609 le = &pExtent->Lists[AFS_EXTENTS_LIST];
3613 while( le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
3616 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3619 // Only trim down extents beyond the aligned offset
3624 if( pExtent->FileOffset.QuadPart >= liAlignedOffset.QuadPart)
3627 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3630 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3633 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3637 AFSRemoveEntryDirtyList( Fcb,
3640 dirtyCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
3642 ASSERT(dirtyCount >= 0);
3645 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3648 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
3650 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
3652 RemoveEntryList( &pExtent->Lists[i] );
3656 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3657 AFS_TRACE_LEVEL_VERBOSE,
3658 "AFSTrimExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3660 Fcb->ObjectInformation->FileId.Cell,
3661 Fcb->ObjectInformation->FileId.Volume,
3662 Fcb->ObjectInformation->FileId.Vnode,
3663 Fcb->ObjectInformation->FileId.Unique,
3664 pExtent->FileOffset.QuadPart,
3667 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
3669 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
3671 ASSERT( pExtent->ActiveCount == 0);
3676 AFSExFreePool( pExtent);
3678 InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
3680 if( InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount) == 0)
3683 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
3691 // Update the request extent status
3694 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
3701 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3702 AFS_TRACE_LEVEL_VERBOSE,
3703 "AFSTrimExtents Releasing Fcb extents lock %08lX thread %08lX\n",
3704 &Fcb->NPFcb->Specific.File.ExtentsResource,
3705 PsGetCurrentThread());
3707 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
3715 AFSTrimSpecifiedExtents( IN AFSFcb *Fcb,
3717 IN AFSFileExtentCB *Result)
3720 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3723 AFSFileExtentCB *pFileExtents = Result;
3724 NTSTATUS ntStatus = STATUS_SUCCESS;
3725 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
3726 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3731 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3733 while( le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST] &&
3737 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3740 // Only trim down extents beyond the aligned offset
3745 if( pExtent->FileOffset.QuadPart == pFileExtents->FileOffset.QuadPart)
3748 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3751 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3754 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3759 AFSRemoveEntryDirtyList( Fcb,
3762 dirtyCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
3764 ASSERT( dirtyCount >= 0);
3768 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3772 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
3774 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
3776 RemoveEntryList( &pExtent->Lists[i] );
3780 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3781 AFS_TRACE_LEVEL_VERBOSE,
3782 "AFSTrimSpecifiedExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3784 Fcb->ObjectInformation->FileId.Cell,
3785 Fcb->ObjectInformation->FileId.Volume,
3786 Fcb->ObjectInformation->FileId.Vnode,
3787 Fcb->ObjectInformation->FileId.Unique,
3788 pExtent->FileOffset.QuadPart,
3791 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
3793 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
3795 ASSERT( pExtent->ActiveCount == 0);
3800 AFSExFreePool( pExtent);
3802 InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
3804 if( InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount) == 0)
3807 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
3813 // Next extent we are looking for
3823 // Update the request extent status
3826 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
3833 AFSReferenceActiveExtents( IN AFSExtent *StartExtent,
3834 IN ULONG ExtentsCount)
3837 AFSExtent *pExtent = StartExtent;
3838 AFSExtent *pNextExtent;
3841 while( ulCount < ExtentsCount)
3844 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
3846 InterlockedIncrement( &pExtent->ActiveCount);
3848 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_ACTIVE_COUNTING,
3849 AFS_TRACE_LEVEL_VERBOSE,
3850 "AFSReferenceActiveExtents Increment count on extent %08lX Cnt %d\n",
3852 pExtent->ActiveCount);
3854 pExtent = pNextExtent;
3863 AFSDereferenceActiveExtents( IN AFSExtent *StartExtent,
3864 IN ULONG ExtentsCount)
3867 AFSExtent *pExtent = StartExtent;
3868 AFSExtent *pNextExtent;
3871 while( ulCount < ExtentsCount)
3874 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
3876 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_ACTIVE_COUNTING,
3877 AFS_TRACE_LEVEL_VERBOSE,
3878 "AFSDereferenceActiveExtents Decrement count on extent %08lX Cnt %d\n",
3880 pExtent->ActiveCount);
3882 ASSERT( pExtent->ActiveCount > 0);
3884 InterlockedDecrement( &pExtent->ActiveCount);
3886 pExtent = pNextExtent;
3895 AFSRemoveEntryDirtyList( IN AFSFcb *Fcb,
3896 IN AFSExtent *Extent)
3899 if( Extent->DirtyList.fLink == NULL)
3902 Fcb->NPFcb->Specific.File.DirtyListTail = (AFSExtent *)Extent->DirtyList.bLink;
3904 if( Fcb->NPFcb->Specific.File.DirtyListTail != NULL)
3907 Fcb->NPFcb->Specific.File.DirtyListTail->DirtyList.fLink = NULL;
3913 ((AFSExtent *)Extent->DirtyList.fLink)->DirtyList.bLink = Extent->DirtyList.bLink;
3916 if( Extent->DirtyList.bLink == NULL)
3919 Fcb->NPFcb->Specific.File.DirtyListHead = (AFSExtent *)Extent->DirtyList.fLink;
3921 if( Fcb->NPFcb->Specific.File.DirtyListHead != NULL)
3924 Fcb->NPFcb->Specific.File.DirtyListHead->DirtyList.bLink = NULL;
3930 ((AFSExtent *)Extent->DirtyList.bLink)->DirtyList.fLink = Extent->DirtyList.fLink;
3939 AFSSetupMD5Hash( IN AFSFcb *Fcb,
3940 IN AFSExtent *StartExtent,
3941 IN ULONG ExtentsCount,
3942 IN void *SystemBuffer,
3943 IN LARGE_INTEGER *ByteOffset,
3947 NTSTATUS ntStatus = STATUS_SUCCESS;
3948 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3949 AFSExtent *pExtent = StartExtent;
3950 AFSExtent *pNextExtent, *pCurrentExtent = NULL;
3952 char *pCurrentBuffer = (char *)SystemBuffer;
3953 char *pMD5Buffer = NULL;
3954 ULONG ulCurrentLen = 0;
3955 void *pExtentBuffer = NULL;
3956 LARGE_INTEGER liByteOffset;
3957 ULONG ulBytesRead = 0;
3962 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3963 AFS_TRACE_LEVEL_VERBOSE,
3964 "AFSSetupMD5Hash Acquiring Fcb extents lock %08lX SHARED %08lX\n",
3965 &Fcb->NPFcb->Specific.File.ExtentsResource,
3966 PsGetCurrentThread());
3968 AFSAcquireShared( &Fcb->NPFcb->Specific.File.ExtentsResource, TRUE);
3970 liByteOffset.QuadPart = ByteOffset->QuadPart;
3972 while( ulCount < ExtentsCount)
3975 RtlZeroMemory( pExtent->MD5,
3976 sizeof( pExtent->MD5));
3978 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
3980 if( liByteOffset.QuadPart == pExtent->FileOffset.QuadPart &&
3981 ByteCount < pExtent->Size)
3984 if( pExtentBuffer == NULL)
3987 pExtentBuffer = AFSExAllocatePoolWithTag( PagedPool,
3989 AFS_GENERIC_MEMORY_9_TAG);
3991 if( pExtentBuffer == NULL)
3998 RtlZeroMemory( pExtentBuffer,
4001 RtlCopyMemory( pExtentBuffer,
4005 pMD5Buffer = (char *)pExtentBuffer;
4007 ulCurrentLen = ByteCount;
4009 else if( liByteOffset.QuadPart != pExtent->FileOffset.QuadPart)
4012 pExtentBuffer = AFSExAllocatePoolWithTag( PagedPool,
4014 AFS_GENERIC_MEMORY_10_TAG);
4016 if( pExtentBuffer == NULL)
4022 RtlZeroMemory( pExtentBuffer,
4025 if( BooleanFlagOn( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE))
4029 RtlCopyMemory( pExtentBuffer,
4030 ((char *)AFSLibCacheBaseAddress + pExtent->CacheOffset.QuadPart),
4033 ASSERT( pExtent->CacheOffset.HighPart == 0);
4034 RtlCopyMemory( pExtentBuffer,
4035 ((char *)AFSLibCacheBaseAddress + pExtent->CacheOffset.LowPart),
4039 ulBytesRead = pExtent->Size;
4044 ntStatus = AFSReadCacheFile( pExtentBuffer,
4045 &pExtent->CacheOffset,
4049 if( !NT_SUCCESS( ntStatus))
4055 pMD5Buffer = (char *)pExtentBuffer;
4057 ulCurrentLen = min( ByteCount, pExtent->Size - (ULONG)(liByteOffset.QuadPart - pExtent->FileOffset.QuadPart));
4059 RtlCopyMemory( (void *)((char *)pExtentBuffer + (ULONG)(liByteOffset.QuadPart - pExtent->FileOffset.QuadPart)),
4066 ulCurrentLen = pExtent->Size;
4068 pMD5Buffer = pCurrentBuffer;
4071 AFSGenerateMD5( pMD5Buffer,
4075 pExtent = pNextExtent;
4079 ByteCount -= ulCurrentLen;
4081 pCurrentBuffer += ulCurrentLen;
4083 liByteOffset.QuadPart += ulCurrentLen;
4086 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4087 AFS_TRACE_LEVEL_VERBOSE,
4088 "AFSSetupMD5Hash Releasing Fcb extents lock %08lX SHARED %08lX\n",
4089 &Fcb->NPFcb->Specific.File.ExtentsResource,
4090 PsGetCurrentThread());
4092 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
4094 if( pExtentBuffer != NULL)
4097 AFSExFreePool( pExtentBuffer);