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 ULONG ExtentsMasks[AFS_NUM_EXTENT_LISTS] = AFS_EXTENTS_MASKS;
43 static VOID VerifyExtentsLists(AFSFcb *Fcb);
44 static AFSExtent *DirtyExtentFor(PLIST_ENTRY le);
47 AFSEntryForOffset( IN AFSFcb *Fcb,
48 IN PLARGE_INTEGER Offset);
52 // Returns with Extents lock EX and no one using them.
56 AFSLockForExtentsTrim( IN AFSFcb *Fcb)
59 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
60 AFS_TRACE_LEVEL_VERBOSE,
61 "AFSLockForExtentsTrim Acquiring Fcb extents lock %08lX EXCL %08lX\n",
62 &Fcb->NPFcb->Specific.File.ExtentsResource,
63 PsGetCurrentThread());
65 AFSAcquireExcl( &Fcb->NPFcb->Specific.File.ExtentsResource, TRUE );
71 // return FALSE *or* with Extents lock EX and noone using them
74 AFSLockForExtentsTrimNoWait( IN AFSFcb *Fcb)
77 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
78 AFS_TRACE_LEVEL_VERBOSE,
79 "AFSLockForExtentsTrimNoWait Attempting to acquire Fcb extent lock %08lX EXCL %08lX\n",
80 &Fcb->NPFcb->Specific.File.ExtentsResource,
81 PsGetCurrentThread());
83 if (!AFSAcquireExcl( &Fcb->NPFcb->Specific.File.ExtentsResource, FALSE ))
86 // Couldn't lock immediately
89 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
90 AFS_TRACE_LEVEL_VERBOSE,
91 "AFSLockForExtentsTrimNoWait Refused to wait for Fcb extent lock %08lX EXCL %08lX\n",
92 &Fcb->NPFcb->Specific.File.ExtentsResource,
93 PsGetCurrentThread());
102 AFSFreeExtent( IN AFSFcb *Fcb,
103 IN AFSExtent *pExtent)
105 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
108 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
110 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
112 RemoveEntryList( &pExtent->Lists[i] );
116 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
118 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
120 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
122 lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount);
127 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
132 AFSExFreePoolWithTag( pExtent, AFS_EXTENT_TAG);
136 // AFSTearDownFcbExtents was originally written to
137 // remove all of the extents from an FCB. For that to happen
138 // it must be an invariant that the extent list cannot change
139 // from the moment the caller decides to execute AFSTearDownFcbExtents
140 // until it returns. This invariant does not hold because the
141 // the decision to call AFSTearDownFcbExtents is made without
142 // holding the ExtentsResource and it is possible that extents
143 // are in active use. Therefore, AFSTearDownFcbExtents now releases
144 // as many non-active extents as it can.
147 AFSTearDownFcbExtents( IN AFSFcb *Fcb,
150 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
151 LIST_ENTRY *le, *leNext;
153 LONG lExtentCount = 0, lProcessCount = 0;
154 ULONG ulReleaseCount = 0;
156 AFSReleaseExtentsCB *pRelease = NULL;
157 BOOLEAN locked = FALSE;
159 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
160 GUID *pAuthGroup = AuthGroup;
167 if( pAuthGroup == NULL ||
168 RtlCompareMemory( pAuthGroup,
169 &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
170 sizeof( GUID)) == sizeof( GUID))
173 RtlZeroMemory( &stAuthGroup,
176 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
181 if( !NT_SUCCESS( ntStatus))
183 try_return( ntStatus);
186 pAuthGroup = &stAuthGroup;
190 // Ensure that no one is working with the extents and grab the
194 AFSLockForExtentsTrim( Fcb );
198 if (0 == Fcb->Specific.File.ExtentCount)
200 try_return ( ntStatus = STATUS_SUCCESS);
203 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
205 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
207 AFS_EXTENT_RELEASE_TAG);
208 if (NULL == pRelease)
211 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
214 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
217 for( le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink,
219 lExtentCount < Fcb->Specific.File.ExtentCount;
220 lExtentCount += lProcessCount)
223 RtlZeroMemory( pRelease,
224 sizeof( AFSReleaseExtentsCB ) +
225 (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB )));
227 for( lProcessCount = 0, ulReleaseCount = 0;
229 ulReleaseCount < AFS_MAXIMUM_EXTENT_RELEASE_COUNT &&
230 lExtentCount + lProcessCount < Fcb->Specific.File.ExtentCount;
231 lProcessCount++, le = leNext)
236 pEntry = ExtentFor( le, AFS_EXTENTS_LIST );
238 if( pEntry->ActiveCount == 0)
241 pRelease->FileExtents[ulReleaseCount].Flags = AFS_EXTENT_FLAG_RELEASE;
244 RtlCopyMemory( pRelease->FileExtents[ulReleaseCount].MD5,
246 sizeof(pEntry->MD5));
248 pRelease->FileExtents[ulReleaseCount].Flags |= AFS_EXTENT_FLAG_MD5_SET;
251 if( BooleanFlagOn( pEntry->Flags, AFS_EXTENT_DIRTY))
256 AFSRemoveEntryDirtyList( Fcb,
259 pRelease->FileExtents[ulReleaseCount].Flags |= AFS_EXTENT_FLAG_DIRTY;
261 dirtyCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
263 ASSERT( dirtyCount >= 0);
266 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
267 AFS_TRACE_LEVEL_VERBOSE,
268 "AFSTearDownFcbExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %08lX-%08lX Len %08lX\n",
270 Fcb->ObjectInformation->FileId.Cell,
271 Fcb->ObjectInformation->FileId.Volume,
272 Fcb->ObjectInformation->FileId.Vnode,
273 Fcb->ObjectInformation->FileId.Unique,
274 pEntry->FileOffset.HighPart,
275 pEntry->FileOffset.LowPart,
278 pRelease->FileExtents[ulReleaseCount].Length = pEntry->Size;
279 pRelease->FileExtents[ulReleaseCount].DirtyLength = pEntry->Size;
280 pRelease->FileExtents[ulReleaseCount].DirtyOffset = 0;
281 pRelease->FileExtents[ulReleaseCount].CacheOffset = pEntry->CacheOffset;
282 pRelease->FileExtents[ulReleaseCount].FileOffset = pEntry->FileOffset;
291 if ( ulReleaseCount > 0)
294 pRelease->ExtentCount = ulReleaseCount;
296 pRelease->Flags = AFS_EXTENT_FLAG_RELEASE;
299 // Update the metadata for this call
302 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
303 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
304 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
305 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
306 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
309 // Send the request down. We cannot send this down
310 // asynchronously - if we did that we could request them
311 // back before the service got this request and then this
312 // request would be a corruption.
315 sz = sizeof( AFSReleaseExtentsCB ) + (lProcessCount * sizeof ( AFSFileExtentCB ));
317 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
318 AFS_REQUEST_FLAG_SYNCHRONOUS,
321 &Fcb->ObjectInformation->FileId,
327 if( !NT_SUCCESS(ntStatus))
331 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
332 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
335 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
336 AFS_TRACE_LEVEL_ERROR,
337 "AFSTearDownFcbExtents AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
338 Fcb->ObjectInformation->FileId.Cell,
339 Fcb->ObjectInformation->FileId.Volume,
340 Fcb->ObjectInformation->FileId.Vnode,
341 Fcb->ObjectInformation->FileId.Unique,
348 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
351 // if all extents have been released, reinitialize the skip lists
354 if( Fcb->Specific.File.ExtentCount == 0)
357 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i++)
359 InitializeListHead(&Fcb->Specific.File.ExtentsLists[i]);
363 // Reinitialize the dirty list as well
366 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
369 ASSERT( Fcb->Specific.File.ExtentsDirtyCount == 0);
371 Fcb->NPFcb->Specific.File.DirtyListHead = NULL;
372 Fcb->NPFcb->Specific.File.DirtyListTail = NULL;
374 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
377 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
384 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
385 AFS_TRACE_LEVEL_VERBOSE,
386 "AFSTearDownFcbExtents Releasing Fcb extent lock %08lX thread %08lX\n",
387 &Fcb->NPFcb->Specific.File.ExtentsResource,
388 PsGetCurrentThread());
390 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
396 AFSExFreePoolWithTag( pRelease, AFS_EXTENT_RELEASE_TAG);
402 ExtentForOffsetInList( IN AFSFcb *Fcb,
405 IN PLARGE_INTEGER Offset)
408 // Return the extent that maps the offset, that
409 // - Contains the offset
410 // - or is immediately ahead of the offset (in this list)
411 // - otherwise return NULL.
414 PLIST_ENTRY pLe = List;
415 AFSExtent *pPrevious = NULL;
417 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
419 while (pLe != &Fcb->Specific.File.ExtentsLists[ListNumber])
423 entry = ExtentFor( pLe, ListNumber );
430 if (Offset->QuadPart < entry->FileOffset.QuadPart)
433 // Offset is ahead of entry. Return previous
438 if (Offset->QuadPart >= (entry->FileOffset.QuadPart + entry->Size))
441 // We start after this extent - carry on round
449 // Otherwise its a match
456 // Got to the end. Return Previous
462 AFSExtentContains( IN AFSExtent *Extent, IN PLARGE_INTEGER Offset)
468 return (Extent->FileOffset.QuadPart <= Offset->QuadPart &&
469 (Extent->FileOffset.QuadPart + Extent->Size) > Offset->QuadPart);
474 // Return the extent that contains the offset
477 AFSExtentForOffsetHint( IN AFSFcb *Fcb,
478 IN PLARGE_INTEGER Offset,
479 IN BOOLEAN ReturnPrevious,
482 AFSExtent *pPrevious = Hint;
486 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
488 #if AFS_VALIDATE_EXTENTS
489 VerifyExtentsLists(Fcb);
493 // So we will go across the skip lists until we find an
494 // appropriate entry (previous or direct match). If it's a match
495 // we are done, other wise we start on the next layer down
497 for (i = AFS_NUM_EXTENT_LISTS-1; i >= AFS_EXTENTS_LIST; i--)
499 if (NULL == pPrevious)
502 // We haven't found anything in the previous layers
504 pLe = Fcb->Specific.File.ExtentsLists[i].Flink;
506 else if (NULL == pPrevious->Lists[i].Flink)
508 ASSERT(AFS_EXTENTS_LIST != i);
510 // The hint doesn't exist at this level, next one down
517 // take the previous into the next
519 pLe = &pPrevious->Lists[i];
522 pPrevious = ExtentForOffsetInList( Fcb, pLe, i, Offset);
524 if (NULL != pPrevious && AFSExtentContains(pPrevious, Offset))
527 // Found it immediately. Stop here
533 if (NULL == pPrevious || ReturnPrevious )
538 ASSERT( !AFSExtentContains(pPrevious, Offset) );
544 AFSEntryForOffset( IN AFSFcb *Fcb,
545 IN PLARGE_INTEGER Offset)
547 AFSExtent *pPrevious = NULL;
551 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
553 #if AFS_VALIDATE_EXTENTS
554 VerifyExtentsLists(Fcb);
558 // So we will go across the skip lists until we find an
559 // appropriate entry (previous or direct match). If it's a match
560 // we are done, other wise we start on the next layer down
562 for (i = AFS_NUM_EXTENT_LISTS-1; i >= AFS_EXTENTS_LIST; i--)
564 if (NULL == pPrevious)
567 // We haven't found anything in the previous layers
569 pLe = Fcb->Specific.File.ExtentsLists[i].Flink;
571 else if (NULL == pPrevious->Lists[i].Flink)
573 ASSERT(AFS_EXTENTS_LIST != i);
575 // The hint doesn't exist at this level, next one down
582 // take the previous into the next
584 pLe = &pPrevious->Lists[i];
587 pPrevious = ExtentForOffsetInList( Fcb, pLe, i, Offset);
589 if (NULL != pPrevious && AFSExtentContains(pPrevious, Offset))
592 // Found it immediately. Stop here
602 AFSExtentForOffset( IN AFSFcb *Fcb,
603 IN PLARGE_INTEGER Offset,
604 IN BOOLEAN ReturnPrevious)
606 return AFSExtentForOffsetHint(Fcb, Offset, ReturnPrevious, NULL);
610 BOOLEAN AFSDoExtentsMapRegion(IN AFSFcb *Fcb,
611 IN PLARGE_INTEGER Offset,
613 IN OUT AFSExtent **FirstExtent,
614 OUT AFSExtent **LastExtent)
617 // Return TRUE region is completely mapped. FALSE
618 // otherwise. If the region isn't mapped then the last
619 // extent to map part of the region is returned.
621 // *LastExtent as input is where to start looking.
622 // *LastExtent as output is either the extent which
623 // contains the Offset, or the last one which doesn't
627 BOOLEAN retVal = FALSE;
632 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
633 AFS_TRACE_LEVEL_VERBOSE,
634 "AFSDoExtentsMapRegion Acquiring Fcb extent lock %08lX SHARED %08lX\n",
635 &Fcb->NPFcb->Specific.File.ExtentsResource,
636 PsGetCurrentThread());
638 AFSAcquireShared( &Fcb->NPFcb->Specific.File.ExtentsResource, TRUE );
642 entry = AFSExtentForOffsetHint(Fcb, Offset, TRUE, *FirstExtent);
643 *FirstExtent = entry;
645 if (NULL == entry || !AFSExtentContains(entry, Offset))
647 try_return (retVal = FALSE);
650 ASSERT(Offset->QuadPart >= entry->FileOffset.QuadPart);
654 if ((entry->FileOffset.QuadPart + entry->Size) >=
655 (Offset->QuadPart + Size))
658 // The end is inside the extent
660 try_return (retVal = TRUE);
663 if (entry->Lists[AFS_EXTENTS_LIST].Flink == &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
666 // Run out of extents
668 try_return (retVal = FALSE);
671 newEntry = NextExtent( entry, AFS_EXTENTS_LIST );
673 if (newEntry->FileOffset.QuadPart !=
674 (entry->FileOffset.QuadPart + entry->Size))
679 try_return (retVal = FALSE);
685 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
690 "EXCEPTION - AFSDoExtentsMapRegion\n");
692 AFSDumpTraceFilesFnc();
697 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
698 AFS_TRACE_LEVEL_VERBOSE,
699 "AFSDoExtentsMapRegion Releasing Fcb extent lock %08lX SHARED %08lX\n",
700 &Fcb->NPFcb->Specific.File.ExtentsResource,
701 PsGetCurrentThread());
703 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
712 AFSRequestExtentsAsync( IN AFSFcb *Fcb,
714 IN PLARGE_INTEGER Offset,
718 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
719 NTSTATUS ntStatus = STATUS_SUCCESS;
720 AFSExtent *pExtent = NULL;
721 AFSRequestExtentsCB request;
722 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
723 AFSExtent *pFirstExtent = NULL;
724 LARGE_INTEGER liAlignedOffset;
725 ULONG ulAlignedLength = 0;
726 BOOLEAN bRegionMapped = FALSE;
727 ULONGLONG ullProcessId = (ULONGLONG)PsGetCurrentProcessId();
732 ASSERT( !ExIsResourceAcquiredLite( &pNPFcb->Specific.File.ExtentsResource ));
735 // If the service set a failure on the file since the last
736 // CreateFile was issued, return it now.
739 if (!NT_SUCCESS( pNPFcb->Specific.File.ExtentsRequestStatus))
743 // If this isn't the same authgroup which caused the failure
744 // then try to request them again
747 if( RtlCompareMemory( &pNPFcb->Specific.File.ExtentsRequestAuthGroup,
749 sizeof( GUID)) == sizeof( GUID))
752 ntStatus = pNPFcb->Specific.File.ExtentsRequestStatus;
754 pNPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
756 RtlZeroMemory( &pNPFcb->Specific.File.ExtentsRequestAuthGroup,
759 try_return( ntStatus);
764 // Check if we are already mapped
767 bRegionMapped = AFSDoExtentsMapRegion( Fcb, Offset, Size, &pFirstExtent, &pExtent);
772 try_return( ntStatus = STATUS_SUCCESS);
776 // Align our request on extent size boundary
779 ulAlignedLength = Size;
781 liAlignedOffset = *Offset;
783 if( liAlignedOffset.QuadPart % pDevExt->Specific.RDR.CacheBlockSize != 0)
786 liAlignedOffset.QuadPart = (ULONGLONG)( (ULONGLONG)(liAlignedOffset.QuadPart / pDevExt->Specific.RDR.CacheBlockSize) * (ULONGLONG)pDevExt->Specific.RDR.CacheBlockSize);
788 ulAlignedLength += (ULONG)(Offset->QuadPart - liAlignedOffset.QuadPart);
791 if( ulAlignedLength % pDevExt->Specific.RDR.CacheBlockSize != 0)
794 ulAlignedLength = (ULONG)(((ulAlignedLength / pDevExt->Specific.RDR.CacheBlockSize) + 1) * pDevExt->Specific.RDR.CacheBlockSize);
797 RtlZeroMemory( &request,
798 sizeof( AFSRequestExtentsCB));
800 request.ByteOffset = liAlignedOffset;
801 request.Length = ulAlignedLength;
803 if( !AFSIsExtentRequestQueued( &Fcb->ObjectInformation->FileId,
808 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
809 AFS_TRACE_LEVEL_VERBOSE,
810 "AFSRequestExtentsAsync Request extents for fid %08lX-%08lX-%08lX-%08lX Offset %08lX Len %08lX Thread %08lX\n",
811 Fcb->ObjectInformation->FileId.Cell,
812 Fcb->ObjectInformation->FileId.Volume,
813 Fcb->ObjectInformation->FileId.Vnode,
814 Fcb->ObjectInformation->FileId.Unique,
815 request.ByteOffset.LowPart,
817 PsGetCurrentThread());
819 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS,
823 &Fcb->ObjectInformation->FileId,
825 sizeof( AFSRequestExtentsCB ),
829 if ( ntStatus == STATUS_ACCESS_DENIED)
834 ntStatus2 = AFSRetrieveValidAuthGroup( Fcb,
839 if ( NT_SUCCESS( ntStatus2) &&
840 RtlCompareMemory( &stAuthGroup,
842 sizeof( GUID)) != sizeof( GUID))
845 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS,
849 &Fcb->ObjectInformation->FileId,
851 sizeof( AFSRequestExtentsCB ),
857 if( NT_SUCCESS( ntStatus))
860 KeClearEvent( &pNPFcb->Specific.File.ExtentsRequestComplete );
866 KeClearEvent( &pNPFcb->Specific.File.ExtentsRequestComplete );
878 AFSProcessExtentsResult( IN AFSFcb *Fcb,
880 IN AFSFileExtentCB *Result)
882 NTSTATUS ntStatus = STATUS_SUCCESS;
883 AFSFileExtentCB *pFileExtents = Result;
886 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
887 ULONG fileExtentsUsed = 0;
888 BOOLEAN bFoundExtent = FALSE;
889 LIST_ENTRY *pSkipEntries[AFS_NUM_EXTENT_LISTS] = { 0 };
890 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
894 // Grab the extents exclusive for the duration
897 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
898 AFS_TRACE_LEVEL_VERBOSE,
899 "AFSProcessExtentsResult Acquiring Fcb extent lock %08lX EXCL %08lX\n",
900 &pNPFcb->Specific.File.ExtentsResource,
901 PsGetCurrentThread());
903 AFSAcquireExcl( &pNPFcb->Specific.File.ExtentsResource, TRUE );
909 // Find where to put the extents
911 for (ULONG i = AFS_EXTENTS_LIST; i < AFS_NUM_EXTENT_LISTS; i++)
914 pSkipEntries[i] = Fcb->Specific.File.ExtentsLists[i].Flink;
917 le = pSkipEntries[AFS_EXTENTS_LIST];
919 if (le == &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
922 // No extents. Insert at head of list (which is where the skip lists point!)
926 else if (0 != pFileExtents->FileOffset.QuadPart)
929 // We want to find the best extents immediately *behind* this offset
931 LARGE_INTEGER offset = pFileExtents->FileOffset;
934 // Ask in the top skip list first, then work down
936 for (LONG i = AFS_NUM_EXTENT_LISTS-1; i >= AFS_EXTENTS_LIST; i--)
938 pExtent = ExtentForOffsetInList( Fcb,
946 // No dice. Header has to become the head of the list
948 pSkipEntries[i] = &Fcb->Specific.File.ExtentsLists[i];
950 // And as a loop invariant we should never have found an extent
952 ASSERT(!bFoundExtent);
957 // pExtent is where to start to insert at this level
959 pSkipEntries[i] = &pExtent->Lists[i];
962 // And also where to start to look at the next level
965 if (i > AFS_EXTENTS_LIST)
967 pSkipEntries[i-1] = &pExtent->Lists[i-1];
975 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
980 le = pExtent->Lists[AFS_EXTENTS_LIST].Blink;
986 // Looking at offset 0, so we must start at the beginning
989 pExtent = ExtentFor(le, AFS_EXTENTS_LIST);
993 // And set up the skip lists
996 for (ULONG i = AFS_EXTENTS_LIST; i < AFS_NUM_EXTENT_LISTS; i++)
998 pSkipEntries[i] = &Fcb->Specific.File.ExtentsLists[i];
1002 while (fileExtentsUsed < Count)
1006 // Loop invariant - le points to where to insert after and
1007 // pExtent points to le->fLink
1010 ASSERT (NULL == pExtent ||
1011 le->Flink == &pExtent->Lists[AFS_EXTENTS_LIST]);
1013 if (NULL == pExtent ||
1014 pExtent->FileOffset.QuadPart > pFileExtents->FileOffset.QuadPart)
1017 // We need to insert a new extent at le. Start with
1018 // some sanity check on spanning
1020 if (NULL != pExtent &&
1021 ((pFileExtents->FileOffset.QuadPart + pFileExtents->Length) >
1022 pExtent->FileOffset.QuadPart))
1025 // File Extents overlaps pExtent
1027 ASSERT( (pFileExtents->FileOffset.QuadPart + pFileExtents->Length) <=
1028 pExtent->FileOffset.QuadPart);
1030 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1034 // File offset is entirely in front of this extent. Create
1035 // a new one (remember le is the previous list entry)
1037 pExtent = (AFSExtent *) AFSExAllocatePoolWithTag( NonPagedPool,
1040 if (NULL == pExtent)
1043 try_return (ntStatus = STATUS_INSUFFICIENT_RESOURCES );
1046 RtlZeroMemory( pExtent, sizeof( AFSExtent ));
1048 pExtent->FileOffset = pFileExtents->FileOffset;
1049 pExtent->CacheOffset = pFileExtents->CacheOffset;
1050 pExtent->Size = pFileExtents->Length;
1052 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1053 AFS_TRACE_LEVEL_VERBOSE,
1054 "AFSProcessExtentsResult Received extent for fid %08lX-%08lX-%08lX-%08lX File Offset %I64X Cache Offset %I64X Len %08lX\n",
1055 Fcb->ObjectInformation->FileId.Cell,
1056 Fcb->ObjectInformation->FileId.Volume,
1057 Fcb->ObjectInformation->FileId.Vnode,
1058 Fcb->ObjectInformation->FileId.Unique,
1059 pFileExtents->FileOffset.QuadPart,
1060 pFileExtents->CacheOffset.QuadPart,
1061 pFileExtents->Length);
1063 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, (LONG)(pExtent->Size/1024));
1065 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, (LONG)(pExtent->Size/1024));
1067 lCount = InterlockedIncrement( &Fcb->Specific.File.ExtentCount);
1069 lCount = InterlockedIncrement( &pControlDevExt->Specific.Control.ExtentCount);
1074 KeClearEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent);
1080 InsertHeadList(le, &pExtent->Lists[AFS_EXTENTS_LIST]);
1081 ASSERT(le->Flink == &pExtent->Lists[AFS_EXTENTS_LIST]);
1082 ASSERT(0 == (pExtent->FileOffset.LowPart & ExtentsMasks[AFS_EXTENTS_LIST]));
1085 // Do not move the cursor - we will do it next time
1089 // And into the (upper) skip lists - Again, do not move the cursor
1091 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1093 if (0 == (pExtent->FileOffset.LowPart & ExtentsMasks[i]))
1095 InsertHeadList(pSkipEntries[i], &pExtent->Lists[i]);
1096 #if AFS_VALIDATE_EXTENTS
1097 VerifyExtentsLists(Fcb);
1102 else if (pExtent->FileOffset.QuadPart == pFileExtents->FileOffset.QuadPart)
1105 if (pExtent->Size != pFileExtents->Length)
1108 ASSERT (pExtent->Size == pFileExtents->Length);
1110 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1114 // Move both cursors forward.
1116 // First the extent pointer
1119 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1122 // Then the skip lists cursors forward if needed
1124 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1126 if (0 == (pExtent->FileOffset.LowPart & ExtentsMasks[i]))
1129 // Check sanity before
1131 #if AFS_VALIDATE_EXTENTS
1132 VerifyExtentsLists(Fcb);
1136 // Skip list should point to us
1138 //ASSERT(pSkipEntries[i] == &pExtent->Lists[i]);
1140 // Move forward cursor
1142 pSkipEntries[i] = pSkipEntries[i]->Flink;
1144 // Check sanity before
1146 #if AFS_VALIDATE_EXTENTS
1147 VerifyExtentsLists(Fcb);
1153 // And then the cursor in the supplied array
1159 // setup pExtent if there is one
1161 if (le->Flink != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
1163 pExtent = NextExtent( pExtent, AFS_EXTENTS_LIST ) ;
1173 ASSERT( pExtent->FileOffset.QuadPart < pFileExtents->FileOffset.QuadPart );
1176 // Sanity check on spanning
1178 if ((pExtent->FileOffset.QuadPart + pExtent->Size) >
1179 pFileExtents->FileOffset.QuadPart)
1182 ASSERT( (pExtent->FileOffset.QuadPart + pExtent->Size) <=
1183 pFileExtents->FileOffset.QuadPart);
1185 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1189 // Move le and pExtent forward
1191 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1195 // Then the check the skip lists cursors
1197 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1199 if (0 == (pFileExtents->FileOffset.LowPart & ExtentsMasks[i]))
1203 // - empty list (pSkipEntries[i]->Flink == pSkipEntries[i]->Flink == fcb->lists[i]
1204 // - We are the last on the list (pSkipEntries[i]->Flink == fcb->lists[i])
1205 // - We are not the last on the list. In that case we have to be strictly less than
1207 if (pSkipEntries[i]->Flink != &Fcb->Specific.File.ExtentsLists[i]) {
1209 AFSExtent *otherExtent = ExtentFor(pSkipEntries[i]->Flink, i);
1210 ASSERT(pFileExtents->FileOffset.QuadPart < otherExtent->FileOffset.QuadPart);
1217 // setup pExtent if there is one
1220 if (le->Flink != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
1222 pExtent = NextExtent( pExtent, AFS_EXTENTS_LIST ) ;
1232 // All done, signal that we are done drop the lock, exit
1237 if( !NT_SUCCESS( ntStatus))
1241 // If we failed the service is going to drop all extents so trim away the
1245 AFSTrimSpecifiedExtents( Fcb,
1250 #if AFS_VALIDATE_EXTENTS
1251 VerifyExtentsLists(Fcb);
1254 KeSetEvent( &pNPFcb->Specific.File.ExtentsRequestComplete,
1258 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1259 AFS_TRACE_LEVEL_VERBOSE,
1260 "AFSProcessExtentsResult Releasing Fcb extent lock %08lX EXCL %08lX\n",
1261 &pNPFcb->Specific.File.ExtentsResource,
1262 PsGetCurrentThread());
1264 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
1271 AFSProcessSetFileExtents( IN AFSSetFileExtentsCB *SetExtents )
1273 AFSFcb *pFcb = NULL;
1274 AFSVolumeCB *pVolumeCB = NULL;
1275 NTSTATUS ntStatus = STATUS_SUCCESS;
1276 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1277 ULONGLONG ullIndex = 0;
1278 AFSObjectInfoCB *pObjectInfo = NULL;
1284 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1285 AFS_TRACE_LEVEL_VERBOSE,
1286 "AFSProcessSetFileExtents Acquiring RDR VolumeTreeLock lock %08lX SHARED %08lX\n",
1287 &pDevExt->Specific.RDR.VolumeTreeLock,
1288 PsGetCurrentThread());
1290 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
1292 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1293 AFS_TRACE_LEVEL_VERBOSE,
1294 "AFSProcessSetFileExtents Set extents for fid %08lX-%08lX-%08lX-%08lX\n",
1295 SetExtents->FileId.Cell,
1296 SetExtents->FileId.Volume,
1297 SetExtents->FileId.Vnode,
1298 SetExtents->FileId.Unique);
1301 // Locate the volume node
1304 ullIndex = AFSCreateHighIndex( &SetExtents->FileId);
1306 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
1308 (AFSBTreeEntry **)&pVolumeCB);
1310 if( pVolumeCB != NULL)
1313 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1314 AFS_TRACE_LEVEL_VERBOSE,
1315 "AFSProcessSetFileExtents Acquiring VolumeRoot FileIDTree.TreeLock lock %08lX SHARED %08lX\n",
1316 pVolumeCB->ObjectInfoTree.TreeLock,
1317 PsGetCurrentThread());
1319 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1322 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
1324 if( !NT_SUCCESS( ntStatus) ||
1328 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1329 AFS_TRACE_LEVEL_ERROR,
1330 "AFSProcessSetFileExtents Set extents for fid %08lX-%08lX-%08lX-%08lX Failed to locate volume Status %08lX\n",
1331 SetExtents->FileId.Cell,
1332 SetExtents->FileId.Volume,
1333 SetExtents->FileId.Vnode,
1334 SetExtents->FileId.Unique,
1337 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1340 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1343 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1346 // Now locate the Object in this volume
1349 ullIndex = AFSCreateLowIndex( &SetExtents->FileId);
1351 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
1353 (AFSBTreeEntry **)&pObjectInfo);
1355 if( pObjectInfo != NULL)
1359 // Reference the node so it won't be torn down
1362 lCount = InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
1364 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1365 AFS_TRACE_LEVEL_VERBOSE,
1366 "AFSProcessSetFileExtents Increment count on object %08lX Cnt %d\n",
1371 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1373 if( !NT_SUCCESS( ntStatus) ||
1374 pObjectInfo == NULL)
1377 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1378 AFS_TRACE_LEVEL_ERROR,
1379 "AFSProcessSetFileExtents Set extents for hash %I64X fid %08lX-%08lX-%08lX-%08lX Failed to locate file in volume %08lX\n",
1381 SetExtents->FileId.Cell,
1382 SetExtents->FileId.Volume,
1383 SetExtents->FileId.Vnode,
1384 SetExtents->FileId.Unique,
1387 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1390 pFcb = pObjectInfo->Fcb;
1393 // If we have a result failure then don't bother trying to set the extents
1396 if( SetExtents->ResultStatus != STATUS_SUCCESS)
1399 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1400 AFS_TRACE_LEVEL_ERROR,
1401 "AFSProcessSetFileExtents Set extents failure fid %08lX-%08lX-%08lX-%08lX ResultStatus %08lX\n",
1402 SetExtents->FileId.Cell,
1403 SetExtents->FileId.Volume,
1404 SetExtents->FileId.Vnode,
1405 SetExtents->FileId.Unique,
1406 SetExtents->ResultStatus);
1408 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1409 AFS_TRACE_LEVEL_VERBOSE,
1410 "AFSProcessSetFileExtents Acquiring Fcb extents lock %08lX EXCL %08lX\n",
1411 &pFcb->NPFcb->Specific.File.ExtentsResource,
1412 PsGetCurrentThread());
1414 AFSAcquireExcl( &pFcb->NPFcb->Specific.File.ExtentsResource,
1417 pFcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_CANCELLED;
1419 KeSetEvent( &pFcb->NPFcb->Specific.File.ExtentsRequestComplete,
1423 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1424 AFS_TRACE_LEVEL_VERBOSE,
1425 "AFSProcessSetFileExtents Releasing Fcb extent lock %08lX EXCL %08lX\n",
1426 &pFcb->NPFcb->Specific.File.ExtentsResource,
1427 PsGetCurrentThread());
1429 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
1431 try_return( ntStatus);
1434 ntStatus = AFSProcessExtentsResult ( pFcb,
1435 SetExtents->ExtentCount,
1436 SetExtents->FileExtents );
1440 if( pObjectInfo != NULL)
1443 lCount = InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
1445 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1446 AFS_TRACE_LEVEL_VERBOSE,
1447 "AFSProcessSetFileExtents Decrement count on object %08lX Cnt %d\n",
1457 // Helper fuctions for Usermode initiation of release of extents
1460 AFSReleaseSpecifiedExtents( IN AFSReleaseFileExtentsCB *Extents,
1462 OUT AFSFileExtentCB *FileExtents,
1463 IN ULONG BufferSize,
1464 OUT ULONG *ExtentCount,
1465 OUT BOOLEAN *DirtyExtents)
1470 ULONG ulExtentCount = 0;
1471 NTSTATUS ntStatus = STATUS_SUCCESS;
1472 BOOLEAN bReleaseAll = FALSE;
1473 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1478 ASSERT( ExIsResourceAcquiredExclusiveLite( &Fcb->NPFcb->Specific.File.ExtentsResource));
1480 if (BufferSize < (Extents->ExtentCount * sizeof( AFSFileExtentCB)))
1483 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1484 AFS_TRACE_LEVEL_VERBOSE,
1485 "AFSReleaseSpecifiedExtents Buffer too small\n");
1487 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL);
1490 RtlZeroMemory( FileExtents, BufferSize);
1493 *DirtyExtents = FALSE;
1496 // iterate until we have dealt with all we were asked for or
1497 // are at the end of the list. Note that this deals (albeit
1498 // badly) with out of order extents
1501 pExtent = AFSExtentForOffset( Fcb,
1502 &Extents->FileExtents[0].FileOffset,
1505 if (NULL == pExtent)
1507 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1511 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1515 if( BooleanFlagOn( Extents->Flags, AFS_RELEASE_EXTENTS_FLAGS_RELEASE_ALL) ||
1516 ( Extents->FileId.Cell == 0 &&
1517 Extents->FileId.Volume == 0 &&
1518 Extents->FileId.Vnode == 0 &&
1519 Extents->FileId.Unique == 0))
1525 while( le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST] &&
1526 ulExtentCount < Extents->ExtentCount)
1530 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
1535 if( pExtent->FileOffset.QuadPart < Extents->FileExtents[ulExtentCount].FileOffset.QuadPart)
1538 // Skip forward through the extent list until we get
1539 // to the one we want
1545 else if (pExtent->FileOffset.QuadPart > Extents->FileExtents[ulExtentCount].FileOffset.QuadPart)
1548 // We don't have the extent asked for so return UNKNOWN
1551 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1552 AFS_TRACE_LEVEL_VERBOSE,
1553 "AFSReleaseSpecifiedExtents Located UNKNOWN extent Offset %I64X Len %08lX\n",
1554 Extents->FileExtents[ulExtentCount].FileOffset.QuadPart,
1555 Extents->FileExtents[ulExtentCount].Length);
1557 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_UNKNOWN;
1559 FileExtents[*ExtentCount].Length = 0;
1560 FileExtents[*ExtentCount].CacheOffset.QuadPart = 0;
1561 FileExtents[*ExtentCount].FileOffset = Extents->FileExtents[ulExtentCount].FileOffset;
1563 *ExtentCount = (*ExtentCount) + 1;
1568 // Reset where we are looking
1571 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1575 else if( pExtent->ActiveCount > 0)
1578 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1579 AFS_TRACE_LEVEL_VERBOSE,
1580 "AFSReleaseSpecifiedExtents Located IN_USE extent Offset %I64X Len %08lX\n",
1581 Extents->FileExtents[ulExtentCount].FileOffset.QuadPart,
1582 Extents->FileExtents[ulExtentCount].Length);
1584 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_IN_USE;
1586 FileExtents[*ExtentCount].Length = 0;
1587 FileExtents[*ExtentCount].CacheOffset.QuadPart = 0;
1588 FileExtents[*ExtentCount].FileOffset = Extents->FileExtents[ulExtentCount].FileOffset;
1590 *ExtentCount = (*ExtentCount) + 1;
1595 // Reset where we are looking
1598 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1607 // If the extent is currently active then skip it
1610 if( pExtent->ActiveCount > 0)
1619 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_RELEASE;
1621 FileExtents[*ExtentCount].Length = pExtent->Size;
1622 FileExtents[*ExtentCount].DirtyLength = pExtent->Size;
1623 FileExtents[*ExtentCount].DirtyOffset = 0;
1624 FileExtents[*ExtentCount].CacheOffset = pExtent->CacheOffset;
1625 FileExtents[*ExtentCount].FileOffset = pExtent->FileOffset;
1627 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1628 AFS_TRACE_LEVEL_VERBOSE,
1629 "AFSReleaseSpecifiedExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
1631 Fcb->ObjectInformation->FileId.Cell,
1632 Fcb->ObjectInformation->FileId.Volume,
1633 Fcb->ObjectInformation->FileId.Vnode,
1634 Fcb->ObjectInformation->FileId.Unique,
1635 FileExtents[*ExtentCount].FileOffset.QuadPart,
1636 FileExtents[*ExtentCount].Length);
1638 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
1641 AFSAcquireExcl( &Fcb->NPFcb->Specific.File.DirtyExtentsListLock,
1644 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
1647 AFSRemoveEntryDirtyList( Fcb,
1650 FileExtents[*ExtentCount].Flags |= AFS_EXTENT_FLAG_DIRTY;
1652 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
1654 *DirtyExtents = TRUE;
1657 AFSReleaseResource( &Fcb->NPFcb->Specific.File.DirtyExtentsListLock);
1661 // move forward all three cursors
1665 *ExtentCount = (*ExtentCount) + 1;
1680 AFSFindFcbToClean(ULONG IgnoreTime, AFSFcb *LastFcb, BOOLEAN Block)
1683 AFSFcb *pFcb = NULL;
1684 AFSVolumeCB *pVolumeCB = NULL;
1685 AFSDeviceExt *pRDRDeviceExt = NULL;
1686 AFSDeviceExt *pControlDeviceExt = NULL;
1687 BOOLEAN bLocatedEntry = FALSE;
1688 AFSObjectInfoCB *pCurrentObject = NULL;
1689 BOOLEAN bReleaseVolumeListLock = FALSE;
1692 pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1693 pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1695 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1696 AFS_TRACE_LEVEL_VERBOSE,
1697 "AFSFindFcbToClean Acquiring RDR VolumeListLock lock %08lX SHARED %08lX\n",
1698 &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1699 PsGetCurrentThread());
1701 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1704 bReleaseVolumeListLock = TRUE;
1706 pVolumeCB = pRDRDeviceExt->Specific.RDR.VolumeListHead;
1708 while( pVolumeCB != NULL)
1712 // The Volume list may move under our feet. Lock it.
1715 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1716 AFS_TRACE_LEVEL_VERBOSE,
1717 "AFSFindFcbToClean Acquiring VolumeRoot ObjectInfoTree lock %08lX SHARED %08lX\n",
1718 pVolumeCB->ObjectInfoTree.TreeLock,
1719 PsGetCurrentThread());
1721 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1723 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1725 bReleaseVolumeListLock = FALSE;
1727 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1730 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1732 if( NULL == LastFcb)
1735 pCurrentObject = pVolumeCB->ObjectInfoListHead;
1740 pCurrentObject = (AFSObjectInfoCB *)LastFcb->ObjectInformation->ListEntry.fLink;
1745 while( pCurrentObject != NULL)
1748 pFcb = (AFSFcb *)pCurrentObject->Fcb;
1751 // If the FCB is a candidate we try to lock it (but without waiting - which
1752 // means we are deadlock free
1756 pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
1762 AFSLockForExtentsTrim( pFcb);
1767 if( !AFSLockForExtentsTrimNoWait( pFcb))
1770 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1779 // Need to be sure there are no current flushes in the queue
1782 if( pFcb->Specific.File.ExtentCount == 0)
1785 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1786 AFS_TRACE_LEVEL_VERBOSE,
1787 "AFSFindFcbToClean Releasing Fcb extent lock %08lX thread %08lX\n",
1788 &pFcb->NPFcb->Specific.File.ExtentsResource,
1789 PsGetCurrentThread());
1791 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
1793 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1800 if( pFcb->Specific.File.QueuedFlushCount > 0)
1803 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1804 AFS_TRACE_LEVEL_VERBOSE,
1805 "AFSFindFcbToClean Releasing Fcb extent lock %08lX thread %08lX\n",
1806 &pFcb->NPFcb->Specific.File.ExtentsResource,
1807 PsGetCurrentThread());
1809 AFSReleaseResource(&pFcb->NPFcb->Specific.File.ExtentsResource);
1813 AFSWaitOnQueuedFlushes( pFcb);
1818 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1826 if( pFcb->OpenHandleCount > 0)
1829 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1830 AFS_TRACE_LEVEL_VERBOSE,
1831 "AFSFindFcbToClean Releasing Fcb extent lock %08lX thread %08lX\n",
1832 &pFcb->NPFcb->Specific.File.ExtentsResource,
1833 PsGetCurrentThread());
1835 AFSReleaseResource(&pFcb->NPFcb->Specific.File.ExtentsResource);
1837 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1845 // A hit a very palpable hit. Pin it
1848 lCount = InterlockedIncrement( &pCurrentObject->ObjectReferenceCount);
1850 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1851 AFS_TRACE_LEVEL_VERBOSE,
1852 "AFSFindFcbToClean Increment count on Fcb %08lX Cnt %d\n",
1856 bLocatedEntry = TRUE;
1861 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1866 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1873 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1876 bReleaseVolumeListLock = TRUE;
1878 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1881 if( bReleaseVolumeListLock)
1884 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1891 AFSProcessExtentFailure( PIRP Irp)
1893 AFSExtentFailureCB *pFailureCB = NULL;
1894 NTSTATUS ntStatus = STATUS_SUCCESS;
1895 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
1896 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1897 AFSVolumeCB *pVolumeCB = NULL;
1898 ULONGLONG ullIndex = 0;
1899 AFSObjectInfoCB *pObjectInfo = NULL;
1904 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSExtentFailureCB))
1907 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1908 AFS_TRACE_LEVEL_ERROR,
1909 "AFSProcessExtentFailure Input buffer too small\n");
1911 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1914 pFailureCB = (AFSExtentFailureCB *)Irp->AssociatedIrp.SystemBuffer;
1916 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1917 AFS_TRACE_LEVEL_ERROR,
1918 "AFSProcessExtentFailure Service Reports Failure fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1919 pFailureCB->FileId.Cell,
1920 pFailureCB->FileId.Volume,
1921 pFailureCB->FileId.Vnode,
1922 pFailureCB->FileId.Unique,
1923 pFailureCB->FailureStatus);
1925 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
1928 // Locate the volume node
1931 ullIndex = AFSCreateHighIndex( &pFailureCB->FileId);
1933 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
1935 (AFSBTreeEntry **)&pVolumeCB);
1937 if( pVolumeCB != NULL)
1940 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1941 AFS_TRACE_LEVEL_VERBOSE,
1942 "AFSProcessExtentFailure Acquiring VolumeRoot FileIDTree.TreeLock lock %08lX SHARED %08lX\n",
1943 pVolumeCB->ObjectInfoTree.TreeLock,
1944 PsGetCurrentThread());
1946 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1949 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
1951 if( !NT_SUCCESS( ntStatus) ||
1955 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1956 AFS_TRACE_LEVEL_ERROR,
1957 "AFSProcessExtentFailure Invalid volume index %I64X status %08X\n",
1958 ullIndex, ntStatus);
1960 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1963 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1966 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1969 // Now locate the Object in this volume
1972 ullIndex = AFSCreateLowIndex( &pFailureCB->FileId);
1974 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
1976 (AFSBTreeEntry **)&pObjectInfo);
1978 if( pObjectInfo != NULL &&
1979 pObjectInfo->Fcb != NULL)
1983 // Reference the node so it won't be torn down
1986 lCount = InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
1988 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1989 AFS_TRACE_LEVEL_VERBOSE,
1990 "AFSProcessExtentFailure Increment count on object %08lX Cnt %d\n",
1995 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1997 if( !NT_SUCCESS( ntStatus) ||
1998 pObjectInfo == NULL ||
1999 pObjectInfo->Fcb == NULL)
2002 if( pObjectInfo == NULL)
2004 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2005 AFS_TRACE_LEVEL_ERROR,
2006 "AFSProcessExtentFailure Invalid file index %I64X\n",
2011 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2012 AFS_TRACE_LEVEL_ERROR,
2013 "AFSProcessExtentFailure Fcb dealocated for %I64X\n",
2017 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2020 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2021 AFS_TRACE_LEVEL_VERBOSE,
2022 "AFSProcessExtentFailure Acquiring Fcb extent lock %08lX EXCL %08lX\n",
2023 &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2024 PsGetCurrentThread());
2026 AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2029 pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestStatus = pFailureCB->FailureStatus;
2031 RtlCopyMemory( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2032 &pFailureCB->AuthGroup,
2035 KeSetEvent( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
2039 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2040 AFS_TRACE_LEVEL_VERBOSE,
2041 "AFSProcessExtentFailure Releasing Fcb extent lock %08lX EXCL %08lX\n",
2042 &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2043 PsGetCurrentThread());
2045 AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource);
2047 lCount = InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
2049 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2050 AFS_TRACE_LEVEL_VERBOSE,
2051 "AFSProcessExtentFailure Decrement count on object %08lX Cnt %d\n",
2064 AFSProcessReleaseFileExtents( IN PIRP Irp)
2066 NTSTATUS ntStatus = STATUS_SUCCESS;
2067 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2068 PFILE_OBJECT pFileObject = pIrpSp->FileObject;
2069 AFSFcb *pFcb = NULL;
2070 AFSVolumeCB *pVolumeCB = NULL;
2071 AFSDeviceExt *pDevExt;
2072 AFSReleaseFileExtentsCB *pExtents;
2073 AFSReleaseFileExtentsResultCB *pResult = NULL;
2074 AFSReleaseFileExtentsResultFileCB *pFile = NULL;
2076 ULONGLONG ullIndex = 0;
2077 AFSObjectInfoCB *pObjectInfo = NULL;
2078 BOOLEAN bLocked = FALSE;
2079 BOOLEAN bDirtyExtents = FALSE;
2086 pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2088 pExtents = (AFSReleaseFileExtentsCB*) Irp->AssociatedIrp.SystemBuffer;
2090 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2091 sizeof( AFSReleaseFileExtentsCB))
2094 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2095 AFS_TRACE_LEVEL_ERROR,
2096 "AFSProcessReleaseFileExtents INPUT Buffer too small\n");
2098 try_return( ntStatus = STATUS_INVALID_PARAMETER );
2101 if ( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength <
2102 sizeof(AFSReleaseFileExtentsResultCB))
2105 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2106 AFS_TRACE_LEVEL_ERROR,
2107 "AFSProcessReleaseFileExtents OUTPUT Buffer too small [1]\n");
2110 // Must have space for one extent in one file
2113 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL);
2116 if (pExtents->ExtentCount == 0)
2119 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2120 AFS_TRACE_LEVEL_ERROR,
2121 "AFSProcessReleaseFileExtents Extent count zero\n");
2123 try_return( ntStatus = STATUS_INVALID_PARAMETER);
2126 if (pExtents->FileId.Cell != 0 ||
2127 pExtents->FileId.Volume != 0 ||
2128 pExtents->FileId.Vnode != 0 ||
2129 pExtents->FileId.Unique != 0)
2132 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2133 AFS_TRACE_LEVEL_VERBOSE,
2134 "AFSProcessReleaseFileExtents Processing FID %08lX:%08lX:%08lX:%08lX\n",
2135 pExtents->FileId.Cell,
2136 pExtents->FileId.Volume,
2137 pExtents->FileId.Vnode,
2138 pExtents->FileId.Unique);
2140 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2141 ( FIELD_OFFSET( AFSReleaseFileExtentsCB, ExtentCount) + sizeof(ULONG)) ||
2142 pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2143 ( FIELD_OFFSET( AFSReleaseFileExtentsCB, ExtentCount) + sizeof(ULONG) +
2144 sizeof (AFSFileExtentCB) * pExtents->ExtentCount))
2147 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2148 AFS_TRACE_LEVEL_ERROR,
2149 "AFSProcessReleaseFileExtents Buffer too small for FID %08lX:%08lx:%08lX:%08lX\n",
2150 pExtents->FileId.Cell,
2151 pExtents->FileId.Volume,
2152 pExtents->FileId.Vnode,
2153 pExtents->FileId.Unique);
2155 try_return( ntStatus = STATUS_INVALID_PARAMETER );
2158 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2159 AFS_TRACE_LEVEL_VERBOSE,
2160 "AFSProcessReleaseFileExtents Acquiring RDR VolumeTreeLock lock %08lX SHARED %08lX\n",
2161 &pDevExt->Specific.RDR.VolumeTreeLock,
2162 PsGetCurrentThread());
2164 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
2167 // Locate the volume node
2170 ullIndex = AFSCreateHighIndex( &pExtents->FileId);
2172 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
2174 (AFSBTreeEntry **)&pVolumeCB);
2176 if( pVolumeCB != NULL)
2179 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2180 AFS_TRACE_LEVEL_VERBOSE,
2181 "AFSProcessReleaseFileExtents Acquiring VolumeRoot FileIDTree.TreeLock lock %08lX SHARED %08lX\n",
2182 pVolumeCB->ObjectInfoTree.TreeLock,
2183 PsGetCurrentThread());
2185 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
2188 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
2190 if( !NT_SUCCESS( ntStatus) ||
2194 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2195 AFS_TRACE_LEVEL_ERROR,
2196 "AFSProcessReleaseFileExtents Invalid volume index %I64X status %08X\n",
2197 ullIndex, ntStatus);
2199 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2202 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
2205 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
2208 // Now locate the Object in this volume
2211 ullIndex = AFSCreateLowIndex( &pExtents->FileId);
2213 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
2215 (AFSBTreeEntry **)&pObjectInfo);
2217 if( pObjectInfo != NULL)
2221 // Reference the node so it won't be torn down
2224 lCount = InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
2226 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2227 AFS_TRACE_LEVEL_VERBOSE,
2228 "AFSProcessReleaseFileExtents Increment count on object %08lX Cnt %d\n",
2233 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2235 if( !NT_SUCCESS( ntStatus) ||
2236 pObjectInfo == NULL)
2239 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2240 AFS_TRACE_LEVEL_ERROR,
2241 "AFSProcessReleaseFileExtents Invalid file index %I64X\n",
2244 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2247 pFcb = pObjectInfo->Fcb;
2252 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2253 AFS_TRACE_LEVEL_ERROR,
2254 "AFSProcessReleaseFileExtents Fcb not initialied (NO EXTENTS) for FID %08lX:%08lx:%08lX:%08lX\n",
2255 pExtents->FileId.Cell,
2256 pExtents->FileId.Volume,
2257 pExtents->FileId.Vnode,
2258 pExtents->FileId.Unique);
2260 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2263 AFSLockForExtentsTrim( pFcb );
2271 // Locate an Fcb to trim down
2274 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2275 AFS_TRACE_LEVEL_VERBOSE,
2276 "AFSProcessReleaseFileExtents Searching for a Fcb to Trim Down\n");
2278 pFcb = AFSFindFcbToClean( 0, NULL, FALSE);
2283 pFcb = AFSFindFcbToClean( 0, NULL, TRUE);
2289 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2290 AFS_TRACE_LEVEL_ERROR,
2291 "AFSProcessReleaseFileExtents Failed to locate Fcb for release ...\n");
2293 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2296 pObjectInfo = pFcb->ObjectInformation;
2302 // Allocate a scratch buffer to move in the extent information
2305 ulSz = (pExtents->ExtentCount-1) * sizeof(AFSFileExtentCB);
2306 ulSz += sizeof(AFSReleaseFileExtentsResultCB);
2308 if (ulSz > pIrpSp->Parameters.DeviceIoControl.OutputBufferLength)
2310 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2311 AFS_TRACE_LEVEL_ERROR,
2312 "AFSProcessReleaseFileExtents OUTPUT Buffer too small [2]\n");
2314 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL );
2317 pResult = (AFSReleaseFileExtentsResultCB*) AFSExAllocatePoolWithTag( PagedPool,
2319 AFS_EXTENTS_RESULT_TAG);
2320 if (NULL == pResult)
2323 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2324 AFS_TRACE_LEVEL_ERROR,
2325 "AFSProcessReleaseFileExtents Failed to allocate result block\n");
2327 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2331 // Set up the header (for an array of one)
2333 pResult->FileCount = 1;
2334 pResult->Flags = AFS_EXTENT_FLAG_RELEASE;
2335 ulSz -= FIELD_OFFSET(AFSReleaseFileExtentsResultCB, Files);
2338 // Setup the first (and only) file
2340 pFile = pResult->Files;
2341 pFile->FileId = pObjectInfo->FileId;
2342 pFile->Flags = AFS_EXTENT_FLAG_RELEASE;
2345 // Stash away the auth group
2348 RtlZeroMemory( &stAuthGroup,
2351 ntStatus = AFSRetrieveValidAuthGroup( pFcb,
2356 if( !NT_SUCCESS( ntStatus))
2358 try_return( ntStatus);
2361 RtlCopyMemory( &pFile->AuthGroup,
2366 // Update the metadata for this call
2369 pFile->AllocationSize = pFcb->ObjectInformation->EndOfFile;
2370 pFile->CreateTime = pFcb->ObjectInformation->CreationTime;
2371 pFile->ChangeTime = pFcb->ObjectInformation->ChangeTime;
2372 pFile->LastAccessTime = pFcb->ObjectInformation->LastAccessTime;
2373 pFile->LastWriteTime = pFcb->ObjectInformation->LastWriteTime;
2375 ulSz -= FIELD_OFFSET(AFSReleaseFileExtentsResultFileCB, FileExtents);
2377 ntStatus = AFSReleaseSpecifiedExtents( pExtents,
2381 &pFile->ExtentCount,
2384 if (!NT_SUCCESS(ntStatus))
2387 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2388 AFS_TRACE_LEVEL_ERROR,
2389 "AFSProcessReleaseFileExtents Failed to release extents Status %08lX\n",
2392 try_return( ntStatus );
2395 if( pExtents->ExtentCount == 0)
2398 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2399 AFS_TRACE_LEVEL_WARNING,
2400 "AFSProcessReleaseFileExtents Failed to release ANY extents\n");
2403 ulSz = sizeof(AFSReleaseFileExtentsResultCB);
2405 if( pExtents->ExtentCount > 0)
2407 ulSz += ((pExtents->ExtentCount-1) * sizeof(AFSFileExtentCB));
2410 RtlCopyMemory( Irp->AssociatedIrp.SystemBuffer,
2419 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2420 AFS_TRACE_LEVEL_VERBOSE,
2421 "AFSProcessReleaseFileExtents Releasing Fcb extent lock %08lX thread %08lX\n",
2422 &pFcb->NPFcb->Specific.File.ExtentsResource,
2423 PsGetCurrentThread());
2425 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
2428 if( NULL != pResult &&
2429 Irp->AssociatedIrp.SystemBuffer != pResult)
2432 AFSExFreePoolWithTag(pResult, AFS_EXTENTS_RESULT_TAG);
2435 if (NT_SUCCESS(ntStatus))
2437 Irp->IoStatus.Information = ulSz;
2441 Irp->IoStatus.Information = 0;
2444 Irp->IoStatus.Status = ntStatus;
2446 if( pObjectInfo != NULL)
2449 lCount = InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
2451 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2452 AFS_TRACE_LEVEL_VERBOSE,
2453 "AFSProcessReleaseFileExtents Decrement count on object %08lX Cnt %d\n",
2463 AFSWaitForExtentMapping( AFSFcb *Fcb,
2466 NTSTATUS ntStatus = STATUS_SUCCESS;
2467 LARGE_INTEGER liTimeOut;
2468 ULONGLONG ullProcessId = (ULONGLONG)PsGetCurrentProcessId();
2473 ASSERT( !ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
2475 if (!NT_SUCCESS( Fcb->NPFcb->Specific.File.ExtentsRequestStatus))
2479 // If this isn't the same authgroup which caused the failure
2480 // then try to request them again
2483 if( RtlCompareMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2485 sizeof( GUID)) == sizeof( GUID))
2488 ntStatus = Fcb->NPFcb->Specific.File.ExtentsRequestStatus;
2490 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
2492 RtlZeroMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2495 try_return( ntStatus);
2499 liTimeOut.QuadPart = -(1 * AFS_ONE_SECOND);
2501 ntStatus = KeWaitForSingleObject( &Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
2507 if (!NT_SUCCESS( Fcb->NPFcb->Specific.File.ExtentsRequestStatus))
2511 // If this isn't the same authgroup which caused the failure
2512 // or the System Process,
2513 // then try to request the extents again
2516 if( RtlCompareMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2518 sizeof( GUID)) == sizeof( GUID) ||
2519 ullProcessId == (ULONGLONG)AFSSysProcess)
2522 ntStatus = Fcb->NPFcb->Specific.File.ExtentsRequestStatus;
2524 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
2526 RtlZeroMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2529 try_return( ntStatus);
2533 if( ntStatus == STATUS_TIMEOUT)
2536 ntStatus = STATUS_SUCCESS;
2548 AFSFlushExtents( IN AFSFcb *Fcb,
2551 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
2552 AFSExtent *pExtent, *pNextExtent;
2554 AFSReleaseExtentsCB *pRelease = NULL;
2556 ULONG initialDirtyCount = 0;
2557 BOOLEAN bExtentsLocked = FALSE;
2560 NTSTATUS ntStatus = STATUS_SUCCESS;
2561 LARGE_INTEGER liLastFlush;
2562 AFSExtent *pDirtyListHead = NULL, *pDirtyListTail = NULL;
2563 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2564 GUID *pAuthGroup = AuthGroup;
2568 ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
2571 // Save, then reset the flush time
2574 liLastFlush = Fcb->Specific.File.LastServerFlush;
2576 KeQueryTickCount( &Fcb->Specific.File.LastServerFlush);
2581 if( pAuthGroup == NULL ||
2582 RtlCompareMemory( pAuthGroup,
2583 &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2584 sizeof( GUID)) == sizeof( GUID))
2587 RtlZeroMemory( &stAuthGroup,
2590 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
2595 if( !NT_SUCCESS( ntStatus))
2597 try_return( ntStatus);
2600 pAuthGroup = &stAuthGroup;
2604 // Lock extents while we count and set up the array to send to
2608 AFSLockForExtentsTrim( Fcb);
2610 bExtentsLocked = TRUE;
2612 lCount = InterlockedIncrement( &Fcb->Specific.File.QueuedFlushCount);
2615 // Clear our queued flush event
2618 KeClearEvent( &Fcb->NPFcb->Specific.File.QueuedFlushEvent);
2621 // Look for a start in the list to flush entries
2626 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
2628 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
2630 AFS_EXTENT_RELEASE_TAG);
2631 if( NULL == pRelease)
2634 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2637 initialDirtyCount = Fcb->Specific.File.ExtentsDirtyCount;
2639 while( Fcb->Specific.File.ExtentsDirtyCount > 0)
2642 pRelease->Flags = AFS_EXTENT_FLAG_DIRTY;
2644 if( BooleanFlagOn( Fcb->Flags, AFS_FCB_FILE_CLOSED))
2647 pRelease->Flags |= AFS_EXTENT_FLAG_FLUSH;
2651 // Update the metadata for this call
2654 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
2655 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
2656 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
2657 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
2658 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
2662 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
2665 pExtent = (AFSExtent *)pNPFcb->Specific.File.DirtyListHead;
2667 while( count < AFS_MAXIMUM_EXTENT_RELEASE_COUNT)
2670 if ( pExtent == NULL)
2676 pNextExtent = (AFSExtent *)pExtent->DirtyList.fLink;
2678 if ( pExtent->ActiveCount > 0)
2680 pExtent = pNextExtent;
2684 AFSRemoveEntryDirtyList( Fcb, pExtent);
2686 pExtent->DirtyList.fLink = NULL;
2687 pExtent->DirtyList.bLink = NULL;
2689 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
2692 // Clear the flag in advance of the write. If we do
2693 // things this was we know that the clear is
2694 // pessimistic (any write which happens from now on
2695 // will set the flag dirty again).
2698 pExtent->Flags &= ~AFS_EXTENT_DIRTY;
2700 pRelease->FileExtents[count].Flags = AFS_EXTENT_FLAG_DIRTY;
2702 pRelease->FileExtents[count].Length = pExtent->Size;
2703 pRelease->FileExtents[count].DirtyLength = pExtent->Size;
2704 pRelease->FileExtents[count].DirtyOffset = 0;
2705 pRelease->FileExtents[count].CacheOffset = pExtent->CacheOffset;
2706 pRelease->FileExtents[count].FileOffset = pExtent->FileOffset;
2709 RtlCopyMemory( pRelease->FileExtents[count].MD5,
2711 sizeof(pExtent->MD5));
2713 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_MD5_SET;
2716 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2717 AFS_TRACE_LEVEL_VERBOSE,
2718 "AFSFlushExtents Releasing DIRTY extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
2720 Fcb->ObjectInformation->FileId.Cell,
2721 Fcb->ObjectInformation->FileId.Volume,
2722 Fcb->ObjectInformation->FileId.Vnode,
2723 Fcb->ObjectInformation->FileId.Unique,
2724 pExtent->FileOffset.QuadPart,
2727 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_RELEASE;
2734 pExtent = pNextExtent;
2737 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
2740 // If we are done then get out
2746 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2747 AFS_TRACE_LEVEL_VERBOSE,
2748 "AFSFlushExtents No more dirty extents found\n");
2754 // Fire off the request synchronously
2757 sz = sizeof( AFSReleaseExtentsCB ) + (count * sizeof ( AFSFileExtentCB ));
2759 pRelease->ExtentCount = count;
2761 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2762 AFS_TRACE_LEVEL_VERBOSE,
2763 "AFSFlushExtents Releasing(1) Fcb extents lock %08lX SHARED %08lX\n",
2764 &pNPFcb->Specific.File.ExtentsResource,
2765 PsGetCurrentThread());
2767 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource);
2768 bExtentsLocked = FALSE;
2770 KeSetEvent( &pNPFcb->Specific.File.FlushEvent,
2774 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
2775 AFS_REQUEST_FLAG_SYNCHRONOUS,
2778 &Fcb->ObjectInformation->FileId,
2784 if( !NT_SUCCESS(ntStatus))
2788 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
2789 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
2792 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2793 AFS_TRACE_LEVEL_ERROR,
2794 "AFSFlushExtents AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2795 Fcb->ObjectInformation->FileId.Cell,
2796 Fcb->ObjectInformation->FileId.Volume,
2797 Fcb->ObjectInformation->FileId.Vnode,
2798 Fcb->ObjectInformation->FileId.Unique,
2802 AFSLockForExtentsTrim( Fcb);
2804 bExtentsLocked = TRUE;
2809 lCount = InterlockedDecrement( &Fcb->Specific.File.QueuedFlushCount);
2814 KeSetEvent( &pNPFcb->Specific.File.QueuedFlushEvent,
2819 KeSetEvent( &pNPFcb->Specific.File.FlushEvent,
2826 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2827 AFS_TRACE_LEVEL_VERBOSE,
2828 "AFSFlushExtents Releasing(2) Fcb extents lock %08lX SHARED %08lX\n",
2829 &pNPFcb->Specific.File.ExtentsResource,
2830 PsGetCurrentThread());
2832 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
2837 AFSExFreePoolWithTag( pRelease, AFS_EXTENT_RELEASE_TAG);
2845 AFSReleaseExtentsWithFlush( IN AFSFcb *Fcb,
2847 IN BOOLEAN bReleaseAll)
2849 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
2852 AFSReleaseExtentsCB *pRelease = NULL;
2854 ULONG initialDirtyCount = 0;
2855 BOOLEAN bExtentsLocked = FALSE;
2858 NTSTATUS ntStatus = STATUS_SUCCESS;
2859 LARGE_INTEGER liLastFlush;
2860 ULONG ulRemainingExtentLength = 0;
2861 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2862 GUID *pAuthGroup = AuthGroup;
2866 ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
2869 // Save, then reset the flush time
2872 liLastFlush = Fcb->Specific.File.LastServerFlush;
2874 KeQueryTickCount( &Fcb->Specific.File.LastServerFlush);
2879 if( pAuthGroup == NULL ||
2880 RtlCompareMemory( pAuthGroup,
2881 &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2882 sizeof( GUID)) == sizeof( GUID))
2885 RtlZeroMemory( &stAuthGroup,
2888 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
2893 if( !NT_SUCCESS( ntStatus))
2895 try_return( ntStatus);
2898 pAuthGroup = &stAuthGroup;
2902 // Look for a start in the list to flush entries
2907 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
2909 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
2911 AFS_EXTENT_RELEASE_TAG);
2912 if( NULL == pRelease)
2915 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2918 if( Fcb->OpenHandleCount > 0 &&
2923 // Don't release everything ...
2926 ulRemainingExtentLength = 1024;
2929 while( Fcb->Specific.File.ExtentLength > (LONG)ulRemainingExtentLength)
2932 AFSLockForExtentsTrim( Fcb);
2934 bExtentsLocked = TRUE;
2936 pRelease->Flags = AFS_EXTENT_FLAG_RELEASE;
2939 // Update the metadata for this call
2942 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
2943 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
2944 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
2945 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
2946 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
2950 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
2952 while( count < AFS_MAXIMUM_EXTENT_RELEASE_COUNT &&
2953 le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
2956 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
2960 if( pExtent->ActiveCount > 0)
2966 pRelease->FileExtents[count].Flags = AFS_EXTENT_FLAG_RELEASE;
2968 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2969 AFS_TRACE_LEVEL_VERBOSE,
2970 "AFSReleaseExtentsWithFlush Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
2972 Fcb->ObjectInformation->FileId.Cell,
2973 Fcb->ObjectInformation->FileId.Volume,
2974 Fcb->ObjectInformation->FileId.Vnode,
2975 Fcb->ObjectInformation->FileId.Unique,
2976 pExtent->FileOffset.QuadPart,
2979 pRelease->FileExtents[count].Length = pExtent->Size;
2980 pRelease->FileExtents[count].DirtyLength = pExtent->Size;
2981 pRelease->FileExtents[count].DirtyOffset = 0;
2982 pRelease->FileExtents[count].CacheOffset = pExtent->CacheOffset;
2983 pRelease->FileExtents[count].FileOffset = pExtent->FileOffset;
2986 RtlCopyMemory( pRelease->FileExtents[count].MD5,
2988 sizeof(pExtent->MD5));
2990 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_MD5_SET;
2993 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
2996 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
2999 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3002 AFSRemoveEntryDirtyList( Fcb,
3005 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_DIRTY;
3007 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
3010 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3020 // If we are done then get out
3026 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3027 AFS_TRACE_LEVEL_VERBOSE,
3028 "AFSReleaseExtentsWithFlush No more dirty extents found\n");
3034 // Fire off the request synchronously
3037 sz = sizeof( AFSReleaseExtentsCB ) + (count * sizeof ( AFSFileExtentCB ));
3039 pRelease->ExtentCount = count;
3042 // Drop the extents lock for the duration of the call to
3043 // the network. We have pinned the extents so, even
3044 // though we might get extents added during this period,
3045 // but none will be removed. Hence we can carry on from
3049 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3050 AFS_TRACE_LEVEL_VERBOSE,
3051 "AFSReleaseExtentsWithFlush Releasing Fcb extents lock %08lX thread %08lX\n",
3052 &pNPFcb->Specific.File.ExtentsResource,
3053 PsGetCurrentThread());
3055 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource);
3056 bExtentsLocked = FALSE;
3058 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
3059 AFS_REQUEST_FLAG_SYNCHRONOUS,
3062 &Fcb->ObjectInformation->FileId,
3068 if( !NT_SUCCESS(ntStatus))
3072 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
3073 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
3076 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3077 AFS_TRACE_LEVEL_ERROR,
3078 "AFSReleaseExtentsWithFlush AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3079 Fcb->ObjectInformation->FileId.Cell,
3080 Fcb->ObjectInformation->FileId.Volume,
3081 Fcb->ObjectInformation->FileId.Vnode,
3082 Fcb->ObjectInformation->FileId.Unique,
3092 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3093 AFS_TRACE_LEVEL_VERBOSE,
3094 "AFSReleaseExtentsWithFlush Releasing Fcb extents lock %08lX thread %08lX\n",
3095 &pNPFcb->Specific.File.ExtentsResource,
3096 PsGetCurrentThread());
3098 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
3103 AFSExFreePoolWithTag( pRelease, AFS_EXTENT_RELEASE_TAG);
3111 AFSReleaseCleanExtents( IN AFSFcb *Fcb,
3114 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3117 AFSReleaseExtentsCB *pRelease = NULL;
3119 ULONG initialDirtyCount = 0;
3120 BOOLEAN bExtentsLocked = FALSE;
3123 NTSTATUS ntStatus = STATUS_SUCCESS;
3124 LARGE_INTEGER liLastFlush;
3125 ULONG ulRemainingExtentLength = 0;
3126 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3127 GUID *pAuthGroup = AuthGroup;
3130 ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
3133 // Save, then reset the flush time
3136 liLastFlush = Fcb->Specific.File.LastServerFlush;
3138 KeQueryTickCount( &Fcb->Specific.File.LastServerFlush);
3143 if( pAuthGroup == NULL ||
3144 RtlCompareMemory( pAuthGroup,
3145 &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
3146 sizeof( GUID)) == sizeof( GUID))
3149 RtlZeroMemory( &stAuthGroup,
3152 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
3157 if( !NT_SUCCESS( ntStatus))
3159 try_return( ntStatus);
3162 pAuthGroup = &stAuthGroup;
3166 // Look for a start in the list to flush entries
3171 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
3173 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
3175 AFS_EXTENT_RELEASE_TAG);
3176 if( NULL == pRelease)
3179 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
3182 while( Fcb->Specific.File.ExtentLength > (LONG)ulRemainingExtentLength)
3185 AFSLockForExtentsTrim( Fcb);
3187 bExtentsLocked = TRUE;
3189 pRelease->Flags = AFS_EXTENT_FLAG_RELEASE;
3192 // Update the metadata for this call
3195 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
3196 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
3197 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
3198 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
3199 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
3203 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3205 while( count < AFS_MAXIMUM_EXTENT_RELEASE_COUNT &&
3206 le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
3209 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3213 if( pExtent->ActiveCount > 0 ||
3214 BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3219 pRelease->FileExtents[count].Flags = AFS_EXTENT_FLAG_RELEASE;
3221 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3222 AFS_TRACE_LEVEL_VERBOSE,
3223 "AFSReleaseCleanExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3225 Fcb->ObjectInformation->FileId.Cell,
3226 Fcb->ObjectInformation->FileId.Volume,
3227 Fcb->ObjectInformation->FileId.Vnode,
3228 Fcb->ObjectInformation->FileId.Unique,
3229 pExtent->FileOffset.QuadPart,
3232 pRelease->FileExtents[count].Length = pExtent->Size;
3233 pRelease->FileExtents[count].DirtyLength = pExtent->Size;
3234 pRelease->FileExtents[count].DirtyOffset = 0;
3235 pRelease->FileExtents[count].CacheOffset = pExtent->CacheOffset;
3236 pRelease->FileExtents[count].FileOffset = pExtent->FileOffset;
3239 RtlCopyMemory( pRelease->FileExtents[count].MD5,
3241 sizeof(pExtent->MD5));
3243 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_MD5_SET;
3253 // If we are done then get out
3259 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3260 AFS_TRACE_LEVEL_VERBOSE,
3261 "AFSReleaseCleanExtents No more dirty extents found\n");
3267 // Fire off the request synchronously
3270 sz = sizeof( AFSReleaseExtentsCB ) + (count * sizeof ( AFSFileExtentCB ));
3272 pRelease->ExtentCount = count;
3275 // Drop the extents lock for the duration of the call to
3276 // the network. We have pinned the extents so, even
3277 // though we might get extents added during this period,
3278 // but none will be removed. Hence we can carry on from
3282 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3283 AFS_TRACE_LEVEL_VERBOSE,
3284 "AFSReleaseCleanExtents Releasing Fcb extents lock %08lX thread %08lX\n",
3285 &pNPFcb->Specific.File.ExtentsResource,
3286 PsGetCurrentThread());
3288 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource);
3289 bExtentsLocked = FALSE;
3291 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
3292 AFS_REQUEST_FLAG_SYNCHRONOUS,
3295 &Fcb->ObjectInformation->FileId,
3301 if( !NT_SUCCESS(ntStatus))
3305 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
3306 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
3309 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3310 AFS_TRACE_LEVEL_ERROR,
3311 "AFSReleaseCleanExtents AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3312 Fcb->ObjectInformation->FileId.Cell,
3313 Fcb->ObjectInformation->FileId.Volume,
3314 Fcb->ObjectInformation->FileId.Vnode,
3315 Fcb->ObjectInformation->FileId.Unique,
3325 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3326 AFS_TRACE_LEVEL_VERBOSE,
3327 "AFSReleaseCleanExtents Releasing Fcb extents lock %08lX thread %08lX\n",
3328 &pNPFcb->Specific.File.ExtentsResource,
3329 PsGetCurrentThread());
3331 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
3336 AFSExFreePoolWithTag( pRelease, AFS_EXTENT_RELEASE_TAG);
3344 AFSMarkDirty( IN AFSFcb *Fcb,
3345 IN AFSExtent *StartExtent,
3346 IN ULONG ExtentsCount,
3347 IN LARGE_INTEGER *StartingByte,
3348 IN BOOLEAN DerefExtents)
3351 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3352 AFSExtent *pExtent = StartExtent;
3353 AFSExtent *pNextExtent, *pCurrentExtent = NULL;
3355 BOOLEAN bInsertTail = FALSE, bInsertHead = FALSE;
3357 BOOLEAN bLocked = FALSE;
3359 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3360 AFS_TRACE_LEVEL_VERBOSE,
3361 "AFSMarkDirty Acquiring Fcb extents lock %08lX SHARED %08lX\n",
3362 &Fcb->NPFcb->Specific.File.ExtentsResource,
3363 PsGetCurrentThread());
3365 if( !ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource))
3367 AFSAcquireShared( &Fcb->NPFcb->Specific.File.ExtentsResource, TRUE);
3371 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3377 // Find the insertion point
3380 if( pNPFcb->Specific.File.DirtyListHead == NULL)
3385 else if( StartingByte->QuadPart == 0)
3393 pCurrentExtent = pNPFcb->Specific.File.DirtyListHead;
3395 while( pCurrentExtent != NULL)
3398 if( pCurrentExtent->FileOffset.QuadPart + pCurrentExtent->Size >= StartingByte->QuadPart ||
3399 pCurrentExtent->DirtyList.fLink == NULL)
3405 pCurrentExtent = (AFSExtent *)pCurrentExtent->DirtyList.fLink;
3409 while( ulCount < ExtentsCount)
3412 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
3414 if( !BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3417 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3418 AFS_TRACE_LEVEL_VERBOSE,
3419 "AFSMarkDirty Marking extent offset %I64X Length %08lX DIRTY\n",
3420 pExtent->FileOffset.QuadPart,
3423 pExtent->DirtyList.fLink = NULL;
3424 pExtent->DirtyList.bLink = NULL;
3429 pExtent->DirtyList.fLink = (void *)pNPFcb->Specific.File.DirtyListHead;
3431 pExtent->DirtyList.bLink = NULL;
3433 pNPFcb->Specific.File.DirtyListHead->DirtyList.bLink = (void *)pExtent;
3435 pNPFcb->Specific.File.DirtyListHead = pExtent;
3437 pCurrentExtent = pExtent;
3439 bInsertHead = FALSE;
3441 else if( bInsertTail)
3444 if( pNPFcb->Specific.File.DirtyListHead == NULL)
3447 pNPFcb->Specific.File.DirtyListHead = pExtent;
3452 pNPFcb->Specific.File.DirtyListTail->DirtyList.fLink = (void *)pExtent;
3454 pExtent->DirtyList.bLink = (void *)pNPFcb->Specific.File.DirtyListTail;
3457 pNPFcb->Specific.File.DirtyListTail = pExtent;
3462 pExtent->DirtyList.fLink = pCurrentExtent->DirtyList.fLink;
3464 pExtent->DirtyList.bLink = (void *)pCurrentExtent;
3466 if( pExtent->DirtyList.fLink == NULL)
3469 pNPFcb->Specific.File.DirtyListTail = pExtent;
3474 ((AFSExtent *)pExtent->DirtyList.fLink)->DirtyList.bLink = (void *)pExtent;
3477 pCurrentExtent->DirtyList.fLink = (void *)pExtent;
3479 pCurrentExtent = pExtent;
3482 pExtent->Flags |= AFS_EXTENT_DIRTY;
3485 // Up the dirty count
3488 lCount = InterlockedIncrement( &Fcb->Specific.File.ExtentsDirtyCount);
3493 pCurrentExtent = pExtent;
3496 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_ACTIVE_COUNTING,
3497 AFS_TRACE_LEVEL_VERBOSE,
3498 "AFSMarkDirty Decrement count on extent %08lX Cnt %d\n",
3500 pExtent->ActiveCount);
3504 ASSERT( pExtent->ActiveCount > 0);
3505 lCount = InterlockedDecrement( &pExtent->ActiveCount);
3508 pExtent = pNextExtent;
3513 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
3518 "EXCEPTION - AFSMarkDirty\n");
3520 AFSDumpTraceFilesFnc();
3523 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3525 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3526 AFS_TRACE_LEVEL_VERBOSE,
3527 "AFSMarkDirty Releasing Fcb extents lock %08lX SHARED %08lX\n",
3528 &Fcb->NPFcb->Specific.File.ExtentsResource,
3529 PsGetCurrentThread());
3533 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
3544 ExtentFor(PLIST_ENTRY le, ULONG SkipList)
3547 return CONTAINING_RECORD( le, AFSExtent, Lists[SkipList] );
3551 NextExtent(AFSExtent *Extent, ULONG SkipList)
3554 return ExtentFor(Extent->Lists[SkipList].Flink, SkipList);
3557 static AFSExtent *DirtyExtentFor(PLIST_ENTRY le)
3560 return CONTAINING_RECORD( le, AFSExtent, DirtyList );
3563 static VOID VerifyExtentsLists(AFSFcb *Fcb)
3567 // Check the ordering of the extents lists
3569 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
3571 ASSERT(Fcb->Specific.File.ExtentsLists[0].Flink != &Fcb->Specific.File.ExtentsLists[1]);
3573 for (ULONG listNo = 0; listNo < AFS_NUM_EXTENT_LISTS; listNo ++)
3575 LARGE_INTEGER lastOffset;
3577 lastOffset.QuadPart = 0;
3579 for (PLIST_ENTRY pLe = Fcb->Specific.File.ExtentsLists[listNo].Flink;
3580 pLe != &Fcb->Specific.File.ExtentsLists[listNo];
3585 pExtent = ExtentFor(pLe, listNo);
3588 ASSERT(pLe != &Fcb->Specific.File.ExtentsLists[1] &&
3589 pLe->Flink !=&Fcb->Specific.File.ExtentsLists[1] &&
3590 pLe->Blink !=&Fcb->Specific.File.ExtentsLists[1]);
3593 ASSERT(pLe->Flink->Blink == pLe);
3594 ASSERT(pLe->Blink->Flink == pLe);
3597 // Should follow on from previous
3599 ASSERT(pExtent->FileOffset.QuadPart >= lastOffset.QuadPart);
3600 lastOffset.QuadPart = pExtent->FileOffset.QuadPart + pExtent->Size;
3603 // Should match alignment criteria
3605 ASSERT( 0 == (pExtent->FileOffset.LowPart & ExtentsMasks[listNo]) );
3608 // "lower" lists should be populated
3610 for (LONG subListNo = listNo-1; subListNo > 0; subListNo --)
3612 ASSERT( !IsListEmpty(&pExtent->Lists[subListNo]));
3620 AFSTrimExtents( IN AFSFcb *Fcb,
3621 IN PLARGE_INTEGER FileSize)
3624 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3627 BOOLEAN locked = FALSE;
3628 NTSTATUS ntStatus = STATUS_SUCCESS;
3629 LARGE_INTEGER liAlignedOffset = {0,0};
3630 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
3631 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3638 // Get an aligned offset
3641 if( FileSize != NULL)
3644 liAlignedOffset = *FileSize;
3647 if( liAlignedOffset.QuadPart > 0 &&
3648 liAlignedOffset.QuadPart % pDevExt->Specific.RDR.CacheBlockSize != 0)
3652 // Align UP to the next cache block size
3655 liAlignedOffset.QuadPart = (ULONGLONG)( (ULONGLONG)((liAlignedOffset.QuadPart / pDevExt->Specific.RDR.CacheBlockSize) + 1) * (ULONGLONG)pDevExt->Specific.RDR.CacheBlockSize);
3659 // Ensure that no one is working with the extents and grab the
3663 AFSLockForExtentsTrim( Fcb);
3667 if( 0 == Fcb->Specific.File.ExtentCount)
3671 // Update the request extent status
3674 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
3676 try_return( ntStatus = STATUS_SUCCESS);
3680 // We are truncating from a specific length in the file. If the offset
3681 // is non-zero then go find the first extent to remove
3684 if( 0 == FileSize->QuadPart)
3687 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3692 pExtent = AFSExtentForOffset( Fcb,
3696 if( NULL == pExtent)
3699 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3703 le = &pExtent->Lists[AFS_EXTENTS_LIST];
3707 while( le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
3710 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3713 // Only trim down extents beyond the aligned offset
3718 if( pExtent->FileOffset.QuadPart >= liAlignedOffset.QuadPart)
3721 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3724 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3727 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3731 AFSRemoveEntryDirtyList( Fcb,
3734 dirtyCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
3736 ASSERT(dirtyCount >= 0);
3739 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3742 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3743 AFS_TRACE_LEVEL_VERBOSE,
3744 "AFSTrimExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3746 Fcb->ObjectInformation->FileId.Cell,
3747 Fcb->ObjectInformation->FileId.Volume,
3748 Fcb->ObjectInformation->FileId.Vnode,
3749 Fcb->ObjectInformation->FileId.Unique,
3750 pExtent->FileOffset.QuadPart,
3753 ASSERT( pExtent->ActiveCount == 0);
3761 // Update the request extent status
3764 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
3771 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3772 AFS_TRACE_LEVEL_VERBOSE,
3773 "AFSTrimExtents Releasing Fcb extents lock %08lX thread %08lX\n",
3774 &Fcb->NPFcb->Specific.File.ExtentsResource,
3775 PsGetCurrentThread());
3777 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
3785 AFSTrimSpecifiedExtents( IN AFSFcb *Fcb,
3787 IN AFSFileExtentCB *Result)
3790 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3793 AFSFileExtentCB *pFileExtents = Result;
3794 NTSTATUS ntStatus = STATUS_SUCCESS;
3795 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
3796 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3802 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3804 while( le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST] &&
3808 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3811 // Only trim down extents beyond the aligned offset
3816 if( pExtent->FileOffset.QuadPart == pFileExtents->FileOffset.QuadPart)
3819 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3822 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3825 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3830 AFSRemoveEntryDirtyList( Fcb,
3833 dirtyCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
3835 ASSERT( dirtyCount >= 0);
3839 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3843 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3844 AFS_TRACE_LEVEL_VERBOSE,
3845 "AFSTrimSpecifiedExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3847 Fcb->ObjectInformation->FileId.Cell,
3848 Fcb->ObjectInformation->FileId.Volume,
3849 Fcb->ObjectInformation->FileId.Vnode,
3850 Fcb->ObjectInformation->FileId.Unique,
3851 pExtent->FileOffset.QuadPart,
3854 ASSERT( pExtent->ActiveCount == 0);
3860 // Next extent we are looking for
3870 // Update the request extent status
3873 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
3880 AFSReferenceActiveExtents( IN AFSExtent *StartExtent,
3881 IN ULONG ExtentsCount)
3884 AFSExtent *pExtent = StartExtent;
3885 AFSExtent *pNextExtent;
3889 while( ulCount < ExtentsCount)
3892 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
3894 lCount = InterlockedIncrement( &pExtent->ActiveCount);
3896 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_ACTIVE_COUNTING,
3897 AFS_TRACE_LEVEL_VERBOSE,
3898 "AFSReferenceActiveExtents Increment count on extent %08lX Cnt %d\n",
3902 pExtent = pNextExtent;
3911 AFSDereferenceActiveExtents( IN AFSExtent *StartExtent,
3912 IN ULONG ExtentsCount)
3915 AFSExtent *pExtent = StartExtent;
3916 AFSExtent *pNextExtent;
3920 while( ulCount < ExtentsCount)
3923 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
3925 ASSERT( pExtent->ActiveCount > 0);
3927 lCount = InterlockedDecrement( &pExtent->ActiveCount);
3929 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_ACTIVE_COUNTING,
3930 AFS_TRACE_LEVEL_VERBOSE,
3931 "AFSDereferenceActiveExtents Decrement count on extent %08lX Cnt %d\n",
3935 pExtent = pNextExtent;
3944 AFSRemoveEntryDirtyList( IN AFSFcb *Fcb,
3945 IN AFSExtent *Extent)
3948 if( Extent->DirtyList.fLink == NULL)
3951 Fcb->NPFcb->Specific.File.DirtyListTail = (AFSExtent *)Extent->DirtyList.bLink;
3953 if( Fcb->NPFcb->Specific.File.DirtyListTail != NULL)
3956 Fcb->NPFcb->Specific.File.DirtyListTail->DirtyList.fLink = NULL;
3962 ((AFSExtent *)Extent->DirtyList.fLink)->DirtyList.bLink = Extent->DirtyList.bLink;
3965 if( Extent->DirtyList.bLink == NULL)
3968 Fcb->NPFcb->Specific.File.DirtyListHead = (AFSExtent *)Extent->DirtyList.fLink;
3970 if( Fcb->NPFcb->Specific.File.DirtyListHead != NULL)
3973 Fcb->NPFcb->Specific.File.DirtyListHead->DirtyList.bLink = NULL;
3979 ((AFSExtent *)Extent->DirtyList.bLink)->DirtyList.fLink = Extent->DirtyList.fLink;
3987 AFSConstructCleanByteRangeList( AFSFcb * pFcb,
3988 AFSByteRange ** pByteRangeList)
3991 ULONG ulByteRangeMax;
3992 ULONG ulByteRangeCount = 0;
3993 AFSByteRange *ByteRangeList;
3994 AFSExtent *pExtent, *pNextExtent;
3996 AFSAcquireShared( &pFcb->NPFcb->Specific.File.DirtyExtentsListLock, TRUE);
3998 ulByteRangeMax = pFcb->Specific.File.ExtentsDirtyCount + 1;
4000 ByteRangeList = (AFSByteRange *) AFSExAllocatePoolWithTag( PagedPool,
4001 ulByteRangeMax * sizeof( AFSByteRange),
4004 if ( ByteRangeList == NULL)
4007 (*pByteRangeList) = NULL;
4009 try_return( ulByteRangeCount = DWORD_MAX);
4012 RtlZeroMemory( ByteRangeList,
4013 ulByteRangeMax * sizeof( AFSByteRange));
4016 // The for loop populates the ByteRangeList entries with values that are
4017 // the gaps in the DirtyList. In other words, if a range is not present
4018 // in the DirtyList it will be represented in the ByteRangeList array.
4021 for ( ulByteRangeCount = 0,
4022 pExtent = (AFSExtent *)pFcb->NPFcb->Specific.File.DirtyListHead;
4023 ulByteRangeCount < ulByteRangeMax && pExtent != NULL;
4024 pExtent = pNextExtent)
4027 pNextExtent = (AFSExtent *)pExtent->DirtyList.fLink;
4030 // The first time the for() is entered the ulByteRangeCount will be zero and
4031 // ByteRangeList[0] FileOffset and Length will both be zero. If the first
4032 // extent is not for offset zero, the ByteRangeList[0] Length is set to the
4033 // FileOffset of the Extent.
4035 // Future passes through the loop behave in a similar fashion but
4036 // ByteRangeList[ulByteRangeCount] FileOffset will have been set below.
4039 if ( pExtent->FileOffset.QuadPart != ByteRangeList[ulByteRangeCount].FileOffset.QuadPart + ByteRangeList[ulByteRangeCount].Length.QuadPart)
4042 ByteRangeList[ulByteRangeCount].Length.QuadPart =
4043 pExtent->FileOffset.QuadPart - ByteRangeList[ulByteRangeCount].FileOffset.QuadPart;
4049 // Having processed the current dirty extent, the following while loop
4050 // searches for the next clean gap between dirty extents.
4053 while ( pNextExtent && pNextExtent->FileOffset.QuadPart == pExtent->FileOffset.QuadPart + pExtent->Size)
4056 pExtent = pNextExtent;
4058 pNextExtent = (AFSExtent *)pExtent->DirtyList.fLink;
4062 // Having found the next gap, the ByteRangeList[] FileOffset is set to the start of the gap.
4063 // The Length is left at zero and will be assigned either when the for loop continues or
4064 // when the for loop exits.
4067 ByteRangeList[ulByteRangeCount].FileOffset.QuadPart = pExtent->FileOffset.QuadPart + pExtent->Size;
4071 // Assign the Length of the final clean range to match the file length.
4074 ByteRangeList[ulByteRangeCount].Length.QuadPart =
4075 pFcb->ObjectInformation->EndOfFile.QuadPart - ByteRangeList[ulByteRangeCount].FileOffset.QuadPart;
4077 (*pByteRangeList) = ByteRangeList;
4081 AFSReleaseResource( &pFcb->NPFcb->Specific.File.DirtyExtentsListLock);
4083 return ulByteRangeCount;
4088 AFSSetupMD5Hash( IN AFSFcb *Fcb,
4089 IN AFSExtent *StartExtent,
4090 IN ULONG ExtentsCount,
4091 IN void *SystemBuffer,
4092 IN LARGE_INTEGER *ByteOffset,
4096 NTSTATUS ntStatus = STATUS_SUCCESS;
4097 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
4098 AFSExtent *pExtent = StartExtent;
4099 AFSExtent *pNextExtent, *pCurrentExtent = NULL;
4101 char *pCurrentBuffer = (char *)SystemBuffer;
4102 char *pMD5Buffer = NULL;
4103 ULONG ulCurrentLen = 0;
4104 void *pExtentBuffer = NULL;
4105 LARGE_INTEGER liByteOffset;
4106 ULONG ulBytesRead = 0;
4111 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4112 AFS_TRACE_LEVEL_VERBOSE,
4113 "AFSSetupMD5Hash Acquiring Fcb extents lock %08lX SHARED %08lX\n",
4114 &Fcb->NPFcb->Specific.File.ExtentsResource,
4115 PsGetCurrentThread());
4117 AFSAcquireShared( &Fcb->NPFcb->Specific.File.ExtentsResource, TRUE);
4121 liByteOffset.QuadPart = ByteOffset->QuadPart;
4123 while( ulCount < ExtentsCount)
4126 RtlZeroMemory( pExtent->MD5,
4127 sizeof( pExtent->MD5));
4129 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
4131 if( liByteOffset.QuadPart == pExtent->FileOffset.QuadPart &&
4132 ByteCount < pExtent->Size)
4135 if( pExtentBuffer == NULL)
4138 pExtentBuffer = AFSExAllocatePoolWithTag( PagedPool,
4140 AFS_GENERIC_MEMORY_9_TAG);
4142 if( pExtentBuffer == NULL)
4149 RtlZeroMemory( pExtentBuffer,
4152 RtlCopyMemory( pExtentBuffer,
4156 pMD5Buffer = (char *)pExtentBuffer;
4158 ulCurrentLen = ByteCount;
4160 else if( liByteOffset.QuadPart != pExtent->FileOffset.QuadPart)
4163 pExtentBuffer = AFSExAllocatePoolWithTag( PagedPool,
4165 AFS_GENERIC_MEMORY_10_TAG);
4167 if( pExtentBuffer == NULL)
4173 RtlZeroMemory( pExtentBuffer,
4176 if( BooleanFlagOn( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE))
4180 RtlCopyMemory( pExtentBuffer,
4181 ((char *)AFSLibCacheBaseAddress + pExtent->CacheOffset.QuadPart),
4184 ASSERT( pExtent->CacheOffset.HighPart == 0);
4185 RtlCopyMemory( pExtentBuffer,
4186 ((char *)AFSLibCacheBaseAddress + pExtent->CacheOffset.LowPart),
4190 ulBytesRead = pExtent->Size;
4195 ntStatus = AFSReadCacheFile( pExtentBuffer,
4196 &pExtent->CacheOffset,
4200 if( !NT_SUCCESS( ntStatus))
4207 pMD5Buffer = (char *)pExtentBuffer;
4209 ulCurrentLen = min( ByteCount, pExtent->Size - (ULONG)(liByteOffset.QuadPart - pExtent->FileOffset.QuadPart));
4211 RtlCopyMemory( (void *)((char *)pExtentBuffer + (ULONG)(liByteOffset.QuadPart - pExtent->FileOffset.QuadPart)),
4218 ulCurrentLen = pExtent->Size;
4220 pMD5Buffer = pCurrentBuffer;
4223 AFSGenerateMD5( pMD5Buffer,
4227 pExtent = pNextExtent;
4231 ByteCount -= ulCurrentLen;
4233 pCurrentBuffer += ulCurrentLen;
4235 liByteOffset.QuadPart += ulCurrentLen;
4238 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4239 AFS_TRACE_LEVEL_VERBOSE,
4240 "AFSSetupMD5Hash Releasing Fcb extents lock %08lX SHARED %08lX\n",
4241 &Fcb->NPFcb->Specific.File.ExtentsResource,
4242 PsGetCurrentThread());
4245 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
4250 "EXCEPTION - AFSSetupMD5Hash\n");
4252 AFSDumpTraceFilesFnc();
4255 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
4257 if( pExtentBuffer != NULL)
4260 AFSExFreePoolWithTag( pExtentBuffer, AFS_GENERIC_MEMORY_9_TAG);