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 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
636 entry = AFSExtentForOffsetHint(Fcb, Offset, TRUE, *FirstExtent);
637 *FirstExtent = entry;
639 if (NULL == entry || !AFSExtentContains(entry, Offset))
641 try_return (retVal = FALSE);
644 ASSERT(Offset->QuadPart >= entry->FileOffset.QuadPart);
648 if ((entry->FileOffset.QuadPart + entry->Size) >=
649 (Offset->QuadPart + Size))
652 // The end is inside the extent
654 try_return (retVal = TRUE);
657 if (entry->Lists[AFS_EXTENTS_LIST].Flink == &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
660 // Run out of extents
662 try_return (retVal = FALSE);
665 newEntry = NextExtent( entry, AFS_EXTENTS_LIST );
667 if (newEntry->FileOffset.QuadPart !=
668 (entry->FileOffset.QuadPart + entry->Size))
673 try_return (retVal = FALSE);
679 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
684 "EXCEPTION - AFSDoExtentsMapRegion\n");
686 AFSDumpTraceFilesFnc();
698 AFSRequestExtentsAsync( IN AFSFcb *Fcb,
700 IN PLARGE_INTEGER Offset,
704 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
705 NTSTATUS ntStatus = STATUS_SUCCESS;
706 AFSExtent *pExtent = NULL;
707 AFSRequestExtentsCB request;
708 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
709 AFSExtent *pFirstExtent = NULL;
710 LARGE_INTEGER liAlignedOffset;
711 ULONG ulAlignedLength = 0;
712 BOOLEAN bRegionMapped = FALSE;
713 ULONGLONG ullProcessId = (ULONGLONG)PsGetCurrentProcessId();
718 ASSERT( !ExIsResourceAcquiredLite( &pNPFcb->Specific.File.ExtentsResource ));
721 // If the service set a failure on the file since the last
722 // CreateFile was issued, return it now.
725 if (!NT_SUCCESS( pNPFcb->Specific.File.ExtentsRequestStatus))
729 // If this isn't the same authgroup which caused the failure
730 // then try to request them again
733 if( RtlCompareMemory( &pNPFcb->Specific.File.ExtentsRequestAuthGroup,
735 sizeof( GUID)) == sizeof( GUID))
738 ntStatus = pNPFcb->Specific.File.ExtentsRequestStatus;
740 pNPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
742 RtlZeroMemory( &pNPFcb->Specific.File.ExtentsRequestAuthGroup,
745 try_return( ntStatus);
750 // Check if we are already mapped
753 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
754 AFS_TRACE_LEVEL_VERBOSE,
755 "AFSRequestExtentsAsync Acquiring Fcb extents lock %08lX SHARED %08lX\n",
756 &pNPFcb->Specific.File.ExtentsResource,
757 PsGetCurrentThread());
759 AFSAcquireShared( &pNPFcb->Specific.File.ExtentsResource, TRUE );
761 bRegionMapped = AFSDoExtentsMapRegion( Fcb, Offset, Size, &pFirstExtent, &pExtent);
766 KeClearEvent( &pNPFcb->Specific.File.ExtentsRequestComplete );
769 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
770 AFS_TRACE_LEVEL_VERBOSE,
771 "AFSRequestExtentsAsync Releasing Fcb extents lock %08lX SHARED %08lX\n",
772 &pNPFcb->Specific.File.ExtentsResource,
773 PsGetCurrentThread());
775 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
780 try_return( ntStatus = STATUS_SUCCESS);
784 // Align our request on extent size boundary
787 ulAlignedLength = Size;
789 liAlignedOffset = *Offset;
791 if( liAlignedOffset.QuadPart % pDevExt->Specific.RDR.CacheBlockSize != 0)
794 liAlignedOffset.QuadPart = (ULONGLONG)( (ULONGLONG)(liAlignedOffset.QuadPart / pDevExt->Specific.RDR.CacheBlockSize) * (ULONGLONG)pDevExt->Specific.RDR.CacheBlockSize);
796 ulAlignedLength += (ULONG)(Offset->QuadPart - liAlignedOffset.QuadPart);
799 if( ulAlignedLength % pDevExt->Specific.RDR.CacheBlockSize != 0)
802 ulAlignedLength = (ULONG)(((ulAlignedLength / pDevExt->Specific.RDR.CacheBlockSize) + 1) * pDevExt->Specific.RDR.CacheBlockSize);
805 RtlZeroMemory( &request,
806 sizeof( AFSRequestExtentsCB));
808 request.ByteOffset = liAlignedOffset;
809 request.Length = ulAlignedLength;
811 if( !AFSIsExtentRequestQueued( &Fcb->ObjectInformation->FileId,
816 KeClearEvent( &pNPFcb->Specific.File.ExtentsRequestComplete );
818 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
819 AFS_TRACE_LEVEL_VERBOSE,
820 "AFSRequestExtentsAsync Request extents for fid %08lX-%08lX-%08lX-%08lX Offset %08lX Len %08lX Thread %08lX\n",
821 Fcb->ObjectInformation->FileId.Cell,
822 Fcb->ObjectInformation->FileId.Volume,
823 Fcb->ObjectInformation->FileId.Vnode,
824 Fcb->ObjectInformation->FileId.Unique,
825 request.ByteOffset.LowPart,
827 PsGetCurrentThread());
829 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS,
833 &Fcb->ObjectInformation->FileId,
835 sizeof( AFSRequestExtentsCB ),
839 if ( ntStatus == STATUS_ACCESS_DENIED)
844 ntStatus2 = AFSRetrieveValidAuthGroup( Fcb,
849 if ( NT_SUCCESS( ntStatus2) &&
850 RtlCompareMemory( &stAuthGroup,
852 sizeof( GUID)) != sizeof( GUID))
855 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS,
859 &Fcb->ObjectInformation->FileId,
861 sizeof( AFSRequestExtentsCB ),
867 if( !NT_SUCCESS( ntStatus))
870 KeSetEvent( &pNPFcb->Specific.File.ExtentsRequestComplete,
885 AFSProcessExtentsResult( IN AFSFcb *Fcb,
887 IN AFSFileExtentCB *Result)
889 NTSTATUS ntStatus = STATUS_SUCCESS;
890 AFSFileExtentCB *pFileExtents = Result;
893 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
894 ULONG fileExtentsUsed = 0;
895 BOOLEAN bFoundExtent = FALSE;
896 LIST_ENTRY *pSkipEntries[AFS_NUM_EXTENT_LISTS] = { 0 };
897 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
901 // Grab the extents exclusive for the duration
904 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
905 AFS_TRACE_LEVEL_VERBOSE,
906 "AFSProcessExtentsResult Acquiring Fcb extent lock %08lX EXCL %08lX\n",
907 &pNPFcb->Specific.File.ExtentsResource,
908 PsGetCurrentThread());
910 AFSAcquireExcl( &pNPFcb->Specific.File.ExtentsResource, TRUE );
916 // Find where to put the extents
918 for (ULONG i = AFS_EXTENTS_LIST; i < AFS_NUM_EXTENT_LISTS; i++)
921 pSkipEntries[i] = Fcb->Specific.File.ExtentsLists[i].Flink;
924 le = pSkipEntries[AFS_EXTENTS_LIST];
926 if (le == &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
929 // No extents. Insert at head of list (which is where the skip lists point!)
933 else if (0 != pFileExtents->FileOffset.QuadPart)
936 // We want to find the best extents immediately *behind* this offset
938 LARGE_INTEGER offset = pFileExtents->FileOffset;
941 // Ask in the top skip list first, then work down
943 for (LONG i = AFS_NUM_EXTENT_LISTS-1; i >= AFS_EXTENTS_LIST; i--)
945 pExtent = ExtentForOffsetInList( Fcb,
953 // No dice. Header has to become the head of the list
955 pSkipEntries[i] = &Fcb->Specific.File.ExtentsLists[i];
957 // And as a loop invariant we should never have found an extent
959 ASSERT(!bFoundExtent);
964 // pExtent is where to start to insert at this level
966 pSkipEntries[i] = &pExtent->Lists[i];
969 // And also where to start to look at the next level
972 if (i > AFS_EXTENTS_LIST)
974 pSkipEntries[i-1] = &pExtent->Lists[i-1];
982 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
987 le = pExtent->Lists[AFS_EXTENTS_LIST].Blink;
993 // Looking at offset 0, so we must start at the beginning
996 pExtent = ExtentFor(le, AFS_EXTENTS_LIST);
1000 // And set up the skip lists
1003 for (ULONG i = AFS_EXTENTS_LIST; i < AFS_NUM_EXTENT_LISTS; i++)
1005 pSkipEntries[i] = &Fcb->Specific.File.ExtentsLists[i];
1009 while (fileExtentsUsed < Count)
1013 // Loop invariant - le points to where to insert after and
1014 // pExtent points to le->fLink
1017 ASSERT (NULL == pExtent ||
1018 le->Flink == &pExtent->Lists[AFS_EXTENTS_LIST]);
1020 if (NULL == pExtent ||
1021 pExtent->FileOffset.QuadPart > pFileExtents->FileOffset.QuadPart)
1024 // We need to insert a new extent at le. Start with
1025 // some sanity check on spanning
1027 if (NULL != pExtent &&
1028 ((pFileExtents->FileOffset.QuadPart + pFileExtents->Length) >
1029 pExtent->FileOffset.QuadPart))
1032 // File Extents overlaps pExtent
1034 ASSERT( (pFileExtents->FileOffset.QuadPart + pFileExtents->Length) <=
1035 pExtent->FileOffset.QuadPart);
1037 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1041 // File offset is entirely in front of this extent. Create
1042 // a new one (remember le is the previous list entry)
1044 pExtent = (AFSExtent *) AFSExAllocatePoolWithTag( NonPagedPool,
1047 if (NULL == pExtent)
1050 try_return (ntStatus = STATUS_INSUFFICIENT_RESOURCES );
1053 RtlZeroMemory( pExtent, sizeof( AFSExtent ));
1055 pExtent->FileOffset = pFileExtents->FileOffset;
1056 pExtent->CacheOffset = pFileExtents->CacheOffset;
1057 pExtent->Size = pFileExtents->Length;
1059 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1060 AFS_TRACE_LEVEL_VERBOSE,
1061 "AFSProcessExtentsResult Received extent for fid %08lX-%08lX-%08lX-%08lX File Offset %I64X Cache Offset %I64X Len %08lX\n",
1062 Fcb->ObjectInformation->FileId.Cell,
1063 Fcb->ObjectInformation->FileId.Volume,
1064 Fcb->ObjectInformation->FileId.Vnode,
1065 Fcb->ObjectInformation->FileId.Unique,
1066 pFileExtents->FileOffset.QuadPart,
1067 pFileExtents->CacheOffset.QuadPart,
1068 pFileExtents->Length);
1070 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, (LONG)(pExtent->Size/1024));
1072 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, (LONG)(pExtent->Size/1024));
1074 lCount = InterlockedIncrement( &Fcb->Specific.File.ExtentCount);
1076 lCount = InterlockedIncrement( &pControlDevExt->Specific.Control.ExtentCount);
1081 KeClearEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent);
1087 InsertHeadList(le, &pExtent->Lists[AFS_EXTENTS_LIST]);
1088 ASSERT(le->Flink == &pExtent->Lists[AFS_EXTENTS_LIST]);
1089 ASSERT(0 == (pExtent->FileOffset.LowPart & ExtentsMasks[AFS_EXTENTS_LIST]));
1092 // Do not move the cursor - we will do it next time
1096 // And into the (upper) skip lists - Again, do not move the cursor
1098 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1100 if (0 == (pExtent->FileOffset.LowPart & ExtentsMasks[i]))
1102 InsertHeadList(pSkipEntries[i], &pExtent->Lists[i]);
1103 #if AFS_VALIDATE_EXTENTS
1104 VerifyExtentsLists(Fcb);
1109 else if (pExtent->FileOffset.QuadPart == pFileExtents->FileOffset.QuadPart)
1112 if (pExtent->Size != pFileExtents->Length)
1115 ASSERT (pExtent->Size == pFileExtents->Length);
1117 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1121 // Move both cursors forward.
1123 // First the extent pointer
1126 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1129 // Then the skip lists cursors forward if needed
1131 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1133 if (0 == (pExtent->FileOffset.LowPart & ExtentsMasks[i]))
1136 // Check sanity before
1138 #if AFS_VALIDATE_EXTENTS
1139 VerifyExtentsLists(Fcb);
1143 // Skip list should point to us
1145 //ASSERT(pSkipEntries[i] == &pExtent->Lists[i]);
1147 // Move forward cursor
1149 pSkipEntries[i] = pSkipEntries[i]->Flink;
1151 // Check sanity before
1153 #if AFS_VALIDATE_EXTENTS
1154 VerifyExtentsLists(Fcb);
1160 // And then the cursor in the supplied array
1166 // setup pExtent if there is one
1168 if (le->Flink != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
1170 pExtent = NextExtent( pExtent, AFS_EXTENTS_LIST ) ;
1180 ASSERT( pExtent->FileOffset.QuadPart < pFileExtents->FileOffset.QuadPart );
1183 // Sanity check on spanning
1185 if ((pExtent->FileOffset.QuadPart + pExtent->Size) >
1186 pFileExtents->FileOffset.QuadPart)
1189 ASSERT( (pExtent->FileOffset.QuadPart + pExtent->Size) <=
1190 pFileExtents->FileOffset.QuadPart);
1192 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1196 // Move le and pExtent forward
1198 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1202 // Then the check the skip lists cursors
1204 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1206 if (0 == (pFileExtents->FileOffset.LowPart & ExtentsMasks[i]))
1210 // - empty list (pSkipEntries[i]->Flink == pSkipEntries[i]->Flink == fcb->lists[i]
1211 // - We are the last on the list (pSkipEntries[i]->Flink == fcb->lists[i])
1212 // - We are not the last on the list. In that case we have to be strictly less than
1214 if (pSkipEntries[i]->Flink != &Fcb->Specific.File.ExtentsLists[i]) {
1216 AFSExtent *otherExtent = ExtentFor(pSkipEntries[i]->Flink, i);
1217 ASSERT(pFileExtents->FileOffset.QuadPart < otherExtent->FileOffset.QuadPart);
1224 // setup pExtent if there is one
1227 if (le->Flink != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
1229 pExtent = NextExtent( pExtent, AFS_EXTENTS_LIST ) ;
1239 // All done, signal that we are done drop the lock, exit
1244 if( !NT_SUCCESS( ntStatus))
1248 // If we failed the service is going to drop all extents so trim away the
1252 AFSTrimSpecifiedExtents( Fcb,
1257 #if AFS_VALIDATE_EXTENTS
1258 VerifyExtentsLists(Fcb);
1261 KeSetEvent( &pNPFcb->Specific.File.ExtentsRequestComplete,
1265 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1266 AFS_TRACE_LEVEL_VERBOSE,
1267 "AFSProcessExtentsResult Releasing Fcb extent lock %08lX EXCL %08lX\n",
1268 &pNPFcb->Specific.File.ExtentsResource,
1269 PsGetCurrentThread());
1271 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
1278 AFSProcessSetFileExtents( IN AFSSetFileExtentsCB *SetExtents )
1280 AFSFcb *pFcb = NULL;
1281 AFSVolumeCB *pVolumeCB = NULL;
1282 NTSTATUS ntStatus = STATUS_SUCCESS;
1283 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1284 ULONGLONG ullIndex = 0;
1285 AFSObjectInfoCB *pObjectInfo = NULL;
1291 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1292 AFS_TRACE_LEVEL_VERBOSE,
1293 "AFSProcessSetFileExtents Acquiring RDR VolumeTreeLock lock %08lX SHARED %08lX\n",
1294 &pDevExt->Specific.RDR.VolumeTreeLock,
1295 PsGetCurrentThread());
1297 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
1299 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1300 AFS_TRACE_LEVEL_VERBOSE,
1301 "AFSProcessSetFileExtents Set extents for fid %08lX-%08lX-%08lX-%08lX\n",
1302 SetExtents->FileId.Cell,
1303 SetExtents->FileId.Volume,
1304 SetExtents->FileId.Vnode,
1305 SetExtents->FileId.Unique);
1308 // Locate the volume node
1311 ullIndex = AFSCreateHighIndex( &SetExtents->FileId);
1313 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
1315 (AFSBTreeEntry **)&pVolumeCB);
1317 if( pVolumeCB != NULL)
1320 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1321 AFS_TRACE_LEVEL_VERBOSE,
1322 "AFSProcessSetFileExtents Acquiring VolumeRoot FileIDTree.TreeLock lock %08lX SHARED %08lX\n",
1323 pVolumeCB->ObjectInfoTree.TreeLock,
1324 PsGetCurrentThread());
1326 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1329 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
1331 if( !NT_SUCCESS( ntStatus) ||
1335 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1336 AFS_TRACE_LEVEL_ERROR,
1337 "AFSProcessSetFileExtents Set extents for fid %08lX-%08lX-%08lX-%08lX Failed to locate volume Status %08lX\n",
1338 SetExtents->FileId.Cell,
1339 SetExtents->FileId.Volume,
1340 SetExtents->FileId.Vnode,
1341 SetExtents->FileId.Unique,
1344 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1347 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1350 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1353 // Now locate the Object in this volume
1356 ullIndex = AFSCreateLowIndex( &SetExtents->FileId);
1358 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
1360 (AFSBTreeEntry **)&pObjectInfo);
1362 if( pObjectInfo != NULL)
1366 // Reference the node so it won't be torn down
1369 lCount = AFSObjectInfoIncrement( pObjectInfo);
1371 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1372 AFS_TRACE_LEVEL_VERBOSE,
1373 "AFSProcessSetFileExtents Increment count on object %08lX Cnt %d\n",
1378 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1380 if( !NT_SUCCESS( ntStatus) ||
1381 pObjectInfo == NULL)
1384 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1385 AFS_TRACE_LEVEL_ERROR,
1386 "AFSProcessSetFileExtents Set extents for hash %I64X fid %08lX-%08lX-%08lX-%08lX Failed to locate file in volume %08lX\n",
1388 SetExtents->FileId.Cell,
1389 SetExtents->FileId.Volume,
1390 SetExtents->FileId.Vnode,
1391 SetExtents->FileId.Unique,
1394 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1397 pFcb = pObjectInfo->Fcb;
1400 // If we have a result failure then don't bother trying to set the extents
1403 if( SetExtents->ResultStatus != STATUS_SUCCESS)
1406 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1407 AFS_TRACE_LEVEL_ERROR,
1408 "AFSProcessSetFileExtents Set extents failure fid %08lX-%08lX-%08lX-%08lX ResultStatus %08lX\n",
1409 SetExtents->FileId.Cell,
1410 SetExtents->FileId.Volume,
1411 SetExtents->FileId.Vnode,
1412 SetExtents->FileId.Unique,
1413 SetExtents->ResultStatus);
1415 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1416 AFS_TRACE_LEVEL_VERBOSE,
1417 "AFSProcessSetFileExtents Acquiring Fcb extents lock %08lX EXCL %08lX\n",
1418 &pFcb->NPFcb->Specific.File.ExtentsResource,
1419 PsGetCurrentThread());
1421 AFSAcquireExcl( &pFcb->NPFcb->Specific.File.ExtentsResource,
1424 pFcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_CANCELLED;
1426 KeSetEvent( &pFcb->NPFcb->Specific.File.ExtentsRequestComplete,
1430 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1431 AFS_TRACE_LEVEL_VERBOSE,
1432 "AFSProcessSetFileExtents Releasing Fcb extent lock %08lX EXCL %08lX\n",
1433 &pFcb->NPFcb->Specific.File.ExtentsResource,
1434 PsGetCurrentThread());
1436 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
1438 try_return( ntStatus);
1441 ntStatus = AFSProcessExtentsResult ( pFcb,
1442 SetExtents->ExtentCount,
1443 SetExtents->FileExtents );
1447 if( pObjectInfo != NULL)
1450 lCount = AFSObjectInfoDecrement( pObjectInfo);
1452 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1453 AFS_TRACE_LEVEL_VERBOSE,
1454 "AFSProcessSetFileExtents Decrement count on object %08lX Cnt %d\n",
1464 // Helper fuctions for Usermode initiation of release of extents
1467 AFSReleaseSpecifiedExtents( IN AFSReleaseFileExtentsCB *Extents,
1469 OUT AFSFileExtentCB *FileExtents,
1470 IN ULONG BufferSize,
1471 OUT ULONG *ExtentCount,
1472 OUT BOOLEAN *DirtyExtents)
1477 ULONG ulExtentCount = 0;
1478 NTSTATUS ntStatus = STATUS_SUCCESS;
1479 BOOLEAN bReleaseAll = FALSE;
1480 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1485 ASSERT( ExIsResourceAcquiredExclusiveLite( &Fcb->NPFcb->Specific.File.ExtentsResource));
1487 if (BufferSize < (Extents->ExtentCount * sizeof( AFSFileExtentCB)))
1490 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1491 AFS_TRACE_LEVEL_VERBOSE,
1492 "AFSReleaseSpecifiedExtents Buffer too small\n");
1494 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL);
1497 RtlZeroMemory( FileExtents, BufferSize);
1500 *DirtyExtents = FALSE;
1503 // iterate until we have dealt with all we were asked for or
1504 // are at the end of the list. Note that this deals (albeit
1505 // badly) with out of order extents
1508 pExtent = AFSExtentForOffset( Fcb,
1509 &Extents->FileExtents[0].FileOffset,
1512 if (NULL == pExtent)
1514 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1518 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1522 if( BooleanFlagOn( Extents->Flags, AFS_RELEASE_EXTENTS_FLAGS_RELEASE_ALL) ||
1523 ( Extents->FileId.Cell == 0 &&
1524 Extents->FileId.Volume == 0 &&
1525 Extents->FileId.Vnode == 0 &&
1526 Extents->FileId.Unique == 0))
1532 while( le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST] &&
1533 ulExtentCount < Extents->ExtentCount)
1537 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
1542 if( pExtent->FileOffset.QuadPart < Extents->FileExtents[ulExtentCount].FileOffset.QuadPart)
1545 // Skip forward through the extent list until we get
1546 // to the one we want
1552 else if (pExtent->FileOffset.QuadPart > Extents->FileExtents[ulExtentCount].FileOffset.QuadPart)
1555 // We don't have the extent asked for so return UNKNOWN
1558 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1559 AFS_TRACE_LEVEL_VERBOSE,
1560 "AFSReleaseSpecifiedExtents Located UNKNOWN extent Offset %I64X Len %08lX\n",
1561 Extents->FileExtents[ulExtentCount].FileOffset.QuadPart,
1562 Extents->FileExtents[ulExtentCount].Length);
1564 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_UNKNOWN;
1566 FileExtents[*ExtentCount].Length = 0;
1567 FileExtents[*ExtentCount].CacheOffset.QuadPart = 0;
1568 FileExtents[*ExtentCount].FileOffset = Extents->FileExtents[ulExtentCount].FileOffset;
1570 *ExtentCount = (*ExtentCount) + 1;
1575 // Reset where we are looking
1578 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1582 else if( pExtent->ActiveCount > 0)
1585 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1586 AFS_TRACE_LEVEL_VERBOSE,
1587 "AFSReleaseSpecifiedExtents Located IN_USE extent Offset %I64X Len %08lX\n",
1588 Extents->FileExtents[ulExtentCount].FileOffset.QuadPart,
1589 Extents->FileExtents[ulExtentCount].Length);
1591 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_IN_USE;
1593 FileExtents[*ExtentCount].Length = 0;
1594 FileExtents[*ExtentCount].CacheOffset.QuadPart = 0;
1595 FileExtents[*ExtentCount].FileOffset = Extents->FileExtents[ulExtentCount].FileOffset;
1597 *ExtentCount = (*ExtentCount) + 1;
1602 // Reset where we are looking
1605 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1614 // If the extent is currently active then skip it
1617 if( pExtent->ActiveCount > 0)
1626 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_RELEASE;
1628 FileExtents[*ExtentCount].Length = pExtent->Size;
1629 FileExtents[*ExtentCount].DirtyLength = pExtent->Size;
1630 FileExtents[*ExtentCount].DirtyOffset = 0;
1631 FileExtents[*ExtentCount].CacheOffset = pExtent->CacheOffset;
1632 FileExtents[*ExtentCount].FileOffset = pExtent->FileOffset;
1634 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1635 AFS_TRACE_LEVEL_VERBOSE,
1636 "AFSReleaseSpecifiedExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
1638 Fcb->ObjectInformation->FileId.Cell,
1639 Fcb->ObjectInformation->FileId.Volume,
1640 Fcb->ObjectInformation->FileId.Vnode,
1641 Fcb->ObjectInformation->FileId.Unique,
1642 FileExtents[*ExtentCount].FileOffset.QuadPart,
1643 FileExtents[*ExtentCount].Length);
1645 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
1648 AFSAcquireExcl( &Fcb->NPFcb->Specific.File.DirtyExtentsListLock,
1651 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
1654 AFSRemoveEntryDirtyList( Fcb,
1657 FileExtents[*ExtentCount].Flags |= AFS_EXTENT_FLAG_DIRTY;
1659 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
1661 *DirtyExtents = TRUE;
1664 AFSReleaseResource( &Fcb->NPFcb->Specific.File.DirtyExtentsListLock);
1668 // move forward all three cursors
1672 *ExtentCount = (*ExtentCount) + 1;
1687 AFSFindFcbToClean(ULONG IgnoreTime, AFSFcb *LastFcb, BOOLEAN Block)
1690 AFSFcb *pFcb = NULL;
1691 AFSVolumeCB *pVolumeCB = NULL;
1692 AFSDeviceExt *pRDRDeviceExt = NULL;
1693 AFSDeviceExt *pControlDeviceExt = NULL;
1694 BOOLEAN bLocatedEntry = FALSE;
1695 AFSObjectInfoCB *pCurrentObject = NULL;
1696 BOOLEAN bReleaseVolumeListLock = FALSE;
1699 pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1700 pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1702 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1703 AFS_TRACE_LEVEL_VERBOSE,
1704 "AFSFindFcbToClean Acquiring RDR VolumeListLock lock %08lX SHARED %08lX\n",
1705 &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1706 PsGetCurrentThread());
1708 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1711 bReleaseVolumeListLock = TRUE;
1713 pVolumeCB = pRDRDeviceExt->Specific.RDR.VolumeListHead;
1715 while( pVolumeCB != NULL)
1719 // The Volume list may move under our feet. Lock it.
1722 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1723 AFS_TRACE_LEVEL_VERBOSE,
1724 "AFSFindFcbToClean Acquiring VolumeRoot ObjectInfoTree lock %08lX SHARED %08lX\n",
1725 pVolumeCB->ObjectInfoTree.TreeLock,
1726 PsGetCurrentThread());
1728 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1730 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1732 bReleaseVolumeListLock = FALSE;
1734 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1737 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1739 if( NULL == LastFcb)
1742 pCurrentObject = pVolumeCB->ObjectInfoListHead;
1747 pCurrentObject = (AFSObjectInfoCB *)LastFcb->ObjectInformation->ListEntry.fLink;
1752 while( pCurrentObject != NULL)
1755 pFcb = (AFSFcb *)pCurrentObject->Fcb;
1758 // If the FCB is a candidate we try to lock it (but without waiting - which
1759 // means we are deadlock free
1763 pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
1769 AFSLockForExtentsTrim( pFcb);
1774 if( !AFSLockForExtentsTrimNoWait( pFcb))
1777 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1786 // Need to be sure there are no current flushes in the queue
1789 if( pFcb->Specific.File.ExtentCount == 0)
1792 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1793 AFS_TRACE_LEVEL_VERBOSE,
1794 "AFSFindFcbToClean Releasing Fcb extent lock %08lX thread %08lX\n",
1795 &pFcb->NPFcb->Specific.File.ExtentsResource,
1796 PsGetCurrentThread());
1798 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
1800 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1807 if( pFcb->Specific.File.QueuedFlushCount > 0)
1810 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1811 AFS_TRACE_LEVEL_VERBOSE,
1812 "AFSFindFcbToClean Releasing Fcb extent lock %08lX thread %08lX\n",
1813 &pFcb->NPFcb->Specific.File.ExtentsResource,
1814 PsGetCurrentThread());
1816 AFSReleaseResource(&pFcb->NPFcb->Specific.File.ExtentsResource);
1820 AFSWaitOnQueuedFlushes( pFcb);
1825 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1833 if( pFcb->OpenHandleCount > 0)
1836 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1837 AFS_TRACE_LEVEL_VERBOSE,
1838 "AFSFindFcbToClean Releasing Fcb extent lock %08lX thread %08lX\n",
1839 &pFcb->NPFcb->Specific.File.ExtentsResource,
1840 PsGetCurrentThread());
1842 AFSReleaseResource(&pFcb->NPFcb->Specific.File.ExtentsResource);
1844 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1852 // A hit a very palpable hit. Pin it
1855 lCount = AFSObjectInfoIncrement( pCurrentObject);
1857 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1858 AFS_TRACE_LEVEL_VERBOSE,
1859 "AFSFindFcbToClean Increment count on Fcb %08lX Cnt %d\n",
1863 bLocatedEntry = TRUE;
1868 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1873 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1880 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1883 bReleaseVolumeListLock = TRUE;
1885 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1888 if( bReleaseVolumeListLock)
1891 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1898 AFSProcessExtentFailure( PIRP Irp)
1900 AFSExtentFailureCB *pFailureCB = NULL;
1901 NTSTATUS ntStatus = STATUS_SUCCESS;
1902 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
1903 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1904 AFSVolumeCB *pVolumeCB = NULL;
1905 ULONGLONG ullIndex = 0;
1906 AFSObjectInfoCB *pObjectInfo = NULL;
1911 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSExtentFailureCB))
1914 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1915 AFS_TRACE_LEVEL_ERROR,
1916 "AFSProcessExtentFailure Input buffer too small\n");
1918 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1921 pFailureCB = (AFSExtentFailureCB *)Irp->AssociatedIrp.SystemBuffer;
1923 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1924 AFS_TRACE_LEVEL_ERROR,
1925 "AFSProcessExtentFailure Service Reports Failure fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1926 pFailureCB->FileId.Cell,
1927 pFailureCB->FileId.Volume,
1928 pFailureCB->FileId.Vnode,
1929 pFailureCB->FileId.Unique,
1930 pFailureCB->FailureStatus);
1932 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
1935 // Locate the volume node
1938 ullIndex = AFSCreateHighIndex( &pFailureCB->FileId);
1940 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
1942 (AFSBTreeEntry **)&pVolumeCB);
1944 if( pVolumeCB != NULL)
1947 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1948 AFS_TRACE_LEVEL_VERBOSE,
1949 "AFSProcessExtentFailure Acquiring VolumeRoot FileIDTree.TreeLock lock %08lX SHARED %08lX\n",
1950 pVolumeCB->ObjectInfoTree.TreeLock,
1951 PsGetCurrentThread());
1953 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1956 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
1958 if( !NT_SUCCESS( ntStatus) ||
1962 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1963 AFS_TRACE_LEVEL_ERROR,
1964 "AFSProcessExtentFailure Invalid volume index %I64X status %08X\n",
1965 ullIndex, ntStatus);
1967 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1970 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1973 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1976 // Now locate the Object in this volume
1979 ullIndex = AFSCreateLowIndex( &pFailureCB->FileId);
1981 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
1983 (AFSBTreeEntry **)&pObjectInfo);
1985 if( pObjectInfo != NULL &&
1986 pObjectInfo->Fcb != NULL)
1990 // Reference the node so it won't be torn down
1993 lCount = AFSObjectInfoIncrement( pObjectInfo);
1995 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1996 AFS_TRACE_LEVEL_VERBOSE,
1997 "AFSProcessExtentFailure Increment count on object %08lX Cnt %d\n",
2002 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2004 if( !NT_SUCCESS( ntStatus) ||
2005 pObjectInfo == NULL ||
2006 pObjectInfo->Fcb == NULL)
2009 if( pObjectInfo == NULL)
2011 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2012 AFS_TRACE_LEVEL_ERROR,
2013 "AFSProcessExtentFailure Invalid file index %I64X\n",
2018 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2019 AFS_TRACE_LEVEL_ERROR,
2020 "AFSProcessExtentFailure Fcb dealocated for %I64X\n",
2024 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2027 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2028 AFS_TRACE_LEVEL_VERBOSE,
2029 "AFSProcessExtentFailure Acquiring Fcb extent lock %08lX EXCL %08lX\n",
2030 &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2031 PsGetCurrentThread());
2033 AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2036 pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestStatus = pFailureCB->FailureStatus;
2038 RtlCopyMemory( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2039 &pFailureCB->AuthGroup,
2042 KeSetEvent( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
2046 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2047 AFS_TRACE_LEVEL_VERBOSE,
2048 "AFSProcessExtentFailure Releasing Fcb extent lock %08lX EXCL %08lX\n",
2049 &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2050 PsGetCurrentThread());
2052 AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource);
2054 lCount = AFSObjectInfoDecrement( pObjectInfo);
2056 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2057 AFS_TRACE_LEVEL_VERBOSE,
2058 "AFSProcessExtentFailure Decrement count on object %08lX Cnt %d\n",
2071 AFSProcessReleaseFileExtents( IN PIRP Irp)
2073 NTSTATUS ntStatus = STATUS_SUCCESS;
2074 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2075 PFILE_OBJECT pFileObject = pIrpSp->FileObject;
2076 AFSFcb *pFcb = NULL;
2077 AFSVolumeCB *pVolumeCB = NULL;
2078 AFSDeviceExt *pDevExt;
2079 AFSReleaseFileExtentsCB *pExtents;
2080 AFSReleaseFileExtentsResultCB *pResult = NULL;
2081 AFSReleaseFileExtentsResultFileCB *pFile = NULL;
2083 ULONGLONG ullIndex = 0;
2084 AFSObjectInfoCB *pObjectInfo = NULL;
2085 BOOLEAN bLocked = FALSE;
2086 BOOLEAN bDirtyExtents = FALSE;
2093 pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2095 pExtents = (AFSReleaseFileExtentsCB*) Irp->AssociatedIrp.SystemBuffer;
2097 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2098 sizeof( AFSReleaseFileExtentsCB))
2101 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2102 AFS_TRACE_LEVEL_ERROR,
2103 "AFSProcessReleaseFileExtents INPUT Buffer too small\n");
2105 try_return( ntStatus = STATUS_INVALID_PARAMETER );
2108 if ( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength <
2109 sizeof(AFSReleaseFileExtentsResultCB))
2112 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2113 AFS_TRACE_LEVEL_ERROR,
2114 "AFSProcessReleaseFileExtents OUTPUT Buffer too small [1]\n");
2117 // Must have space for one extent in one file
2120 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL);
2123 if (pExtents->ExtentCount == 0)
2126 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2127 AFS_TRACE_LEVEL_ERROR,
2128 "AFSProcessReleaseFileExtents Extent count zero\n");
2130 try_return( ntStatus = STATUS_INVALID_PARAMETER);
2133 if (pExtents->FileId.Cell != 0 ||
2134 pExtents->FileId.Volume != 0 ||
2135 pExtents->FileId.Vnode != 0 ||
2136 pExtents->FileId.Unique != 0)
2139 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2140 AFS_TRACE_LEVEL_VERBOSE,
2141 "AFSProcessReleaseFileExtents Processing FID %08lX:%08lX:%08lX:%08lX\n",
2142 pExtents->FileId.Cell,
2143 pExtents->FileId.Volume,
2144 pExtents->FileId.Vnode,
2145 pExtents->FileId.Unique);
2147 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2148 ( FIELD_OFFSET( AFSReleaseFileExtentsCB, ExtentCount) + sizeof(ULONG)) ||
2149 pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2150 ( FIELD_OFFSET( AFSReleaseFileExtentsCB, ExtentCount) + sizeof(ULONG) +
2151 sizeof (AFSFileExtentCB) * pExtents->ExtentCount))
2154 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2155 AFS_TRACE_LEVEL_ERROR,
2156 "AFSProcessReleaseFileExtents Buffer too small for FID %08lX:%08lx:%08lX:%08lX\n",
2157 pExtents->FileId.Cell,
2158 pExtents->FileId.Volume,
2159 pExtents->FileId.Vnode,
2160 pExtents->FileId.Unique);
2162 try_return( ntStatus = STATUS_INVALID_PARAMETER );
2165 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2166 AFS_TRACE_LEVEL_VERBOSE,
2167 "AFSProcessReleaseFileExtents Acquiring RDR VolumeTreeLock lock %08lX SHARED %08lX\n",
2168 &pDevExt->Specific.RDR.VolumeTreeLock,
2169 PsGetCurrentThread());
2171 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
2174 // Locate the volume node
2177 ullIndex = AFSCreateHighIndex( &pExtents->FileId);
2179 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
2181 (AFSBTreeEntry **)&pVolumeCB);
2183 if( pVolumeCB != NULL)
2186 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2187 AFS_TRACE_LEVEL_VERBOSE,
2188 "AFSProcessReleaseFileExtents Acquiring VolumeRoot FileIDTree.TreeLock lock %08lX SHARED %08lX\n",
2189 pVolumeCB->ObjectInfoTree.TreeLock,
2190 PsGetCurrentThread());
2192 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
2195 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
2197 if( !NT_SUCCESS( ntStatus) ||
2201 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2202 AFS_TRACE_LEVEL_ERROR,
2203 "AFSProcessReleaseFileExtents Invalid volume index %I64X status %08X\n",
2204 ullIndex, ntStatus);
2206 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2209 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
2212 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
2215 // Now locate the Object in this volume
2218 ullIndex = AFSCreateLowIndex( &pExtents->FileId);
2220 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
2222 (AFSBTreeEntry **)&pObjectInfo);
2224 if( pObjectInfo != NULL)
2228 // Reference the node so it won't be torn down
2231 lCount = AFSObjectInfoIncrement( pObjectInfo);
2233 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2234 AFS_TRACE_LEVEL_VERBOSE,
2235 "AFSProcessReleaseFileExtents Increment count on object %08lX Cnt %d\n",
2240 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2242 if( !NT_SUCCESS( ntStatus) ||
2243 pObjectInfo == NULL)
2246 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2247 AFS_TRACE_LEVEL_ERROR,
2248 "AFSProcessReleaseFileExtents Invalid file index %I64X\n",
2251 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2254 pFcb = pObjectInfo->Fcb;
2259 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2260 AFS_TRACE_LEVEL_ERROR,
2261 "AFSProcessReleaseFileExtents Fcb not initialied (NO EXTENTS) for FID %08lX:%08lx:%08lX:%08lX\n",
2262 pExtents->FileId.Cell,
2263 pExtents->FileId.Volume,
2264 pExtents->FileId.Vnode,
2265 pExtents->FileId.Unique);
2267 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2270 AFSLockForExtentsTrim( pFcb );
2278 // Locate an Fcb to trim down
2281 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2282 AFS_TRACE_LEVEL_VERBOSE,
2283 "AFSProcessReleaseFileExtents Searching for a Fcb to Trim Down\n");
2285 pFcb = AFSFindFcbToClean( 0, NULL, FALSE);
2290 pFcb = AFSFindFcbToClean( 0, NULL, TRUE);
2296 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2297 AFS_TRACE_LEVEL_ERROR,
2298 "AFSProcessReleaseFileExtents Failed to locate Fcb for release ...\n");
2300 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2303 pObjectInfo = pFcb->ObjectInformation;
2309 // Allocate a scratch buffer to move in the extent information
2312 ulSz = (pExtents->ExtentCount-1) * sizeof(AFSFileExtentCB);
2313 ulSz += sizeof(AFSReleaseFileExtentsResultCB);
2315 if (ulSz > pIrpSp->Parameters.DeviceIoControl.OutputBufferLength)
2317 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2318 AFS_TRACE_LEVEL_ERROR,
2319 "AFSProcessReleaseFileExtents OUTPUT Buffer too small [2]\n");
2321 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL );
2324 pResult = (AFSReleaseFileExtentsResultCB*) AFSExAllocatePoolWithTag( PagedPool,
2326 AFS_EXTENTS_RESULT_TAG);
2327 if (NULL == pResult)
2330 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2331 AFS_TRACE_LEVEL_ERROR,
2332 "AFSProcessReleaseFileExtents Failed to allocate result block\n");
2334 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2338 // Set up the header (for an array of one)
2340 pResult->FileCount = 1;
2341 pResult->Flags = AFS_EXTENT_FLAG_RELEASE;
2342 ulSz -= FIELD_OFFSET(AFSReleaseFileExtentsResultCB, Files);
2345 // Setup the first (and only) file
2347 pFile = pResult->Files;
2348 pFile->FileId = pObjectInfo->FileId;
2349 pFile->Flags = AFS_EXTENT_FLAG_RELEASE;
2352 // Stash away the auth group
2355 RtlZeroMemory( &stAuthGroup,
2358 ntStatus = AFSRetrieveValidAuthGroup( pFcb,
2363 if( !NT_SUCCESS( ntStatus))
2365 try_return( ntStatus);
2368 RtlCopyMemory( &pFile->AuthGroup,
2373 // Update the metadata for this call
2376 pFile->AllocationSize = pFcb->ObjectInformation->EndOfFile;
2377 pFile->CreateTime = pFcb->ObjectInformation->CreationTime;
2378 pFile->ChangeTime = pFcb->ObjectInformation->ChangeTime;
2379 pFile->LastAccessTime = pFcb->ObjectInformation->LastAccessTime;
2380 pFile->LastWriteTime = pFcb->ObjectInformation->LastWriteTime;
2382 ulSz -= FIELD_OFFSET(AFSReleaseFileExtentsResultFileCB, FileExtents);
2384 ntStatus = AFSReleaseSpecifiedExtents( pExtents,
2388 &pFile->ExtentCount,
2391 if (!NT_SUCCESS(ntStatus))
2394 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2395 AFS_TRACE_LEVEL_ERROR,
2396 "AFSProcessReleaseFileExtents Failed to release extents Status %08lX\n",
2399 try_return( ntStatus );
2402 if( pExtents->ExtentCount == 0)
2405 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2406 AFS_TRACE_LEVEL_WARNING,
2407 "AFSProcessReleaseFileExtents Failed to release ANY extents\n");
2410 ulSz = sizeof(AFSReleaseFileExtentsResultCB);
2412 if( pExtents->ExtentCount > 0)
2414 ulSz += ((pExtents->ExtentCount-1) * sizeof(AFSFileExtentCB));
2417 RtlCopyMemory( Irp->AssociatedIrp.SystemBuffer,
2426 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2427 AFS_TRACE_LEVEL_VERBOSE,
2428 "AFSProcessReleaseFileExtents Releasing Fcb extent lock %08lX thread %08lX\n",
2429 &pFcb->NPFcb->Specific.File.ExtentsResource,
2430 PsGetCurrentThread());
2432 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
2435 if( NULL != pResult &&
2436 Irp->AssociatedIrp.SystemBuffer != pResult)
2439 AFSExFreePoolWithTag(pResult, AFS_EXTENTS_RESULT_TAG);
2442 if (NT_SUCCESS(ntStatus))
2444 Irp->IoStatus.Information = ulSz;
2448 Irp->IoStatus.Information = 0;
2451 Irp->IoStatus.Status = ntStatus;
2453 if( pObjectInfo != NULL)
2456 lCount = AFSObjectInfoDecrement( pObjectInfo);
2458 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2459 AFS_TRACE_LEVEL_VERBOSE,
2460 "AFSProcessReleaseFileExtents Decrement count on object %08lX Cnt %d\n",
2470 AFSWaitForExtentMapping( AFSFcb *Fcb,
2473 NTSTATUS ntStatus = STATUS_SUCCESS;
2474 LARGE_INTEGER liTimeOut;
2475 ULONGLONG ullProcessId = (ULONGLONG)PsGetCurrentProcessId();
2480 ASSERT( !ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
2482 if (!NT_SUCCESS( Fcb->NPFcb->Specific.File.ExtentsRequestStatus))
2486 // If this isn't the same authgroup which caused the failure
2487 // then try to request them again
2490 if( RtlCompareMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2492 sizeof( GUID)) == sizeof( GUID))
2495 ntStatus = Fcb->NPFcb->Specific.File.ExtentsRequestStatus;
2497 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
2499 RtlZeroMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2502 try_return( ntStatus);
2506 liTimeOut.QuadPart = -(1 * AFS_ONE_SECOND);
2508 ntStatus = KeWaitForSingleObject( &Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
2514 if (!NT_SUCCESS( Fcb->NPFcb->Specific.File.ExtentsRequestStatus))
2518 // If this isn't the same authgroup which caused the failure
2519 // or the System Process,
2520 // then try to request the extents again
2523 if( RtlCompareMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2525 sizeof( GUID)) == sizeof( GUID) ||
2526 ullProcessId == (ULONGLONG)AFSSysProcess)
2529 ntStatus = Fcb->NPFcb->Specific.File.ExtentsRequestStatus;
2531 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
2533 RtlZeroMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2536 try_return( ntStatus);
2540 if( ntStatus == STATUS_TIMEOUT)
2543 ntStatus = STATUS_SUCCESS;
2555 AFSFlushExtents( IN AFSFcb *Fcb,
2558 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
2559 AFSExtent *pExtent, *pNextExtent;
2561 AFSReleaseExtentsCB *pRelease = NULL;
2563 ULONG initialDirtyCount = 0;
2564 BOOLEAN bExtentsLocked = FALSE;
2567 NTSTATUS ntStatus = STATUS_SUCCESS;
2568 LARGE_INTEGER liLastFlush;
2569 AFSExtent *pDirtyListHead = NULL, *pDirtyListTail = NULL;
2570 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2571 GUID *pAuthGroup = AuthGroup;
2575 ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
2578 // Save, then reset the flush time
2581 liLastFlush = Fcb->Specific.File.LastServerFlush;
2583 KeQueryTickCount( &Fcb->Specific.File.LastServerFlush);
2588 lCount = InterlockedIncrement( &Fcb->Specific.File.QueuedFlushCount);
2590 if( pAuthGroup == NULL ||
2591 RtlCompareMemory( pAuthGroup,
2592 &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2593 sizeof( GUID)) == sizeof( GUID))
2596 RtlZeroMemory( &stAuthGroup,
2599 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
2604 if( !NT_SUCCESS( ntStatus))
2606 try_return( ntStatus);
2609 pAuthGroup = &stAuthGroup;
2613 // Lock extents while we count and set up the array to send to
2617 AFSLockForExtentsTrim( Fcb);
2619 bExtentsLocked = TRUE;
2622 // Clear our queued flush event
2625 KeClearEvent( &Fcb->NPFcb->Specific.File.QueuedFlushEvent);
2628 // Look for a start in the list to flush entries
2633 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
2635 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
2637 AFS_EXTENT_RELEASE_TAG);
2638 if( NULL == pRelease)
2641 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2644 initialDirtyCount = Fcb->Specific.File.ExtentsDirtyCount;
2646 while( Fcb->Specific.File.ExtentsDirtyCount > 0)
2649 pRelease->Flags = AFS_EXTENT_FLAG_DIRTY;
2651 if( BooleanFlagOn( Fcb->Flags, AFS_FCB_FILE_CLOSED))
2654 pRelease->Flags |= AFS_EXTENT_FLAG_FLUSH;
2658 // Update the metadata for this call
2661 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
2662 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
2663 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
2664 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
2665 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
2669 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
2672 pExtent = (AFSExtent *)pNPFcb->Specific.File.DirtyListHead;
2674 while( count < AFS_MAXIMUM_EXTENT_RELEASE_COUNT)
2677 if ( pExtent == NULL)
2683 pNextExtent = (AFSExtent *)pExtent->DirtyList.fLink;
2685 if ( pExtent->ActiveCount > 0)
2687 pExtent = pNextExtent;
2691 AFSRemoveEntryDirtyList( Fcb, pExtent);
2693 pExtent->DirtyList.fLink = NULL;
2694 pExtent->DirtyList.bLink = NULL;
2696 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
2699 // Clear the flag in advance of the write. If we do
2700 // things this was we know that the clear is
2701 // pessimistic (any write which happens from now on
2702 // will set the flag dirty again).
2705 pExtent->Flags &= ~AFS_EXTENT_DIRTY;
2707 pRelease->FileExtents[count].Flags = AFS_EXTENT_FLAG_DIRTY;
2709 pRelease->FileExtents[count].Length = pExtent->Size;
2710 pRelease->FileExtents[count].DirtyLength = pExtent->Size;
2711 pRelease->FileExtents[count].DirtyOffset = 0;
2712 pRelease->FileExtents[count].CacheOffset = pExtent->CacheOffset;
2713 pRelease->FileExtents[count].FileOffset = pExtent->FileOffset;
2716 RtlCopyMemory( pRelease->FileExtents[count].MD5,
2718 sizeof(pExtent->MD5));
2720 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_MD5_SET;
2723 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2724 AFS_TRACE_LEVEL_VERBOSE,
2725 "AFSFlushExtents Releasing DIRTY extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
2727 Fcb->ObjectInformation->FileId.Cell,
2728 Fcb->ObjectInformation->FileId.Volume,
2729 Fcb->ObjectInformation->FileId.Vnode,
2730 Fcb->ObjectInformation->FileId.Unique,
2731 pExtent->FileOffset.QuadPart,
2734 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_RELEASE;
2741 pExtent = pNextExtent;
2744 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
2747 // If we are done then get out
2753 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2754 AFS_TRACE_LEVEL_VERBOSE,
2755 "AFSFlushExtents No more dirty extents found\n");
2761 // Fire off the request synchronously
2764 sz = sizeof( AFSReleaseExtentsCB ) + (count * sizeof ( AFSFileExtentCB ));
2766 pRelease->ExtentCount = count;
2768 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2769 AFS_TRACE_LEVEL_VERBOSE,
2770 "AFSFlushExtents Releasing(1) Fcb extents lock %08lX SHARED %08lX\n",
2771 &pNPFcb->Specific.File.ExtentsResource,
2772 PsGetCurrentThread());
2774 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource);
2775 bExtentsLocked = FALSE;
2777 KeSetEvent( &pNPFcb->Specific.File.FlushEvent,
2781 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
2782 AFS_REQUEST_FLAG_SYNCHRONOUS,
2785 &Fcb->ObjectInformation->FileId,
2791 if( !NT_SUCCESS(ntStatus))
2795 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
2796 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
2799 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2800 AFS_TRACE_LEVEL_ERROR,
2801 "AFSFlushExtents AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2802 Fcb->ObjectInformation->FileId.Cell,
2803 Fcb->ObjectInformation->FileId.Volume,
2804 Fcb->ObjectInformation->FileId.Vnode,
2805 Fcb->ObjectInformation->FileId.Unique,
2809 AFSLockForExtentsTrim( Fcb);
2811 bExtentsLocked = TRUE;
2816 lCount = InterlockedDecrement( &Fcb->Specific.File.QueuedFlushCount);
2818 ASSERT( lCount >= 0);
2823 KeSetEvent( &pNPFcb->Specific.File.QueuedFlushEvent,
2828 KeSetEvent( &pNPFcb->Specific.File.FlushEvent,
2835 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2836 AFS_TRACE_LEVEL_VERBOSE,
2837 "AFSFlushExtents Releasing(2) Fcb extents lock %08lX SHARED %08lX\n",
2838 &pNPFcb->Specific.File.ExtentsResource,
2839 PsGetCurrentThread());
2841 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
2846 AFSExFreePoolWithTag( pRelease, AFS_EXTENT_RELEASE_TAG);
2854 AFSReleaseExtentsWithFlush( IN AFSFcb *Fcb,
2856 IN BOOLEAN bReleaseAll)
2858 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
2861 AFSReleaseExtentsCB *pRelease = NULL;
2863 ULONG initialDirtyCount = 0;
2864 BOOLEAN bExtentsLocked = FALSE;
2867 NTSTATUS ntStatus = STATUS_SUCCESS;
2868 LARGE_INTEGER liLastFlush;
2869 ULONG ulRemainingExtentLength = 0;
2870 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2871 GUID *pAuthGroup = AuthGroup;
2875 ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
2878 // Save, then reset the flush time
2881 liLastFlush = Fcb->Specific.File.LastServerFlush;
2883 KeQueryTickCount( &Fcb->Specific.File.LastServerFlush);
2888 if( pAuthGroup == NULL ||
2889 RtlCompareMemory( pAuthGroup,
2890 &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2891 sizeof( GUID)) == sizeof( GUID))
2894 RtlZeroMemory( &stAuthGroup,
2897 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
2902 if( !NT_SUCCESS( ntStatus))
2904 try_return( ntStatus);
2907 pAuthGroup = &stAuthGroup;
2911 // Look for a start in the list to flush entries
2916 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
2918 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
2920 AFS_EXTENT_RELEASE_TAG);
2921 if( NULL == pRelease)
2924 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2927 if( Fcb->OpenHandleCount > 0 &&
2932 // Don't release everything ...
2935 ulRemainingExtentLength = 1024;
2938 while( Fcb->Specific.File.ExtentLength > (LONG)ulRemainingExtentLength)
2941 AFSLockForExtentsTrim( Fcb);
2943 bExtentsLocked = TRUE;
2945 pRelease->Flags = AFS_EXTENT_FLAG_RELEASE;
2948 // Update the metadata for this call
2951 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
2952 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
2953 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
2954 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
2955 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
2959 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
2961 while( count < AFS_MAXIMUM_EXTENT_RELEASE_COUNT &&
2962 le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
2965 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
2969 if( pExtent->ActiveCount > 0)
2975 pRelease->FileExtents[count].Flags = AFS_EXTENT_FLAG_RELEASE;
2977 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2978 AFS_TRACE_LEVEL_VERBOSE,
2979 "AFSReleaseExtentsWithFlush Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
2981 Fcb->ObjectInformation->FileId.Cell,
2982 Fcb->ObjectInformation->FileId.Volume,
2983 Fcb->ObjectInformation->FileId.Vnode,
2984 Fcb->ObjectInformation->FileId.Unique,
2985 pExtent->FileOffset.QuadPart,
2988 pRelease->FileExtents[count].Length = pExtent->Size;
2989 pRelease->FileExtents[count].DirtyLength = pExtent->Size;
2990 pRelease->FileExtents[count].DirtyOffset = 0;
2991 pRelease->FileExtents[count].CacheOffset = pExtent->CacheOffset;
2992 pRelease->FileExtents[count].FileOffset = pExtent->FileOffset;
2995 RtlCopyMemory( pRelease->FileExtents[count].MD5,
2997 sizeof(pExtent->MD5));
2999 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_MD5_SET;
3002 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3005 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3008 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3011 AFSRemoveEntryDirtyList( Fcb,
3014 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_DIRTY;
3016 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
3019 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3029 // If we are done then get out
3035 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3036 AFS_TRACE_LEVEL_VERBOSE,
3037 "AFSReleaseExtentsWithFlush No more dirty extents found\n");
3043 // Fire off the request synchronously
3046 sz = sizeof( AFSReleaseExtentsCB ) + (count * sizeof ( AFSFileExtentCB ));
3048 pRelease->ExtentCount = count;
3051 // Drop the extents lock for the duration of the call to
3052 // the network. We have pinned the extents so, even
3053 // though we might get extents added during this period,
3054 // but none will be removed. Hence we can carry on from
3058 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3059 AFS_TRACE_LEVEL_VERBOSE,
3060 "AFSReleaseExtentsWithFlush Releasing Fcb extents lock %08lX thread %08lX\n",
3061 &pNPFcb->Specific.File.ExtentsResource,
3062 PsGetCurrentThread());
3064 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource);
3065 bExtentsLocked = FALSE;
3067 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
3068 AFS_REQUEST_FLAG_SYNCHRONOUS,
3071 &Fcb->ObjectInformation->FileId,
3077 if( !NT_SUCCESS(ntStatus))
3081 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
3082 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
3085 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3086 AFS_TRACE_LEVEL_ERROR,
3087 "AFSReleaseExtentsWithFlush AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3088 Fcb->ObjectInformation->FileId.Cell,
3089 Fcb->ObjectInformation->FileId.Volume,
3090 Fcb->ObjectInformation->FileId.Vnode,
3091 Fcb->ObjectInformation->FileId.Unique,