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 *NextExtent( AFSExtent *Extent, ULONG SkipList );
43 static ULONG ExtentsMasks[AFS_NUM_EXTENT_LISTS] = AFS_EXTENTS_MASKS;
44 static VOID VerifyExtentsLists(AFSFcb *Fcb);
45 static AFSExtent *DirtyExtentFor(PLIST_ENTRY le);
48 AFSEntryForOffset( IN AFSFcb *Fcb,
49 IN PLARGE_INTEGER Offset);
53 // Returns with Extents lock EX and no one using them.
57 AFSLockForExtentsTrim( IN AFSFcb *Fcb)
60 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
62 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
63 AFS_TRACE_LEVEL_VERBOSE,
64 "AFSLockForExtentsTrim Acquiring Fcb extents lock %08lX EXCL %08lX\n",
65 &pNPFcb->Specific.File.ExtentsResource,
66 PsGetCurrentThread());
68 AFSAcquireExcl( &pNPFcb->Specific.File.ExtentsResource, TRUE );
74 // return FALSE *or* with Extents lock EX and noone using them
77 AFSLockForExtentsTrimNoWait( IN AFSFcb *Fcb)
79 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
81 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
82 AFS_TRACE_LEVEL_VERBOSE,
83 "AFSLockForExtentsTrimNoWait Attempting to acquire Fcb extent lock %08lX EXCL %08lX\n",
84 &pNPFcb->Specific.File.ExtentsResource,
85 PsGetCurrentThread());
87 if (!AFSAcquireExcl( &pNPFcb->Specific.File.ExtentsResource, FALSE ))
90 // Couldn't lock immediately
93 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
94 AFS_TRACE_LEVEL_VERBOSE,
95 "AFSLockForExtentsTrimNoWait Refused to wait for Fcb extent lock %08lX EXCL %08lX\n",
96 &pNPFcb->Specific.File.ExtentsResource,
97 PsGetCurrentThread());
105 // Pull all the extents away from the FCB.
108 AFSTearDownFcbExtents( IN AFSFcb *Fcb,
111 BOOLEAN bFoundExtents = FALSE;
112 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
115 ULONG ulCount = 0, ulReleaseCount = 0, ulProcessCount = 0;
117 AFSReleaseExtentsCB *pRelease = NULL;
118 BOOLEAN locked = FALSE;
120 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
121 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 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
284 lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount);
289 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
296 // Send the request down. We cannot send this down
297 // asynchronously - if we did that we could request them
298 // back before the service got this request and then this
299 // request would be a corruption.
302 sz = sizeof( AFSReleaseExtentsCB ) + (ulProcessCount * sizeof ( AFSFileExtentCB ));
304 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
305 AFS_REQUEST_FLAG_SYNCHRONOUS,
308 &Fcb->ObjectInformation->FileId,
314 if( !NT_SUCCESS(ntStatus))
318 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
319 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
322 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
323 AFS_TRACE_LEVEL_ERROR,
324 "AFSTearDownFcbExtents AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
325 Fcb->ObjectInformation->FileId.Cell,
326 Fcb->ObjectInformation->FileId.Volume,
327 Fcb->ObjectInformation->FileId.Vnode,
328 Fcb->ObjectInformation->FileId.Unique,
333 ulReleaseCount += ulProcessCount;
337 // Reinitialize the skip lists
340 ASSERT( Fcb->Specific.File.ExtentCount == 0);
342 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i++)
344 InitializeListHead(&Fcb->Specific.File.ExtentsLists[i]);
348 // Reinitialize the dirty list as well
351 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
354 ASSERT( Fcb->Specific.File.ExtentsDirtyCount == 0);
356 Fcb->NPFcb->Specific.File.DirtyListHead = NULL;
357 Fcb->NPFcb->Specific.File.DirtyListTail = NULL;
359 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
361 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
368 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
369 AFS_TRACE_LEVEL_VERBOSE,
370 "AFSTearDownFcbExtents Releasing Fcb extent lock %08lX thread %08lX\n",
371 &Fcb->NPFcb->Specific.File.ExtentsResource,
372 PsGetCurrentThread());
374 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
380 AFSExFreePool( pRelease);
384 return bFoundExtents;
388 ExtentForOffsetInList( IN AFSFcb *Fcb,
391 IN PLARGE_INTEGER Offset)
394 // Return the extent that maps the offset, that
395 // - Contains the offset
396 // - or is immediately ahead of the offset (in this list)
397 // - otherwise return NULL.
400 PLIST_ENTRY pLe = List;
401 AFSExtent *pPrevious = NULL;
403 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
405 while (pLe != &Fcb->Specific.File.ExtentsLists[ListNumber])
409 entry = ExtentFor( pLe, ListNumber );
416 if (Offset->QuadPart < entry->FileOffset.QuadPart)
419 // Offset is ahead of entry. Return previous
424 if (Offset->QuadPart >= (entry->FileOffset.QuadPart + entry->Size))
427 // We start after this extent - carry on round
435 // Otherwise its a match
442 // Got to the end. Return Previous
448 AFSExtentContains( IN AFSExtent *Extent, IN PLARGE_INTEGER Offset)
454 return (Extent->FileOffset.QuadPart <= Offset->QuadPart &&
455 (Extent->FileOffset.QuadPart + Extent->Size) > Offset->QuadPart);
460 // Return the extent that contains the offset
463 AFSExtentForOffsetHint( IN AFSFcb *Fcb,
464 IN PLARGE_INTEGER Offset,
465 IN BOOLEAN ReturnPrevious,
468 AFSExtent *pPrevious = Hint;
472 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
474 #if AFS_VALIDATE_EXTENTS
475 VerifyExtentsLists(Fcb);
479 // So we will go across the skip lists until we find an
480 // appropriate entry (previous or direct match). If it's a match
481 // we are done, other wise we start on the next layer down
483 for (i = AFS_NUM_EXTENT_LISTS-1; i >= AFS_EXTENTS_LIST; i--)
485 if (NULL == pPrevious)
488 // We haven't found anything in the previous layers
490 pLe = Fcb->Specific.File.ExtentsLists[i].Flink;
492 else if (NULL == pPrevious->Lists[i].Flink)
494 ASSERT(AFS_EXTENTS_LIST != i);
496 // The hint doesn't exist at this level, next one down
503 // take the previous into the next
505 pLe = &pPrevious->Lists[i];
508 pPrevious = ExtentForOffsetInList( Fcb, pLe, i, Offset);
510 if (NULL != pPrevious && AFSExtentContains(pPrevious, Offset))
513 // Found it immediately. Stop here
519 if (NULL == pPrevious || ReturnPrevious )
524 ASSERT( !AFSExtentContains(pPrevious, Offset) );
530 AFSEntryForOffset( IN AFSFcb *Fcb,
531 IN PLARGE_INTEGER Offset)
533 AFSExtent *pPrevious = NULL;
537 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
539 #if AFS_VALIDATE_EXTENTS
540 VerifyExtentsLists(Fcb);
544 // So we will go across the skip lists until we find an
545 // appropriate entry (previous or direct match). If it's a match
546 // we are done, other wise we start on the next layer down
548 for (i = AFS_NUM_EXTENT_LISTS-1; i >= AFS_EXTENTS_LIST; i--)
550 if (NULL == pPrevious)
553 // We haven't found anything in the previous layers
555 pLe = Fcb->Specific.File.ExtentsLists[i].Flink;
557 else if (NULL == pPrevious->Lists[i].Flink)
559 ASSERT(AFS_EXTENTS_LIST != i);
561 // The hint doesn't exist at this level, next one down
568 // take the previous into the next
570 pLe = &pPrevious->Lists[i];
573 pPrevious = ExtentForOffsetInList( Fcb, pLe, i, Offset);
575 if (NULL != pPrevious && AFSExtentContains(pPrevious, Offset))
578 // Found it immediately. Stop here
588 AFSExtentForOffset( IN AFSFcb *Fcb,
589 IN PLARGE_INTEGER Offset,
590 IN BOOLEAN ReturnPrevious)
592 return AFSExtentForOffsetHint(Fcb, Offset, ReturnPrevious, NULL);
596 BOOLEAN AFSDoExtentsMapRegion(IN AFSFcb *Fcb,
597 IN PLARGE_INTEGER Offset,
599 IN OUT AFSExtent **FirstExtent,
600 OUT AFSExtent **LastExtent)
603 // Return TRUE region is completely mapped. FALSE
604 // otherwise. If the region isn't mapped then the last
605 // extent to map part of the region is returned.
607 // *LastExtent as input is where to start looking.
608 // *LastExtent as output is either the extent which
609 // contains the Offset, or the last one which doesn't
613 BOOLEAN retVal = FALSE;
618 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
619 AFS_TRACE_LEVEL_VERBOSE,
620 "AFSDoExtentsMapRegion Acquiring Fcb extent lock %08lX SHARED %08lX\n",
621 &Fcb->NPFcb->Specific.File.ExtentsResource,
622 PsGetCurrentThread());
624 AFSAcquireShared( &Fcb->NPFcb->Specific.File.ExtentsResource, TRUE );
628 entry = AFSExtentForOffsetHint(Fcb, Offset, TRUE, *FirstExtent);
629 *FirstExtent = entry;
631 if (NULL == entry || !AFSExtentContains(entry, Offset))
633 try_return (retVal = FALSE);
636 ASSERT(Offset->QuadPart >= entry->FileOffset.QuadPart);
640 if ((entry->FileOffset.QuadPart + entry->Size) >=
641 (Offset->QuadPart + Size))
644 // The end is inside the extent
646 try_return (retVal = TRUE);
649 if (entry->Lists[AFS_EXTENTS_LIST].Flink == &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
652 // Run out of extents
654 try_return (retVal = FALSE);
657 newEntry = NextExtent( entry, AFS_EXTENTS_LIST );
659 if (newEntry->FileOffset.QuadPart !=
660 (entry->FileOffset.QuadPart + entry->Size))
665 try_return (retVal = FALSE);
671 __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
676 "EXCEPTION - AFSDoExtentsMapRegion\n");
681 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
682 AFS_TRACE_LEVEL_VERBOSE,
683 "AFSDoExtentsMapRegion Releasing Fcb extent lock %08lX SHARED %08lX\n",
684 &Fcb->NPFcb->Specific.File.ExtentsResource,
685 PsGetCurrentThread());
687 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
696 AFSRequestExtentsAsync( IN AFSFcb *Fcb,
698 IN PLARGE_INTEGER Offset,
702 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
703 NTSTATUS ntStatus = STATUS_SUCCESS;
704 AFSExtent *pExtent = NULL;
705 AFSRequestExtentsCB request;
706 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
707 AFSExtent *pFirstExtent = NULL;
708 LARGE_INTEGER liAlignedOffset;
709 ULONG ulAlignedLength = 0;
710 BOOLEAN bRegionMapped = FALSE;
711 ULONGLONG ullProcessId = (ULONGLONG)PsGetCurrentProcessId();
716 ASSERT( !ExIsResourceAcquiredLite( &pNPFcb->Specific.File.ExtentsResource ));
719 // If the service set a failure on the file since the last
720 // CreateFile was issued, return it now.
723 if (!NT_SUCCESS( pNPFcb->Specific.File.ExtentsRequestStatus))
727 // If this isn't the same authgroup which caused the failure
728 // then try to request them again
731 if( RtlCompareMemory( &pNPFcb->Specific.File.ExtentsRequestAuthGroup,
733 sizeof( GUID)) == sizeof( GUID))
736 ntStatus = pNPFcb->Specific.File.ExtentsRequestStatus;
738 pNPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
740 RtlZeroMemory( &pNPFcb->Specific.File.ExtentsRequestAuthGroup,
743 try_return( ntStatus);
748 // Check if we are already mapped
751 bRegionMapped = AFSDoExtentsMapRegion( Fcb, Offset, Size, &pFirstExtent, &pExtent);
756 try_return( ntStatus = STATUS_SUCCESS);
760 // Align our request on extent size boundary
763 ulAlignedLength = Size;
765 liAlignedOffset = *Offset;
767 if( liAlignedOffset.QuadPart % pDevExt->Specific.RDR.CacheBlockSize != 0)
770 liAlignedOffset.QuadPart = (ULONGLONG)( (ULONGLONG)(liAlignedOffset.QuadPart / pDevExt->Specific.RDR.CacheBlockSize) * (ULONGLONG)pDevExt->Specific.RDR.CacheBlockSize);
772 ulAlignedLength += (ULONG)(Offset->QuadPart - liAlignedOffset.QuadPart);
775 if( ulAlignedLength % pDevExt->Specific.RDR.CacheBlockSize != 0)
778 ulAlignedLength = (ULONG)(((ulAlignedLength / pDevExt->Specific.RDR.CacheBlockSize) + 1) * pDevExt->Specific.RDR.CacheBlockSize);
781 RtlZeroMemory( &request,
782 sizeof( AFSRequestExtentsCB));
784 request.ByteOffset = liAlignedOffset;
785 request.Length = ulAlignedLength;
787 if( !AFSIsExtentRequestQueued( &Fcb->ObjectInformation->FileId,
792 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
793 AFS_TRACE_LEVEL_VERBOSE,
794 "AFSRequestExtentsAsync Request extents for fid %08lX-%08lX-%08lX-%08lX Offset %08lX Len %08lX Thread %08lX\n",
795 Fcb->ObjectInformation->FileId.Cell,
796 Fcb->ObjectInformation->FileId.Volume,
797 Fcb->ObjectInformation->FileId.Vnode,
798 Fcb->ObjectInformation->FileId.Unique,
799 request.ByteOffset.LowPart,
801 PsGetCurrentThread());
803 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS,
807 &Fcb->ObjectInformation->FileId,
809 sizeof( AFSRequestExtentsCB ),
813 if ( ntStatus == STATUS_ACCESS_DENIED)
818 ntStatus2 = AFSRetrieveValidAuthGroup( Fcb,
823 if ( NT_SUCCESS( ntStatus2) &&
824 RtlCompareMemory( &stAuthGroup,
826 sizeof( GUID)) != sizeof( GUID))
829 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS,
833 &Fcb->ObjectInformation->FileId,
835 sizeof( AFSRequestExtentsCB ),
841 if( NT_SUCCESS( ntStatus))
844 KeClearEvent( &pNPFcb->Specific.File.ExtentsRequestComplete );
850 KeClearEvent( &pNPFcb->Specific.File.ExtentsRequestComplete );
862 AFSProcessExtentsResult( IN AFSFcb *Fcb,
864 IN AFSFileExtentCB *Result)
866 NTSTATUS ntStatus = STATUS_SUCCESS;
867 AFSFileExtentCB *pFileExtents = Result;
870 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
871 ULONG fileExtentsUsed = 0;
872 BOOLEAN bFoundExtent = FALSE;
873 LIST_ENTRY *pSkipEntries[AFS_NUM_EXTENT_LISTS] = { 0 };
874 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
878 // Grab the extents exclusive for the duration
881 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
882 AFS_TRACE_LEVEL_VERBOSE,
883 "AFSProcessExtentsResult Acquiring Fcb extent lock %08lX EXCL %08lX\n",
884 &pNPFcb->Specific.File.ExtentsResource,
885 PsGetCurrentThread());
887 AFSAcquireExcl( &pNPFcb->Specific.File.ExtentsResource, TRUE );
893 // Find where to put the extents
895 for (ULONG i = AFS_EXTENTS_LIST; i < AFS_NUM_EXTENT_LISTS; i++)
898 pSkipEntries[i] = Fcb->Specific.File.ExtentsLists[i].Flink;
901 le = pSkipEntries[AFS_EXTENTS_LIST];
903 if (le == &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
906 // No extents. Insert at head of list (which is where the skip lists point!)
910 else if (0 != pFileExtents->FileOffset.QuadPart)
913 // We want to find the best extents immediately *behind* this offset
915 LARGE_INTEGER offset = pFileExtents->FileOffset;
918 // Ask in the top skip list first, then work down
920 for (LONG i = AFS_NUM_EXTENT_LISTS-1; i >= AFS_EXTENTS_LIST; i--)
922 pExtent = ExtentForOffsetInList( Fcb,
930 // No dice. Header has to become the head of the list
932 pSkipEntries[i] = &Fcb->Specific.File.ExtentsLists[i];
934 // And as a loop invariant we should never have found an extent
936 ASSERT(!bFoundExtent);
941 // pExtent is where to start to insert at this level
943 pSkipEntries[i] = &pExtent->Lists[i];
946 // And also where to start to look at the next level
949 if (i > AFS_EXTENTS_LIST)
951 pSkipEntries[i-1] = &pExtent->Lists[i-1];
959 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
964 le = pExtent->Lists[AFS_EXTENTS_LIST].Blink;
970 // Looking at offset 0, so we must start at the beginning
973 pExtent = ExtentFor(le, AFS_EXTENTS_LIST);
977 // And set up the skip lists
980 for (ULONG i = AFS_EXTENTS_LIST; i < AFS_NUM_EXTENT_LISTS; i++)
982 pSkipEntries[i] = &Fcb->Specific.File.ExtentsLists[i];
986 while (fileExtentsUsed < Count)
990 // Loop invariant - le points to where to insert after and
991 // pExtent points to le->fLink
994 ASSERT (NULL == pExtent ||
995 le->Flink == &pExtent->Lists[AFS_EXTENTS_LIST]);
997 if (NULL == pExtent ||
998 pExtent->FileOffset.QuadPart > pFileExtents->FileOffset.QuadPart)
1001 // We need to insert a new extent at le. Start with
1002 // some sanity check on spanning
1004 if (NULL != pExtent &&
1005 ((pFileExtents->FileOffset.QuadPart + pFileExtents->Length) >
1006 pExtent->FileOffset.QuadPart))
1009 // File Extents overlaps pExtent
1011 ASSERT( (pFileExtents->FileOffset.QuadPart + pFileExtents->Length) <=
1012 pExtent->FileOffset.QuadPart);
1014 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1018 // File offset is entirely in front of this extent. Create
1019 // a new one (remember le is the previous list entry)
1021 pExtent = (AFSExtent *) AFSExAllocatePoolWithTag( NonPagedPool,
1024 if (NULL == pExtent)
1027 try_return (ntStatus = STATUS_INSUFFICIENT_RESOURCES );
1030 RtlZeroMemory( pExtent, sizeof( AFSExtent ));
1032 pExtent->FileOffset = pFileExtents->FileOffset;
1033 pExtent->CacheOffset = pFileExtents->CacheOffset;
1034 pExtent->Size = pFileExtents->Length;
1036 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1037 AFS_TRACE_LEVEL_VERBOSE,
1038 "AFSProcessExtentsResult Received extent for fid %08lX-%08lX-%08lX-%08lX File Offset %I64X Cache Offset %I64X Len %08lX\n",
1039 Fcb->ObjectInformation->FileId.Cell,
1040 Fcb->ObjectInformation->FileId.Volume,
1041 Fcb->ObjectInformation->FileId.Vnode,
1042 Fcb->ObjectInformation->FileId.Unique,
1043 pFileExtents->FileOffset.QuadPart,
1044 pFileExtents->CacheOffset.QuadPart,
1045 pFileExtents->Length);
1047 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, (LONG)(pExtent->Size/1024));
1049 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, (LONG)(pExtent->Size/1024));
1051 lCount = InterlockedIncrement( &Fcb->Specific.File.ExtentCount);
1053 lCount = InterlockedIncrement( &pControlDevExt->Specific.Control.ExtentCount);
1058 KeClearEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent);
1064 InsertHeadList(le, &pExtent->Lists[AFS_EXTENTS_LIST]);
1065 ASSERT(le->Flink == &pExtent->Lists[AFS_EXTENTS_LIST]);
1066 ASSERT(0 == (pExtent->FileOffset.LowPart & ExtentsMasks[AFS_EXTENTS_LIST]));
1069 // Do not move the cursor - we will do it next time
1073 // And into the (upper) skip lists - Again, do not move the cursor
1075 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1077 if (0 == (pExtent->FileOffset.LowPart & ExtentsMasks[i]))
1079 InsertHeadList(pSkipEntries[i], &pExtent->Lists[i]);
1080 #if AFS_VALIDATE_EXTENTS
1081 VerifyExtentsLists(Fcb);
1086 else if (pExtent->FileOffset.QuadPart == pFileExtents->FileOffset.QuadPart)
1089 if (pExtent->Size != pFileExtents->Length)
1092 ASSERT (pExtent->Size == pFileExtents->Length);
1094 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1098 // Move both cursors forward.
1100 // First the extent pointer
1103 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1106 // Then the skip lists cursors forward if needed
1108 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1110 if (0 == (pExtent->FileOffset.LowPart & ExtentsMasks[i]))
1113 // Check sanity before
1115 #if AFS_VALIDATE_EXTENTS
1116 VerifyExtentsLists(Fcb);
1120 // Skip list should point to us
1122 //ASSERT(pSkipEntries[i] == &pExtent->Lists[i]);
1124 // Move forward cursor
1126 pSkipEntries[i] = pSkipEntries[i]->Flink;
1128 // Check sanity before
1130 #if AFS_VALIDATE_EXTENTS
1131 VerifyExtentsLists(Fcb);
1137 // And then the cursor in the supplied array
1143 // setup pExtent if there is one
1145 if (le->Flink != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
1147 pExtent = NextExtent( pExtent, AFS_EXTENTS_LIST ) ;
1157 ASSERT( pExtent->FileOffset.QuadPart < pFileExtents->FileOffset.QuadPart );
1160 // Sanity check on spanning
1162 if ((pExtent->FileOffset.QuadPart + pExtent->Size) >
1163 pFileExtents->FileOffset.QuadPart)
1166 ASSERT( (pExtent->FileOffset.QuadPart + pExtent->Size) <=
1167 pFileExtents->FileOffset.QuadPart);
1169 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1173 // Move le and pExtent forward
1175 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1179 // Then the check the skip lists cursors
1181 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1183 if (0 == (pFileExtents->FileOffset.LowPart & ExtentsMasks[i]))
1187 // - empty list (pSkipEntries[i]->Flink == pSkipEntries[i]->Flink == fcb->lists[i]
1188 // - We are the last on the list (pSkipEntries[i]->Flink == fcb->lists[i])
1189 // - We are not the last on the list. In that case we have to be strictly less than
1191 if (pSkipEntries[i]->Flink != &Fcb->Specific.File.ExtentsLists[i]) {
1193 AFSExtent *otherExtent = ExtentFor(pSkipEntries[i]->Flink, i);
1194 ASSERT(pFileExtents->FileOffset.QuadPart < otherExtent->FileOffset.QuadPart);
1201 // setup pExtent if there is one
1204 if (le->Flink != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
1206 pExtent = NextExtent( pExtent, AFS_EXTENTS_LIST ) ;
1216 // All done, signal that we are done drop the lock, exit
1221 if( !NT_SUCCESS( ntStatus))
1225 // If we failed the service is going to drop all extents so trim away the
1229 AFSTrimSpecifiedExtents( Fcb,
1234 #if AFS_VALIDATE_EXTENTS
1235 VerifyExtentsLists(Fcb);
1238 KeSetEvent( &pNPFcb->Specific.File.ExtentsRequestComplete,
1242 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1243 AFS_TRACE_LEVEL_VERBOSE,
1244 "AFSProcessExtentsResult Releasing Fcb extent lock %08lX EXCL %08lX\n",
1245 &pNPFcb->Specific.File.ExtentsResource,
1246 PsGetCurrentThread());
1248 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
1255 AFSProcessSetFileExtents( IN AFSSetFileExtentsCB *SetExtents )
1257 AFSFcb *pFcb = NULL;
1258 AFSVolumeCB *pVolumeCB = NULL;
1259 NTSTATUS ntStatus = STATUS_SUCCESS;
1260 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1261 ULONGLONG ullIndex = 0;
1262 AFSObjectInfoCB *pObjectInfo = NULL;
1268 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1269 AFS_TRACE_LEVEL_VERBOSE,
1270 "AFSProcessSetFileExtents Acquiring RDR VolumeTreeLock lock %08lX SHARED %08lX\n",
1271 &pDevExt->Specific.RDR.VolumeTreeLock,
1272 PsGetCurrentThread());
1274 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
1276 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1277 AFS_TRACE_LEVEL_VERBOSE,
1278 "AFSProcessSetFileExtents Set extents for fid %08lX-%08lX-%08lX-%08lX\n",
1279 SetExtents->FileId.Cell,
1280 SetExtents->FileId.Volume,
1281 SetExtents->FileId.Vnode,
1282 SetExtents->FileId.Unique);
1285 // Locate the volume node
1288 ullIndex = AFSCreateHighIndex( &SetExtents->FileId);
1290 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
1292 (AFSBTreeEntry **)&pVolumeCB);
1294 if( pVolumeCB != NULL)
1297 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1298 AFS_TRACE_LEVEL_VERBOSE,
1299 "AFSProcessSetFileExtents Acquiring VolumeRoot FileIDTree.TreeLock lock %08lX SHARED %08lX\n",
1300 pVolumeCB->ObjectInfoTree.TreeLock,
1301 PsGetCurrentThread());
1303 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1306 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
1308 if( !NT_SUCCESS( ntStatus) ||
1312 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1313 AFS_TRACE_LEVEL_ERROR,
1314 "AFSProcessSetFileExtents Set extents for fid %08lX-%08lX-%08lX-%08lX Failed to locate volume Status %08lX\n",
1315 SetExtents->FileId.Cell,
1316 SetExtents->FileId.Volume,
1317 SetExtents->FileId.Vnode,
1318 SetExtents->FileId.Unique,
1321 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1324 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1327 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1330 // Now locate the Object in this volume
1333 ullIndex = AFSCreateLowIndex( &SetExtents->FileId);
1335 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
1337 (AFSBTreeEntry **)&pObjectInfo);
1339 if( pObjectInfo != NULL)
1343 // Reference the node so it won't be torn down
1346 lCount = InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
1348 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1349 AFS_TRACE_LEVEL_VERBOSE,
1350 "AFSProcessSetFileExtents Increment count on object %08lX Cnt %d\n",
1355 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1357 if( !NT_SUCCESS( ntStatus) ||
1358 pObjectInfo == NULL)
1361 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1362 AFS_TRACE_LEVEL_ERROR,
1363 "AFSProcessSetFileExtents Set extents for hash %I64X fid %08lX-%08lX-%08lX-%08lX Failed to locate file in volume %08lX\n",
1365 SetExtents->FileId.Cell,
1366 SetExtents->FileId.Volume,
1367 SetExtents->FileId.Vnode,
1368 SetExtents->FileId.Unique,
1371 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1374 pFcb = pObjectInfo->Fcb;
1377 // If we have a result failure then don't bother trying to set the extents
1380 if( SetExtents->ResultStatus != STATUS_SUCCESS)
1383 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1384 AFS_TRACE_LEVEL_ERROR,
1385 "AFSProcessSetFileExtents Set extents failure fid %08lX-%08lX-%08lX-%08lX ResultStatus %08lX\n",
1386 SetExtents->FileId.Cell,
1387 SetExtents->FileId.Volume,
1388 SetExtents->FileId.Vnode,
1389 SetExtents->FileId.Unique,
1390 SetExtents->ResultStatus);
1392 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1393 AFS_TRACE_LEVEL_VERBOSE,
1394 "AFSProcessSetFileExtents Acquiring Fcb extents lock %08lX EXCL %08lX\n",
1395 &pFcb->NPFcb->Specific.File.ExtentsResource,
1396 PsGetCurrentThread());
1398 AFSAcquireExcl( &pFcb->NPFcb->Specific.File.ExtentsResource,
1401 pFcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_CANCELLED;
1403 KeSetEvent( &pFcb->NPFcb->Specific.File.ExtentsRequestComplete,
1407 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1408 AFS_TRACE_LEVEL_VERBOSE,
1409 "AFSProcessSetFileExtents Releasing Fcb extent lock %08lX EXCL %08lX\n",
1410 &pFcb->NPFcb->Specific.File.ExtentsResource,
1411 PsGetCurrentThread());
1413 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
1415 try_return( ntStatus);
1418 ntStatus = AFSProcessExtentsResult ( pFcb,
1419 SetExtents->ExtentCount,
1420 SetExtents->FileExtents );
1424 if( pObjectInfo != NULL)
1427 lCount = InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
1429 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1430 AFS_TRACE_LEVEL_VERBOSE,
1431 "AFSProcessSetFileExtents Decrement count on object %08lX Cnt %d\n",
1441 // Helper fuctions for Usermode initiation of release of extents
1444 AFSReleaseSpecifiedExtents( IN AFSReleaseFileExtentsCB *Extents,
1446 OUT AFSFileExtentCB *FileExtents,
1447 IN ULONG BufferSize,
1448 OUT ULONG *ExtentCount,
1449 OUT BOOLEAN *DirtyExtents)
1454 ULONG ulExtentCount = 0;
1455 NTSTATUS ntStatus = STATUS_SUCCESS;
1456 BOOLEAN bReleaseAll = FALSE;
1457 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1462 ASSERT( ExIsResourceAcquiredExclusiveLite( &Fcb->NPFcb->Specific.File.ExtentsResource));
1464 if (BufferSize < (Extents->ExtentCount * sizeof( AFSFileExtentCB)))
1467 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1468 AFS_TRACE_LEVEL_VERBOSE,
1469 "AFSReleaseSpecifiedExtents Buffer too small\n");
1471 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL);
1474 RtlZeroMemory( FileExtents, BufferSize);
1477 *DirtyExtents = FALSE;
1480 // iterate until we have dealt with all we were asked for or
1481 // are at the end of the list. Note that this deals (albeit
1482 // badly) with out of order extents
1485 pExtent = AFSExtentForOffset( Fcb,
1486 &Extents->FileExtents[0].FileOffset,
1489 if (NULL == pExtent)
1491 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1495 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1499 if( BooleanFlagOn( Extents->Flags, AFS_RELEASE_EXTENTS_FLAGS_RELEASE_ALL) ||
1500 ( Extents->FileId.Cell == 0 &&
1501 Extents->FileId.Volume == 0 &&
1502 Extents->FileId.Vnode == 0 &&
1503 Extents->FileId.Unique == 0))
1509 while( le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST] &&
1510 ulExtentCount < Extents->ExtentCount)
1514 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
1519 if( pExtent->FileOffset.QuadPart < Extents->FileExtents[ulExtentCount].FileOffset.QuadPart)
1522 // Skip forward through the extent list until we get
1523 // to the one we want
1529 else if (pExtent->FileOffset.QuadPart > Extents->FileExtents[ulExtentCount].FileOffset.QuadPart)
1532 // We don't have the extent asked for so return UNKNOWN
1535 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1536 AFS_TRACE_LEVEL_VERBOSE,
1537 "AFSReleaseSpecifiedExtents Located UNKNOWN extent Offset %I64X Len %08lX\n",
1538 Extents->FileExtents[ulExtentCount].FileOffset.QuadPart,
1539 Extents->FileExtents[ulExtentCount].Length);
1541 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_UNKNOWN;
1543 FileExtents[*ExtentCount].Length = 0;
1544 FileExtents[*ExtentCount].CacheOffset.QuadPart = 0;
1545 FileExtents[*ExtentCount].FileOffset = Extents->FileExtents[ulExtentCount].FileOffset;
1547 *ExtentCount = (*ExtentCount) + 1;
1552 // Reset where we are looking
1555 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1559 else if( pExtent->ActiveCount > 0)
1562 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1563 AFS_TRACE_LEVEL_VERBOSE,
1564 "AFSReleaseSpecifiedExtents Located IN_USE extent Offset %I64X Len %08lX\n",
1565 Extents->FileExtents[ulExtentCount].FileOffset.QuadPart,
1566 Extents->FileExtents[ulExtentCount].Length);
1568 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_IN_USE;
1570 FileExtents[*ExtentCount].Length = 0;
1571 FileExtents[*ExtentCount].CacheOffset.QuadPart = 0;
1572 FileExtents[*ExtentCount].FileOffset = Extents->FileExtents[ulExtentCount].FileOffset;
1574 *ExtentCount = (*ExtentCount) + 1;
1579 // Reset where we are looking
1582 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1591 // If the extent is currently active then skip it
1594 if( pExtent->ActiveCount > 0)
1603 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_RELEASE;
1605 FileExtents[*ExtentCount].Length = pExtent->Size;
1606 FileExtents[*ExtentCount].DirtyLength = pExtent->Size;
1607 FileExtents[*ExtentCount].DirtyOffset = 0;
1608 FileExtents[*ExtentCount].CacheOffset = pExtent->CacheOffset;
1609 FileExtents[*ExtentCount].FileOffset = pExtent->FileOffset;
1611 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1612 AFS_TRACE_LEVEL_VERBOSE,
1613 "AFSReleaseSpecifiedExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
1615 Fcb->ObjectInformation->FileId.Cell,
1616 Fcb->ObjectInformation->FileId.Volume,
1617 Fcb->ObjectInformation->FileId.Vnode,
1618 Fcb->ObjectInformation->FileId.Unique,
1619 FileExtents[*ExtentCount].FileOffset.QuadPart,
1620 FileExtents[*ExtentCount].Length);
1622 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
1625 AFSAcquireExcl( &Fcb->NPFcb->Specific.File.DirtyExtentsListLock,
1628 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
1631 AFSRemoveEntryDirtyList( Fcb,
1634 FileExtents[*ExtentCount].Flags |= AFS_EXTENT_FLAG_DIRTY;
1636 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
1638 *DirtyExtents = TRUE;
1641 AFSReleaseResource( &Fcb->NPFcb->Specific.File.DirtyExtentsListLock);
1645 // move forward all three cursors
1649 *ExtentCount = (*ExtentCount) + 1;
1654 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
1656 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
1658 RemoveEntryList( &pExtent->Lists[i] );
1662 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
1664 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
1669 AFSExFreePool( pExtent);
1671 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
1673 lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount);
1678 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
1693 AFSFindFcbToClean(ULONG IgnoreTime, AFSFcb *LastFcb, BOOLEAN Block)
1696 AFSFcb *pFcb = NULL;
1697 AFSVolumeCB *pVolumeCB = NULL;
1698 AFSDeviceExt *pRDRDeviceExt = NULL;
1699 AFSDeviceExt *pControlDeviceExt = NULL;
1700 BOOLEAN bLocatedEntry = FALSE;
1701 AFSObjectInfoCB *pCurrentObject = NULL;
1702 BOOLEAN bReleaseVolumeListLock = FALSE;
1705 pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1706 pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1708 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1709 AFS_TRACE_LEVEL_VERBOSE,
1710 "AFSFindFcbToClean Acquiring RDR VolumeListLock lock %08lX SHARED %08lX\n",
1711 &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1712 PsGetCurrentThread());
1714 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1717 bReleaseVolumeListLock = TRUE;
1719 pVolumeCB = pRDRDeviceExt->Specific.RDR.VolumeListHead;
1721 while( pVolumeCB != NULL)
1725 // The Volume list may move under our feet. Lock it.
1728 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1729 AFS_TRACE_LEVEL_VERBOSE,
1730 "AFSFindFcbToClean Acquiring VolumeRoot ObjectInfoTree lock %08lX SHARED %08lX\n",
1731 pVolumeCB->ObjectInfoTree.TreeLock,
1732 PsGetCurrentThread());
1734 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1736 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1738 bReleaseVolumeListLock = FALSE;
1740 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1743 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1745 if( NULL == LastFcb)
1748 pCurrentObject = pVolumeCB->ObjectInfoListHead;
1753 pCurrentObject = (AFSObjectInfoCB *)LastFcb->ObjectInformation->ListEntry.fLink;
1758 while( pCurrentObject != NULL)
1761 pFcb = (AFSFcb *)pCurrentObject->Fcb;
1764 // If the FCB is a candidate we try to lock it (but without waiting - which
1765 // means we are deadlock free
1769 pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
1775 AFSLockForExtentsTrim( pFcb);
1780 if( !AFSLockForExtentsTrimNoWait( pFcb))
1783 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1792 // Need to be sure there are no current flushes in the queue
1795 if( pFcb->Specific.File.ExtentCount == 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);
1806 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1813 if( pFcb->Specific.File.QueuedFlushCount > 0)
1816 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1817 AFS_TRACE_LEVEL_VERBOSE,
1818 "AFSFindFcbToClean Releasing Fcb extent lock %08lX thread %08lX\n",
1819 &pFcb->NPFcb->Specific.File.ExtentsResource,
1820 PsGetCurrentThread());
1822 AFSReleaseResource(&pFcb->NPFcb->Specific.File.ExtentsResource);
1826 AFSWaitOnQueuedFlushes( pFcb);
1831 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1839 if( pFcb->OpenHandleCount > 0)
1842 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1843 AFS_TRACE_LEVEL_VERBOSE,
1844 "AFSFindFcbToClean Releasing Fcb extent lock %08lX thread %08lX\n",
1845 &pFcb->NPFcb->Specific.File.ExtentsResource,
1846 PsGetCurrentThread());
1848 AFSReleaseResource(&pFcb->NPFcb->Specific.File.ExtentsResource);
1850 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1858 // A hit a very palpable hit. Pin it
1861 lCount = InterlockedIncrement( &pCurrentObject->ObjectReferenceCount);
1863 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1864 AFS_TRACE_LEVEL_VERBOSE,
1865 "AFSFindFcbToClean Increment count on Fcb %08lX Cnt %d\n",
1869 bLocatedEntry = TRUE;
1874 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1879 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1886 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1889 bReleaseVolumeListLock = TRUE;
1891 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1894 if( bReleaseVolumeListLock)
1897 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1904 AFSProcessExtentFailure( PIRP Irp)
1906 AFSExtentFailureCB *pFailureCB = NULL;
1907 NTSTATUS ntStatus = STATUS_SUCCESS;
1908 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
1909 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1910 AFSVolumeCB *pVolumeCB = NULL;
1911 ULONGLONG ullIndex = 0;
1912 AFSObjectInfoCB *pObjectInfo = NULL;
1917 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSExtentFailureCB))
1920 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1921 AFS_TRACE_LEVEL_ERROR,
1922 "AFSProcessExtentFailure Input buffer too small\n");
1924 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1927 pFailureCB = (AFSExtentFailureCB *)Irp->AssociatedIrp.SystemBuffer;
1929 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1930 AFS_TRACE_LEVEL_ERROR,
1931 "AFSProcessExtentFailure Service Reports Failure fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1932 pFailureCB->FileId.Cell,
1933 pFailureCB->FileId.Volume,
1934 pFailureCB->FileId.Vnode,
1935 pFailureCB->FileId.Unique,
1936 pFailureCB->FailureStatus);
1938 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
1941 // Locate the volume node
1944 ullIndex = AFSCreateHighIndex( &pFailureCB->FileId);
1946 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
1948 (AFSBTreeEntry **)&pVolumeCB);
1950 if( pVolumeCB != NULL)
1953 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1954 AFS_TRACE_LEVEL_VERBOSE,
1955 "AFSProcessExtentFailure Acquiring VolumeRoot FileIDTree.TreeLock lock %08lX SHARED %08lX\n",
1956 pVolumeCB->ObjectInfoTree.TreeLock,
1957 PsGetCurrentThread());
1959 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1962 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
1964 if( !NT_SUCCESS( ntStatus) ||
1968 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1969 AFS_TRACE_LEVEL_ERROR,
1970 "AFSProcessExtentFailure Invalid volume index %I64X status %08X\n",
1971 ullIndex, ntStatus);
1973 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1976 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1979 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1982 // Now locate the Object in this volume
1985 ullIndex = AFSCreateLowIndex( &pFailureCB->FileId);
1987 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
1989 (AFSBTreeEntry **)&pObjectInfo);
1991 if( pObjectInfo != NULL &&
1992 pObjectInfo->Fcb != NULL)
1996 // Reference the node so it won't be torn down
1999 lCount = InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
2001 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2002 AFS_TRACE_LEVEL_VERBOSE,
2003 "AFSProcessExtentFailure Increment count on object %08lX Cnt %d\n",
2008 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2010 if( !NT_SUCCESS( ntStatus) ||
2011 pObjectInfo == NULL ||
2012 pObjectInfo->Fcb == NULL)
2015 if( pObjectInfo == NULL)
2017 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2018 AFS_TRACE_LEVEL_ERROR,
2019 "AFSProcessExtentFailure Invalid file index %I64X\n",
2024 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2025 AFS_TRACE_LEVEL_ERROR,
2026 "AFSProcessExtentFailure Fcb dealocated for %I64X\n",
2030 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2033 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2034 AFS_TRACE_LEVEL_VERBOSE,
2035 "AFSProcessExtentFailure Acquiring Fcb extent lock %08lX EXCL %08lX\n",
2036 &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2037 PsGetCurrentThread());
2039 AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2042 pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestStatus = pFailureCB->FailureStatus;
2044 RtlCopyMemory( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2045 &pFailureCB->AuthGroup,
2048 KeSetEvent( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
2052 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2053 AFS_TRACE_LEVEL_VERBOSE,
2054 "AFSProcessExtentFailure Releasing Fcb extent lock %08lX EXCL %08lX\n",
2055 &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2056 PsGetCurrentThread());
2058 AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource);
2060 lCount = InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
2062 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2063 AFS_TRACE_LEVEL_VERBOSE,
2064 "AFSProcessExtentFailure Decrement count on object %08lX Cnt %d\n",
2077 AFSProcessReleaseFileExtents( IN PIRP Irp)
2079 NTSTATUS ntStatus = STATUS_SUCCESS;
2080 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2081 PFILE_OBJECT pFileObject = pIrpSp->FileObject;
2082 AFSFcb *pFcb = NULL;
2083 AFSVolumeCB *pVolumeCB = NULL;
2084 AFSDeviceExt *pDevExt;
2085 AFSReleaseFileExtentsCB *pExtents;
2086 AFSReleaseFileExtentsResultCB *pResult = NULL;
2087 AFSReleaseFileExtentsResultFileCB *pFile = NULL;
2089 ULONGLONG ullIndex = 0;
2090 AFSObjectInfoCB *pObjectInfo = NULL;
2091 BOOLEAN bLocked = FALSE;
2092 BOOLEAN bDirtyExtents = FALSE;
2099 pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2101 pExtents = (AFSReleaseFileExtentsCB*) Irp->AssociatedIrp.SystemBuffer;
2103 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2104 sizeof( AFSReleaseFileExtentsCB))
2107 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2108 AFS_TRACE_LEVEL_ERROR,
2109 "AFSProcessReleaseFileExtents INPUT Buffer too small\n");
2111 try_return( ntStatus = STATUS_INVALID_PARAMETER );
2114 if ( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength <
2115 sizeof(AFSReleaseFileExtentsResultCB))
2118 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2119 AFS_TRACE_LEVEL_ERROR,
2120 "AFSProcessReleaseFileExtents OUTPUT Buffer too small [1]\n");
2123 // Must have space for one extent in one file
2126 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL);
2129 if (pExtents->ExtentCount == 0)
2132 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2133 AFS_TRACE_LEVEL_ERROR,
2134 "AFSProcessReleaseFileExtents Extent count zero\n");
2136 try_return( ntStatus = STATUS_INVALID_PARAMETER);
2139 if (pExtents->FileId.Cell != 0 ||
2140 pExtents->FileId.Volume != 0 ||
2141 pExtents->FileId.Vnode != 0 ||
2142 pExtents->FileId.Unique != 0)
2145 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2146 AFS_TRACE_LEVEL_VERBOSE,
2147 "AFSProcessReleaseFileExtents Processing FID %08lX:%08lX:%08lX:%08lX\n",
2148 pExtents->FileId.Cell,
2149 pExtents->FileId.Volume,
2150 pExtents->FileId.Vnode,
2151 pExtents->FileId.Unique);
2153 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2154 ( FIELD_OFFSET( AFSReleaseFileExtentsCB, ExtentCount) + sizeof(ULONG)) ||
2155 pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2156 ( FIELD_OFFSET( AFSReleaseFileExtentsCB, ExtentCount) + sizeof(ULONG) +
2157 sizeof (AFSFileExtentCB) * pExtents->ExtentCount))
2160 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2161 AFS_TRACE_LEVEL_ERROR,
2162 "AFSProcessReleaseFileExtents Buffer too small for FID %08lX:%08lx:%08lX:%08lX\n",
2163 pExtents->FileId.Cell,
2164 pExtents->FileId.Volume,
2165 pExtents->FileId.Vnode,
2166 pExtents->FileId.Unique);
2168 try_return( ntStatus = STATUS_INVALID_PARAMETER );
2171 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2172 AFS_TRACE_LEVEL_VERBOSE,
2173 "AFSProcessReleaseFileExtents Acquiring RDR VolumeTreeLock lock %08lX SHARED %08lX\n",
2174 &pDevExt->Specific.RDR.VolumeTreeLock,
2175 PsGetCurrentThread());
2177 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
2180 // Locate the volume node
2183 ullIndex = AFSCreateHighIndex( &pExtents->FileId);
2185 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
2187 (AFSBTreeEntry **)&pVolumeCB);
2189 if( pVolumeCB != NULL)
2192 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2193 AFS_TRACE_LEVEL_VERBOSE,
2194 "AFSProcessReleaseFileExtents Acquiring VolumeRoot FileIDTree.TreeLock lock %08lX SHARED %08lX\n",
2195 pVolumeCB->ObjectInfoTree.TreeLock,
2196 PsGetCurrentThread());
2198 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
2201 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
2203 if( !NT_SUCCESS( ntStatus) ||
2207 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2208 AFS_TRACE_LEVEL_ERROR,
2209 "AFSProcessReleaseFileExtents Invalid volume index %I64X status %08X\n",
2210 ullIndex, ntStatus);
2212 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2215 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
2218 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
2221 // Now locate the Object in this volume
2224 ullIndex = AFSCreateLowIndex( &pExtents->FileId);
2226 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
2228 (AFSBTreeEntry **)&pObjectInfo);
2230 if( pObjectInfo != NULL)
2234 // Reference the node so it won't be torn down
2237 lCount = InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
2239 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2240 AFS_TRACE_LEVEL_VERBOSE,
2241 "AFSProcessReleaseFileExtents Increment count on object %08lX Cnt %d\n",
2246 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2248 if( !NT_SUCCESS( ntStatus) ||
2249 pObjectInfo == NULL)
2252 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2253 AFS_TRACE_LEVEL_ERROR,
2254 "AFSProcessReleaseFileExtents Invalid file index %I64X\n",
2257 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2260 pFcb = pObjectInfo->Fcb;
2265 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2266 AFS_TRACE_LEVEL_ERROR,
2267 "AFSProcessReleaseFileExtents Fcb not initialied (NO EXTENTS) for FID %08lX:%08lx:%08lX:%08lX\n",
2268 pExtents->FileId.Cell,
2269 pExtents->FileId.Volume,
2270 pExtents->FileId.Vnode,
2271 pExtents->FileId.Unique);
2273 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2276 AFSLockForExtentsTrim( pFcb );
2284 // Locate an Fcb to trim down
2287 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2288 AFS_TRACE_LEVEL_VERBOSE,
2289 "AFSProcessReleaseFileExtents Searching for a Fcb to Trim Down\n");
2291 pFcb = AFSFindFcbToClean( 0, NULL, FALSE);
2296 pFcb = AFSFindFcbToClean( 0, NULL, TRUE);
2302 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2303 AFS_TRACE_LEVEL_ERROR,
2304 "AFSProcessReleaseFileExtents Failed to locate Fcb for release ...\n");
2306 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2309 pObjectInfo = pFcb->ObjectInformation;
2315 // Allocate a scratch buffer to move in the extent information
2318 ulSz = (pExtents->ExtentCount-1) * sizeof(AFSFileExtentCB);
2319 ulSz += sizeof(AFSReleaseFileExtentsResultCB);
2321 if (ulSz > pIrpSp->Parameters.DeviceIoControl.OutputBufferLength)
2323 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2324 AFS_TRACE_LEVEL_ERROR,
2325 "AFSProcessReleaseFileExtents OUTPUT Buffer too small [2]\n");
2327 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL );
2330 pResult = (AFSReleaseFileExtentsResultCB*) AFSExAllocatePoolWithTag( PagedPool,
2332 AFS_EXTENTS_RESULT_TAG);
2333 if (NULL == pResult)
2336 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2337 AFS_TRACE_LEVEL_ERROR,
2338 "AFSProcessReleaseFileExtents Failed to allocate result block\n");
2340 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2344 // Set up the header (for an array of one)
2346 pResult->FileCount = 1;
2347 pResult->Flags = AFS_EXTENT_FLAG_RELEASE;
2348 ulSz -= FIELD_OFFSET(AFSReleaseFileExtentsResultCB, Files);
2351 // Setup the first (and only) file
2353 pFile = pResult->Files;
2354 pFile->FileId = pObjectInfo->FileId;
2355 pFile->Flags = AFS_EXTENT_FLAG_RELEASE;
2358 // Stash away the auth group
2361 RtlZeroMemory( &stAuthGroup,
2364 ntStatus = AFSRetrieveValidAuthGroup( pFcb,
2369 if( !NT_SUCCESS( ntStatus))
2371 try_return( ntStatus);
2374 RtlCopyMemory( &pFile->AuthGroup,
2379 // Update the metadata for this call
2382 pFile->AllocationSize = pFcb->ObjectInformation->EndOfFile;
2383 pFile->CreateTime = pFcb->ObjectInformation->CreationTime;
2384 pFile->ChangeTime = pFcb->ObjectInformation->ChangeTime;
2385 pFile->LastAccessTime = pFcb->ObjectInformation->LastAccessTime;
2386 pFile->LastWriteTime = pFcb->ObjectInformation->LastWriteTime;
2388 ulSz -= FIELD_OFFSET(AFSReleaseFileExtentsResultFileCB, FileExtents);
2390 ntStatus = AFSReleaseSpecifiedExtents( pExtents,
2394 &pFile->ExtentCount,
2397 if (!NT_SUCCESS(ntStatus))
2400 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2401 AFS_TRACE_LEVEL_ERROR,
2402 "AFSProcessReleaseFileExtents Failed to release extents Status %08lX\n",
2405 try_return( ntStatus );
2408 if( pExtents->ExtentCount == 0)
2411 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2412 AFS_TRACE_LEVEL_WARNING,
2413 "AFSProcessReleaseFileExtents Failed to release ANY extents\n");
2416 ulSz = sizeof(AFSReleaseFileExtentsResultCB);
2418 if( pExtents->ExtentCount > 0)
2420 ulSz += ((pExtents->ExtentCount-1) * sizeof(AFSFileExtentCB));
2423 RtlCopyMemory( Irp->AssociatedIrp.SystemBuffer,
2432 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2433 AFS_TRACE_LEVEL_VERBOSE,
2434 "AFSProcessReleaseFileExtents Releasing Fcb extent lock %08lX thread %08lX\n",
2435 &pFcb->NPFcb->Specific.File.ExtentsResource,
2436 PsGetCurrentThread());
2438 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
2441 if( NULL != pResult &&
2442 Irp->AssociatedIrp.SystemBuffer != pResult)
2445 AFSExFreePool(pResult);
2448 if (NT_SUCCESS(ntStatus))
2450 Irp->IoStatus.Information = ulSz;
2454 Irp->IoStatus.Information = 0;
2457 Irp->IoStatus.Status = ntStatus;
2459 if( pObjectInfo != NULL)
2462 lCount = InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
2464 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2465 AFS_TRACE_LEVEL_VERBOSE,
2466 "AFSProcessReleaseFileExtents Decrement count on object %08lX Cnt %d\n",
2476 AFSWaitForExtentMapping( AFSFcb *Fcb,
2479 NTSTATUS ntStatus = STATUS_SUCCESS;
2480 LARGE_INTEGER liTimeOut;
2481 ULONGLONG ullProcessId = (ULONGLONG)PsGetCurrentProcessId();
2486 ASSERT( !ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
2488 if (!NT_SUCCESS( Fcb->NPFcb->Specific.File.ExtentsRequestStatus))
2492 // If this isn't the same authgroup which caused the failure
2493 // then try to request them again
2496 if( RtlCompareMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2498 sizeof( GUID)) == sizeof( GUID))
2501 ntStatus = Fcb->NPFcb->Specific.File.ExtentsRequestStatus;
2503 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
2505 RtlZeroMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2508 try_return( ntStatus);
2512 liTimeOut.QuadPart = -(1 * AFS_ONE_SECOND);
2514 ntStatus = KeWaitForSingleObject( &Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
2520 if (!NT_SUCCESS( Fcb->NPFcb->Specific.File.ExtentsRequestStatus))
2524 // If this isn't the same authgroup which caused the failure
2525 // or the System Process,
2526 // then try to request the extents again
2529 if( RtlCompareMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2531 sizeof( GUID)) == sizeof( GUID) ||
2532 ullProcessId == (ULONGLONG)AFSSysProcess)
2535 ntStatus = Fcb->NPFcb->Specific.File.ExtentsRequestStatus;
2537 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
2539 RtlZeroMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2542 try_return( ntStatus);
2546 if( ntStatus == STATUS_TIMEOUT)
2549 ntStatus = STATUS_SUCCESS;
2561 AFSFlushExtents( IN AFSFcb *Fcb,
2564 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
2565 AFSExtent *pExtent, *pNextExtent;
2567 AFSReleaseExtentsCB *pRelease = NULL;
2569 ULONG initialDirtyCount = 0;
2570 BOOLEAN bExtentsLocked = FALSE;
2573 NTSTATUS ntStatus = STATUS_SUCCESS;
2574 LARGE_INTEGER liLastFlush;
2575 AFSExtent *pDirtyListHead = NULL, *pDirtyListTail = NULL;
2576 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2577 GUID *pAuthGroup = AuthGroup;
2581 ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
2584 // Save, then reset the flush time
2587 liLastFlush = Fcb->Specific.File.LastServerFlush;
2589 KeQueryTickCount( &Fcb->Specific.File.LastServerFlush);
2594 if( pAuthGroup == NULL ||
2595 RtlCompareMemory( pAuthGroup,
2596 &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2597 sizeof( GUID)) == sizeof( GUID))
2600 RtlZeroMemory( &stAuthGroup,
2603 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
2608 if( !NT_SUCCESS( ntStatus))
2610 try_return( ntStatus);
2613 pAuthGroup = &stAuthGroup;
2617 // Lock extents while we count and set up the array to send to
2621 AFSLockForExtentsTrim( Fcb);
2623 bExtentsLocked = TRUE;
2625 lCount = InterlockedIncrement( &Fcb->Specific.File.QueuedFlushCount);
2628 // Clear our queued flush event
2631 KeClearEvent( &Fcb->NPFcb->Specific.File.QueuedFlushEvent);
2634 // Look for a start in the list to flush entries
2639 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
2641 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
2643 AFS_EXTENT_RELEASE_TAG);
2644 if( NULL == pRelease)
2647 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2650 initialDirtyCount = Fcb->Specific.File.ExtentsDirtyCount;
2652 while( Fcb->Specific.File.ExtentsDirtyCount > 0)
2655 pRelease->Flags = AFS_EXTENT_FLAG_DIRTY;
2657 if( BooleanFlagOn( Fcb->Flags, AFS_FCB_FILE_CLOSED))
2660 pRelease->Flags |= AFS_EXTENT_FLAG_FLUSH;
2664 // Update the metadata for this call
2667 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
2668 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
2669 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
2670 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
2671 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
2675 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
2678 pExtent = (AFSExtent *)pNPFcb->Specific.File.DirtyListHead;
2680 while( count < AFS_MAXIMUM_EXTENT_RELEASE_COUNT)
2683 if ( pExtent == NULL)
2689 pNextExtent = (AFSExtent *)pExtent->DirtyList.fLink;
2691 if ( pExtent->ActiveCount > 0)
2693 pExtent = pNextExtent;
2697 AFSRemoveEntryDirtyList( Fcb, pExtent);
2699 pExtent->DirtyList.fLink = NULL;
2700 pExtent->DirtyList.bLink = NULL;
2702 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
2705 // Clear the flag in advance of the write. If we do
2706 // things this was we know that the clear is
2707 // pessimistic (any write which happens from now on
2708 // will set the flag dirty again).
2711 pExtent->Flags &= ~AFS_EXTENT_DIRTY;
2713 pRelease->FileExtents[count].Flags = AFS_EXTENT_FLAG_DIRTY;
2715 pRelease->FileExtents[count].Length = pExtent->Size;
2716 pRelease->FileExtents[count].DirtyLength = pExtent->Size;
2717 pRelease->FileExtents[count].DirtyOffset = 0;
2718 pRelease->FileExtents[count].CacheOffset = pExtent->CacheOffset;
2719 pRelease->FileExtents[count].FileOffset = pExtent->FileOffset;
2722 RtlCopyMemory( pRelease->FileExtents[count].MD5,
2724 sizeof(pExtent->MD5));
2726 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_MD5_SET;
2729 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2730 AFS_TRACE_LEVEL_VERBOSE,
2731 "AFSFlushExtents Releasing DIRTY extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
2733 Fcb->ObjectInformation->FileId.Cell,
2734 Fcb->ObjectInformation->FileId.Volume,
2735 Fcb->ObjectInformation->FileId.Vnode,
2736 Fcb->ObjectInformation->FileId.Unique,
2737 pExtent->FileOffset.QuadPart,
2740 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_RELEASE;
2743 // Need to pull this extent from the main list as well
2746 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
2748 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
2750 RemoveEntryList( &pExtent->Lists[i] );
2754 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
2756 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
2758 AFSExFreePool( pExtent);
2760 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
2762 lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount);
2767 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
2774 pExtent = pNextExtent;
2777 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
2780 // If we are done then get out
2786 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2787 AFS_TRACE_LEVEL_VERBOSE,
2788 "AFSFlushExtents No more dirty extents found\n");
2794 // Fire off the request synchronously
2797 sz = sizeof( AFSReleaseExtentsCB ) + (count * sizeof ( AFSFileExtentCB ));
2799 pRelease->ExtentCount = count;
2801 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2802 AFS_TRACE_LEVEL_VERBOSE,
2803 "AFSFlushExtents Releasing(1) Fcb extents lock %08lX SHARED %08lX\n",
2804 &pNPFcb->Specific.File.ExtentsResource,
2805 PsGetCurrentThread());
2807 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource);
2808 bExtentsLocked = FALSE;
2810 KeSetEvent( &pNPFcb->Specific.File.FlushEvent,
2814 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
2815 AFS_REQUEST_FLAG_SYNCHRONOUS,
2818 &Fcb->ObjectInformation->FileId,
2824 if( !NT_SUCCESS(ntStatus))
2828 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
2829 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
2832 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2833 AFS_TRACE_LEVEL_ERROR,
2834 "AFSFlushExtents AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2835 Fcb->ObjectInformation->FileId.Cell,
2836 Fcb->ObjectInformation->FileId.Volume,
2837 Fcb->ObjectInformation->FileId.Vnode,
2838 Fcb->ObjectInformation->FileId.Unique,
2842 AFSLockForExtentsTrim( Fcb);
2844 bExtentsLocked = TRUE;
2849 lCount = InterlockedDecrement( &Fcb->Specific.File.QueuedFlushCount);
2854 KeSetEvent( &pNPFcb->Specific.File.QueuedFlushEvent,
2859 KeSetEvent( &pNPFcb->Specific.File.FlushEvent,
2866 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2867 AFS_TRACE_LEVEL_VERBOSE,
2868 "AFSFlushExtents Releasing(2) Fcb extents lock %08lX SHARED %08lX\n",
2869 &pNPFcb->Specific.File.ExtentsResource,
2870 PsGetCurrentThread());
2872 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
2877 AFSExFreePool( pRelease);
2885 AFSReleaseExtentsWithFlush( IN AFSFcb *Fcb,
2888 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
2891 AFSReleaseExtentsCB *pRelease = NULL;
2893 ULONG initialDirtyCount = 0;
2894 BOOLEAN bExtentsLocked = FALSE;
2897 NTSTATUS ntStatus = STATUS_SUCCESS;
2898 LARGE_INTEGER liLastFlush;
2899 ULONG ulRemainingExtentLength = 0;
2900 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2901 GUID *pAuthGroup = AuthGroup;
2905 ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
2908 // Save, then reset the flush time
2911 liLastFlush = Fcb->Specific.File.LastServerFlush;
2913 KeQueryTickCount( &Fcb->Specific.File.LastServerFlush);
2918 if( pAuthGroup == NULL ||
2919 RtlCompareMemory( pAuthGroup,
2920 &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2921 sizeof( GUID)) == sizeof( GUID))
2924 RtlZeroMemory( &stAuthGroup,
2927 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
2932 if( !NT_SUCCESS( ntStatus))
2934 try_return( ntStatus);
2937 pAuthGroup = &stAuthGroup;
2941 // Look for a start in the list to flush entries
2946 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
2948 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
2950 AFS_EXTENT_RELEASE_TAG);
2951 if( NULL == pRelease)
2954 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2957 if( Fcb->OpenHandleCount > 0)
2961 // Don't release everything ...
2965 // For now release everything
2968 //ulRemainingExtentLength = 1500;
2971 while( Fcb->Specific.File.ExtentLength > (LONG)ulRemainingExtentLength)
2974 AFSLockForExtentsTrim( Fcb);
2976 bExtentsLocked = TRUE;
2978 pRelease->Flags = AFS_EXTENT_FLAG_RELEASE;
2981 // Update the metadata for this call
2984 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
2985 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
2986 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
2987 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
2988 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
2992 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
2994 while( count < AFS_MAXIMUM_EXTENT_RELEASE_COUNT &&
2995 le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
2998 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3002 if( pExtent->ActiveCount > 0)
3008 pRelease->FileExtents[count].Flags = AFS_EXTENT_FLAG_RELEASE;
3010 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3011 AFS_TRACE_LEVEL_VERBOSE,
3012 "AFSReleaseExtentsWithFlush Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3014 Fcb->ObjectInformation->FileId.Cell,
3015 Fcb->ObjectInformation->FileId.Volume,
3016 Fcb->ObjectInformation->FileId.Vnode,
3017 Fcb->ObjectInformation->FileId.Unique,
3018 pExtent->FileOffset.QuadPart,
3021 pRelease->FileExtents[count].Length = pExtent->Size;
3022 pRelease->FileExtents[count].DirtyLength = pExtent->Size;
3023 pRelease->FileExtents[count].DirtyOffset = 0;
3024 pRelease->FileExtents[count].CacheOffset = pExtent->CacheOffset;
3025 pRelease->FileExtents[count].FileOffset = pExtent->FileOffset;
3028 RtlCopyMemory( pRelease->FileExtents[count].MD5,
3030 sizeof(pExtent->MD5));
3032 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_MD5_SET;
3035 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3038 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3041 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3044 AFSRemoveEntryDirtyList( Fcb,
3047 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_DIRTY;
3049 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
3052 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3056 // Need to pull this extent from the main list as well
3059 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
3061 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
3063 RemoveEntryList( &pExtent->Lists[i] );
3067 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
3069 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
3071 AFSExFreePool( pExtent);
3073 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
3075 lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount);
3080 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
3089 // If we are done then get out
3095 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3096 AFS_TRACE_LEVEL_VERBOSE,
3097 "AFSReleaseExtentsWithFlush No more dirty extents found\n");
3103 // Fire off the request synchronously
3106 sz = sizeof( AFSReleaseExtentsCB ) + (count * sizeof ( AFSFileExtentCB ));
3108 pRelease->ExtentCount = count;
3111 // Drop the extents lock for the duration of the call to
3112 // the network. We have pinned the extents so, even
3113 // though we might get extents added during this period,
3114 // but none will be removed. Hence we can carry on from
3118 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3119 AFS_TRACE_LEVEL_VERBOSE,
3120 "AFSReleaseExtentsWithFlush Releasing Fcb extents lock %08lX thread %08lX\n",
3121 &pNPFcb->Specific.File.ExtentsResource,
3122 PsGetCurrentThread());
3124 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource);
3125 bExtentsLocked = FALSE;
3127 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
3128 AFS_REQUEST_FLAG_SYNCHRONOUS,
3131 &Fcb->ObjectInformation->FileId,
3137 if( !NT_SUCCESS(ntStatus))
3141 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
3142 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
3145 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3146 AFS_TRACE_LEVEL_ERROR,
3147 "AFSReleaseExtentsWithFlush AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3148 Fcb->ObjectInformation->FileId.Cell,
3149 Fcb->ObjectInformation->FileId.Volume,
3150 Fcb->ObjectInformation->FileId.Vnode,
3151 Fcb->ObjectInformation->FileId.Unique,
3161 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3162 AFS_TRACE_LEVEL_VERBOSE,
3163 "AFSReleaseExtentsWithFlush Releasing Fcb extents lock %08lX thread %08lX\n",
3164 &pNPFcb->Specific.File.ExtentsResource,
3165 PsGetCurrentThread());
3167 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
3172 AFSExFreePool( pRelease);
3180 AFSReleaseCleanExtents( IN AFSFcb *Fcb,
3183 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3186 AFSReleaseExtentsCB *pRelease = NULL;
3188 ULONG initialDirtyCount = 0;
3189 BOOLEAN bExtentsLocked = FALSE;
3192 NTSTATUS ntStatus = STATUS_SUCCESS;
3193 LARGE_INTEGER liLastFlush;
3194 ULONG ulRemainingExtentLength = 0;
3195 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3196 GUID *pAuthGroup = AuthGroup;
3199 ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
3202 // Save, then reset the flush time
3205 liLastFlush = Fcb->Specific.File.LastServerFlush;
3207 KeQueryTickCount( &Fcb->Specific.File.LastServerFlush);
3212 if( pAuthGroup == NULL ||
3213 RtlCompareMemory( pAuthGroup,
3214 &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
3215 sizeof( GUID)) == sizeof( GUID))
3218 RtlZeroMemory( &stAuthGroup,
3221 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
3226 if( !NT_SUCCESS( ntStatus))
3228 try_return( ntStatus);
3231 pAuthGroup = &stAuthGroup;
3235 // Look for a start in the list to flush entries
3240 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
3242 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
3244 AFS_EXTENT_RELEASE_TAG);
3245 if( NULL == pRelease)
3248 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
3251 while( Fcb->Specific.File.ExtentLength > (LONG)ulRemainingExtentLength)
3254 AFSLockForExtentsTrim( Fcb);
3256 bExtentsLocked = TRUE;
3258 pRelease->Flags = AFS_EXTENT_FLAG_RELEASE;
3261 // Update the metadata for this call
3264 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
3265 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
3266 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
3267 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
3268 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
3272 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3274 while( count < AFS_MAXIMUM_EXTENT_RELEASE_COUNT &&
3275 le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
3278 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3282 if( pExtent->ActiveCount > 0 ||
3283 BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3288 pRelease->FileExtents[count].Flags = AFS_EXTENT_FLAG_RELEASE;
3290 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3291 AFS_TRACE_LEVEL_VERBOSE,
3292 "AFSReleaseCleanExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3294 Fcb->ObjectInformation->FileId.Cell,
3295 Fcb->ObjectInformation->FileId.Volume,
3296 Fcb->ObjectInformation->FileId.Vnode,
3297 Fcb->ObjectInformation->FileId.Unique,
3298 pExtent->FileOffset.QuadPart,
3301 pRelease->FileExtents[count].Length = pExtent->Size;
3302 pRelease->FileExtents[count].DirtyLength = pExtent->Size;
3303 pRelease->FileExtents[count].DirtyOffset = 0;
3304 pRelease->FileExtents[count].CacheOffset = pExtent->CacheOffset;
3305 pRelease->FileExtents[count].FileOffset = pExtent->FileOffset;
3308 RtlCopyMemory( pRelease->FileExtents[count].MD5,
3310 sizeof(pExtent->MD5));
3312 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_MD5_SET;
3316 // Need to pull this extent from the main list as well
3319 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
3321 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
3323 RemoveEntryList( &pExtent->Lists[i] );
3327 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
3329 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
3331 AFSExFreePool( pExtent);
3333 InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
3335 if( InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount) == 0)
3338 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
3347 // If we are done then get out
3353 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3354 AFS_TRACE_LEVEL_VERBOSE,
3355 "AFSReleaseCleanExtents No more dirty extents found\n");
3361 // Fire off the request synchronously
3364 sz = sizeof( AFSReleaseExtentsCB ) + (count * sizeof ( AFSFileExtentCB ));
3366 pRelease->ExtentCount = count;
3369 // Drop the extents lock for the duration of the call to
3370 // the network. We have pinned the extents so, even
3371 // though we might get extents added during this period,
3372 // but none will be removed. Hence we can carry on from
3376 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3377 AFS_TRACE_LEVEL_VERBOSE,
3378 "AFSReleaseCleanExtents Releasing Fcb extents lock %08lX thread %08lX\n",
3379 &pNPFcb->Specific.File.ExtentsResource,
3380 PsGetCurrentThread());
3382 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource);
3383 bExtentsLocked = FALSE;
3385 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
3386 AFS_REQUEST_FLAG_SYNCHRONOUS,
3389 &Fcb->ObjectInformation->FileId,
3395 if( !NT_SUCCESS(ntStatus))
3399 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
3400 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
3403 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3404 AFS_TRACE_LEVEL_ERROR,
3405 "AFSReleaseCleanExtents AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3406 Fcb->ObjectInformation->FileId.Cell,
3407 Fcb->ObjectInformation->FileId.Volume,
3408 Fcb->ObjectInformation->FileId.Vnode,
3409 Fcb->ObjectInformation->FileId.Unique,
3419 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3420 AFS_TRACE_LEVEL_VERBOSE,
3421 "AFSReleaseCleanExtents Releasing Fcb extents lock %08lX thread %08lX\n",
3422 &pNPFcb->Specific.File.ExtentsResource,
3423 PsGetCurrentThread());
3425 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
3430 AFSExFreePool( pRelease);
3438 AFSMarkDirty( IN AFSFcb *Fcb,
3439 IN AFSExtent *StartExtent,
3440 IN ULONG ExtentsCount,
3441 IN LARGE_INTEGER *StartingByte,
3442 IN BOOLEAN DerefExtents)
3445 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3446 AFSExtent *pExtent = StartExtent;
3447 AFSExtent *pNextExtent, *pCurrentExtent = NULL;
3449 BOOLEAN bInsertTail = FALSE, bInsertHead = FALSE;
3451 BOOLEAN bLocked = FALSE;
3453 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3454 AFS_TRACE_LEVEL_VERBOSE,
3455 "AFSMarkDirty Acquiring Fcb extents lock %08lX SHARED %08lX\n",
3456 &Fcb->NPFcb->Specific.File.ExtentsResource,
3457 PsGetCurrentThread());
3459 if( !ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource))
3461 AFSAcquireShared( &Fcb->NPFcb->Specific.File.ExtentsResource, TRUE);
3465 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3471 // Find the insertion point
3474 if( pNPFcb->Specific.File.DirtyListHead == NULL)
3479 else if( StartingByte->QuadPart == 0)
3487 pCurrentExtent = pNPFcb->Specific.File.DirtyListHead;
3489 while( pCurrentExtent != NULL)
3492 if( pCurrentExtent->FileOffset.QuadPart + pCurrentExtent->Size >= StartingByte->QuadPart ||
3493 pCurrentExtent->DirtyList.fLink == NULL)
3499 pCurrentExtent = (AFSExtent *)pCurrentExtent->DirtyList.fLink;
3503 while( ulCount < ExtentsCount)
3506 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
3508 if( !BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3511 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3512 AFS_TRACE_LEVEL_VERBOSE,
3513 "AFSMarkDirty Marking extent offset %I64X Length %08lX DIRTY\n",
3514 pExtent->FileOffset.QuadPart,
3517 pExtent->DirtyList.fLink = NULL;
3518 pExtent->DirtyList.bLink = NULL;
3523 pExtent->DirtyList.fLink = (void *)pNPFcb->Specific.File.DirtyListHead;
3525 pExtent->DirtyList.bLink = NULL;
3527 pNPFcb->Specific.File.DirtyListHead->DirtyList.bLink = (void *)pExtent;
3529 pNPFcb->Specific.File.DirtyListHead = pExtent;
3531 pCurrentExtent = pExtent;
3533 bInsertHead = FALSE;
3535 else if( bInsertTail)
3538 if( pNPFcb->Specific.File.DirtyListHead == NULL)
3541 pNPFcb->Specific.File.DirtyListHead = pExtent;
3546 pNPFcb->Specific.File.DirtyListTail->DirtyList.fLink = (void *)pExtent;
3548 pExtent->DirtyList.bLink = (void *)pNPFcb->Specific.File.DirtyListTail;
3551 pNPFcb->Specific.File.DirtyListTail = pExtent;
3556 pExtent->DirtyList.fLink = pCurrentExtent->DirtyList.fLink;
3558 pExtent->DirtyList.bLink = (void *)pCurrentExtent;
3560 if( pExtent->DirtyList.fLink == NULL)
3563 pNPFcb->Specific.File.DirtyListTail = pExtent;
3568 ((AFSExtent *)pExtent->DirtyList.fLink)->DirtyList.bLink = (void *)pExtent;
3571 pCurrentExtent->DirtyList.fLink = (void *)pExtent;
3573 pCurrentExtent = pExtent;
3576 pExtent->Flags |= AFS_EXTENT_DIRTY;
3579 // Up the dirty count
3582 lCount = InterlockedIncrement( &Fcb->Specific.File.ExtentsDirtyCount);
3587 pCurrentExtent = pExtent;
3590 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_ACTIVE_COUNTING,
3591 AFS_TRACE_LEVEL_VERBOSE,
3592 "AFSMarkDirty Decrement count on extent %08lX Cnt %d\n",
3594 pExtent->ActiveCount);
3598 ASSERT( pExtent->ActiveCount > 0);
3599 lCount = InterlockedDecrement( &pExtent->ActiveCount);
3602 pExtent = pNextExtent;
3607 __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
3612 "EXCEPTION - AFSMarkDirty\n");
3615 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3617 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3618 AFS_TRACE_LEVEL_VERBOSE,
3619 "AFSMarkDirty Releasing Fcb extents lock %08lX SHARED %08lX\n",
3620 &Fcb->NPFcb->Specific.File.ExtentsResource,
3621 PsGetCurrentThread());
3625 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
3636 ExtentFor(PLIST_ENTRY le, ULONG SkipList)
3638 return CONTAINING_RECORD( le, AFSExtent, Lists[SkipList] );
3641 static AFSExtent *NextExtent(AFSExtent *Extent, ULONG SkipList)
3643 return ExtentFor(Extent->Lists[SkipList].Flink, SkipList);
3646 static AFSExtent *DirtyExtentFor(PLIST_ENTRY le)
3648 return CONTAINING_RECORD( le, AFSExtent, DirtyList );
3651 static VOID VerifyExtentsLists(AFSFcb *Fcb)
3655 // Check the ordering of the extents lists
3657 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
3659 ASSERT(Fcb->Specific.File.ExtentsLists[0].Flink != &Fcb->Specific.File.ExtentsLists[1]);
3661 for (ULONG listNo = 0; listNo < AFS_NUM_EXTENT_LISTS; listNo ++)
3663 LARGE_INTEGER lastOffset;
3665 lastOffset.QuadPart = 0;
3667 for (PLIST_ENTRY pLe = Fcb->Specific.File.ExtentsLists[listNo].Flink;
3668 pLe != &Fcb->Specific.File.ExtentsLists[listNo];
3673 pExtent = ExtentFor(pLe, listNo);
3676 ASSERT(pLe != &Fcb->Specific.File.ExtentsLists[1] &&
3677 pLe->Flink !=&Fcb->Specific.File.ExtentsLists[1] &&
3678 pLe->Blink !=&Fcb->Specific.File.ExtentsLists[1]);
3681 ASSERT(pLe->Flink->Blink == pLe);
3682 ASSERT(pLe->Blink->Flink == pLe);
3685 // Should follow on from previous
3687 ASSERT(pExtent->FileOffset.QuadPart >= lastOffset.QuadPart);
3688 lastOffset.QuadPart = pExtent->FileOffset.QuadPart + pExtent->Size;
3691 // Should match alignment criteria
3693 ASSERT( 0 == (pExtent->FileOffset.LowPart & ExtentsMasks[listNo]) );
3696 // "lower" lists should be populated
3698 for (LONG subListNo = listNo-1; subListNo > 0; subListNo --)
3700 ASSERT( !IsListEmpty(&pExtent->Lists[subListNo]));
3708 AFSTrimExtents( IN AFSFcb *Fcb,
3709 IN PLARGE_INTEGER FileSize)
3712 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3715 BOOLEAN locked = FALSE;
3716 NTSTATUS ntStatus = STATUS_SUCCESS;
3717 LARGE_INTEGER liAlignedOffset = {0,0};
3718 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
3719 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3726 // Get an aligned offset
3729 if( FileSize != NULL)
3732 liAlignedOffset = *FileSize;
3735 if( liAlignedOffset.QuadPart > 0 &&
3736 liAlignedOffset.QuadPart % pDevExt->Specific.RDR.CacheBlockSize != 0)
3740 // Align UP to the next cache block size
3743 liAlignedOffset.QuadPart = (ULONGLONG)( (ULONGLONG)((liAlignedOffset.QuadPart / pDevExt->Specific.RDR.CacheBlockSize) + 1) * (ULONGLONG)pDevExt->Specific.RDR.CacheBlockSize);
3747 // Ensure that no one is working with the extents and grab the
3751 AFSLockForExtentsTrim( Fcb);
3755 if( 0 == Fcb->Specific.File.ExtentCount)
3759 // Update the request extent status
3762 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
3764 try_return( ntStatus = STATUS_SUCCESS);
3768 // We are truncating from a specific length in the file. If the offset
3769 // is non-zero then go find the first extent to remove
3772 if( 0 == FileSize->QuadPart)
3775 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3780 pExtent = AFSExtentForOffset( Fcb,
3784 if( NULL == pExtent)
3787 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3791 le = &pExtent->Lists[AFS_EXTENTS_LIST];
3795 while( le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
3798 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3801 // Only trim down extents beyond the aligned offset
3806 if( pExtent->FileOffset.QuadPart >= liAlignedOffset.QuadPart)
3809 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3812 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3815 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3819 AFSRemoveEntryDirtyList( Fcb,
3822 dirtyCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
3824 ASSERT(dirtyCount >= 0);
3827 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3830 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
3832 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
3834 RemoveEntryList( &pExtent->Lists[i] );
3838 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3839 AFS_TRACE_LEVEL_VERBOSE,
3840 "AFSTrimExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3842 Fcb->ObjectInformation->FileId.Cell,
3843 Fcb->ObjectInformation->FileId.Volume,
3844 Fcb->ObjectInformation->FileId.Vnode,
3845 Fcb->ObjectInformation->FileId.Unique,
3846 pExtent->FileOffset.QuadPart,
3849 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
3851 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
3853 ASSERT( pExtent->ActiveCount == 0);
3858 AFSExFreePool( pExtent);
3860 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
3862 lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount);
3867 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
3875 // Update the request extent status
3878 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
3885 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3886 AFS_TRACE_LEVEL_VERBOSE,
3887 "AFSTrimExtents Releasing Fcb extents lock %08lX thread %08lX\n",
3888 &Fcb->NPFcb->Specific.File.ExtentsResource,
3889 PsGetCurrentThread());
3891 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
3899 AFSTrimSpecifiedExtents( IN AFSFcb *Fcb,
3901 IN AFSFileExtentCB *Result)
3904 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3907 AFSFileExtentCB *pFileExtents = Result;
3908 NTSTATUS ntStatus = STATUS_SUCCESS;
3909 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
3910 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3916 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3918 while( le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST] &&
3922 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3925 // Only trim down extents beyond the aligned offset
3930 if( pExtent->FileOffset.QuadPart == pFileExtents->FileOffset.QuadPart)
3933 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3936 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3939 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3944 AFSRemoveEntryDirtyList( Fcb,
3947 dirtyCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
3949 ASSERT( dirtyCount >= 0);
3953 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3957 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
3959 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
3961 RemoveEntryList( &pExtent->Lists[i] );
3965 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3966 AFS_TRACE_LEVEL_VERBOSE,
3967 "AFSTrimSpecifiedExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3969 Fcb->ObjectInformation->FileId.Cell,
3970 Fcb->ObjectInformation->FileId.Volume,
3971 Fcb->ObjectInformation->FileId.Vnode,
3972 Fcb->ObjectInformation->FileId.Unique,
3973 pExtent->FileOffset.QuadPart,
3976 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
3978 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
3980 ASSERT( pExtent->ActiveCount == 0);
3985 AFSExFreePool( pExtent);
3987 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
3989 lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount);
3994 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
4000 // Next extent we are looking for
4010 // Update the request extent status
4013 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
4020 AFSReferenceActiveExtents( IN AFSExtent *StartExtent,
4021 IN ULONG ExtentsCount)
4024 AFSExtent *pExtent = StartExtent;
4025 AFSExtent *pNextExtent;
4029 while( ulCount < ExtentsCount)
4032 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
4034 lCount = InterlockedIncrement( &pExtent->ActiveCount);
4036 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_ACTIVE_COUNTING,
4037 AFS_TRACE_LEVEL_VERBOSE,
4038 "AFSReferenceActiveExtents Increment count on extent %08lX Cnt %d\n",
4042 pExtent = pNextExtent;
4051 AFSDereferenceActiveExtents( IN AFSExtent *StartExtent,
4052 IN ULONG ExtentsCount)
4055 AFSExtent *pExtent = StartExtent;
4056 AFSExtent *pNextExtent;
4060 while( ulCount < ExtentsCount)
4063 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
4065 ASSERT( pExtent->ActiveCount > 0);
4067 lCount = InterlockedDecrement( &pExtent->ActiveCount);
4069 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_ACTIVE_COUNTING,
4070 AFS_TRACE_LEVEL_VERBOSE,
4071 "AFSDereferenceActiveExtents Decrement count on extent %08lX Cnt %d\n",
4075 pExtent = pNextExtent;
4084 AFSRemoveEntryDirtyList( IN AFSFcb *Fcb,
4085 IN AFSExtent *Extent)
4088 if( Extent->DirtyList.fLink == NULL)
4091 Fcb->NPFcb->Specific.File.DirtyListTail = (AFSExtent *)Extent->DirtyList.bLink;
4093 if( Fcb->NPFcb->Specific.File.DirtyListTail != NULL)
4096 Fcb->NPFcb->Specific.File.DirtyListTail->DirtyList.fLink = NULL;
4102 ((AFSExtent *)Extent->DirtyList.fLink)->DirtyList.bLink = Extent->DirtyList.bLink;
4105 if( Extent->DirtyList.bLink == NULL)
4108 Fcb->NPFcb->Specific.File.DirtyListHead = (AFSExtent *)Extent->DirtyList.fLink;
4110 if( Fcb->NPFcb->Specific.File.DirtyListHead != NULL)
4113 Fcb->NPFcb->Specific.File.DirtyListHead->DirtyList.bLink = NULL;
4119 ((AFSExtent *)Extent->DirtyList.bLink)->DirtyList.fLink = Extent->DirtyList.fLink;
4127 AFSConstructCleanByteRangeList( AFSFcb * pFcb,
4128 AFSByteRange ** pByteRangeList)
4131 ULONG ulByteRangeMax;
4132 ULONG ulByteRangeCount = 0;
4133 AFSByteRange *ByteRangeList;
4134 AFSExtent *pExtent, *pNextExtent;
4136 AFSAcquireShared( &pFcb->NPFcb->Specific.File.DirtyExtentsListLock, TRUE);
4138 ulByteRangeMax = pFcb->Specific.File.ExtentsDirtyCount + 1;
4140 ByteRangeList = (AFSByteRange *) AFSExAllocatePoolWithTag( PagedPool,
4141 ulByteRangeMax * sizeof( AFSByteRange),
4144 if ( ByteRangeList == NULL)
4147 (*pByteRangeList) = NULL;
4149 try_return( ulByteRangeCount = DWORD_MAX);
4152 RtlZeroMemory( ByteRangeList,
4153 ulByteRangeMax * sizeof( AFSByteRange));
4156 // The for loop populates the ByteRangeList entries with values that are
4157 // the gaps in the DirtyList. In other words, if a range is not present
4158 // in the DirtyList it will be represented in the ByteRangeList array.
4161 for ( ulByteRangeCount = 0,
4162 pExtent = (AFSExtent *)pFcb->NPFcb->Specific.File.DirtyListHead;
4163 ulByteRangeCount < ulByteRangeMax && pExtent != NULL;
4164 pExtent = pNextExtent)
4167 pNextExtent = (AFSExtent *)pExtent->DirtyList.fLink;
4170 // The first time the for() is entered the ulByteRangeCount will be zero and
4171 // ByteRangeList[0] FileOffset and Length will both be zero. If the first
4172 // extent is not for offset zero, the ByteRangeList[0] Length is set to the
4173 // FileOffset of the Extent.
4175 // Future passes through the loop behave in a similar fashion but
4176 // ByteRangeList[ulByteRangeCount] FileOffset will have been set below.
4179 if ( pExtent->FileOffset.QuadPart != ByteRangeList[ulByteRangeCount].FileOffset.QuadPart + ByteRangeList[ulByteRangeCount].Length.QuadPart)
4182 ByteRangeList[ulByteRangeCount].Length.QuadPart =
4183 pExtent->FileOffset.QuadPart - ByteRangeList[ulByteRangeCount].FileOffset.QuadPart;
4189 // Having processed the current dirty extent, the following while loop
4190 // searches for the next clean gap between dirty extents.
4193 while ( pNextExtent && pNextExtent->FileOffset.QuadPart == pExtent->FileOffset.QuadPart + pExtent->Size)
4196 pExtent = pNextExtent;
4198 pNextExtent = (AFSExtent *)pExtent->DirtyList.fLink;
4202 // Having found the next gap, the ByteRangeList[] FileOffset is set to the start of the gap.
4203 // The Length is left at zero and will be assigned either when the for loop continues or
4204 // when the for loop exits.
4207 ByteRangeList[ulByteRangeCount].FileOffset.QuadPart = pExtent->FileOffset.QuadPart + pExtent->Size;
4211 // Assign the Length of the final clean range to match the file length.
4214 ByteRangeList[ulByteRangeCount].Length.QuadPart =
4215 pFcb->ObjectInformation->EndOfFile.QuadPart - ByteRangeList[ulByteRangeCount].FileOffset.QuadPart;
4217 (*pByteRangeList) = ByteRangeList;
4221 AFSReleaseResource( &pFcb->NPFcb->Specific.File.DirtyExtentsListLock);
4223 return ulByteRangeCount;
4228 AFSSetupMD5Hash( IN AFSFcb *Fcb,
4229 IN AFSExtent *StartExtent,
4230 IN ULONG ExtentsCount,
4231 IN void *SystemBuffer,
4232 IN LARGE_INTEGER *ByteOffset,
4236 NTSTATUS ntStatus = STATUS_SUCCESS;
4237 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
4238 AFSExtent *pExtent = StartExtent;
4239 AFSExtent *pNextExtent, *pCurrentExtent = NULL;
4241 char *pCurrentBuffer = (char *)SystemBuffer;
4242 char *pMD5Buffer = NULL;
4243 ULONG ulCurrentLen = 0;
4244 void *pExtentBuffer = NULL;
4245 LARGE_INTEGER liByteOffset;
4246 ULONG ulBytesRead = 0;
4251 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4252 AFS_TRACE_LEVEL_VERBOSE,
4253 "AFSSetupMD5Hash Acquiring Fcb extents lock %08lX SHARED %08lX\n",
4254 &Fcb->NPFcb->Specific.File.ExtentsResource,
4255 PsGetCurrentThread());
4257 AFSAcquireShared( &Fcb->NPFcb->Specific.File.ExtentsResource, TRUE);
4261 liByteOffset.QuadPart = ByteOffset->QuadPart;
4263 while( ulCount < ExtentsCount)
4266 RtlZeroMemory( pExtent->MD5,
4267 sizeof( pExtent->MD5));
4269 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
4271 if( liByteOffset.QuadPart == pExtent->FileOffset.QuadPart &&
4272 ByteCount < pExtent->Size)
4275 if( pExtentBuffer == NULL)
4278 pExtentBuffer = AFSExAllocatePoolWithTag( PagedPool,
4280 AFS_GENERIC_MEMORY_9_TAG);
4282 if( pExtentBuffer == NULL)
4289 RtlZeroMemory( pExtentBuffer,
4292 RtlCopyMemory( pExtentBuffer,
4296 pMD5Buffer = (char *)pExtentBuffer;
4298 ulCurrentLen = ByteCount;
4300 else if( liByteOffset.QuadPart != pExtent->FileOffset.QuadPart)
4303 pExtentBuffer = AFSExAllocatePoolWithTag( PagedPool,
4305 AFS_GENERIC_MEMORY_10_TAG);
4307 if( pExtentBuffer == NULL)
4313 RtlZeroMemory( pExtentBuffer,
4316 if( BooleanFlagOn( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE))
4320 RtlCopyMemory( pExtentBuffer,
4321 ((char *)AFSLibCacheBaseAddress + pExtent->CacheOffset.QuadPart),
4324 ASSERT( pExtent->CacheOffset.HighPart == 0);
4325 RtlCopyMemory( pExtentBuffer,
4326 ((char *)AFSLibCacheBaseAddress + pExtent->CacheOffset.LowPart),
4330 ulBytesRead = pExtent->Size;
4335 ntStatus = AFSReadCacheFile( pExtentBuffer,
4336 &pExtent->CacheOffset,
4340 if( !NT_SUCCESS( ntStatus))
4347 pMD5Buffer = (char *)pExtentBuffer;
4349 ulCurrentLen = min( ByteCount, pExtent->Size - (ULONG)(liByteOffset.QuadPart - pExtent->FileOffset.QuadPart));
4351 RtlCopyMemory( (void *)((char *)pExtentBuffer + (ULONG)(liByteOffset.QuadPart - pExtent->FileOffset.QuadPart)),
4358 ulCurrentLen = pExtent->Size;
4360 pMD5Buffer = pCurrentBuffer;
4363 AFSGenerateMD5( pMD5Buffer,
4367 pExtent = pNextExtent;
4371 ByteCount -= ulCurrentLen;
4373 pCurrentBuffer += ulCurrentLen;
4375 liByteOffset.QuadPart += ulCurrentLen;
4378 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4379 AFS_TRACE_LEVEL_VERBOSE,
4380 "AFSSetupMD5Hash Releasing Fcb extents lock %08lX SHARED %08lX\n",
4381 &Fcb->NPFcb->Specific.File.ExtentsResource,
4382 PsGetCurrentThread());
4385 __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
4390 "EXCEPTION - AFSSetupMD5Hash\n");
4393 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
4395 if( pExtentBuffer != NULL)
4398 AFSExFreePool( pExtentBuffer);