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 ( ntStatus == STATUS_ACCESS_DENIED)
806 ntStatus2 = AFSRetrieveValidAuthGroup( Fcb,
811 if ( NT_SUCCESS( ntStatus2) &&
812 RtlCompareMemory( &stAuthGroup,
814 sizeof( GUID)) != sizeof( GUID))
817 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS,
821 &Fcb->ObjectInformation->FileId,
823 sizeof( AFSRequestExtentsCB ),
829 if( NT_SUCCESS( ntStatus))
832 KeClearEvent( &pNPFcb->Specific.File.ExtentsRequestComplete );
838 KeClearEvent( &pNPFcb->Specific.File.ExtentsRequestComplete );
850 AFSProcessExtentsResult( IN AFSFcb *Fcb,
852 IN AFSFileExtentCB *Result)
854 NTSTATUS ntStatus = STATUS_SUCCESS;
855 AFSFileExtentCB *pFileExtents = Result;
858 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
859 ULONG fileExtentsUsed = 0;
860 BOOLEAN bFoundExtent = FALSE;
861 LIST_ENTRY *pSkipEntries[AFS_NUM_EXTENT_LISTS] = { 0 };
862 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
865 // Grab the extents exclusive for the duration
868 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
869 AFS_TRACE_LEVEL_VERBOSE,
870 "AFSProcessExtentsResult Acquiring Fcb extent lock %08lX EXCL %08lX\n",
871 &pNPFcb->Specific.File.ExtentsResource,
872 PsGetCurrentThread());
874 AFSAcquireExcl( &pNPFcb->Specific.File.ExtentsResource, TRUE );
880 // Find where to put the extents
882 for (ULONG i = AFS_EXTENTS_LIST; i < AFS_NUM_EXTENT_LISTS; i++)
885 pSkipEntries[i] = Fcb->Specific.File.ExtentsLists[i].Flink;
888 le = pSkipEntries[AFS_EXTENTS_LIST];
890 if (le == &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
893 // No extents. Insert at head of list (which is where the skip lists point!)
897 else if (0 != pFileExtents->FileOffset.QuadPart)
900 // We want to find the best extents immediately *behind* this offset
902 LARGE_INTEGER offset = pFileExtents->FileOffset;
905 // Ask in the top skip list first, then work down
907 for (LONG i = AFS_NUM_EXTENT_LISTS-1; i >= AFS_EXTENTS_LIST; i--)
909 pExtent = ExtentForOffsetInList( Fcb,
917 // No dice. Header has to become the head of the list
919 pSkipEntries[i] = &Fcb->Specific.File.ExtentsLists[i];
921 // And as a loop invariant we should never have found an extent
923 ASSERT(!bFoundExtent);
928 // pExtent is where to start to insert at this level
930 pSkipEntries[i] = &pExtent->Lists[i];
933 // And also where to start to look at the next level
936 if (i > AFS_EXTENTS_LIST)
938 pSkipEntries[i-1] = &pExtent->Lists[i-1];
946 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
951 le = pExtent->Lists[AFS_EXTENTS_LIST].Blink;
957 // Looking at offset 0, so we must start at the beginning
960 pExtent = ExtentFor(le, AFS_EXTENTS_LIST);
964 // And set up the skip lists
967 for (ULONG i = AFS_EXTENTS_LIST; i < AFS_NUM_EXTENT_LISTS; i++)
969 pSkipEntries[i] = &Fcb->Specific.File.ExtentsLists[i];
973 while (fileExtentsUsed < Count)
977 // Loop invariant - le points to where to insert after and
978 // pExtent points to le->fLink
981 ASSERT (NULL == pExtent ||
982 le->Flink == &pExtent->Lists[AFS_EXTENTS_LIST]);
984 if (NULL == pExtent ||
985 pExtent->FileOffset.QuadPart > pFileExtents->FileOffset.QuadPart)
988 // We need to insert a new extent at le. Start with
989 // some sanity check on spanning
991 if (NULL != pExtent &&
992 ((pFileExtents->FileOffset.QuadPart + pFileExtents->Length) >
993 pExtent->FileOffset.QuadPart))
996 // File Extents overlaps pExtent
998 ASSERT( (pFileExtents->FileOffset.QuadPart + pFileExtents->Length) <=
999 pExtent->FileOffset.QuadPart);
1001 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1005 // File offset is entirely in front of this extent. Create
1006 // a new one (remember le is the previous list entry)
1008 pExtent = (AFSExtent *) AFSExAllocatePoolWithTag( NonPagedPool,
1011 if (NULL == pExtent)
1016 try_return (ntStatus = STATUS_INSUFFICIENT_RESOURCES );
1019 RtlZeroMemory( pExtent, sizeof( AFSExtent ));
1021 pExtent->FileOffset = pFileExtents->FileOffset;
1022 pExtent->CacheOffset = pFileExtents->CacheOffset;
1023 pExtent->Size = pFileExtents->Length;
1025 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1026 AFS_TRACE_LEVEL_VERBOSE,
1027 "AFSProcessExtentsResult Received extent for fid %08lX-%08lX-%08lX-%08lX File Offset %I64X Cache Offset %I64X Len %08lX\n",
1028 Fcb->ObjectInformation->FileId.Cell,
1029 Fcb->ObjectInformation->FileId.Volume,
1030 Fcb->ObjectInformation->FileId.Vnode,
1031 Fcb->ObjectInformation->FileId.Unique,
1032 pFileExtents->FileOffset.QuadPart,
1033 pFileExtents->CacheOffset.QuadPart,
1034 pFileExtents->Length);
1036 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, (LONG)(pExtent->Size/1024));
1038 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, (LONG)(pExtent->Size/1024));
1040 InterlockedIncrement( &Fcb->Specific.File.ExtentCount);
1042 if( InterlockedIncrement( &pControlDevExt->Specific.Control.ExtentCount) == 1)
1045 KeClearEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent);
1051 InsertHeadList(le, &pExtent->Lists[AFS_EXTENTS_LIST]);
1052 ASSERT(le->Flink == &pExtent->Lists[AFS_EXTENTS_LIST]);
1053 ASSERT(0 == (pExtent->FileOffset.LowPart & ExtentsMasks[AFS_EXTENTS_LIST]));
1056 // Do not move the cursor - we will do it next time
1060 // And into the (upper) skip lists - Again, do not move the cursor
1062 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1064 if (0 == (pExtent->FileOffset.LowPart & ExtentsMasks[i]))
1066 InsertHeadList(pSkipEntries[i], &pExtent->Lists[i]);
1067 #if AFS_VALIDATE_EXTENTS
1068 VerifyExtentsLists(Fcb);
1073 else if (pExtent->FileOffset.QuadPart == pFileExtents->FileOffset.QuadPart)
1076 if (pExtent->Size != pFileExtents->Length)
1079 ASSERT (pExtent->Size == pFileExtents->Length);
1081 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1085 // Move both cursors forward.
1087 // First the extent pointer
1090 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1093 // Then the skip lists cursors forward if needed
1095 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1097 if (0 == (pExtent->FileOffset.LowPart & ExtentsMasks[i]))
1100 // Check sanity before
1102 #if AFS_VALIDATE_EXTENTS
1103 VerifyExtentsLists(Fcb);
1107 // Skip list should point to us
1109 //ASSERT(pSkipEntries[i] == &pExtent->Lists[i]);
1111 // Move forward cursor
1113 pSkipEntries[i] = pSkipEntries[i]->Flink;
1115 // Check sanity before
1117 #if AFS_VALIDATE_EXTENTS
1118 VerifyExtentsLists(Fcb);
1124 // And then the cursor in the supplied array
1130 // setup pExtent if there is one
1132 if (le->Flink != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
1134 pExtent = NextExtent( pExtent, AFS_EXTENTS_LIST ) ;
1144 ASSERT( pExtent->FileOffset.QuadPart < pFileExtents->FileOffset.QuadPart );
1147 // Sanity check on spanning
1149 if ((pExtent->FileOffset.QuadPart + pExtent->Size) >
1150 pFileExtents->FileOffset.QuadPart)
1153 ASSERT( (pExtent->FileOffset.QuadPart + pExtent->Size) <=
1154 pFileExtents->FileOffset.QuadPart);
1156 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1160 // Move le and pExtent forward
1162 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1166 // Then the check the skip lists cursors
1168 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1170 if (0 == (pFileExtents->FileOffset.LowPart & ExtentsMasks[i]))
1174 // - empty list (pSkipEntries[i]->Flink == pSkipEntries[i]->Flink == fcb->lists[i]
1175 // - We are the last on the list (pSkipEntries[i]->Flink == fcb->lists[i])
1176 // - We are not the last on the list. In that case we have to be strictly less than
1178 if (pSkipEntries[i]->Flink != &Fcb->Specific.File.ExtentsLists[i]) {
1180 AFSExtent *otherExtent = ExtentFor(pSkipEntries[i]->Flink, i);
1181 ASSERT(pFileExtents->FileOffset.QuadPart < otherExtent->FileOffset.QuadPart);
1188 // setup pExtent if there is one
1191 if (le->Flink != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
1193 pExtent = NextExtent( pExtent, AFS_EXTENTS_LIST ) ;
1203 // All done, signal that we are done drop the lock, exit
1208 if( !NT_SUCCESS( ntStatus))
1212 // If we failed the service is going to drop all extents so trim away the
1216 AFSTrimSpecifiedExtents( Fcb,
1221 #if AFS_VALIDATE_EXTENTS
1222 VerifyExtentsLists(Fcb);
1225 KeSetEvent( &pNPFcb->Specific.File.ExtentsRequestComplete,
1229 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1230 AFS_TRACE_LEVEL_VERBOSE,
1231 "AFSProcessExtentsResult Releasing Fcb extent lock %08lX EXCL %08lX\n",
1232 &pNPFcb->Specific.File.ExtentsResource,
1233 PsGetCurrentThread());
1235 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
1242 AFSProcessSetFileExtents( IN AFSSetFileExtentsCB *SetExtents )
1244 AFSFcb *pFcb = NULL;
1245 AFSVolumeCB *pVolumeCB = NULL;
1246 NTSTATUS ntStatus = STATUS_SUCCESS;
1247 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1248 ULONGLONG ullIndex = 0;
1249 AFSObjectInfoCB *pObjectInfo = NULL;
1254 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1255 AFS_TRACE_LEVEL_VERBOSE,
1256 "AFSProcessSetFileExtents Acquiring RDR VolumeTreeLock lock %08lX SHARED %08lX\n",
1257 &pDevExt->Specific.RDR.VolumeTreeLock,
1258 PsGetCurrentThread());
1260 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
1262 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1263 AFS_TRACE_LEVEL_VERBOSE,
1264 "AFSProcessSetFileExtents Set extents for fid %08lX-%08lX-%08lX-%08lX\n",
1265 SetExtents->FileId.Cell,
1266 SetExtents->FileId.Volume,
1267 SetExtents->FileId.Vnode,
1268 SetExtents->FileId.Unique);
1271 // Locate the volume node
1274 ullIndex = AFSCreateHighIndex( &SetExtents->FileId);
1276 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
1278 (AFSBTreeEntry **)&pVolumeCB);
1280 if( pVolumeCB != NULL)
1283 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1284 AFS_TRACE_LEVEL_VERBOSE,
1285 "AFSProcessSetFileExtents Acquiring VolumeRoot FileIDTree.TreeLock lock %08lX SHARED %08lX\n",
1286 pVolumeCB->ObjectInfoTree.TreeLock,
1287 PsGetCurrentThread());
1289 InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1292 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
1294 if( !NT_SUCCESS( ntStatus) ||
1298 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1299 AFS_TRACE_LEVEL_ERROR,
1300 "AFSProcessSetFileExtents Set extents for fid %08lX-%08lX-%08lX-%08lX Failed to locate volume Status %08lX\n",
1301 SetExtents->FileId.Cell,
1302 SetExtents->FileId.Volume,
1303 SetExtents->FileId.Vnode,
1304 SetExtents->FileId.Unique,
1307 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1310 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1313 InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1316 // Now locate the Object in this volume
1319 ullIndex = AFSCreateLowIndex( &SetExtents->FileId);
1321 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
1323 (AFSBTreeEntry **)&pObjectInfo);
1325 if( pObjectInfo != NULL)
1329 // Reference the node so it won't be torn down
1332 InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
1334 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1335 AFS_TRACE_LEVEL_VERBOSE,
1336 "AFSProcessSetFileExtents Increment count on object %08lX Cnt %d\n",
1338 pObjectInfo->ObjectReferenceCount);
1341 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1343 if( !NT_SUCCESS( ntStatus) ||
1344 pObjectInfo == NULL)
1347 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1348 AFS_TRACE_LEVEL_ERROR,
1349 "AFSProcessSetFileExtents Set extents for hash %I64X fid %08lX-%08lX-%08lX-%08lX Failed to locate file in volume %08lX\n",
1351 SetExtents->FileId.Cell,
1352 SetExtents->FileId.Volume,
1353 SetExtents->FileId.Vnode,
1354 SetExtents->FileId.Unique,
1357 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1360 pFcb = pObjectInfo->Fcb;
1363 // If we have a result failure then don't bother trying to set the extents
1366 if( SetExtents->ResultStatus != STATUS_SUCCESS)
1369 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1370 AFS_TRACE_LEVEL_ERROR,
1371 "AFSProcessSetFileExtents Set extents failure fid %08lX-%08lX-%08lX-%08lX ResultStatus %08lX\n",
1372 SetExtents->FileId.Cell,
1373 SetExtents->FileId.Volume,
1374 SetExtents->FileId.Vnode,
1375 SetExtents->FileId.Unique,
1376 SetExtents->ResultStatus);
1378 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1379 AFS_TRACE_LEVEL_VERBOSE,
1380 "AFSProcessSetFileExtents Acquiring Fcb extents lock %08lX EXCL %08lX\n",
1381 &pFcb->NPFcb->Specific.File.ExtentsResource,
1382 PsGetCurrentThread());
1384 AFSAcquireExcl( &pFcb->NPFcb->Specific.File.ExtentsResource,
1387 pFcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_CANCELLED;
1389 KeSetEvent( &pFcb->NPFcb->Specific.File.ExtentsRequestComplete,
1393 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1394 AFS_TRACE_LEVEL_VERBOSE,
1395 "AFSProcessSetFileExtents Releasing Fcb extent lock %08lX EXCL %08lX\n",
1396 &pFcb->NPFcb->Specific.File.ExtentsResource,
1397 PsGetCurrentThread());
1399 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
1401 try_return( ntStatus);
1404 ntStatus = AFSProcessExtentsResult ( pFcb,
1405 SetExtents->ExtentCount,
1406 SetExtents->FileExtents );
1410 if( pObjectInfo != NULL)
1413 InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
1415 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1416 AFS_TRACE_LEVEL_VERBOSE,
1417 "AFSProcessSetFileExtents Decrement count on object %08lX Cnt %d\n",
1419 pObjectInfo->ObjectReferenceCount);
1427 // Helper fuctions for Usermode initiation of release of extents
1430 AFSReleaseSpecifiedExtents( IN AFSReleaseFileExtentsCB *Extents,
1432 OUT AFSFileExtentCB *FileExtents,
1433 IN ULONG BufferSize,
1434 OUT ULONG *ExtentCount,
1435 OUT BOOLEAN *DirtyExtents)
1440 ULONG ulExtentCount = 0;
1441 NTSTATUS ntStatus = STATUS_SUCCESS;
1442 BOOLEAN bReleaseAll = FALSE;
1443 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1447 ASSERT( ExIsResourceAcquiredExclusiveLite( &Fcb->NPFcb->Specific.File.ExtentsResource));
1449 if (BufferSize < (Extents->ExtentCount * sizeof( AFSFileExtentCB)))
1452 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1453 AFS_TRACE_LEVEL_VERBOSE,
1454 "AFSReleaseSpecifiedExtents Buffer too small\n");
1456 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL);
1459 RtlZeroMemory( FileExtents, BufferSize);
1462 *DirtyExtents = FALSE;
1465 // iterate until we have dealt with all we were asked for or
1466 // are at the end of the list. Note that this deals (albeit
1467 // badly) with out of order extents
1470 pExtent = AFSExtentForOffset( Fcb,
1471 &Extents->FileExtents[0].FileOffset,
1474 if (NULL == pExtent)
1476 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1480 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1484 if( BooleanFlagOn( Extents->Flags, AFS_RELEASE_EXTENTS_FLAGS_RELEASE_ALL) ||
1485 ( Extents->FileId.Cell == 0 &&
1486 Extents->FileId.Volume == 0 &&
1487 Extents->FileId.Vnode == 0 &&
1488 Extents->FileId.Unique == 0))
1494 while( le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST] &&
1495 ulExtentCount < Extents->ExtentCount)
1499 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
1504 if( pExtent->FileOffset.QuadPart < Extents->FileExtents[ulExtentCount].FileOffset.QuadPart)
1507 // Skip forward through the extent list until we get
1508 // to the one we want
1514 else if (pExtent->FileOffset.QuadPart > Extents->FileExtents[ulExtentCount].FileOffset.QuadPart)
1517 // We don't have the extent asked for so return UNKNOWN
1520 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1521 AFS_TRACE_LEVEL_VERBOSE,
1522 "AFSReleaseSpecifiedExtents Located UNKNOWN extent Offset %I64X Len %08lX\n",
1523 Extents->FileExtents[ulExtentCount].FileOffset.QuadPart,
1524 Extents->FileExtents[ulExtentCount].Length);
1526 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_UNKNOWN;
1528 FileExtents[*ExtentCount].Length = 0;
1529 FileExtents[*ExtentCount].CacheOffset.QuadPart = 0;
1530 FileExtents[*ExtentCount].FileOffset = Extents->FileExtents[ulExtentCount].FileOffset;
1532 *ExtentCount = (*ExtentCount) + 1;
1537 // Reset where we are looking
1540 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1544 else if( pExtent->ActiveCount > 0)
1547 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1548 AFS_TRACE_LEVEL_VERBOSE,
1549 "AFSReleaseSpecifiedExtents Located IN_USE extent Offset %I64X Len %08lX\n",
1550 Extents->FileExtents[ulExtentCount].FileOffset.QuadPart,
1551 Extents->FileExtents[ulExtentCount].Length);
1553 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_IN_USE;
1555 FileExtents[*ExtentCount].Length = 0;
1556 FileExtents[*ExtentCount].CacheOffset.QuadPart = 0;
1557 FileExtents[*ExtentCount].FileOffset = Extents->FileExtents[ulExtentCount].FileOffset;
1559 *ExtentCount = (*ExtentCount) + 1;
1564 // Reset where we are looking
1567 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1576 // If the extent is currently active then skip it
1579 if( pExtent->ActiveCount > 0)
1588 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_RELEASE;
1590 FileExtents[*ExtentCount].Length = pExtent->Size;
1591 FileExtents[*ExtentCount].DirtyLength = pExtent->Size;
1592 FileExtents[*ExtentCount].DirtyOffset = 0;
1593 FileExtents[*ExtentCount].CacheOffset = pExtent->CacheOffset;
1594 FileExtents[*ExtentCount].FileOffset = pExtent->FileOffset;
1596 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1597 AFS_TRACE_LEVEL_VERBOSE,
1598 "AFSReleaseSpecifiedExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
1600 Fcb->ObjectInformation->FileId.Cell,
1601 Fcb->ObjectInformation->FileId.Volume,
1602 Fcb->ObjectInformation->FileId.Vnode,
1603 Fcb->ObjectInformation->FileId.Unique,
1604 FileExtents[*ExtentCount].FileOffset.QuadPart,
1605 FileExtents[*ExtentCount].Length);
1607 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
1610 AFSAcquireExcl( &Fcb->NPFcb->Specific.File.DirtyExtentsListLock,
1613 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
1616 AFSRemoveEntryDirtyList( Fcb,
1619 FileExtents[*ExtentCount].Flags |= AFS_EXTENT_FLAG_DIRTY;
1621 InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
1623 *DirtyExtents = TRUE;
1626 AFSReleaseResource( &Fcb->NPFcb->Specific.File.DirtyExtentsListLock);
1630 // move forward all three cursors
1634 *ExtentCount = (*ExtentCount) + 1;
1639 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
1641 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
1643 RemoveEntryList( &pExtent->Lists[i] );
1647 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
1649 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
1654 AFSExFreePool( pExtent);
1656 InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
1658 if( InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount) == 0)
1661 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
1676 AFSFindFcbToClean(ULONG IgnoreTime, AFSFcb *LastFcb, BOOLEAN Block)
1679 AFSFcb *pFcb = NULL;
1680 AFSVolumeCB *pVolumeCB = NULL;
1681 AFSDeviceExt *pRDRDeviceExt = NULL;
1682 AFSDeviceExt *pControlDeviceExt = NULL;
1683 BOOLEAN bLocatedEntry = FALSE;
1684 AFSObjectInfoCB *pCurrentObject = NULL;
1685 BOOLEAN bReleaseVolumeListLock = FALSE;
1687 pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1688 pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1690 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1691 AFS_TRACE_LEVEL_VERBOSE,
1692 "AFSFindFcbToClean Acquiring RDR VolumeListLock lock %08lX SHARED %08lX\n",
1693 &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1694 PsGetCurrentThread());
1696 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1699 bReleaseVolumeListLock = TRUE;
1701 pVolumeCB = pRDRDeviceExt->Specific.RDR.VolumeListHead;
1703 while( pVolumeCB != NULL)
1707 // The Volume list may move under our feet. Lock it.
1710 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1711 AFS_TRACE_LEVEL_VERBOSE,
1712 "AFSFindFcbToClean Acquiring VolumeRoot ObjectInfoTree lock %08lX SHARED %08lX\n",
1713 pVolumeCB->ObjectInfoTree.TreeLock,
1714 PsGetCurrentThread());
1716 InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1718 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1720 bReleaseVolumeListLock = FALSE;
1722 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1725 InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1727 if( NULL == LastFcb)
1730 pCurrentObject = pVolumeCB->ObjectInfoListHead;
1735 pCurrentObject = (AFSObjectInfoCB *)LastFcb->ObjectInformation->ListEntry.fLink;
1740 while( pCurrentObject != NULL)
1743 pFcb = (AFSFcb *)pCurrentObject->Fcb;
1746 // If the FCB is a candidate we try to lock it (but without waiting - which
1747 // means we are deadlock free
1751 pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
1757 AFSLockForExtentsTrim( pFcb);
1762 if( !AFSLockForExtentsTrimNoWait( pFcb))
1765 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1774 // Need to be sure there are no current flushes in the queue
1777 if( pFcb->Specific.File.ExtentCount == 0)
1780 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1781 AFS_TRACE_LEVEL_VERBOSE,
1782 "AFSFindFcbToClean Releasing Fcb extent lock %08lX thread %08lX\n",
1783 &pFcb->NPFcb->Specific.File.ExtentsResource,
1784 PsGetCurrentThread());
1786 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
1788 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1795 if( pFcb->Specific.File.QueuedFlushCount > 0)
1798 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1799 AFS_TRACE_LEVEL_VERBOSE,
1800 "AFSFindFcbToClean Releasing Fcb extent lock %08lX thread %08lX\n",
1801 &pFcb->NPFcb->Specific.File.ExtentsResource,
1802 PsGetCurrentThread());
1804 AFSReleaseResource(&pFcb->NPFcb->Specific.File.ExtentsResource);
1808 AFSWaitOnQueuedFlushes( pFcb);
1813 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1821 if( pFcb->OpenHandleCount > 0)
1824 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1825 AFS_TRACE_LEVEL_VERBOSE,
1826 "AFSFindFcbToClean Releasing Fcb extent lock %08lX thread %08lX\n",
1827 &pFcb->NPFcb->Specific.File.ExtentsResource,
1828 PsGetCurrentThread());
1830 AFSReleaseResource(&pFcb->NPFcb->Specific.File.ExtentsResource);
1832 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1840 // A hit a very palpable hit. Pin it
1843 InterlockedIncrement( &pCurrentObject->ObjectReferenceCount);
1845 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1846 AFS_TRACE_LEVEL_VERBOSE,
1847 "AFSFindFcbToClean Increment count on Fcb %08lX Cnt %d\n",
1849 pCurrentObject->ObjectReferenceCount);
1851 bLocatedEntry = TRUE;
1856 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1861 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1868 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1871 bReleaseVolumeListLock = TRUE;
1873 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1876 if( bReleaseVolumeListLock)
1879 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1886 AFSProcessExtentFailure( PIRP Irp)
1888 AFSExtentFailureCB *pFailureCB = NULL;
1889 NTSTATUS ntStatus = STATUS_SUCCESS;
1890 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
1891 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1892 AFSVolumeCB *pVolumeCB = NULL;
1893 ULONGLONG ullIndex = 0;
1894 AFSObjectInfoCB *pObjectInfo = NULL;
1898 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSExtentFailureCB))
1901 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1902 AFS_TRACE_LEVEL_ERROR,
1903 "AFSProcessExtentFailure Input buffer too small\n");
1905 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1908 pFailureCB = (AFSExtentFailureCB *)Irp->AssociatedIrp.SystemBuffer;
1910 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1911 AFS_TRACE_LEVEL_ERROR,
1912 "AFSProcessExtentFailure Service Reports Failure fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1913 pFailureCB->FileId.Cell,
1914 pFailureCB->FileId.Volume,
1915 pFailureCB->FileId.Vnode,
1916 pFailureCB->FileId.Unique,
1917 pFailureCB->FailureStatus);
1919 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
1922 // Locate the volume node
1925 ullIndex = AFSCreateHighIndex( &pFailureCB->FileId);
1927 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
1929 (AFSBTreeEntry **)&pVolumeCB);
1931 if( pVolumeCB != NULL)
1934 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1935 AFS_TRACE_LEVEL_VERBOSE,
1936 "AFSProcessExtentFailure Acquiring VolumeRoot FileIDTree.TreeLock lock %08lX SHARED %08lX\n",
1937 pVolumeCB->ObjectInfoTree.TreeLock,
1938 PsGetCurrentThread());
1940 InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1943 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
1945 if( !NT_SUCCESS( ntStatus) ||
1949 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1950 AFS_TRACE_LEVEL_ERROR,
1951 "AFSProcessExtentFailure Invalid volume index %I64X status %08X\n",
1952 ullIndex, ntStatus);
1954 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1957 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1960 InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1963 // Now locate the Object in this volume
1966 ullIndex = AFSCreateLowIndex( &pFailureCB->FileId);
1968 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
1970 (AFSBTreeEntry **)&pObjectInfo);
1972 if( pObjectInfo != NULL &&
1973 pObjectInfo->Fcb != NULL)
1977 // Reference the node so it won't be torn down
1980 InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
1982 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1983 AFS_TRACE_LEVEL_VERBOSE,
1984 "AFSProcessExtentFailure Increment count on object %08lX Cnt %d\n",
1986 pObjectInfo->ObjectReferenceCount);
1989 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1991 if( !NT_SUCCESS( ntStatus) ||
1992 pObjectInfo == NULL ||
1993 pObjectInfo->Fcb == NULL)
1996 if( pObjectInfo == NULL)
1998 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1999 AFS_TRACE_LEVEL_ERROR,
2000 "AFSProcessExtentFailure Invalid file index %I64X\n",
2005 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2006 AFS_TRACE_LEVEL_ERROR,
2007 "AFSProcessExtentFailure Fcb dealocated for %I64X\n",
2011 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2014 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2015 AFS_TRACE_LEVEL_VERBOSE,
2016 "AFSProcessExtentFailure Acquiring Fcb extent lock %08lX EXCL %08lX\n",
2017 &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2018 PsGetCurrentThread());
2020 AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2023 pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestStatus = pFailureCB->FailureStatus;
2025 RtlCopyMemory( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2026 &pFailureCB->AuthGroup,
2029 KeSetEvent( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
2033 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2034 AFS_TRACE_LEVEL_VERBOSE,
2035 "AFSProcessExtentFailure Releasing Fcb extent lock %08lX EXCL %08lX\n",
2036 &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2037 PsGetCurrentThread());
2039 AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource);
2041 InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
2043 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2044 AFS_TRACE_LEVEL_VERBOSE,
2045 "AFSProcessExtentFailure Decrement count on object %08lX Cnt %d\n",
2047 pObjectInfo->ObjectReferenceCount);
2058 AFSProcessReleaseFileExtents( IN PIRP Irp)
2060 NTSTATUS ntStatus = STATUS_SUCCESS;
2061 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2062 PFILE_OBJECT pFileObject = pIrpSp->FileObject;
2063 AFSFcb *pFcb = NULL;
2064 AFSVolumeCB *pVolumeCB = NULL;
2065 AFSDeviceExt *pDevExt;
2066 AFSReleaseFileExtentsCB *pExtents;
2067 AFSReleaseFileExtentsResultCB *pResult = NULL;
2068 AFSReleaseFileExtentsResultFileCB *pFile = NULL;
2070 ULONGLONG ullIndex = 0;
2071 AFSObjectInfoCB *pObjectInfo = NULL;
2072 BOOLEAN bLocked = FALSE;
2073 BOOLEAN bDirtyExtents = FALSE;
2079 pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2081 pExtents = (AFSReleaseFileExtentsCB*) Irp->AssociatedIrp.SystemBuffer;
2083 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2084 sizeof( AFSReleaseFileExtentsCB))
2087 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2088 AFS_TRACE_LEVEL_ERROR,
2089 "AFSProcessReleaseFileExtents INPUT Buffer too small\n");
2091 try_return( ntStatus = STATUS_INVALID_PARAMETER );
2094 if ( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength <
2095 sizeof(AFSReleaseFileExtentsResultCB))
2098 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2099 AFS_TRACE_LEVEL_ERROR,
2100 "AFSProcessReleaseFileExtents OUTPUT Buffer too small [1]\n");
2103 // Must have space for one extent in one file
2106 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL);
2109 if (pExtents->ExtentCount == 0)
2112 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2113 AFS_TRACE_LEVEL_ERROR,
2114 "AFSProcessReleaseFileExtents Extent count zero\n");
2116 try_return( ntStatus = STATUS_INVALID_PARAMETER);
2119 if (pExtents->FileId.Cell != 0 ||
2120 pExtents->FileId.Volume != 0 ||
2121 pExtents->FileId.Vnode != 0 ||
2122 pExtents->FileId.Unique != 0)
2125 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2126 AFS_TRACE_LEVEL_VERBOSE,
2127 "AFSProcessReleaseFileExtents Processing FID %08lX:%08lX:%08lX:%08lX\n",
2128 pExtents->FileId.Cell,
2129 pExtents->FileId.Volume,
2130 pExtents->FileId.Vnode,
2131 pExtents->FileId.Unique);
2133 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2134 ( FIELD_OFFSET( AFSReleaseFileExtentsCB, ExtentCount) + sizeof(ULONG)) ||
2135 pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2136 ( FIELD_OFFSET( AFSReleaseFileExtentsCB, ExtentCount) + sizeof(ULONG) +
2137 sizeof (AFSFileExtentCB) * pExtents->ExtentCount))
2140 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2141 AFS_TRACE_LEVEL_ERROR,
2142 "AFSProcessReleaseFileExtents Buffer too small for FID %08lX:%08lx:%08lX:%08lX\n",
2143 pExtents->FileId.Cell,
2144 pExtents->FileId.Volume,
2145 pExtents->FileId.Vnode,
2146 pExtents->FileId.Unique);
2148 try_return( ntStatus = STATUS_INVALID_PARAMETER );
2151 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2152 AFS_TRACE_LEVEL_VERBOSE,
2153 "AFSProcessReleaseFileExtents Acquiring RDR VolumeTreeLock lock %08lX SHARED %08lX\n",
2154 &pDevExt->Specific.RDR.VolumeTreeLock,
2155 PsGetCurrentThread());
2157 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
2160 // Locate the volume node
2163 ullIndex = AFSCreateHighIndex( &pExtents->FileId);
2165 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
2167 (AFSBTreeEntry **)&pVolumeCB);
2169 if( pVolumeCB != NULL)
2172 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2173 AFS_TRACE_LEVEL_VERBOSE,
2174 "AFSProcessReleaseFileExtents Acquiring VolumeRoot FileIDTree.TreeLock lock %08lX SHARED %08lX\n",
2175 pVolumeCB->ObjectInfoTree.TreeLock,
2176 PsGetCurrentThread());
2178 InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
2181 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
2183 if( !NT_SUCCESS( ntStatus) ||
2187 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2188 AFS_TRACE_LEVEL_ERROR,
2189 "AFSProcessReleaseFileExtents Invalid volume index %I64X status %08X\n",
2190 ullIndex, ntStatus);
2192 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2195 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
2198 InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
2201 // Now locate the Object in this volume
2204 ullIndex = AFSCreateLowIndex( &pExtents->FileId);
2206 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
2208 (AFSBTreeEntry **)&pObjectInfo);
2210 if( pObjectInfo != NULL)
2214 // Reference the node so it won't be torn down
2217 InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
2219 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2220 AFS_TRACE_LEVEL_VERBOSE,
2221 "AFSProcessReleaseFileExtents Increment count on object %08lX Cnt %d\n",
2223 pObjectInfo->ObjectReferenceCount);
2226 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2228 if( !NT_SUCCESS( ntStatus) ||
2229 pObjectInfo == NULL)
2232 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2233 AFS_TRACE_LEVEL_ERROR,
2234 "AFSProcessReleaseFileExtents Invalid file index %I64X\n",
2237 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2240 pFcb = pObjectInfo->Fcb;
2245 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2246 AFS_TRACE_LEVEL_ERROR,
2247 "AFSProcessReleaseFileExtents Fcb not initialied (NO EXTENTS) for FID %08lX:%08lx:%08lX:%08lX\n",
2248 pExtents->FileId.Cell,
2249 pExtents->FileId.Volume,
2250 pExtents->FileId.Vnode,
2251 pExtents->FileId.Unique);
2253 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2256 AFSLockForExtentsTrim( pFcb );
2264 // Locate an Fcb to trim down
2267 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2268 AFS_TRACE_LEVEL_VERBOSE,
2269 "AFSProcessReleaseFileExtents Searching for a Fcb to Trim Down\n");
2271 pFcb = AFSFindFcbToClean( 0, NULL, FALSE);
2276 pFcb = AFSFindFcbToClean( 0, NULL, TRUE);
2282 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2283 AFS_TRACE_LEVEL_ERROR,
2284 "AFSProcessReleaseFileExtents Failed to locate Fcb for release ...\n");
2286 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2289 pObjectInfo = pFcb->ObjectInformation;
2295 // Allocate a scratch buffer to move in the extent information
2298 ulSz = (pExtents->ExtentCount-1) * sizeof(AFSFileExtentCB);
2299 ulSz += sizeof(AFSReleaseFileExtentsResultCB);
2301 if (ulSz > pIrpSp->Parameters.DeviceIoControl.OutputBufferLength)
2303 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2304 AFS_TRACE_LEVEL_ERROR,
2305 "AFSProcessReleaseFileExtents OUTPUT Buffer too small [2]\n");
2307 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL );
2310 pResult = (AFSReleaseFileExtentsResultCB*) AFSExAllocatePoolWithTag( PagedPool,
2312 AFS_EXTENTS_RESULT_TAG);
2313 if (NULL == pResult)
2316 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2317 AFS_TRACE_LEVEL_ERROR,
2318 "AFSProcessReleaseFileExtents Failed to allocate result block\n");
2320 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2324 // Set up the header (for an array of one)
2326 pResult->FileCount = 1;
2327 pResult->Flags = AFS_EXTENT_FLAG_RELEASE;
2328 ulSz -= FIELD_OFFSET(AFSReleaseFileExtentsResultCB, Files);
2331 // Setup the first (and only) file
2333 pFile = pResult->Files;
2334 pFile->FileId = pObjectInfo->FileId;
2335 pFile->Flags = AFS_EXTENT_FLAG_RELEASE;
2338 // Stash away the auth group
2341 RtlZeroMemory( &stAuthGroup,
2344 ntStatus = AFSRetrieveValidAuthGroup( pFcb,
2349 if( !NT_SUCCESS( ntStatus))
2351 try_return( ntStatus);
2354 RtlCopyMemory( &pFile->AuthGroup,
2359 // Update the metadata for this call
2362 pFile->AllocationSize = pFcb->ObjectInformation->EndOfFile;
2363 pFile->CreateTime = pFcb->ObjectInformation->CreationTime;
2364 pFile->ChangeTime = pFcb->ObjectInformation->ChangeTime;
2365 pFile->LastAccessTime = pFcb->ObjectInformation->LastAccessTime;
2366 pFile->LastWriteTime = pFcb->ObjectInformation->LastWriteTime;
2368 ulSz -= FIELD_OFFSET(AFSReleaseFileExtentsResultFileCB, FileExtents);
2370 ntStatus = AFSReleaseSpecifiedExtents( pExtents,
2374 &pFile->ExtentCount,
2377 if (!NT_SUCCESS(ntStatus))
2380 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2381 AFS_TRACE_LEVEL_ERROR,
2382 "AFSProcessReleaseFileExtents Failed to release extents Status %08lX\n",
2385 try_return( ntStatus );
2388 if( pExtents->ExtentCount == 0)
2391 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2392 AFS_TRACE_LEVEL_WARNING,
2393 "AFSProcessReleaseFileExtents Failed to release ANY extents\n");
2396 ulSz = sizeof(AFSReleaseFileExtentsResultCB);
2398 if( pExtents->ExtentCount > 0)
2400 ulSz += ((pExtents->ExtentCount-1) * sizeof(AFSFileExtentCB));
2403 RtlCopyMemory( Irp->AssociatedIrp.SystemBuffer,
2412 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2413 AFS_TRACE_LEVEL_VERBOSE,
2414 "AFSProcessReleaseFileExtents Releasing Fcb extent lock %08lX thread %08lX\n",
2415 &pFcb->NPFcb->Specific.File.ExtentsResource,
2416 PsGetCurrentThread());
2418 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
2421 if( NULL != pResult &&
2422 Irp->AssociatedIrp.SystemBuffer != pResult)
2425 AFSExFreePool(pResult);
2428 if (NT_SUCCESS(ntStatus))
2430 Irp->IoStatus.Information = ulSz;
2434 Irp->IoStatus.Information = 0;
2437 Irp->IoStatus.Status = ntStatus;
2439 if( pObjectInfo != NULL)
2442 InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
2444 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2445 AFS_TRACE_LEVEL_VERBOSE,
2446 "AFSProcessReleaseFileExtents Decrement count on object %08lX Cnt %d\n",
2448 pObjectInfo->ObjectReferenceCount);
2456 AFSWaitForExtentMapping( AFSFcb *Fcb,
2459 NTSTATUS ntStatus = STATUS_SUCCESS;
2460 LARGE_INTEGER liTimeOut;
2461 ULONGLONG ullProcessId = (ULONGLONG)PsGetCurrentProcessId();
2466 ASSERT( !ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
2468 if (!NT_SUCCESS( Fcb->NPFcb->Specific.File.ExtentsRequestStatus))
2472 // If this isn't the same authgroup which caused the failure
2473 // then try to request them again
2476 if( RtlCompareMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2478 sizeof( GUID)) == sizeof( GUID))
2481 ntStatus = Fcb->NPFcb->Specific.File.ExtentsRequestStatus;
2483 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
2485 RtlZeroMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2488 try_return( ntStatus);
2492 liTimeOut.QuadPart = -(1 * AFS_ONE_SECOND);
2494 ntStatus = KeWaitForSingleObject( &Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
2500 if (!NT_SUCCESS( Fcb->NPFcb->Specific.File.ExtentsRequestStatus))
2504 // If this isn't the same authgroup which caused the failure
2505 // or the System Process,
2506 // then try to request the extents again
2509 if( RtlCompareMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2511 sizeof( GUID)) == sizeof( GUID) ||
2512 ullProcessId == (ULONGLONG)AFSSysProcess)
2515 ntStatus = Fcb->NPFcb->Specific.File.ExtentsRequestStatus;
2517 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
2519 RtlZeroMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2522 try_return( ntStatus);
2526 if( ntStatus == STATUS_TIMEOUT)
2529 ntStatus = STATUS_SUCCESS;
2541 AFSFlushExtents( IN AFSFcb *Fcb,
2544 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
2545 AFSExtent *pExtent, *pNextExtent;
2547 AFSReleaseExtentsCB *pRelease = NULL;
2549 ULONG initialDirtyCount = 0;
2550 BOOLEAN bExtentsLocked = FALSE;
2553 NTSTATUS ntStatus = STATUS_SUCCESS;
2554 LARGE_INTEGER liLastFlush;
2555 AFSExtent *pDirtyListHead = NULL, *pDirtyListTail = NULL;
2556 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2557 GUID *pAuthGroup = AuthGroup;
2560 ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
2563 // Save, then reset the flush time
2566 liLastFlush = Fcb->Specific.File.LastServerFlush;
2568 KeQueryTickCount( &Fcb->Specific.File.LastServerFlush);
2573 if( pAuthGroup == NULL ||
2574 RtlCompareMemory( pAuthGroup,
2575 &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2576 sizeof( GUID)) == sizeof( GUID))
2579 RtlZeroMemory( &stAuthGroup,
2582 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
2587 if( !NT_SUCCESS( ntStatus))
2589 try_return( ntStatus);
2592 pAuthGroup = &stAuthGroup;
2596 // Lock extents while we count and set up the array to send to
2600 AFSLockForExtentsTrim( Fcb);
2602 bExtentsLocked = TRUE;
2604 InterlockedIncrement( &Fcb->Specific.File.QueuedFlushCount);
2607 // Clear our queued flush event
2610 KeClearEvent( &Fcb->NPFcb->Specific.File.QueuedFlushEvent);
2613 // Look for a start in the list to flush entries
2618 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
2620 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
2622 AFS_EXTENT_RELEASE_TAG);
2623 if( NULL == pRelease)
2626 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2629 initialDirtyCount = Fcb->Specific.File.ExtentsDirtyCount;
2631 while( Fcb->Specific.File.ExtentsDirtyCount > 0)
2634 pRelease->Flags = AFS_EXTENT_FLAG_DIRTY;
2636 if( BooleanFlagOn( Fcb->Flags, AFS_FCB_FILE_CLOSED))
2639 pRelease->Flags |= AFS_EXTENT_FLAG_FLUSH;
2643 // Update the metadata for this call
2646 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
2647 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
2648 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
2649 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
2650 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
2654 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
2657 pExtent = (AFSExtent *)pNPFcb->Specific.File.DirtyListHead;
2659 while( count < AFS_MAXIMUM_EXTENT_RELEASE_COUNT)
2662 if ( pExtent == NULL)
2668 pNextExtent = (AFSExtent *)pExtent->DirtyList.fLink;
2670 if ( pExtent->ActiveCount > 0)
2672 pExtent = pNextExtent;
2676 AFSRemoveEntryDirtyList( Fcb, pExtent);
2678 pExtent->DirtyList.fLink = NULL;
2679 pExtent->DirtyList.bLink = NULL;
2681 InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
2684 // Clear the flag in advance of the write. If we do
2685 // things this was we know that the clear is
2686 // pessimistic (any write which happens from now on
2687 // will set the flag dirty again).
2690 pExtent->Flags &= ~AFS_EXTENT_DIRTY;
2692 pRelease->FileExtents[count].Flags = AFS_EXTENT_FLAG_DIRTY;
2694 pRelease->FileExtents[count].Length = pExtent->Size;
2695 pRelease->FileExtents[count].DirtyLength = pExtent->Size;
2696 pRelease->FileExtents[count].DirtyOffset = 0;
2697 pRelease->FileExtents[count].CacheOffset = pExtent->CacheOffset;
2698 pRelease->FileExtents[count].FileOffset = pExtent->FileOffset;
2701 RtlCopyMemory( pRelease->FileExtents[count].MD5,
2703 sizeof(pExtent->MD5));
2705 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_MD5_SET;
2708 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2709 AFS_TRACE_LEVEL_VERBOSE,
2710 "AFSFlushExtents Releasing DIRTY extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
2712 Fcb->ObjectInformation->FileId.Cell,
2713 Fcb->ObjectInformation->FileId.Volume,
2714 Fcb->ObjectInformation->FileId.Vnode,
2715 Fcb->ObjectInformation->FileId.Unique,
2716 pExtent->FileOffset.QuadPart,
2719 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_RELEASE;
2722 // Need to pull this extent from the main list as well
2725 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
2727 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
2729 RemoveEntryList( &pExtent->Lists[i] );
2733 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
2735 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
2737 AFSExFreePool( pExtent);
2739 InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
2741 if( InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount) == 0)
2744 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
2751 pExtent = pNextExtent;
2754 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
2757 // If we are done then get out
2763 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2764 AFS_TRACE_LEVEL_VERBOSE,
2765 "AFSFlushExtents No more dirty extents found\n");
2771 // Fire off the request synchronously
2774 sz = sizeof( AFSReleaseExtentsCB ) + (count * sizeof ( AFSFileExtentCB ));
2776 pRelease->ExtentCount = count;
2778 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2779 AFS_TRACE_LEVEL_VERBOSE,
2780 "AFSFlushExtents Releasing(1) Fcb extents lock %08lX SHARED %08lX\n",
2781 &pNPFcb->Specific.File.ExtentsResource,
2782 PsGetCurrentThread());
2784 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource);
2785 bExtentsLocked = FALSE;
2787 KeSetEvent( &pNPFcb->Specific.File.FlushEvent,
2791 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
2792 AFS_REQUEST_FLAG_SYNCHRONOUS,
2795 &Fcb->ObjectInformation->FileId,
2801 if( !NT_SUCCESS(ntStatus))
2805 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
2806 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
2809 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2810 AFS_TRACE_LEVEL_ERROR,
2811 "AFSFlushExtents AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2812 Fcb->ObjectInformation->FileId.Cell,
2813 Fcb->ObjectInformation->FileId.Volume,
2814 Fcb->ObjectInformation->FileId.Vnode,
2815 Fcb->ObjectInformation->FileId.Unique,
2819 AFSLockForExtentsTrim( Fcb);
2821 bExtentsLocked = TRUE;
2826 if( InterlockedDecrement( &Fcb->Specific.File.QueuedFlushCount) == 0)
2829 KeSetEvent( &pNPFcb->Specific.File.QueuedFlushEvent,
2834 KeSetEvent( &pNPFcb->Specific.File.FlushEvent,
2841 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2842 AFS_TRACE_LEVEL_VERBOSE,
2843 "AFSFlushExtents Releasing(2) Fcb extents lock %08lX SHARED %08lX\n",
2844 &pNPFcb->Specific.File.ExtentsResource,
2845 PsGetCurrentThread());
2847 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
2852 AFSExFreePool( pRelease);
2860 AFSReleaseExtentsWithFlush( IN AFSFcb *Fcb,
2863 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
2866 AFSReleaseExtentsCB *pRelease = NULL;
2868 ULONG initialDirtyCount = 0;
2869 BOOLEAN bExtentsLocked = FALSE;
2872 NTSTATUS ntStatus = STATUS_SUCCESS;
2873 LARGE_INTEGER liLastFlush;
2874 ULONG ulRemainingExtentLength = 0;
2875 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2876 GUID *pAuthGroup = AuthGroup;
2879 ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
2882 // Save, then reset the flush time
2885 liLastFlush = Fcb->Specific.File.LastServerFlush;
2887 KeQueryTickCount( &Fcb->Specific.File.LastServerFlush);
2892 if( pAuthGroup == NULL ||
2893 RtlCompareMemory( pAuthGroup,
2894 &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2895 sizeof( GUID)) == sizeof( GUID))
2898 RtlZeroMemory( &stAuthGroup,
2901 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
2906 if( !NT_SUCCESS( ntStatus))
2908 try_return( ntStatus);
2911 pAuthGroup = &stAuthGroup;
2915 // Look for a start in the list to flush entries
2920 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
2922 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
2924 AFS_EXTENT_RELEASE_TAG);
2925 if( NULL == pRelease)
2928 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2931 if( Fcb->OpenHandleCount > 0)
2935 // Don't release everything ...
2939 // For now release everything
2942 //ulRemainingExtentLength = 1500;
2945 while( Fcb->Specific.File.ExtentLength > (LONG)ulRemainingExtentLength)
2948 AFSLockForExtentsTrim( Fcb);
2950 bExtentsLocked = TRUE;
2952 pRelease->Flags = AFS_EXTENT_FLAG_RELEASE;
2955 // Update the metadata for this call
2958 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
2959 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
2960 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
2961 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
2962 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
2966 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
2968 while( count < AFS_MAXIMUM_EXTENT_RELEASE_COUNT &&
2969 le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
2972 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
2976 if( pExtent->ActiveCount > 0)
2982 pRelease->FileExtents[count].Flags = AFS_EXTENT_FLAG_RELEASE;
2984 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2985 AFS_TRACE_LEVEL_VERBOSE,
2986 "AFSReleaseExtentsWithFlush Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
2988 Fcb->ObjectInformation->FileId.Cell,
2989 Fcb->ObjectInformation->FileId.Volume,
2990 Fcb->ObjectInformation->FileId.Vnode,
2991 Fcb->ObjectInformation->FileId.Unique,
2992 pExtent->FileOffset.QuadPart,
2995 pRelease->FileExtents[count].Length = pExtent->Size;
2996 pRelease->FileExtents[count].DirtyLength = pExtent->Size;
2997 pRelease->FileExtents[count].DirtyOffset = 0;
2998 pRelease->FileExtents[count].CacheOffset = pExtent->CacheOffset;
2999 pRelease->FileExtents[count].FileOffset = pExtent->FileOffset;
3002 RtlCopyMemory( pRelease->FileExtents[count].MD5,
3004 sizeof(pExtent->MD5));
3006 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_MD5_SET;
3009 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3012 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3015 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3018 AFSRemoveEntryDirtyList( Fcb,
3021 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_DIRTY;
3023 InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
3026 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3030 // Need to pull this extent from the main list as well
3033 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
3035 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
3037 RemoveEntryList( &pExtent->Lists[i] );
3041 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
3043 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
3045 AFSExFreePool( pExtent);
3047 InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
3049 if( InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount) == 0)
3052 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
3061 // If we are done then get out
3067 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3068 AFS_TRACE_LEVEL_VERBOSE,
3069 "AFSReleaseExtentsWithFlush No more dirty extents found\n");
3075 // Fire off the request synchronously
3078 sz = sizeof( AFSReleaseExtentsCB ) + (count * sizeof ( AFSFileExtentCB ));
3080 pRelease->ExtentCount = count;
3083 // Drop the extents lock for the duration of the call to
3084 // the network. We have pinned the extents so, even
3085 // though we might get extents added during this period,
3086 // but none will be removed. Hence we can carry on from
3090 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3091 AFS_TRACE_LEVEL_VERBOSE,
3092 "AFSReleaseExtentsWithFlush Releasing Fcb extents lock %08lX thread %08lX\n",
3093 &pNPFcb->Specific.File.ExtentsResource,
3094 PsGetCurrentThread());
3096 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource);
3097 bExtentsLocked = FALSE;
3099 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
3100 AFS_REQUEST_FLAG_SYNCHRONOUS,
3103 &Fcb->ObjectInformation->FileId,
3109 if( !NT_SUCCESS(ntStatus))
3113 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
3114 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
3117 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3118 AFS_TRACE_LEVEL_ERROR,
3119 "AFSReleaseExtentsWithFlush AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3120 Fcb->ObjectInformation->FileId.Cell,
3121 Fcb->ObjectInformation->FileId.Volume,
3122 Fcb->ObjectInformation->FileId.Vnode,
3123 Fcb->ObjectInformation->FileId.Unique,
3133 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3134 AFS_TRACE_LEVEL_VERBOSE,
3135 "AFSReleaseExtentsWithFlush Releasing Fcb extents lock %08lX thread %08lX\n",
3136 &pNPFcb->Specific.File.ExtentsResource,
3137 PsGetCurrentThread());
3139 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
3144 AFSExFreePool( pRelease);
3152 AFSMarkDirty( IN AFSFcb *Fcb,
3153 IN AFSExtent *StartExtent,
3154 IN ULONG ExtentsCount,
3155 IN LARGE_INTEGER *StartingByte)
3158 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3159 AFSExtent *pExtent = StartExtent;
3160 AFSExtent *pNextExtent, *pCurrentExtent = NULL;
3162 BOOLEAN bInsertTail = FALSE, bInsertHead = FALSE;
3164 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3165 AFS_TRACE_LEVEL_VERBOSE,
3166 "AFSMarkDirty Acquiring Fcb extents lock %08lX SHARED %08lX\n",
3167 &Fcb->NPFcb->Specific.File.ExtentsResource,
3168 PsGetCurrentThread());
3170 AFSAcquireShared( &Fcb->NPFcb->Specific.File.ExtentsResource, TRUE);
3172 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3176 // Find the insertion point
3179 if( pNPFcb->Specific.File.DirtyListHead == NULL)
3184 else if( StartingByte->QuadPart == 0)
3192 pCurrentExtent = pNPFcb->Specific.File.DirtyListHead;
3194 while( pCurrentExtent != NULL)
3197 if( pCurrentExtent->FileOffset.QuadPart + pCurrentExtent->Size >= StartingByte->QuadPart ||
3198 pCurrentExtent->DirtyList.fLink == NULL)
3204 pCurrentExtent = (AFSExtent *)pCurrentExtent->DirtyList.fLink;
3208 while( ulCount < ExtentsCount)
3211 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
3213 if( !BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3216 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3217 AFS_TRACE_LEVEL_VERBOSE,
3218 "AFSMarkDirty Marking extent offset %I64X Length %08lX DIRTY\n",
3219 pExtent->FileOffset.QuadPart,
3222 pExtent->DirtyList.fLink = NULL;
3223 pExtent->DirtyList.bLink = NULL;
3228 pExtent->DirtyList.fLink = (void *)pNPFcb->Specific.File.DirtyListHead;
3230 pExtent->DirtyList.bLink = NULL;
3232 pNPFcb->Specific.File.DirtyListHead->DirtyList.bLink = (void *)pExtent;
3234 pNPFcb->Specific.File.DirtyListHead = pExtent;
3236 pCurrentExtent = pExtent;
3238 bInsertHead = FALSE;
3240 else if( bInsertTail)
3243 if( pNPFcb->Specific.File.DirtyListHead == NULL)
3246 pNPFcb->Specific.File.DirtyListHead = pExtent;
3251 pNPFcb->Specific.File.DirtyListTail->DirtyList.fLink = (void *)pExtent;
3253 pExtent->DirtyList.bLink = (void *)pNPFcb->Specific.File.DirtyListTail;
3256 pNPFcb->Specific.File.DirtyListTail = pExtent;
3261 pExtent->DirtyList.fLink = pCurrentExtent->DirtyList.fLink;
3262 pExtent->DirtyList.bLink = (void *)pCurrentExtent;
3264 if( pExtent->DirtyList.fLink == NULL)
3267 pNPFcb->Specific.File.DirtyListTail = pExtent;
3272 ((AFSExtent *)pExtent->DirtyList.fLink)->DirtyList.bLink = (void *)pExtent;
3275 pCurrentExtent->DirtyList.fLink = (void *)pExtent;
3277 pCurrentExtent = pExtent;
3280 pExtent->Flags |= AFS_EXTENT_DIRTY;
3283 // Up the dirty count
3286 InterlockedIncrement( &Fcb->Specific.File.ExtentsDirtyCount);
3291 pCurrentExtent = pExtent;
3294 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_ACTIVE_COUNTING,
3295 AFS_TRACE_LEVEL_VERBOSE,
3296 "AFSMarkDirty Decrement count on extent %08lX Cnt %d\n",
3298 pExtent->ActiveCount);
3300 ASSERT( pExtent->ActiveCount > 0);
3302 InterlockedDecrement( &pExtent->ActiveCount);
3304 pExtent = pNextExtent;
3309 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3311 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3312 AFS_TRACE_LEVEL_VERBOSE,
3313 "AFSMarkDirty Releasing Fcb extents lock %08lX SHARED %08lX\n",
3314 &Fcb->NPFcb->Specific.File.ExtentsResource,
3315 PsGetCurrentThread());
3317 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
3326 static AFSExtent *ExtentFor(PLIST_ENTRY le, ULONG SkipList)
3328 return CONTAINING_RECORD( le, AFSExtent, Lists[SkipList] );
3331 static AFSExtent *NextExtent(AFSExtent *Extent, ULONG SkipList)
3333 return ExtentFor(Extent->Lists[SkipList].Flink, SkipList);
3336 static AFSExtent *DirtyExtentFor(PLIST_ENTRY le)
3338 return CONTAINING_RECORD( le, AFSExtent, DirtyList );
3341 static VOID VerifyExtentsLists(AFSFcb *Fcb)
3345 // Check the ordering of the extents lists
3347 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
3349 ASSERT(Fcb->Specific.File.ExtentsLists[0].Flink != &Fcb->Specific.File.ExtentsLists[1]);
3351 for (ULONG listNo = 0; listNo < AFS_NUM_EXTENT_LISTS; listNo ++)
3353 LARGE_INTEGER lastOffset;
3355 lastOffset.QuadPart = 0;
3357 for (PLIST_ENTRY pLe = Fcb->Specific.File.ExtentsLists[listNo].Flink;
3358 pLe != &Fcb->Specific.File.ExtentsLists[listNo];
3363 pExtent = ExtentFor(pLe, listNo);
3366 ASSERT(pLe != &Fcb->Specific.File.ExtentsLists[1] &&
3367 pLe->Flink !=&Fcb->Specific.File.ExtentsLists[1] &&
3368 pLe->Blink !=&Fcb->Specific.File.ExtentsLists[1]);
3371 ASSERT(pLe->Flink->Blink == pLe);
3372 ASSERT(pLe->Blink->Flink == pLe);
3375 // Should follow on from previous
3377 ASSERT(pExtent->FileOffset.QuadPart >= lastOffset.QuadPart);
3378 lastOffset.QuadPart = pExtent->FileOffset.QuadPart + pExtent->Size;
3381 // Should match alignment criteria
3383 ASSERT( 0 == (pExtent->FileOffset.LowPart & ExtentsMasks[listNo]) );
3386 // "lower" lists should be populated
3388 for (LONG subListNo = listNo-1; subListNo > 0; subListNo --)
3390 ASSERT( !IsListEmpty(&pExtent->Lists[subListNo]));
3398 AFSTrimExtents( IN AFSFcb *Fcb,
3399 IN PLARGE_INTEGER FileSize)
3402 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3405 BOOLEAN locked = FALSE;
3406 NTSTATUS ntStatus = STATUS_SUCCESS;
3407 LARGE_INTEGER liAlignedOffset = {0,0};
3408 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
3409 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3415 // Get an aligned offset
3418 if( FileSize != NULL)
3421 liAlignedOffset = *FileSize;
3424 if( liAlignedOffset.QuadPart > 0 &&
3425 liAlignedOffset.QuadPart % pDevExt->Specific.RDR.CacheBlockSize != 0)
3429 // Align UP to the next cache block size
3432 liAlignedOffset.QuadPart = (ULONGLONG)( (ULONGLONG)((liAlignedOffset.QuadPart / pDevExt->Specific.RDR.CacheBlockSize) + 1) * (ULONGLONG)pDevExt->Specific.RDR.CacheBlockSize);
3436 // Ensure that no one is working with the extents and grab the
3440 AFSLockForExtentsTrim( Fcb);
3444 if( 0 == Fcb->Specific.File.ExtentCount)
3448 // Update the request extent status
3451 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
3453 try_return( ntStatus = STATUS_SUCCESS);
3457 // We are truncating from a specific length in the file. If the offset
3458 // is non-zero then go find the first extent to remove
3461 if( 0 == FileSize->QuadPart)
3464 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3469 pExtent = AFSExtentForOffset( Fcb,
3473 if( NULL == pExtent)
3476 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3480 le = &pExtent->Lists[AFS_EXTENTS_LIST];
3484 while( le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
3487 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3490 // Only trim down extents beyond the aligned offset
3495 if( pExtent->FileOffset.QuadPart >= liAlignedOffset.QuadPart)
3498 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3501 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3504 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3508 AFSRemoveEntryDirtyList( Fcb,
3511 dirtyCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
3513 ASSERT(dirtyCount >= 0);
3516 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3519 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
3521 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
3523 RemoveEntryList( &pExtent->Lists[i] );
3527 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3528 AFS_TRACE_LEVEL_VERBOSE,
3529 "AFSTrimExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3531 Fcb->ObjectInformation->FileId.Cell,
3532 Fcb->ObjectInformation->FileId.Volume,
3533 Fcb->ObjectInformation->FileId.Vnode,
3534 Fcb->ObjectInformation->FileId.Unique,
3535 pExtent->FileOffset.QuadPart,
3538 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
3540 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
3542 ASSERT( pExtent->ActiveCount == 0);
3547 AFSExFreePool( pExtent);
3549 InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
3551 if( InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount) == 0)
3554 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
3562 // Update the request extent status
3565 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
3572 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3573 AFS_TRACE_LEVEL_VERBOSE,
3574 "AFSTrimExtents Releasing Fcb extents lock %08lX thread %08lX\n",
3575 &Fcb->NPFcb->Specific.File.ExtentsResource,
3576 PsGetCurrentThread());
3578 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
3586 AFSTrimSpecifiedExtents( IN AFSFcb *Fcb,
3588 IN AFSFileExtentCB *Result)
3591 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3594 AFSFileExtentCB *pFileExtents = Result;
3595 NTSTATUS ntStatus = STATUS_SUCCESS;
3596 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
3597 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3602 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3604 while( le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST] &&
3608 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3611 // Only trim down extents beyond the aligned offset
3616 if( pExtent->FileOffset.QuadPart == pFileExtents->FileOffset.QuadPart)
3619 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3622 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3625 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3630 AFSRemoveEntryDirtyList( Fcb,
3633 dirtyCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
3635 ASSERT( dirtyCount >= 0);
3639 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3643 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
3645 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
3647 RemoveEntryList( &pExtent->Lists[i] );
3651 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3652 AFS_TRACE_LEVEL_VERBOSE,
3653 "AFSTrimSpecifiedExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3655 Fcb->ObjectInformation->FileId.Cell,
3656 Fcb->ObjectInformation->FileId.Volume,
3657 Fcb->ObjectInformation->FileId.Vnode,
3658 Fcb->ObjectInformation->FileId.Unique,
3659 pExtent->FileOffset.QuadPart,
3662 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
3664 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
3666 ASSERT( pExtent->ActiveCount == 0);
3671 AFSExFreePool( pExtent);
3673 InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
3675 if( InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount) == 0)
3678 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
3684 // Next extent we are looking for
3694 // Update the request extent status
3697 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
3704 AFSReferenceActiveExtents( IN AFSExtent *StartExtent,
3705 IN ULONG ExtentsCount)
3708 AFSExtent *pExtent = StartExtent;
3709 AFSExtent *pNextExtent;
3712 while( ulCount < ExtentsCount)
3715 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
3717 InterlockedIncrement( &pExtent->ActiveCount);
3719 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_ACTIVE_COUNTING,
3720 AFS_TRACE_LEVEL_VERBOSE,
3721 "AFSReferenceActiveExtents Increment count on extent %08lX Cnt %d\n",
3723 pExtent->ActiveCount);
3725 pExtent = pNextExtent;
3734 AFSDereferenceActiveExtents( IN AFSExtent *StartExtent,
3735 IN ULONG ExtentsCount)
3738 AFSExtent *pExtent = StartExtent;
3739 AFSExtent *pNextExtent;
3742 while( ulCount < ExtentsCount)
3745 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
3747 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_ACTIVE_COUNTING,
3748 AFS_TRACE_LEVEL_VERBOSE,
3749 "AFSDereferenceActiveExtents Decrement count on extent %08lX Cnt %d\n",
3751 pExtent->ActiveCount);
3753 ASSERT( pExtent->ActiveCount > 0);
3755 InterlockedDecrement( &pExtent->ActiveCount);
3757 pExtent = pNextExtent;
3766 AFSRemoveEntryDirtyList( IN AFSFcb *Fcb,
3767 IN AFSExtent *Extent)
3770 if( Extent->DirtyList.fLink == NULL)
3773 Fcb->NPFcb->Specific.File.DirtyListTail = (AFSExtent *)Extent->DirtyList.bLink;
3775 if( Fcb->NPFcb->Specific.File.DirtyListTail != NULL)
3778 Fcb->NPFcb->Specific.File.DirtyListTail->DirtyList.fLink = NULL;
3784 ((AFSExtent *)Extent->DirtyList.fLink)->DirtyList.bLink = Extent->DirtyList.bLink;
3787 if( Extent->DirtyList.bLink == NULL)
3790 Fcb->NPFcb->Specific.File.DirtyListHead = (AFSExtent *)Extent->DirtyList.fLink;
3792 if( Fcb->NPFcb->Specific.File.DirtyListHead != NULL)
3795 Fcb->NPFcb->Specific.File.DirtyListHead->DirtyList.bLink = NULL;
3801 ((AFSExtent *)Extent->DirtyList.bLink)->DirtyList.fLink = Extent->DirtyList.fLink;
3810 AFSSetupMD5Hash( IN AFSFcb *Fcb,
3811 IN AFSExtent *StartExtent,
3812 IN ULONG ExtentsCount,
3813 IN void *SystemBuffer,
3814 IN LARGE_INTEGER *ByteOffset,
3818 NTSTATUS ntStatus = STATUS_SUCCESS;
3819 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3820 AFSExtent *pExtent = StartExtent;
3821 AFSExtent *pNextExtent, *pCurrentExtent = NULL;
3823 char *pCurrentBuffer = (char *)SystemBuffer;
3824 char *pMD5Buffer = NULL;
3825 ULONG ulCurrentLen = 0;
3826 void *pExtentBuffer = NULL;
3827 LARGE_INTEGER liByteOffset;
3828 ULONG ulBytesRead = 0;
3833 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3834 AFS_TRACE_LEVEL_VERBOSE,
3835 "AFSSetupMD5Hash Acquiring Fcb extents lock %08lX SHARED %08lX\n",
3836 &Fcb->NPFcb->Specific.File.ExtentsResource,
3837 PsGetCurrentThread());
3839 AFSAcquireShared( &Fcb->NPFcb->Specific.File.ExtentsResource, TRUE);
3841 liByteOffset.QuadPart = ByteOffset->QuadPart;
3843 while( ulCount < ExtentsCount)
3846 RtlZeroMemory( pExtent->MD5,
3847 sizeof( pExtent->MD5));
3849 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
3851 if( liByteOffset.QuadPart == pExtent->FileOffset.QuadPart &&
3852 ByteCount < pExtent->Size)
3855 if( pExtentBuffer == NULL)
3858 pExtentBuffer = AFSExAllocatePoolWithTag( PagedPool,
3860 AFS_GENERIC_MEMORY_9_TAG);
3862 if( pExtentBuffer == NULL)
3869 RtlZeroMemory( pExtentBuffer,
3872 RtlCopyMemory( pExtentBuffer,
3876 pMD5Buffer = (char *)pExtentBuffer;
3878 ulCurrentLen = ByteCount;
3880 else if( liByteOffset.QuadPart != pExtent->FileOffset.QuadPart)
3883 pExtentBuffer = AFSExAllocatePoolWithTag( PagedPool,
3885 AFS_GENERIC_MEMORY_10_TAG);
3887 if( pExtentBuffer == NULL)
3893 RtlZeroMemory( pExtentBuffer,
3896 if( BooleanFlagOn( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE))
3900 RtlCopyMemory( pExtentBuffer,
3901 ((char *)AFSLibCacheBaseAddress + pExtent->CacheOffset.QuadPart),
3904 ASSERT( pExtent->CacheOffset.HighPart == 0);
3905 RtlCopyMemory( pExtentBuffer,
3906 ((char *)AFSLibCacheBaseAddress + pExtent->CacheOffset.LowPart),
3910 ulBytesRead = pExtent->Size;
3915 ntStatus = AFSReadCacheFile( pExtentBuffer,
3916 &pExtent->CacheOffset,
3920 if( !NT_SUCCESS( ntStatus))
3926 pMD5Buffer = (char *)pExtentBuffer;
3928 ulCurrentLen = min( ByteCount, pExtent->Size - (ULONG)(liByteOffset.QuadPart - pExtent->FileOffset.QuadPart));
3930 RtlCopyMemory( (void *)((char *)pExtentBuffer + (ULONG)(liByteOffset.QuadPart - pExtent->FileOffset.QuadPart)),
3937 ulCurrentLen = pExtent->Size;
3939 pMD5Buffer = pCurrentBuffer;
3942 AFSGenerateMD5( pMD5Buffer,
3946 pExtent = pNextExtent;
3950 ByteCount -= ulCurrentLen;
3952 pCurrentBuffer += ulCurrentLen;
3954 liByteOffset.QuadPart += ulCurrentLen;
3957 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3958 AFS_TRACE_LEVEL_VERBOSE,
3959 "AFSSetupMD5Hash Releasing Fcb extents lock %08lX SHARED %08lX\n",
3960 &Fcb->NPFcb->Specific.File.ExtentsResource,
3961 PsGetCurrentThread());
3963 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
3965 if( pExtentBuffer != NULL)
3968 AFSExFreePool( pExtentBuffer);