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,
112 BOOLEAN bFoundExtents = FALSE;
113 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
116 ULONG ulCount = 0, ulReleaseCount = 0, ulProcessCount = 0;
118 AFSReleaseExtentsCB *pRelease = NULL;
119 BOOLEAN locked = FALSE;
121 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
122 GUID *pAuthGroup = AuthGroup;
128 if( pAuthGroup == NULL ||
129 RtlCompareMemory( pAuthGroup,
130 &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
131 sizeof( GUID)) == sizeof( GUID))
134 RtlZeroMemory( &stAuthGroup,
137 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
142 if( !NT_SUCCESS( ntStatus))
144 try_return( ntStatus);
147 pAuthGroup = &stAuthGroup;
151 // Ensure that no one is working with the extents and grab the
155 AFSLockForExtentsTrim( Fcb );
159 if (0 == Fcb->Specific.File.ExtentCount)
161 try_return ( ntStatus = STATUS_SUCCESS);
165 // Release a max of 100 extents at a time
168 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
170 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
172 AFS_EXTENT_RELEASE_TAG);
173 if (NULL == pRelease)
176 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
179 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
181 ulCount = Fcb->Specific.File.ExtentCount;
183 while( ulReleaseCount < ulCount)
186 bFoundExtents = TRUE;
188 RtlZeroMemory( pRelease,
189 sizeof( AFSReleaseExtentsCB ) +
190 (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB )));
192 if( ulCount - ulReleaseCount <= AFS_MAXIMUM_EXTENT_RELEASE_COUNT)
194 ulProcessCount = ulCount - ulReleaseCount;
198 ulProcessCount = AFS_MAXIMUM_EXTENT_RELEASE_COUNT;
201 pRelease->Flags = AFS_EXTENT_FLAG_RELEASE;
202 pRelease->ExtentCount = ulProcessCount;
205 // Update the metadata for this call
208 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
209 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
210 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
211 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
212 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
216 while (ulProcessCount < pRelease->ExtentCount)
218 pEntry = ExtentFor( le, AFS_EXTENTS_LIST );
220 pRelease->FileExtents[ulProcessCount].Flags = AFS_EXTENT_FLAG_RELEASE;
223 RtlCopyMemory( pRelease->FileExtents[ulProcessCount].MD5,
225 sizeof(pEntry->MD5));
227 pRelease->FileExtents[ulProcessCount].Flags |= AFS_EXTENT_FLAG_MD5_SET;
230 if( BooleanFlagOn( pEntry->Flags, AFS_EXTENT_DIRTY))
233 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
236 if( BooleanFlagOn( pEntry->Flags, AFS_EXTENT_DIRTY))
241 AFSRemoveEntryDirtyList( Fcb,
244 pRelease->FileExtents[ulProcessCount].Flags |= AFS_EXTENT_FLAG_DIRTY;
246 dirtyCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
248 ASSERT( dirtyCount >= 0);
251 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
254 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
255 AFS_TRACE_LEVEL_VERBOSE,
256 "AFSTearDownFcbExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %08lX-%08lX Len %08lX\n",
258 Fcb->ObjectInformation->FileId.Cell,
259 Fcb->ObjectInformation->FileId.Volume,
260 Fcb->ObjectInformation->FileId.Vnode,
261 Fcb->ObjectInformation->FileId.Unique,
262 pEntry->FileOffset.HighPart,
263 pEntry->FileOffset.LowPart,
266 pRelease->FileExtents[ulProcessCount].Length = pEntry->Size;
267 pRelease->FileExtents[ulProcessCount].DirtyLength = pEntry->Size;
268 pRelease->FileExtents[ulProcessCount].DirtyOffset = 0;
269 pRelease->FileExtents[ulProcessCount].CacheOffset = pEntry->CacheOffset;
270 pRelease->FileExtents[ulProcessCount].FileOffset = pEntry->FileOffset;
272 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pEntry->Size/1024)));
274 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pEntry->Size/1024)));
276 ASSERT( pEntry->ActiveCount == 0);
280 AFSExFreePool( pEntry);
282 InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
284 if( InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount) == 0)
287 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
294 // Send the request down. We cannot send this down
295 // asynchronously - if we did that we could request them
296 // back before the service got this request and then this
297 // request would be a corruption.
300 sz = sizeof( AFSReleaseExtentsCB ) + (ulProcessCount * sizeof ( AFSFileExtentCB ));
302 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
303 AFS_REQUEST_FLAG_SYNCHRONOUS,
306 &Fcb->ObjectInformation->FileId,
312 if( !NT_SUCCESS(ntStatus))
316 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
317 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
320 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
321 AFS_TRACE_LEVEL_ERROR,
322 "AFSTearDownFcbExtents AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
323 Fcb->ObjectInformation->FileId.Cell,
324 Fcb->ObjectInformation->FileId.Volume,
325 Fcb->ObjectInformation->FileId.Vnode,
326 Fcb->ObjectInformation->FileId.Unique,
331 ulReleaseCount += ulProcessCount;
335 // Reinitialize the skip lists
338 ASSERT( Fcb->Specific.File.ExtentCount == 0);
340 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i++)
342 InitializeListHead(&Fcb->Specific.File.ExtentsLists[i]);
346 // Reinitialize the dirty list as well
349 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
352 ASSERT( Fcb->Specific.File.ExtentsDirtyCount == 0);
354 Fcb->NPFcb->Specific.File.DirtyListHead = NULL;
355 Fcb->NPFcb->Specific.File.DirtyListTail = NULL;
357 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
359 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
366 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
367 AFS_TRACE_LEVEL_VERBOSE,
368 "AFSTearDownFcbExtents Releasing Fcb extent lock %08lX thread %08lX\n",
369 &Fcb->NPFcb->Specific.File.ExtentsResource,
370 PsGetCurrentThread());
372 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
378 AFSExFreePool( pRelease);
382 return bFoundExtents;
386 ExtentForOffsetInList( IN AFSFcb *Fcb,
389 IN PLARGE_INTEGER Offset)
392 // Return the extent that maps the offset, that
393 // - Contains the offset
394 // - or is immediately ahead of the offset (in this list)
395 // - otherwise return NULL.
398 PLIST_ENTRY pLe = List;
399 AFSExtent *pPrevious = NULL;
401 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
403 while (pLe != &Fcb->Specific.File.ExtentsLists[ListNumber])
407 entry = ExtentFor( pLe, ListNumber );
414 if (Offset->QuadPart < entry->FileOffset.QuadPart)
417 // Offset is ahead of entry. Return previous
422 if (Offset->QuadPart >= (entry->FileOffset.QuadPart + entry->Size))
425 // We start after this extent - carry on round
433 // Otherwise its a match
440 // Got to the end. Return Previous
446 AFSExtentContains( IN AFSExtent *Extent, IN PLARGE_INTEGER Offset)
452 return (Extent->FileOffset.QuadPart <= Offset->QuadPart &&
453 (Extent->FileOffset.QuadPart + Extent->Size) > Offset->QuadPart);
458 // Return the extent that contains the offset
461 AFSExtentForOffsetHint( IN AFSFcb *Fcb,
462 IN PLARGE_INTEGER Offset,
463 IN BOOLEAN ReturnPrevious,
466 AFSExtent *pPrevious = Hint;
470 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
472 #if AFS_VALIDATE_EXTENTS
473 VerifyExtentsLists(Fcb);
477 // So we will go across the skip lists until we find an
478 // appropriate entry (previous or direct match). If it's a match
479 // we are done, other wise we start on the next layer down
481 for (i = AFS_NUM_EXTENT_LISTS-1; i >= AFS_EXTENTS_LIST; i--)
483 if (NULL == pPrevious)
486 // We haven't found anything in the previous layers
488 pLe = Fcb->Specific.File.ExtentsLists[i].Flink;
490 else if (NULL == pPrevious->Lists[i].Flink)
492 ASSERT(AFS_EXTENTS_LIST != i);
494 // The hint doesn't exist at this level, next one down
501 // take the previous into the next
503 pLe = &pPrevious->Lists[i];
506 pPrevious = ExtentForOffsetInList( Fcb, pLe, i, Offset);
508 if (NULL != pPrevious && AFSExtentContains(pPrevious, Offset))
511 // Found it immediately. Stop here
517 if (NULL == pPrevious || ReturnPrevious )
522 ASSERT( !AFSExtentContains(pPrevious, Offset) );
528 AFSEntryForOffset( IN AFSFcb *Fcb,
529 IN PLARGE_INTEGER Offset)
531 AFSExtent *pPrevious = NULL;
535 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
537 #if AFS_VALIDATE_EXTENTS
538 VerifyExtentsLists(Fcb);
542 // So we will go across the skip lists until we find an
543 // appropriate entry (previous or direct match). If it's a match
544 // we are done, other wise we start on the next layer down
546 for (i = AFS_NUM_EXTENT_LISTS-1; i >= AFS_EXTENTS_LIST; i--)
548 if (NULL == pPrevious)
551 // We haven't found anything in the previous layers
553 pLe = Fcb->Specific.File.ExtentsLists[i].Flink;
555 else if (NULL == pPrevious->Lists[i].Flink)
557 ASSERT(AFS_EXTENTS_LIST != i);
559 // The hint doesn't exist at this level, next one down
566 // take the previous into the next
568 pLe = &pPrevious->Lists[i];
571 pPrevious = ExtentForOffsetInList( Fcb, pLe, i, Offset);
573 if (NULL != pPrevious && AFSExtentContains(pPrevious, Offset))
576 // Found it immediately. Stop here
586 AFSExtentForOffset( IN AFSFcb *Fcb,
587 IN PLARGE_INTEGER Offset,
588 IN BOOLEAN ReturnPrevious)
590 return AFSExtentForOffsetHint(Fcb, Offset, ReturnPrevious, NULL);
594 BOOLEAN AFSDoExtentsMapRegion(IN AFSFcb *Fcb,
595 IN PLARGE_INTEGER Offset,
597 IN OUT AFSExtent **FirstExtent,
598 OUT AFSExtent **LastExtent)
601 // Return TRUE region is completely mapped. FALSE
602 // otherwise. If the region isn't mapped then the last
603 // extent to map part of the region is returned.
605 // *LastExtent as input is where to start looking.
606 // *LastExtent as output is either the extent which
607 // contains the Offset, or the last one which doesn't
611 BOOLEAN retVal = FALSE;
616 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
617 AFS_TRACE_LEVEL_VERBOSE,
618 "AFSDoExtentsMapRegion Acquiring Fcb extent lock %08lX SHARED %08lX\n",
619 &Fcb->NPFcb->Specific.File.ExtentsResource,
620 PsGetCurrentThread());
622 AFSAcquireShared( &Fcb->NPFcb->Specific.File.ExtentsResource, TRUE );
624 entry = AFSExtentForOffsetHint(Fcb, Offset, TRUE, *FirstExtent);
625 *FirstExtent = entry;
627 if (NULL == entry || !AFSExtentContains(entry, Offset))
629 try_return (retVal = FALSE);
632 ASSERT(Offset->QuadPart >= entry->FileOffset.QuadPart);
636 if ((entry->FileOffset.QuadPart + entry->Size) >=
637 (Offset->QuadPart + Size))
640 // The end is inside the extent
642 try_return (retVal = TRUE);
645 if (entry->Lists[AFS_EXTENTS_LIST].Flink == &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
648 // Run out of extents
650 try_return (retVal = FALSE);
653 newEntry = NextExtent( entry, AFS_EXTENTS_LIST );
655 if (newEntry->FileOffset.QuadPart !=
656 (entry->FileOffset.QuadPart + entry->Size))
661 try_return (retVal = FALSE);
669 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
670 AFS_TRACE_LEVEL_VERBOSE,
671 "AFSDoExtentsMapRegion Releasing Fcb extent lock %08lX SHARED %08lX\n",
672 &Fcb->NPFcb->Specific.File.ExtentsResource,
673 PsGetCurrentThread());
675 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
684 AFSRequestExtentsAsync( IN AFSFcb *Fcb,
686 IN PLARGE_INTEGER Offset,
690 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
691 NTSTATUS ntStatus = STATUS_SUCCESS;
692 AFSExtent *pExtent = NULL;
693 AFSRequestExtentsCB request;
694 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
695 AFSExtent *pFirstExtent = NULL;
696 LARGE_INTEGER liAlignedOffset;
697 ULONG ulAlignedLength = 0;
698 BOOLEAN bRegionMapped = FALSE;
699 ULONGLONG ullProcessId = (ULONGLONG)PsGetCurrentProcessId();
704 ASSERT( !ExIsResourceAcquiredLite( &pNPFcb->Specific.File.ExtentsResource ));
707 // If the service set a failure on the file since the last
708 // CreateFile was issued, return it now.
711 if (!NT_SUCCESS( pNPFcb->Specific.File.ExtentsRequestStatus))
715 // If this isn't the same authgroup which caused the failure
716 // then try to request them again
719 if( RtlCompareMemory( &pNPFcb->Specific.File.ExtentsRequestAuthGroup,
721 sizeof( GUID)) == sizeof( GUID))
724 ntStatus = pNPFcb->Specific.File.ExtentsRequestStatus;
726 pNPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
728 RtlZeroMemory( &pNPFcb->Specific.File.ExtentsRequestAuthGroup,
731 try_return( ntStatus);
736 // Check if we are already mapped
739 bRegionMapped = AFSDoExtentsMapRegion( Fcb, Offset, Size, &pFirstExtent, &pExtent);
744 try_return( ntStatus = STATUS_SUCCESS);
748 // Align our request on extent size boundary
751 ulAlignedLength = Size;
753 liAlignedOffset = *Offset;
755 if( liAlignedOffset.QuadPart % pDevExt->Specific.RDR.CacheBlockSize != 0)
758 liAlignedOffset.QuadPart = (ULONGLONG)( (ULONGLONG)(liAlignedOffset.QuadPart / pDevExt->Specific.RDR.CacheBlockSize) * (ULONGLONG)pDevExt->Specific.RDR.CacheBlockSize);
760 ulAlignedLength += (ULONG)(Offset->QuadPart - liAlignedOffset.QuadPart);
763 if( ulAlignedLength % pDevExt->Specific.RDR.CacheBlockSize != 0)
766 ulAlignedLength = (ULONG)(((ulAlignedLength / pDevExt->Specific.RDR.CacheBlockSize) + 1) * pDevExt->Specific.RDR.CacheBlockSize);
769 RtlZeroMemory( &request,
770 sizeof( AFSRequestExtentsCB));
772 request.ByteOffset = liAlignedOffset;
773 request.Length = ulAlignedLength;
775 if( !AFSIsExtentRequestQueued( &Fcb->ObjectInformation->FileId,
780 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
781 AFS_TRACE_LEVEL_VERBOSE,
782 "AFSRequestExtentsAsync Request extents for fid %08lX-%08lX-%08lX-%08lX Offset %08lX Len %08lX Thread %08lX\n",
783 Fcb->ObjectInformation->FileId.Cell,
784 Fcb->ObjectInformation->FileId.Volume,
785 Fcb->ObjectInformation->FileId.Vnode,
786 Fcb->ObjectInformation->FileId.Unique,
787 request.ByteOffset.LowPart,
789 PsGetCurrentThread());
791 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS,
795 &Fcb->ObjectInformation->FileId,
797 sizeof( AFSRequestExtentsCB ),
801 if( NT_SUCCESS( ntStatus))
804 KeClearEvent( &pNPFcb->Specific.File.ExtentsRequestComplete );
810 KeClearEvent( &pNPFcb->Specific.File.ExtentsRequestComplete );
822 AFSProcessExtentsResult( IN AFSFcb *Fcb,
824 IN AFSFileExtentCB *Result)
826 NTSTATUS ntStatus = STATUS_SUCCESS;
827 AFSFileExtentCB *pFileExtents = Result;
830 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
831 ULONG fileExtentsUsed = 0;
832 BOOLEAN bFoundExtent = FALSE;
833 LIST_ENTRY *pSkipEntries[AFS_NUM_EXTENT_LISTS] = { 0 };
834 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
837 // Grab the extents exclusive for the duration
840 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
841 AFS_TRACE_LEVEL_VERBOSE,
842 "AFSProcessExtentsResult Acquiring Fcb extent lock %08lX EXCL %08lX\n",
843 &pNPFcb->Specific.File.ExtentsResource,
844 PsGetCurrentThread());
846 AFSAcquireExcl( &pNPFcb->Specific.File.ExtentsResource, TRUE );
852 // Find where to put the extents
854 for (ULONG i = AFS_EXTENTS_LIST; i < AFS_NUM_EXTENT_LISTS; i++)
857 pSkipEntries[i] = Fcb->Specific.File.ExtentsLists[i].Flink;
860 le = pSkipEntries[AFS_EXTENTS_LIST];
862 if (le == &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
865 // No extents. Insert at head of list (which is where the skip lists point!)
869 else if (0 != pFileExtents->FileOffset.QuadPart)
872 // We want to find the best extents immediately *behind* this offset
874 LARGE_INTEGER offset = pFileExtents->FileOffset;
877 // Ask in the top skip list first, then work down
879 for (LONG i = AFS_NUM_EXTENT_LISTS-1; i >= AFS_EXTENTS_LIST; i--)
881 pExtent = ExtentForOffsetInList( Fcb,
889 // No dice. Header has to become the head of the list
891 pSkipEntries[i] = &Fcb->Specific.File.ExtentsLists[i];
893 // And as a loop invariant we should never have found an extent
895 ASSERT(!bFoundExtent);
900 // pExtent is where to start to insert at this level
902 pSkipEntries[i] = &pExtent->Lists[i];
905 // And also where to start to look at the next level
908 if (i > AFS_EXTENTS_LIST)
910 pSkipEntries[i-1] = &pExtent->Lists[i-1];
918 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
923 le = pExtent->Lists[AFS_EXTENTS_LIST].Blink;
929 // Looking at offset 0, so we must start at the beginning
932 pExtent = ExtentFor(le, AFS_EXTENTS_LIST);
936 // And set up the skip lists
939 for (ULONG i = AFS_EXTENTS_LIST; i < AFS_NUM_EXTENT_LISTS; i++)
941 pSkipEntries[i] = &Fcb->Specific.File.ExtentsLists[i];
945 while (fileExtentsUsed < Count)
949 // Loop invariant - le points to where to insert after and
950 // pExtent points to le->fLink
953 ASSERT (NULL == pExtent ||
954 le->Flink == &pExtent->Lists[AFS_EXTENTS_LIST]);
956 if (NULL == pExtent ||
957 pExtent->FileOffset.QuadPart > pFileExtents->FileOffset.QuadPart)
960 // We need to insert a new extent at le. Start with
961 // some sanity check on spanning
963 if (NULL != pExtent &&
964 ((pFileExtents->FileOffset.QuadPart + pFileExtents->Length) >
965 pExtent->FileOffset.QuadPart))
968 // File Extents overlaps pExtent
970 ASSERT( (pFileExtents->FileOffset.QuadPart + pFileExtents->Length) <=
971 pExtent->FileOffset.QuadPart);
973 try_return (ntStatus = STATUS_INVALID_PARAMETER);
977 // File offset is entirely in front of this extent. Create
978 // a new one (remember le is the previous list entry)
980 pExtent = (AFSExtent *) AFSExAllocatePoolWithTag( NonPagedPool,
988 try_return (ntStatus = STATUS_INSUFFICIENT_RESOURCES );
991 RtlZeroMemory( pExtent, sizeof( AFSExtent ));
993 pExtent->FileOffset = pFileExtents->FileOffset;
994 pExtent->CacheOffset = pFileExtents->CacheOffset;
995 pExtent->Size = pFileExtents->Length;
997 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
998 AFS_TRACE_LEVEL_VERBOSE,
999 "AFSProcessExtentsResult Received extent for fid %08lX-%08lX-%08lX-%08lX File Offset %I64X Cache Offset %I64X Len %08lX\n",
1000 Fcb->ObjectInformation->FileId.Cell,
1001 Fcb->ObjectInformation->FileId.Volume,
1002 Fcb->ObjectInformation->FileId.Vnode,
1003 Fcb->ObjectInformation->FileId.Unique,
1004 pFileExtents->FileOffset.QuadPart,
1005 pFileExtents->CacheOffset.QuadPart,
1006 pFileExtents->Length);
1008 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, (LONG)(pExtent->Size/1024));
1010 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, (LONG)(pExtent->Size/1024));
1012 InterlockedIncrement( &Fcb->Specific.File.ExtentCount);
1014 if( InterlockedIncrement( &pControlDevExt->Specific.Control.ExtentCount) == 1)
1017 KeClearEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent);
1023 InsertHeadList(le, &pExtent->Lists[AFS_EXTENTS_LIST]);
1024 ASSERT(le->Flink == &pExtent->Lists[AFS_EXTENTS_LIST]);
1025 ASSERT(0 == (pExtent->FileOffset.LowPart & ExtentsMasks[AFS_EXTENTS_LIST]));
1028 // Do not move the cursor - we will do it next time
1032 // And into the (upper) skip lists - Again, do not move the cursor
1034 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1036 if (0 == (pExtent->FileOffset.LowPart & ExtentsMasks[i]))
1038 InsertHeadList(pSkipEntries[i], &pExtent->Lists[i]);
1039 #if AFS_VALIDATE_EXTENTS
1040 VerifyExtentsLists(Fcb);
1045 else if (pExtent->FileOffset.QuadPart == pFileExtents->FileOffset.QuadPart)
1048 if (pExtent->Size != pFileExtents->Length)
1051 ASSERT (pExtent->Size == pFileExtents->Length);
1053 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1057 // Move both cursors forward.
1059 // First the extent pointer
1062 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1065 // Then the skip lists cursors forward if needed
1067 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1069 if (0 == (pExtent->FileOffset.LowPart & ExtentsMasks[i]))
1072 // Check sanity before
1074 #if AFS_VALIDATE_EXTENTS
1075 VerifyExtentsLists(Fcb);
1079 // Skip list should point to us
1081 //ASSERT(pSkipEntries[i] == &pExtent->Lists[i]);
1083 // Move forward cursor
1085 pSkipEntries[i] = pSkipEntries[i]->Flink;
1087 // Check sanity before
1089 #if AFS_VALIDATE_EXTENTS
1090 VerifyExtentsLists(Fcb);
1096 // And then the cursor in the supplied array
1102 // setup pExtent if there is one
1104 if (le->Flink != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
1106 pExtent = NextExtent( pExtent, AFS_EXTENTS_LIST ) ;
1116 ASSERT( pExtent->FileOffset.QuadPart < pFileExtents->FileOffset.QuadPart );
1119 // Sanity check on spanning
1121 if ((pExtent->FileOffset.QuadPart + pExtent->Size) >
1122 pFileExtents->FileOffset.QuadPart)
1125 ASSERT( (pExtent->FileOffset.QuadPart + pExtent->Size) <=
1126 pFileExtents->FileOffset.QuadPart);
1128 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1132 // Move le and pExtent forward
1134 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1138 // Then the check the skip lists cursors
1140 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1142 if (0 == (pFileExtents->FileOffset.LowPart & ExtentsMasks[i]))
1146 // - empty list (pSkipEntries[i]->Flink == pSkipEntries[i]->Flink == fcb->lists[i]
1147 // - We are the last on the list (pSkipEntries[i]->Flink == fcb->lists[i])
1148 // - We are not the last on the list. In that case we have to be strictly less than
1150 if (pSkipEntries[i]->Flink != &Fcb->Specific.File.ExtentsLists[i]) {
1152 AFSExtent *otherExtent = ExtentFor(pSkipEntries[i]->Flink, i);
1153 ASSERT(pFileExtents->FileOffset.QuadPart < otherExtent->FileOffset.QuadPart);
1160 // setup pExtent if there is one
1163 if (le->Flink != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
1165 pExtent = NextExtent( pExtent, AFS_EXTENTS_LIST ) ;
1175 // All done, signal that we are done drop the lock, exit
1180 if( !NT_SUCCESS( ntStatus))
1184 // If we failed the service is going to drop all extents so trim away the
1188 AFSTrimSpecifiedExtents( Fcb,
1193 #if AFS_VALIDATE_EXTENTS
1194 VerifyExtentsLists(Fcb);
1197 KeSetEvent( &pNPFcb->Specific.File.ExtentsRequestComplete,
1201 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1202 AFS_TRACE_LEVEL_VERBOSE,
1203 "AFSProcessExtentsResult Releasing Fcb extent lock %08lX EXCL %08lX\n",
1204 &pNPFcb->Specific.File.ExtentsResource,
1205 PsGetCurrentThread());
1207 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
1214 AFSProcessSetFileExtents( IN AFSSetFileExtentsCB *SetExtents )
1216 AFSFcb *pFcb = NULL;
1217 AFSVolumeCB *pVolumeCB = NULL;
1218 NTSTATUS ntStatus = STATUS_SUCCESS;
1219 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1220 ULONGLONG ullIndex = 0;
1221 AFSObjectInfoCB *pObjectInfo = NULL;
1226 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1227 AFS_TRACE_LEVEL_VERBOSE,
1228 "AFSProcessSetFileExtents Acquiring RDR VolumeTreeLock lock %08lX SHARED %08lX\n",
1229 &pDevExt->Specific.RDR.VolumeTreeLock,
1230 PsGetCurrentThread());
1232 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
1234 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1235 AFS_TRACE_LEVEL_VERBOSE,
1236 "AFSProcessSetFileExtents Set extents for fid %08lX-%08lX-%08lX-%08lX\n",
1237 SetExtents->FileId.Cell,
1238 SetExtents->FileId.Volume,
1239 SetExtents->FileId.Vnode,
1240 SetExtents->FileId.Unique);
1243 // Locate the volume node
1246 ullIndex = AFSCreateHighIndex( &SetExtents->FileId);
1248 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
1250 (AFSBTreeEntry **)&pVolumeCB);
1252 if( pVolumeCB != NULL)
1255 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1256 AFS_TRACE_LEVEL_VERBOSE,
1257 "AFSProcessSetFileExtents Acquiring VolumeRoot FileIDTree.TreeLock lock %08lX SHARED %08lX\n",
1258 pVolumeCB->ObjectInfoTree.TreeLock,
1259 PsGetCurrentThread());
1261 InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1264 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
1266 if( !NT_SUCCESS( ntStatus) ||
1270 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1271 AFS_TRACE_LEVEL_ERROR,
1272 "AFSProcessSetFileExtents Set extents for fid %08lX-%08lX-%08lX-%08lX Failed to locate volume Status %08lX\n",
1273 SetExtents->FileId.Cell,
1274 SetExtents->FileId.Volume,
1275 SetExtents->FileId.Vnode,
1276 SetExtents->FileId.Unique,
1279 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1282 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1285 InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1288 // Now locate the Object in this volume
1291 ullIndex = AFSCreateLowIndex( &SetExtents->FileId);
1293 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
1295 (AFSBTreeEntry **)&pObjectInfo);
1297 if( pObjectInfo != NULL)
1301 // Reference the node so it won't be torn down
1304 InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
1306 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1307 AFS_TRACE_LEVEL_VERBOSE,
1308 "AFSProcessSetFileExtents Increment count on object %08lX Cnt %d\n",
1310 pObjectInfo->ObjectReferenceCount);
1313 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1315 if( !NT_SUCCESS( ntStatus) ||
1316 pObjectInfo == NULL)
1319 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1320 AFS_TRACE_LEVEL_ERROR,
1321 "AFSProcessSetFileExtents Set extents for hash %I64X fid %08lX-%08lX-%08lX-%08lX Failed to locate file in volume %08lX\n",
1323 SetExtents->FileId.Cell,
1324 SetExtents->FileId.Volume,
1325 SetExtents->FileId.Vnode,
1326 SetExtents->FileId.Unique,
1329 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1332 pFcb = pObjectInfo->Fcb;
1335 // If we have a result failure then don't bother trying to set the extents
1338 if( SetExtents->ResultStatus != STATUS_SUCCESS)
1341 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1342 AFS_TRACE_LEVEL_ERROR,
1343 "AFSProcessSetFileExtents Set extents failure fid %08lX-%08lX-%08lX-%08lX ResultStatus %08lX\n",
1344 SetExtents->FileId.Cell,
1345 SetExtents->FileId.Volume,
1346 SetExtents->FileId.Vnode,
1347 SetExtents->FileId.Unique,
1348 SetExtents->ResultStatus);
1350 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1351 AFS_TRACE_LEVEL_VERBOSE,
1352 "AFSProcessSetFileExtents Acquiring Fcb extents lock %08lX EXCL %08lX\n",
1353 &pFcb->NPFcb->Specific.File.ExtentsResource,
1354 PsGetCurrentThread());
1356 AFSAcquireExcl( &pFcb->NPFcb->Specific.File.ExtentsResource,
1359 pFcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_CANCELLED;
1361 KeSetEvent( &pFcb->NPFcb->Specific.File.ExtentsRequestComplete,
1365 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1366 AFS_TRACE_LEVEL_VERBOSE,
1367 "AFSProcessSetFileExtents Releasing Fcb extent lock %08lX EXCL %08lX\n",
1368 &pFcb->NPFcb->Specific.File.ExtentsResource,
1369 PsGetCurrentThread());
1371 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
1373 try_return( ntStatus);
1376 ntStatus = AFSProcessExtentsResult ( pFcb,
1377 SetExtents->ExtentCount,
1378 SetExtents->FileExtents );
1382 if( pObjectInfo != NULL)
1385 InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
1387 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1388 AFS_TRACE_LEVEL_VERBOSE,
1389 "AFSProcessSetFileExtents Decrement count on object %08lX Cnt %d\n",
1391 pObjectInfo->ObjectReferenceCount);
1399 // Helper fuctions for Usermode initiation of release of extents
1402 AFSReleaseSpecifiedExtents( IN AFSReleaseFileExtentsCB *Extents,
1404 OUT AFSFileExtentCB *FileExtents,
1405 IN ULONG BufferSize,
1406 OUT ULONG *ExtentCount,
1407 OUT BOOLEAN *DirtyExtents)
1412 ULONG ulExtentCount = 0;
1413 NTSTATUS ntStatus = STATUS_SUCCESS;
1414 BOOLEAN bReleaseAll = FALSE;
1415 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1419 ASSERT( ExIsResourceAcquiredExclusiveLite( &Fcb->NPFcb->Specific.File.ExtentsResource));
1421 if (BufferSize < (Extents->ExtentCount * sizeof( AFSFileExtentCB)))
1424 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1425 AFS_TRACE_LEVEL_VERBOSE,
1426 "AFSReleaseSpecifiedExtents Buffer too small\n");
1428 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL);
1431 RtlZeroMemory( FileExtents, BufferSize);
1434 *DirtyExtents = FALSE;
1437 // iterate until we have dealt with all we were asked for or
1438 // are at the end of the list. Note that this deals (albeit
1439 // badly) with out of order extents
1442 pExtent = AFSExtentForOffset( Fcb,
1443 &Extents->FileExtents[0].FileOffset,
1446 if (NULL == pExtent)
1448 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1452 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1456 if( BooleanFlagOn( Extents->Flags, AFS_RELEASE_EXTENTS_FLAGS_RELEASE_ALL) ||
1457 ( Extents->FileId.Cell == 0 &&
1458 Extents->FileId.Volume == 0 &&
1459 Extents->FileId.Vnode == 0 &&
1460 Extents->FileId.Unique == 0))
1466 while( le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST] &&
1467 ulExtentCount < Extents->ExtentCount)
1471 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
1476 if( pExtent->FileOffset.QuadPart < Extents->FileExtents[ulExtentCount].FileOffset.QuadPart)
1479 // Skip forward through the extent list until we get
1480 // to the one we want
1486 else if (pExtent->FileOffset.QuadPart > Extents->FileExtents[ulExtentCount].FileOffset.QuadPart)
1489 // We don't have the extent asked for so return UNKNOWN
1492 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1493 AFS_TRACE_LEVEL_VERBOSE,
1494 "AFSReleaseSpecifiedExtents Located UNKNOWN extent Offset %I64X Len %08lX\n",
1495 Extents->FileExtents[ulExtentCount].FileOffset.QuadPart,
1496 Extents->FileExtents[ulExtentCount].Length);
1498 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_UNKNOWN;
1500 FileExtents[*ExtentCount].Length = 0;
1501 FileExtents[*ExtentCount].CacheOffset.QuadPart = 0;
1502 FileExtents[*ExtentCount].FileOffset = Extents->FileExtents[ulExtentCount].FileOffset;
1504 *ExtentCount = (*ExtentCount) + 1;
1509 // Reset where we are looking
1512 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1516 else if( pExtent->ActiveCount > 0)
1519 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1520 AFS_TRACE_LEVEL_VERBOSE,
1521 "AFSReleaseSpecifiedExtents Located IN_USE extent Offset %I64X Len %08lX\n",
1522 Extents->FileExtents[ulExtentCount].FileOffset.QuadPart,
1523 Extents->FileExtents[ulExtentCount].Length);
1525 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_IN_USE;
1527 FileExtents[*ExtentCount].Length = 0;
1528 FileExtents[*ExtentCount].CacheOffset.QuadPart = 0;
1529 FileExtents[*ExtentCount].FileOffset = Extents->FileExtents[ulExtentCount].FileOffset;
1531 *ExtentCount = (*ExtentCount) + 1;
1536 // Reset where we are looking
1539 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1548 // If the extent is currently active then skip it
1551 if( pExtent->ActiveCount > 0)
1560 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_RELEASE;
1562 FileExtents[*ExtentCount].Length = pExtent->Size;
1563 FileExtents[*ExtentCount].DirtyLength = pExtent->Size;
1564 FileExtents[*ExtentCount].DirtyOffset = 0;
1565 FileExtents[*ExtentCount].CacheOffset = pExtent->CacheOffset;
1566 FileExtents[*ExtentCount].FileOffset = pExtent->FileOffset;
1568 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1569 AFS_TRACE_LEVEL_VERBOSE,
1570 "AFSReleaseSpecifiedExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
1572 Fcb->ObjectInformation->FileId.Cell,
1573 Fcb->ObjectInformation->FileId.Volume,
1574 Fcb->ObjectInformation->FileId.Vnode,
1575 Fcb->ObjectInformation->FileId.Unique,
1576 FileExtents[*ExtentCount].FileOffset.QuadPart,
1577 FileExtents[*ExtentCount].Length);
1579 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
1582 AFSAcquireExcl( &Fcb->NPFcb->Specific.File.DirtyExtentsListLock,
1585 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
1588 AFSRemoveEntryDirtyList( Fcb,
1591 FileExtents[*ExtentCount].Flags |= AFS_EXTENT_FLAG_DIRTY;
1593 InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
1595 *DirtyExtents = TRUE;
1598 AFSReleaseResource( &Fcb->NPFcb->Specific.File.DirtyExtentsListLock);
1602 // move forward all three cursors
1606 *ExtentCount = (*ExtentCount) + 1;
1611 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
1613 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
1615 RemoveEntryList( &pExtent->Lists[i] );
1619 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
1621 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
1626 AFSExFreePool( pExtent);
1628 InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
1630 if( InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount) == 0)
1633 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
1648 AFSFindFcbToClean(ULONG IgnoreTime, AFSFcb *LastFcb, BOOLEAN Block)
1651 AFSFcb *pFcb = NULL;
1652 AFSVolumeCB *pVolumeCB = NULL;
1653 AFSDeviceExt *pRDRDeviceExt = NULL;
1654 AFSDeviceExt *pControlDeviceExt = NULL;
1655 BOOLEAN bLocatedEntry = FALSE;
1656 AFSObjectInfoCB *pCurrentObject = NULL;
1657 BOOLEAN bReleaseVolumeListLock = FALSE;
1659 pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1660 pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1662 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1663 AFS_TRACE_LEVEL_VERBOSE,
1664 "AFSFindFcbToClean Acquiring RDR VolumeListLock lock %08lX SHARED %08lX\n",
1665 &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1666 PsGetCurrentThread());
1668 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1671 bReleaseVolumeListLock = TRUE;
1673 pVolumeCB = pRDRDeviceExt->Specific.RDR.VolumeListHead;
1675 while( pVolumeCB != NULL)
1679 // The Volume list may move under our feet. Lock it.
1682 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1683 AFS_TRACE_LEVEL_VERBOSE,
1684 "AFSFindFcbToClean Acquiring VolumeRoot ObjectInfoTree lock %08lX SHARED %08lX\n",
1685 pVolumeCB->ObjectInfoTree.TreeLock,
1686 PsGetCurrentThread());
1688 InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1690 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1692 bReleaseVolumeListLock = FALSE;
1694 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1697 InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1699 if( NULL == LastFcb)
1702 pCurrentObject = pVolumeCB->ObjectInfoListHead;
1707 pCurrentObject = (AFSObjectInfoCB *)LastFcb->ObjectInformation->ListEntry.fLink;
1712 while( pCurrentObject != NULL)
1715 pFcb = (AFSFcb *)pCurrentObject->Fcb;
1718 // If the FCB is a candidate we try to lock it (but without waiting - which
1719 // means we are deadlock free
1723 pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
1729 AFSLockForExtentsTrim( pFcb);
1734 if( !AFSLockForExtentsTrimNoWait( pFcb))
1737 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1746 // Need to be sure there are no current flushes in the queue
1749 if( pFcb->Specific.File.ExtentCount == 0)
1752 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1753 AFS_TRACE_LEVEL_VERBOSE,
1754 "AFSFindFcbToClean Releasing Fcb extent lock %08lX thread %08lX\n",
1755 &pFcb->NPFcb->Specific.File.ExtentsResource,
1756 PsGetCurrentThread());
1758 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
1760 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1767 if( pFcb->Specific.File.QueuedFlushCount > 0)
1770 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1771 AFS_TRACE_LEVEL_VERBOSE,
1772 "AFSFindFcbToClean Releasing Fcb extent lock %08lX thread %08lX\n",
1773 &pFcb->NPFcb->Specific.File.ExtentsResource,
1774 PsGetCurrentThread());
1776 AFSReleaseResource(&pFcb->NPFcb->Specific.File.ExtentsResource);
1780 AFSWaitOnQueuedFlushes( pFcb);
1785 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1793 if( pFcb->OpenHandleCount > 0)
1796 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1797 AFS_TRACE_LEVEL_VERBOSE,
1798 "AFSFindFcbToClean Releasing Fcb extent lock %08lX thread %08lX\n",
1799 &pFcb->NPFcb->Specific.File.ExtentsResource,
1800 PsGetCurrentThread());
1802 AFSReleaseResource(&pFcb->NPFcb->Specific.File.ExtentsResource);
1804 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1812 // A hit a very palpable hit. Pin it
1815 InterlockedIncrement( &pCurrentObject->ObjectReferenceCount);
1817 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1818 AFS_TRACE_LEVEL_VERBOSE,
1819 "AFSFindFcbToClean Increment count on Fcb %08lX Cnt %d\n",
1821 pCurrentObject->ObjectReferenceCount);
1823 bLocatedEntry = TRUE;
1828 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1833 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1840 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1843 bReleaseVolumeListLock = TRUE;
1845 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1848 if( bReleaseVolumeListLock)
1851 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1858 AFSProcessExtentFailure( PIRP Irp)
1860 AFSExtentFailureCB *pFailureCB = NULL;
1861 NTSTATUS ntStatus = STATUS_SUCCESS;
1862 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
1863 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1864 AFSVolumeCB *pVolumeCB = NULL;
1865 ULONGLONG ullIndex = 0;
1866 AFSObjectInfoCB *pObjectInfo = NULL;
1870 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSExtentFailureCB))
1873 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1874 AFS_TRACE_LEVEL_ERROR,
1875 "AFSProcessExtentFailure Input buffer too small\n");
1877 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1880 pFailureCB = (AFSExtentFailureCB *)Irp->AssociatedIrp.SystemBuffer;
1882 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1883 AFS_TRACE_LEVEL_ERROR,
1884 "AFSProcessExtentFailure Service Reports Failure fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1885 pFailureCB->FileId.Cell,
1886 pFailureCB->FileId.Volume,
1887 pFailureCB->FileId.Vnode,
1888 pFailureCB->FileId.Unique,
1889 pFailureCB->FailureStatus);
1891 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
1894 // Locate the volume node
1897 ullIndex = AFSCreateHighIndex( &pFailureCB->FileId);
1899 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
1901 (AFSBTreeEntry **)&pVolumeCB);
1903 if( pVolumeCB != NULL)
1906 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1907 AFS_TRACE_LEVEL_VERBOSE,
1908 "AFSProcessExtentFailure Acquiring VolumeRoot FileIDTree.TreeLock lock %08lX SHARED %08lX\n",
1909 pVolumeCB->ObjectInfoTree.TreeLock,
1910 PsGetCurrentThread());
1912 InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1915 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
1917 if( !NT_SUCCESS( ntStatus) ||
1921 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1922 AFS_TRACE_LEVEL_ERROR,
1923 "AFSProcessExtentFailure Invalid volume index %I64X status %08X\n",
1924 ullIndex, ntStatus);
1926 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1929 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1932 InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1935 // Now locate the Object in this volume
1938 ullIndex = AFSCreateLowIndex( &pFailureCB->FileId);
1940 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
1942 (AFSBTreeEntry **)&pObjectInfo);
1944 if( pObjectInfo != NULL &&
1945 pObjectInfo->Fcb != NULL)
1949 // Reference the node so it won't be torn down
1952 InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
1954 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1955 AFS_TRACE_LEVEL_VERBOSE,
1956 "AFSProcessExtentFailure Increment count on object %08lX Cnt %d\n",
1958 pObjectInfo->ObjectReferenceCount);
1961 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1963 if( !NT_SUCCESS( ntStatus) ||
1964 pObjectInfo == NULL ||
1965 pObjectInfo->Fcb == NULL)
1968 if( pObjectInfo == NULL)
1970 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1971 AFS_TRACE_LEVEL_ERROR,
1972 "AFSProcessExtentFailure Invalid file index %I64X\n",
1977 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1978 AFS_TRACE_LEVEL_ERROR,
1979 "AFSProcessExtentFailure Fcb dealocated for %I64X\n",
1983 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1986 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1987 AFS_TRACE_LEVEL_VERBOSE,
1988 "AFSProcessExtentFailure Acquiring Fcb extent lock %08lX EXCL %08lX\n",
1989 &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
1990 PsGetCurrentThread());
1992 AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
1995 pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestStatus = pFailureCB->FailureStatus;
1997 RtlCopyMemory( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
1998 &pFailureCB->AuthGroup,
2001 KeSetEvent( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
2005 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2006 AFS_TRACE_LEVEL_VERBOSE,
2007 "AFSProcessExtentFailure Releasing Fcb extent lock %08lX EXCL %08lX\n",
2008 &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2009 PsGetCurrentThread());
2011 AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource);
2013 InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
2015 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2016 AFS_TRACE_LEVEL_VERBOSE,
2017 "AFSProcessExtentFailure Decrement count on object %08lX Cnt %d\n",
2019 pObjectInfo->ObjectReferenceCount);
2030 AFSProcessReleaseFileExtents( IN PIRP Irp)
2032 NTSTATUS ntStatus = STATUS_SUCCESS;
2033 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2034 PFILE_OBJECT pFileObject = pIrpSp->FileObject;
2035 AFSFcb *pFcb = NULL;
2036 AFSVolumeCB *pVolumeCB = NULL;
2037 AFSDeviceExt *pDevExt;
2038 AFSReleaseFileExtentsCB *pExtents;
2039 AFSReleaseFileExtentsResultCB *pResult = NULL;
2040 AFSReleaseFileExtentsResultFileCB *pFile = NULL;
2042 ULONGLONG ullIndex = 0;
2043 AFSObjectInfoCB *pObjectInfo = NULL;
2044 BOOLEAN bLocked = FALSE;
2045 BOOLEAN bDirtyExtents = FALSE;
2051 pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2053 pExtents = (AFSReleaseFileExtentsCB*) Irp->AssociatedIrp.SystemBuffer;
2055 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2056 sizeof( AFSReleaseFileExtentsCB))
2059 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2060 AFS_TRACE_LEVEL_ERROR,
2061 "AFSProcessReleaseFileExtents INPUT Buffer too small\n");
2063 try_return( ntStatus = STATUS_INVALID_PARAMETER );
2066 if ( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength <
2067 sizeof(AFSReleaseFileExtentsResultCB))
2070 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2071 AFS_TRACE_LEVEL_ERROR,
2072 "AFSProcessReleaseFileExtents OUTPUT Buffer too small [1]\n");
2075 // Must have space for one extent in one file
2078 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL);
2081 if (pExtents->ExtentCount == 0)
2084 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2085 AFS_TRACE_LEVEL_ERROR,
2086 "AFSProcessReleaseFileExtents Extent count zero\n");
2088 try_return( ntStatus = STATUS_INVALID_PARAMETER);
2091 if (pExtents->FileId.Cell != 0 ||
2092 pExtents->FileId.Volume != 0 ||
2093 pExtents->FileId.Vnode != 0 ||
2094 pExtents->FileId.Unique != 0)
2097 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2098 AFS_TRACE_LEVEL_VERBOSE,
2099 "AFSProcessReleaseFileExtents Processing FID %08lX:%08lX:%08lX:%08lX\n",
2100 pExtents->FileId.Cell,
2101 pExtents->FileId.Volume,
2102 pExtents->FileId.Vnode,
2103 pExtents->FileId.Unique);
2105 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2106 ( FIELD_OFFSET( AFSReleaseFileExtentsCB, ExtentCount) + sizeof(ULONG)) ||
2107 pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2108 ( FIELD_OFFSET( AFSReleaseFileExtentsCB, ExtentCount) + sizeof(ULONG) +
2109 sizeof (AFSFileExtentCB) * pExtents->ExtentCount))
2112 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2113 AFS_TRACE_LEVEL_ERROR,
2114 "AFSProcessReleaseFileExtents Buffer too small for FID %08lX:%08lx:%08lX:%08lX\n",
2115 pExtents->FileId.Cell,
2116 pExtents->FileId.Volume,
2117 pExtents->FileId.Vnode,
2118 pExtents->FileId.Unique);
2120 try_return( ntStatus = STATUS_INVALID_PARAMETER );
2123 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2124 AFS_TRACE_LEVEL_VERBOSE,
2125 "AFSProcessReleaseFileExtents Acquiring RDR VolumeTreeLock lock %08lX SHARED %08lX\n",
2126 &pDevExt->Specific.RDR.VolumeTreeLock,
2127 PsGetCurrentThread());
2129 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
2132 // Locate the volume node
2135 ullIndex = AFSCreateHighIndex( &pExtents->FileId);
2137 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
2139 (AFSBTreeEntry **)&pVolumeCB);
2141 if( pVolumeCB != NULL)
2144 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2145 AFS_TRACE_LEVEL_VERBOSE,
2146 "AFSProcessReleaseFileExtents Acquiring VolumeRoot FileIDTree.TreeLock lock %08lX SHARED %08lX\n",
2147 pVolumeCB->ObjectInfoTree.TreeLock,
2148 PsGetCurrentThread());
2150 InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
2153 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
2155 if( !NT_SUCCESS( ntStatus) ||
2159 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2160 AFS_TRACE_LEVEL_ERROR,
2161 "AFSProcessReleaseFileExtents Invalid volume index %I64X status %08X\n",
2162 ullIndex, ntStatus);
2164 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2167 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
2170 InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
2173 // Now locate the Object in this volume
2176 ullIndex = AFSCreateLowIndex( &pExtents->FileId);
2178 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
2180 (AFSBTreeEntry **)&pObjectInfo);
2182 if( pObjectInfo != NULL)
2186 // Reference the node so it won't be torn down
2189 InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
2191 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2192 AFS_TRACE_LEVEL_VERBOSE,
2193 "AFSProcessReleaseFileExtents Increment count on object %08lX Cnt %d\n",
2195 pObjectInfo->ObjectReferenceCount);
2198 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2200 if( !NT_SUCCESS( ntStatus) ||
2201 pObjectInfo == NULL)
2204 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2205 AFS_TRACE_LEVEL_ERROR,
2206 "AFSProcessReleaseFileExtents Invalid file index %I64X\n",
2209 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2212 pFcb = pObjectInfo->Fcb;
2217 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2218 AFS_TRACE_LEVEL_ERROR,
2219 "AFSProcessReleaseFileExtents Fcb not initialied (NO EXTENTS) for FID %08lX:%08lx:%08lX:%08lX\n",
2220 pExtents->FileId.Cell,
2221 pExtents->FileId.Volume,
2222 pExtents->FileId.Vnode,
2223 pExtents->FileId.Unique);
2225 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2228 AFSLockForExtentsTrim( pFcb );
2236 // Locate an Fcb to trim down
2239 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2240 AFS_TRACE_LEVEL_VERBOSE,
2241 "AFSProcessReleaseFileExtents Searching for a Fcb to Trim Down\n");
2243 pFcb = AFSFindFcbToClean( 0, NULL, FALSE);
2248 pFcb = AFSFindFcbToClean( 0, NULL, TRUE);
2254 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2255 AFS_TRACE_LEVEL_ERROR,
2256 "AFSProcessReleaseFileExtents Failed to locate Fcb for release ...\n");
2258 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2261 pObjectInfo = pFcb->ObjectInformation;
2267 // Allocate a scratch buffer to move in the extent information
2270 ulSz = (pExtents->ExtentCount-1) * sizeof(AFSFileExtentCB);
2271 ulSz += sizeof(AFSReleaseFileExtentsResultCB);
2273 if (ulSz > pIrpSp->Parameters.DeviceIoControl.OutputBufferLength)
2275 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2276 AFS_TRACE_LEVEL_ERROR,
2277 "AFSProcessReleaseFileExtents OUTPUT Buffer too small [2]\n");
2279 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL );
2282 pResult = (AFSReleaseFileExtentsResultCB*) AFSExAllocatePoolWithTag( PagedPool,
2284 AFS_EXTENTS_RESULT_TAG);
2285 if (NULL == pResult)
2288 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2289 AFS_TRACE_LEVEL_ERROR,
2290 "AFSProcessReleaseFileExtents Failed to allocate result block\n");
2292 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2296 // Set up the header (for an array of one)
2298 pResult->FileCount = 1;
2299 pResult->Flags = AFS_EXTENT_FLAG_RELEASE;
2300 ulSz -= FIELD_OFFSET(AFSReleaseFileExtentsResultCB, Files);
2303 // Setup the first (and only) file
2305 pFile = pResult->Files;
2306 pFile->FileId = pObjectInfo->FileId;
2307 pFile->Flags = AFS_EXTENT_FLAG_RELEASE;
2310 // Stash away the auth group
2313 RtlZeroMemory( &stAuthGroup,
2316 ntStatus = AFSRetrieveValidAuthGroup( pFcb,
2321 if( !NT_SUCCESS( ntStatus))
2323 try_return( ntStatus);
2326 RtlCopyMemory( &pFile->AuthGroup,
2331 // Update the metadata for this call
2334 pFile->AllocationSize = pFcb->ObjectInformation->EndOfFile;
2335 pFile->CreateTime = pFcb->ObjectInformation->CreationTime;
2336 pFile->ChangeTime = pFcb->ObjectInformation->ChangeTime;
2337 pFile->LastAccessTime = pFcb->ObjectInformation->LastAccessTime;
2338 pFile->LastWriteTime = pFcb->ObjectInformation->LastWriteTime;
2340 ulSz -= FIELD_OFFSET(AFSReleaseFileExtentsResultFileCB, FileExtents);
2342 ntStatus = AFSReleaseSpecifiedExtents( pExtents,
2346 &pFile->ExtentCount,
2349 if (!NT_SUCCESS(ntStatus))
2352 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2353 AFS_TRACE_LEVEL_ERROR,
2354 "AFSProcessReleaseFileExtents Failed to release extents Status %08lX\n",
2357 try_return( ntStatus );
2360 if( pExtents->ExtentCount == 0)
2363 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2364 AFS_TRACE_LEVEL_WARNING,
2365 "AFSProcessReleaseFileExtents Failed to release ANY extents\n");
2368 ulSz = sizeof(AFSReleaseFileExtentsResultCB);
2370 if( pExtents->ExtentCount > 0)
2372 ulSz += ((pExtents->ExtentCount-1) * sizeof(AFSFileExtentCB));
2375 RtlCopyMemory( Irp->AssociatedIrp.SystemBuffer,
2384 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2385 AFS_TRACE_LEVEL_VERBOSE,
2386 "AFSProcessReleaseFileExtents Releasing Fcb extent lock %08lX thread %08lX\n",
2387 &pFcb->NPFcb->Specific.File.ExtentsResource,
2388 PsGetCurrentThread());
2390 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
2393 if( NULL != pResult &&
2394 Irp->AssociatedIrp.SystemBuffer != pResult)
2397 AFSExFreePool(pResult);
2400 if (NT_SUCCESS(ntStatus))
2402 Irp->IoStatus.Information = ulSz;
2406 Irp->IoStatus.Information = 0;
2409 Irp->IoStatus.Status = ntStatus;
2411 if( pObjectInfo != NULL)
2414 InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
2416 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2417 AFS_TRACE_LEVEL_VERBOSE,
2418 "AFSProcessReleaseFileExtents Decrement count on object %08lX Cnt %d\n",
2420 pObjectInfo->ObjectReferenceCount);
2428 AFSWaitForExtentMapping( AFSFcb *Fcb,
2431 NTSTATUS ntStatus = STATUS_SUCCESS;
2432 LARGE_INTEGER liTimeOut;
2433 ULONGLONG ullProcessId = (ULONGLONG)PsGetCurrentProcessId();
2438 ASSERT( !ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
2440 if (!NT_SUCCESS( Fcb->NPFcb->Specific.File.ExtentsRequestStatus))
2444 // If this isn't the same authgroup which caused the failure
2445 // then try to request them again
2448 if( RtlCompareMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2450 sizeof( GUID)) == sizeof( GUID))
2453 ntStatus = Fcb->NPFcb->Specific.File.ExtentsRequestStatus;
2455 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
2457 RtlZeroMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2460 try_return( ntStatus);
2464 liTimeOut.QuadPart = -(1 * AFS_ONE_SECOND);
2466 ntStatus = KeWaitForSingleObject( &Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
2472 if (!NT_SUCCESS( Fcb->NPFcb->Specific.File.ExtentsRequestStatus))
2476 // If this isn't the same authgroup which caused the failure
2477 // or the System Process,
2478 // then try to request the extents again
2481 if( RtlCompareMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2483 sizeof( GUID)) == sizeof( GUID) ||
2484 ullProcessId == (ULONGLONG)AFSSysProcess)
2487 ntStatus = Fcb->NPFcb->Specific.File.ExtentsRequestStatus;
2489 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
2491 RtlZeroMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2494 try_return( ntStatus);
2498 if( ntStatus == STATUS_TIMEOUT)
2501 ntStatus = STATUS_SUCCESS;
2513 AFSFlushExtents( IN AFSFcb *Fcb,
2516 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
2517 AFSExtent *pExtent, *pNextExtent;
2519 AFSReleaseExtentsCB *pRelease = NULL;
2521 ULONG initialDirtyCount = 0;
2522 BOOLEAN bExtentsLocked = FALSE;
2525 NTSTATUS ntStatus = STATUS_SUCCESS;
2526 LARGE_INTEGER liLastFlush;
2527 AFSExtent *pDirtyListHead = NULL, *pDirtyListTail = NULL;
2528 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2529 GUID *pAuthGroup = AuthGroup;
2532 ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
2535 // Save, then reset the flush time
2538 liLastFlush = Fcb->Specific.File.LastServerFlush;
2540 KeQueryTickCount( &Fcb->Specific.File.LastServerFlush);
2545 if( pAuthGroup == NULL ||
2546 RtlCompareMemory( pAuthGroup,
2547 &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2548 sizeof( GUID)) == sizeof( GUID))
2551 RtlZeroMemory( &stAuthGroup,
2554 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
2559 if( !NT_SUCCESS( ntStatus))
2561 try_return( ntStatus);
2564 pAuthGroup = &stAuthGroup;
2568 // Lock extents while we count and set up the array to send to
2572 AFSLockForExtentsTrim( Fcb);
2574 bExtentsLocked = TRUE;
2576 InterlockedIncrement( &Fcb->Specific.File.QueuedFlushCount);
2579 // Clear our queued flush event
2582 KeClearEvent( &Fcb->NPFcb->Specific.File.QueuedFlushEvent);
2585 // Look for a start in the list to flush entries
2590 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
2592 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
2594 AFS_EXTENT_RELEASE_TAG);
2595 if( NULL == pRelease)
2598 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2601 initialDirtyCount = Fcb->Specific.File.ExtentsDirtyCount;
2603 while( Fcb->Specific.File.ExtentsDirtyCount > 0)
2606 pRelease->Flags = AFS_EXTENT_FLAG_DIRTY;
2608 if( BooleanFlagOn( Fcb->Flags, AFS_FCB_FILE_CLOSED))
2611 pRelease->Flags |= AFS_EXTENT_FLAG_FLUSH;
2615 // Update the metadata for this call
2618 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
2619 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
2620 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
2621 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
2622 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
2626 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
2629 pExtent = (AFSExtent *)pNPFcb->Specific.File.DirtyListHead;
2631 while( count < AFS_MAXIMUM_EXTENT_RELEASE_COUNT)
2634 if ( pExtent == NULL)
2640 pNextExtent = (AFSExtent *)pExtent->DirtyList.fLink;
2642 if ( pExtent->ActiveCount > 0)
2644 pExtent = pNextExtent;
2648 AFSRemoveEntryDirtyList( Fcb, pExtent);
2650 pExtent->DirtyList.fLink = NULL;
2651 pExtent->DirtyList.bLink = NULL;
2653 InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
2656 // Clear the flag in advance of the write. If we do
2657 // things this was we know that the clear is
2658 // pessimistic (any write which happens from now on
2659 // will set the flag dirty again).
2662 pExtent->Flags &= ~AFS_EXTENT_DIRTY;
2664 pRelease->FileExtents[count].Flags = AFS_EXTENT_FLAG_DIRTY;
2666 pRelease->FileExtents[count].Length = pExtent->Size;
2667 pRelease->FileExtents[count].DirtyLength = pExtent->Size;
2668 pRelease->FileExtents[count].DirtyOffset = 0;
2669 pRelease->FileExtents[count].CacheOffset = pExtent->CacheOffset;
2670 pRelease->FileExtents[count].FileOffset = pExtent->FileOffset;
2673 RtlCopyMemory( pRelease->FileExtents[count].MD5,
2675 sizeof(pExtent->MD5));
2677 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_MD5_SET;
2680 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2681 AFS_TRACE_LEVEL_VERBOSE,
2682 "AFSFlushExtents Releasing DIRTY extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
2684 Fcb->ObjectInformation->FileId.Cell,
2685 Fcb->ObjectInformation->FileId.Volume,
2686 Fcb->ObjectInformation->FileId.Vnode,
2687 Fcb->ObjectInformation->FileId.Unique,
2688 pExtent->FileOffset.QuadPart,
2691 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_RELEASE;
2694 // Need to pull this extent from the main list as well
2697 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
2699 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
2701 RemoveEntryList( &pExtent->Lists[i] );
2705 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
2707 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
2709 AFSExFreePool( pExtent);
2711 InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
2713 if( InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount) == 0)
2716 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
2723 pExtent = pNextExtent;
2726 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
2729 // If we are done then get out
2735 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2736 AFS_TRACE_LEVEL_VERBOSE,
2737 "AFSFlushExtents No more dirty extents found\n");
2743 // Fire off the request synchronously
2746 sz = sizeof( AFSReleaseExtentsCB ) + (count * sizeof ( AFSFileExtentCB ));
2748 pRelease->ExtentCount = count;
2750 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2751 AFS_TRACE_LEVEL_VERBOSE,
2752 "AFSFlushExtents Releasing(1) Fcb extents lock %08lX SHARED %08lX\n",
2753 &pNPFcb->Specific.File.ExtentsResource,
2754 PsGetCurrentThread());
2756 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource);
2757 bExtentsLocked = FALSE;
2759 KeSetEvent( &pNPFcb->Specific.File.FlushEvent,
2763 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
2764 AFS_REQUEST_FLAG_SYNCHRONOUS,
2767 &Fcb->ObjectInformation->FileId,
2773 if( !NT_SUCCESS(ntStatus))
2777 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
2778 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
2781 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2782 AFS_TRACE_LEVEL_ERROR,
2783 "AFSFlushExtents AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2784 Fcb->ObjectInformation->FileId.Cell,
2785 Fcb->ObjectInformation->FileId.Volume,
2786 Fcb->ObjectInformation->FileId.Vnode,
2787 Fcb->ObjectInformation->FileId.Unique,
2791 AFSLockForExtentsTrim( Fcb);
2793 bExtentsLocked = TRUE;
2798 if( InterlockedDecrement( &Fcb->Specific.File.QueuedFlushCount) == 0)
2801 KeSetEvent( &pNPFcb->Specific.File.QueuedFlushEvent,
2806 KeSetEvent( &pNPFcb->Specific.File.FlushEvent,
2813 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2814 AFS_TRACE_LEVEL_VERBOSE,
2815 "AFSFlushExtents Releasing(2) Fcb extents lock %08lX SHARED %08lX\n",
2816 &pNPFcb->Specific.File.ExtentsResource,
2817 PsGetCurrentThread());
2819 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
2824 AFSExFreePool( pRelease);
2832 AFSReleaseExtentsWithFlush( IN AFSFcb *Fcb,
2835 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
2838 AFSReleaseExtentsCB *pRelease = NULL;
2840 ULONG initialDirtyCount = 0;
2841 BOOLEAN bExtentsLocked = FALSE;
2844 NTSTATUS ntStatus = STATUS_SUCCESS;
2845 LARGE_INTEGER liLastFlush;
2846 ULONG ulRemainingExtentLength = 0;
2847 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2848 GUID *pAuthGroup = AuthGroup;
2851 ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
2854 // Save, then reset the flush time
2857 liLastFlush = Fcb->Specific.File.LastServerFlush;
2859 KeQueryTickCount( &Fcb->Specific.File.LastServerFlush);
2864 if( pAuthGroup == NULL ||
2865 RtlCompareMemory( pAuthGroup,
2866 &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2867 sizeof( GUID)) == sizeof( GUID))
2870 RtlZeroMemory( &stAuthGroup,
2873 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
2878 if( !NT_SUCCESS( ntStatus))
2880 try_return( ntStatus);
2883 pAuthGroup = &stAuthGroup;
2887 // Look for a start in the list to flush entries
2892 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
2894 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
2896 AFS_EXTENT_RELEASE_TAG);
2897 if( NULL == pRelease)
2900 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2903 if( Fcb->OpenHandleCount > 0)
2907 // Don't release everything ...
2911 // For now release everything
2914 //ulRemainingExtentLength = 1500;
2917 while( Fcb->Specific.File.ExtentLength > (LONG)ulRemainingExtentLength)
2920 AFSLockForExtentsTrim( Fcb);
2922 bExtentsLocked = TRUE;
2924 pRelease->Flags = AFS_EXTENT_FLAG_RELEASE;
2927 // Update the metadata for this call
2930 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
2931 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
2932 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
2933 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
2934 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
2938 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
2940 while( count < AFS_MAXIMUM_EXTENT_RELEASE_COUNT &&
2941 le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
2944 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
2948 if( pExtent->ActiveCount > 0)
2954 pRelease->FileExtents[count].Flags = AFS_EXTENT_FLAG_RELEASE;
2956 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2957 AFS_TRACE_LEVEL_VERBOSE,
2958 "AFSReleaseExtentsWithFlush Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
2960 Fcb->ObjectInformation->FileId.Cell,
2961 Fcb->ObjectInformation->FileId.Volume,
2962 Fcb->ObjectInformation->FileId.Vnode,
2963 Fcb->ObjectInformation->FileId.Unique,
2964 pExtent->FileOffset.QuadPart,
2967 pRelease->FileExtents[count].Length = pExtent->Size;
2968 pRelease->FileExtents[count].DirtyLength = pExtent->Size;
2969 pRelease->FileExtents[count].DirtyOffset = 0;
2970 pRelease->FileExtents[count].CacheOffset = pExtent->CacheOffset;
2971 pRelease->FileExtents[count].FileOffset = pExtent->FileOffset;
2974 RtlCopyMemory( pRelease->FileExtents[count].MD5,
2976 sizeof(pExtent->MD5));
2978 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_MD5_SET;
2981 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
2984 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
2987 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
2990 AFSRemoveEntryDirtyList( Fcb,
2993 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_DIRTY;
2995 InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
2998 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3002 // Need to pull this extent from the main list as well
3005 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
3007 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
3009 RemoveEntryList( &pExtent->Lists[i] );
3013 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
3015 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
3017 AFSExFreePool( pExtent);
3019 InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
3021 if( InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount) == 0)
3024 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
3033 // If we are done then get out
3039 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3040 AFS_TRACE_LEVEL_VERBOSE,
3041 "AFSReleaseExtentsWithFlush No more dirty extents found\n");
3047 // Fire off the request synchronously
3050 sz = sizeof( AFSReleaseExtentsCB ) + (count * sizeof ( AFSFileExtentCB ));
3052 pRelease->ExtentCount = count;
3055 // Drop the extents lock for the duration of the call to
3056 // the network. We have pinned the extents so, even
3057 // though we might get extents added during this period,
3058 // but none will be removed. Hence we can carry on from
3062 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3063 AFS_TRACE_LEVEL_VERBOSE,
3064 "AFSReleaseExtentsWithFlush Releasing Fcb extents lock %08lX thread %08lX\n",
3065 &pNPFcb->Specific.File.ExtentsResource,
3066 PsGetCurrentThread());
3068 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource);
3069 bExtentsLocked = FALSE;
3071 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
3072 AFS_REQUEST_FLAG_SYNCHRONOUS,
3075 &Fcb->ObjectInformation->FileId,
3081 if( !NT_SUCCESS(ntStatus))
3085 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
3086 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
3089 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3090 AFS_TRACE_LEVEL_ERROR,
3091 "AFSReleaseExtentsWithFlush AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3092 Fcb->ObjectInformation->FileId.Cell,
3093 Fcb->ObjectInformation->FileId.Volume,
3094 Fcb->ObjectInformation->FileId.Vnode,
3095 Fcb->ObjectInformation->FileId.Unique,
3105 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,