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( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
676 "EXCEPTION - AFSDoExtentsMapRegion\n");
678 AFSDumpTraceFilesFnc();
683 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
684 AFS_TRACE_LEVEL_VERBOSE,
685 "AFSDoExtentsMapRegion Releasing Fcb extent lock %08lX SHARED %08lX\n",
686 &Fcb->NPFcb->Specific.File.ExtentsResource,
687 PsGetCurrentThread());
689 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
698 AFSRequestExtentsAsync( IN AFSFcb *Fcb,
700 IN PLARGE_INTEGER Offset,
704 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
705 NTSTATUS ntStatus = STATUS_SUCCESS;
706 AFSExtent *pExtent = NULL;
707 AFSRequestExtentsCB request;
708 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
709 AFSExtent *pFirstExtent = NULL;
710 LARGE_INTEGER liAlignedOffset;
711 ULONG ulAlignedLength = 0;
712 BOOLEAN bRegionMapped = FALSE;
713 ULONGLONG ullProcessId = (ULONGLONG)PsGetCurrentProcessId();
718 ASSERT( !ExIsResourceAcquiredLite( &pNPFcb->Specific.File.ExtentsResource ));
721 // If the service set a failure on the file since the last
722 // CreateFile was issued, return it now.
725 if (!NT_SUCCESS( pNPFcb->Specific.File.ExtentsRequestStatus))
729 // If this isn't the same authgroup which caused the failure
730 // then try to request them again
733 if( RtlCompareMemory( &pNPFcb->Specific.File.ExtentsRequestAuthGroup,
735 sizeof( GUID)) == sizeof( GUID))
738 ntStatus = pNPFcb->Specific.File.ExtentsRequestStatus;
740 pNPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
742 RtlZeroMemory( &pNPFcb->Specific.File.ExtentsRequestAuthGroup,
745 try_return( ntStatus);
750 // Check if we are already mapped
753 bRegionMapped = AFSDoExtentsMapRegion( Fcb, Offset, Size, &pFirstExtent, &pExtent);
758 try_return( ntStatus = STATUS_SUCCESS);
762 // Align our request on extent size boundary
765 ulAlignedLength = Size;
767 liAlignedOffset = *Offset;
769 if( liAlignedOffset.QuadPart % pDevExt->Specific.RDR.CacheBlockSize != 0)
772 liAlignedOffset.QuadPart = (ULONGLONG)( (ULONGLONG)(liAlignedOffset.QuadPart / pDevExt->Specific.RDR.CacheBlockSize) * (ULONGLONG)pDevExt->Specific.RDR.CacheBlockSize);
774 ulAlignedLength += (ULONG)(Offset->QuadPart - liAlignedOffset.QuadPart);
777 if( ulAlignedLength % pDevExt->Specific.RDR.CacheBlockSize != 0)
780 ulAlignedLength = (ULONG)(((ulAlignedLength / pDevExt->Specific.RDR.CacheBlockSize) + 1) * pDevExt->Specific.RDR.CacheBlockSize);
783 RtlZeroMemory( &request,
784 sizeof( AFSRequestExtentsCB));
786 request.ByteOffset = liAlignedOffset;
787 request.Length = ulAlignedLength;
789 if( !AFSIsExtentRequestQueued( &Fcb->ObjectInformation->FileId,
794 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
795 AFS_TRACE_LEVEL_VERBOSE,
796 "AFSRequestExtentsAsync Request extents for fid %08lX-%08lX-%08lX-%08lX Offset %08lX Len %08lX Thread %08lX\n",
797 Fcb->ObjectInformation->FileId.Cell,
798 Fcb->ObjectInformation->FileId.Volume,
799 Fcb->ObjectInformation->FileId.Vnode,
800 Fcb->ObjectInformation->FileId.Unique,
801 request.ByteOffset.LowPart,
803 PsGetCurrentThread());
805 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS,
809 &Fcb->ObjectInformation->FileId,
811 sizeof( AFSRequestExtentsCB ),
815 if ( ntStatus == STATUS_ACCESS_DENIED)
820 ntStatus2 = AFSRetrieveValidAuthGroup( Fcb,
825 if ( NT_SUCCESS( ntStatus2) &&
826 RtlCompareMemory( &stAuthGroup,
828 sizeof( GUID)) != sizeof( GUID))
831 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS,
835 &Fcb->ObjectInformation->FileId,
837 sizeof( AFSRequestExtentsCB ),
843 if( NT_SUCCESS( ntStatus))
846 KeClearEvent( &pNPFcb->Specific.File.ExtentsRequestComplete );
852 KeClearEvent( &pNPFcb->Specific.File.ExtentsRequestComplete );
864 AFSProcessExtentsResult( IN AFSFcb *Fcb,
866 IN AFSFileExtentCB *Result)
868 NTSTATUS ntStatus = STATUS_SUCCESS;
869 AFSFileExtentCB *pFileExtents = Result;
872 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
873 ULONG fileExtentsUsed = 0;
874 BOOLEAN bFoundExtent = FALSE;
875 LIST_ENTRY *pSkipEntries[AFS_NUM_EXTENT_LISTS] = { 0 };
876 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
880 // Grab the extents exclusive for the duration
883 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
884 AFS_TRACE_LEVEL_VERBOSE,
885 "AFSProcessExtentsResult Acquiring Fcb extent lock %08lX EXCL %08lX\n",
886 &pNPFcb->Specific.File.ExtentsResource,
887 PsGetCurrentThread());
889 AFSAcquireExcl( &pNPFcb->Specific.File.ExtentsResource, TRUE );
895 // Find where to put the extents
897 for (ULONG i = AFS_EXTENTS_LIST; i < AFS_NUM_EXTENT_LISTS; i++)
900 pSkipEntries[i] = Fcb->Specific.File.ExtentsLists[i].Flink;
903 le = pSkipEntries[AFS_EXTENTS_LIST];
905 if (le == &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
908 // No extents. Insert at head of list (which is where the skip lists point!)
912 else if (0 != pFileExtents->FileOffset.QuadPart)
915 // We want to find the best extents immediately *behind* this offset
917 LARGE_INTEGER offset = pFileExtents->FileOffset;
920 // Ask in the top skip list first, then work down
922 for (LONG i = AFS_NUM_EXTENT_LISTS-1; i >= AFS_EXTENTS_LIST; i--)
924 pExtent = ExtentForOffsetInList( Fcb,
932 // No dice. Header has to become the head of the list
934 pSkipEntries[i] = &Fcb->Specific.File.ExtentsLists[i];
936 // And as a loop invariant we should never have found an extent
938 ASSERT(!bFoundExtent);
943 // pExtent is where to start to insert at this level
945 pSkipEntries[i] = &pExtent->Lists[i];
948 // And also where to start to look at the next level
951 if (i > AFS_EXTENTS_LIST)
953 pSkipEntries[i-1] = &pExtent->Lists[i-1];
961 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
966 le = pExtent->Lists[AFS_EXTENTS_LIST].Blink;
972 // Looking at offset 0, so we must start at the beginning
975 pExtent = ExtentFor(le, AFS_EXTENTS_LIST);
979 // And set up the skip lists
982 for (ULONG i = AFS_EXTENTS_LIST; i < AFS_NUM_EXTENT_LISTS; i++)
984 pSkipEntries[i] = &Fcb->Specific.File.ExtentsLists[i];
988 while (fileExtentsUsed < Count)
992 // Loop invariant - le points to where to insert after and
993 // pExtent points to le->fLink
996 ASSERT (NULL == pExtent ||
997 le->Flink == &pExtent->Lists[AFS_EXTENTS_LIST]);
999 if (NULL == pExtent ||
1000 pExtent->FileOffset.QuadPart > pFileExtents->FileOffset.QuadPart)
1003 // We need to insert a new extent at le. Start with
1004 // some sanity check on spanning
1006 if (NULL != pExtent &&
1007 ((pFileExtents->FileOffset.QuadPart + pFileExtents->Length) >
1008 pExtent->FileOffset.QuadPart))
1011 // File Extents overlaps pExtent
1013 ASSERT( (pFileExtents->FileOffset.QuadPart + pFileExtents->Length) <=
1014 pExtent->FileOffset.QuadPart);
1016 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1020 // File offset is entirely in front of this extent. Create
1021 // a new one (remember le is the previous list entry)
1023 pExtent = (AFSExtent *) AFSExAllocatePoolWithTag( NonPagedPool,
1026 if (NULL == pExtent)
1029 try_return (ntStatus = STATUS_INSUFFICIENT_RESOURCES );
1032 RtlZeroMemory( pExtent, sizeof( AFSExtent ));
1034 pExtent->FileOffset = pFileExtents->FileOffset;
1035 pExtent->CacheOffset = pFileExtents->CacheOffset;
1036 pExtent->Size = pFileExtents->Length;
1038 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1039 AFS_TRACE_LEVEL_VERBOSE,
1040 "AFSProcessExtentsResult Received extent for fid %08lX-%08lX-%08lX-%08lX File Offset %I64X Cache Offset %I64X Len %08lX\n",
1041 Fcb->ObjectInformation->FileId.Cell,
1042 Fcb->ObjectInformation->FileId.Volume,
1043 Fcb->ObjectInformation->FileId.Vnode,
1044 Fcb->ObjectInformation->FileId.Unique,
1045 pFileExtents->FileOffset.QuadPart,
1046 pFileExtents->CacheOffset.QuadPart,
1047 pFileExtents->Length);
1049 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, (LONG)(pExtent->Size/1024));
1051 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, (LONG)(pExtent->Size/1024));
1053 lCount = InterlockedIncrement( &Fcb->Specific.File.ExtentCount);
1055 lCount = InterlockedIncrement( &pControlDevExt->Specific.Control.ExtentCount);
1060 KeClearEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent);
1066 InsertHeadList(le, &pExtent->Lists[AFS_EXTENTS_LIST]);
1067 ASSERT(le->Flink == &pExtent->Lists[AFS_EXTENTS_LIST]);
1068 ASSERT(0 == (pExtent->FileOffset.LowPart & ExtentsMasks[AFS_EXTENTS_LIST]));
1071 // Do not move the cursor - we will do it next time
1075 // And into the (upper) skip lists - Again, do not move the cursor
1077 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1079 if (0 == (pExtent->FileOffset.LowPart & ExtentsMasks[i]))
1081 InsertHeadList(pSkipEntries[i], &pExtent->Lists[i]);
1082 #if AFS_VALIDATE_EXTENTS
1083 VerifyExtentsLists(Fcb);
1088 else if (pExtent->FileOffset.QuadPart == pFileExtents->FileOffset.QuadPart)
1091 if (pExtent->Size != pFileExtents->Length)
1094 ASSERT (pExtent->Size == pFileExtents->Length);
1096 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1100 // Move both cursors forward.
1102 // First the extent pointer
1105 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1108 // Then the skip lists cursors forward if needed
1110 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1112 if (0 == (pExtent->FileOffset.LowPart & ExtentsMasks[i]))
1115 // Check sanity before
1117 #if AFS_VALIDATE_EXTENTS
1118 VerifyExtentsLists(Fcb);
1122 // Skip list should point to us
1124 //ASSERT(pSkipEntries[i] == &pExtent->Lists[i]);
1126 // Move forward cursor
1128 pSkipEntries[i] = pSkipEntries[i]->Flink;
1130 // Check sanity before
1132 #if AFS_VALIDATE_EXTENTS
1133 VerifyExtentsLists(Fcb);
1139 // And then the cursor in the supplied array
1145 // setup pExtent if there is one
1147 if (le->Flink != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
1149 pExtent = NextExtent( pExtent, AFS_EXTENTS_LIST ) ;
1159 ASSERT( pExtent->FileOffset.QuadPart < pFileExtents->FileOffset.QuadPart );
1162 // Sanity check on spanning
1164 if ((pExtent->FileOffset.QuadPart + pExtent->Size) >
1165 pFileExtents->FileOffset.QuadPart)
1168 ASSERT( (pExtent->FileOffset.QuadPart + pExtent->Size) <=
1169 pFileExtents->FileOffset.QuadPart);
1171 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1175 // Move le and pExtent forward
1177 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1181 // Then the check the skip lists cursors
1183 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1185 if (0 == (pFileExtents->FileOffset.LowPart & ExtentsMasks[i]))
1189 // - empty list (pSkipEntries[i]->Flink == pSkipEntries[i]->Flink == fcb->lists[i]
1190 // - We are the last on the list (pSkipEntries[i]->Flink == fcb->lists[i])
1191 // - We are not the last on the list. In that case we have to be strictly less than
1193 if (pSkipEntries[i]->Flink != &Fcb->Specific.File.ExtentsLists[i]) {
1195 AFSExtent *otherExtent = ExtentFor(pSkipEntries[i]->Flink, i);
1196 ASSERT(pFileExtents->FileOffset.QuadPart < otherExtent->FileOffset.QuadPart);
1203 // setup pExtent if there is one
1206 if (le->Flink != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
1208 pExtent = NextExtent( pExtent, AFS_EXTENTS_LIST ) ;
1218 // All done, signal that we are done drop the lock, exit
1223 if( !NT_SUCCESS( ntStatus))
1227 // If we failed the service is going to drop all extents so trim away the
1231 AFSTrimSpecifiedExtents( Fcb,
1236 #if AFS_VALIDATE_EXTENTS
1237 VerifyExtentsLists(Fcb);
1240 KeSetEvent( &pNPFcb->Specific.File.ExtentsRequestComplete,
1244 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1245 AFS_TRACE_LEVEL_VERBOSE,
1246 "AFSProcessExtentsResult Releasing Fcb extent lock %08lX EXCL %08lX\n",
1247 &pNPFcb->Specific.File.ExtentsResource,
1248 PsGetCurrentThread());
1250 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
1257 AFSProcessSetFileExtents( IN AFSSetFileExtentsCB *SetExtents )
1259 AFSFcb *pFcb = NULL;
1260 AFSVolumeCB *pVolumeCB = NULL;
1261 NTSTATUS ntStatus = STATUS_SUCCESS;
1262 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1263 ULONGLONG ullIndex = 0;
1264 AFSObjectInfoCB *pObjectInfo = NULL;
1270 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1271 AFS_TRACE_LEVEL_VERBOSE,
1272 "AFSProcessSetFileExtents Acquiring RDR VolumeTreeLock lock %08lX SHARED %08lX\n",
1273 &pDevExt->Specific.RDR.VolumeTreeLock,
1274 PsGetCurrentThread());
1276 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
1278 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1279 AFS_TRACE_LEVEL_VERBOSE,
1280 "AFSProcessSetFileExtents Set extents for fid %08lX-%08lX-%08lX-%08lX\n",
1281 SetExtents->FileId.Cell,
1282 SetExtents->FileId.Volume,
1283 SetExtents->FileId.Vnode,
1284 SetExtents->FileId.Unique);
1287 // Locate the volume node
1290 ullIndex = AFSCreateHighIndex( &SetExtents->FileId);
1292 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
1294 (AFSBTreeEntry **)&pVolumeCB);
1296 if( pVolumeCB != NULL)
1299 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1300 AFS_TRACE_LEVEL_VERBOSE,
1301 "AFSProcessSetFileExtents Acquiring VolumeRoot FileIDTree.TreeLock lock %08lX SHARED %08lX\n",
1302 pVolumeCB->ObjectInfoTree.TreeLock,
1303 PsGetCurrentThread());
1305 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1308 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
1310 if( !NT_SUCCESS( ntStatus) ||
1314 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1315 AFS_TRACE_LEVEL_ERROR,
1316 "AFSProcessSetFileExtents Set extents for fid %08lX-%08lX-%08lX-%08lX Failed to locate volume Status %08lX\n",
1317 SetExtents->FileId.Cell,
1318 SetExtents->FileId.Volume,
1319 SetExtents->FileId.Vnode,
1320 SetExtents->FileId.Unique,
1323 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1326 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1329 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1332 // Now locate the Object in this volume
1335 ullIndex = AFSCreateLowIndex( &SetExtents->FileId);
1337 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
1339 (AFSBTreeEntry **)&pObjectInfo);
1341 if( pObjectInfo != NULL)
1345 // Reference the node so it won't be torn down
1348 lCount = InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
1350 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1351 AFS_TRACE_LEVEL_VERBOSE,
1352 "AFSProcessSetFileExtents Increment count on object %08lX Cnt %d\n",
1357 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1359 if( !NT_SUCCESS( ntStatus) ||
1360 pObjectInfo == NULL)
1363 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1364 AFS_TRACE_LEVEL_ERROR,
1365 "AFSProcessSetFileExtents Set extents for hash %I64X fid %08lX-%08lX-%08lX-%08lX Failed to locate file in volume %08lX\n",
1367 SetExtents->FileId.Cell,
1368 SetExtents->FileId.Volume,
1369 SetExtents->FileId.Vnode,
1370 SetExtents->FileId.Unique,
1373 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1376 pFcb = pObjectInfo->Fcb;
1379 // If we have a result failure then don't bother trying to set the extents
1382 if( SetExtents->ResultStatus != STATUS_SUCCESS)
1385 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1386 AFS_TRACE_LEVEL_ERROR,
1387 "AFSProcessSetFileExtents Set extents failure fid %08lX-%08lX-%08lX-%08lX ResultStatus %08lX\n",
1388 SetExtents->FileId.Cell,
1389 SetExtents->FileId.Volume,
1390 SetExtents->FileId.Vnode,
1391 SetExtents->FileId.Unique,
1392 SetExtents->ResultStatus);
1394 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1395 AFS_TRACE_LEVEL_VERBOSE,
1396 "AFSProcessSetFileExtents Acquiring Fcb extents lock %08lX EXCL %08lX\n",
1397 &pFcb->NPFcb->Specific.File.ExtentsResource,
1398 PsGetCurrentThread());
1400 AFSAcquireExcl( &pFcb->NPFcb->Specific.File.ExtentsResource,
1403 pFcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_CANCELLED;
1405 KeSetEvent( &pFcb->NPFcb->Specific.File.ExtentsRequestComplete,
1409 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1410 AFS_TRACE_LEVEL_VERBOSE,
1411 "AFSProcessSetFileExtents Releasing Fcb extent lock %08lX EXCL %08lX\n",
1412 &pFcb->NPFcb->Specific.File.ExtentsResource,
1413 PsGetCurrentThread());
1415 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
1417 try_return( ntStatus);
1420 ntStatus = AFSProcessExtentsResult ( pFcb,
1421 SetExtents->ExtentCount,
1422 SetExtents->FileExtents );
1426 if( pObjectInfo != NULL)
1429 lCount = InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
1431 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1432 AFS_TRACE_LEVEL_VERBOSE,
1433 "AFSProcessSetFileExtents Decrement count on object %08lX Cnt %d\n",
1443 // Helper fuctions for Usermode initiation of release of extents
1446 AFSReleaseSpecifiedExtents( IN AFSReleaseFileExtentsCB *Extents,
1448 OUT AFSFileExtentCB *FileExtents,
1449 IN ULONG BufferSize,
1450 OUT ULONG *ExtentCount,
1451 OUT BOOLEAN *DirtyExtents)
1456 ULONG ulExtentCount = 0;
1457 NTSTATUS ntStatus = STATUS_SUCCESS;
1458 BOOLEAN bReleaseAll = FALSE;
1459 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1464 ASSERT( ExIsResourceAcquiredExclusiveLite( &Fcb->NPFcb->Specific.File.ExtentsResource));
1466 if (BufferSize < (Extents->ExtentCount * sizeof( AFSFileExtentCB)))
1469 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1470 AFS_TRACE_LEVEL_VERBOSE,
1471 "AFSReleaseSpecifiedExtents Buffer too small\n");
1473 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL);
1476 RtlZeroMemory( FileExtents, BufferSize);
1479 *DirtyExtents = FALSE;
1482 // iterate until we have dealt with all we were asked for or
1483 // are at the end of the list. Note that this deals (albeit
1484 // badly) with out of order extents
1487 pExtent = AFSExtentForOffset( Fcb,
1488 &Extents->FileExtents[0].FileOffset,
1491 if (NULL == pExtent)
1493 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1497 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1501 if( BooleanFlagOn( Extents->Flags, AFS_RELEASE_EXTENTS_FLAGS_RELEASE_ALL) ||
1502 ( Extents->FileId.Cell == 0 &&
1503 Extents->FileId.Volume == 0 &&
1504 Extents->FileId.Vnode == 0 &&
1505 Extents->FileId.Unique == 0))
1511 while( le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST] &&
1512 ulExtentCount < Extents->ExtentCount)
1516 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
1521 if( pExtent->FileOffset.QuadPart < Extents->FileExtents[ulExtentCount].FileOffset.QuadPart)
1524 // Skip forward through the extent list until we get
1525 // to the one we want
1531 else if (pExtent->FileOffset.QuadPart > Extents->FileExtents[ulExtentCount].FileOffset.QuadPart)
1534 // We don't have the extent asked for so return UNKNOWN
1537 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1538 AFS_TRACE_LEVEL_VERBOSE,
1539 "AFSReleaseSpecifiedExtents Located UNKNOWN extent Offset %I64X Len %08lX\n",
1540 Extents->FileExtents[ulExtentCount].FileOffset.QuadPart,
1541 Extents->FileExtents[ulExtentCount].Length);
1543 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_UNKNOWN;
1545 FileExtents[*ExtentCount].Length = 0;
1546 FileExtents[*ExtentCount].CacheOffset.QuadPart = 0;
1547 FileExtents[*ExtentCount].FileOffset = Extents->FileExtents[ulExtentCount].FileOffset;
1549 *ExtentCount = (*ExtentCount) + 1;
1554 // Reset where we are looking
1557 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1561 else if( pExtent->ActiveCount > 0)
1564 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1565 AFS_TRACE_LEVEL_VERBOSE,
1566 "AFSReleaseSpecifiedExtents Located IN_USE extent Offset %I64X Len %08lX\n",
1567 Extents->FileExtents[ulExtentCount].FileOffset.QuadPart,
1568 Extents->FileExtents[ulExtentCount].Length);
1570 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_IN_USE;
1572 FileExtents[*ExtentCount].Length = 0;
1573 FileExtents[*ExtentCount].CacheOffset.QuadPart = 0;
1574 FileExtents[*ExtentCount].FileOffset = Extents->FileExtents[ulExtentCount].FileOffset;
1576 *ExtentCount = (*ExtentCount) + 1;
1581 // Reset where we are looking
1584 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1593 // If the extent is currently active then skip it
1596 if( pExtent->ActiveCount > 0)
1605 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_RELEASE;
1607 FileExtents[*ExtentCount].Length = pExtent->Size;
1608 FileExtents[*ExtentCount].DirtyLength = pExtent->Size;
1609 FileExtents[*ExtentCount].DirtyOffset = 0;
1610 FileExtents[*ExtentCount].CacheOffset = pExtent->CacheOffset;
1611 FileExtents[*ExtentCount].FileOffset = pExtent->FileOffset;
1613 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1614 AFS_TRACE_LEVEL_VERBOSE,
1615 "AFSReleaseSpecifiedExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
1617 Fcb->ObjectInformation->FileId.Cell,
1618 Fcb->ObjectInformation->FileId.Volume,
1619 Fcb->ObjectInformation->FileId.Vnode,
1620 Fcb->ObjectInformation->FileId.Unique,
1621 FileExtents[*ExtentCount].FileOffset.QuadPart,
1622 FileExtents[*ExtentCount].Length);
1624 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
1627 AFSAcquireExcl( &Fcb->NPFcb->Specific.File.DirtyExtentsListLock,
1630 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
1633 AFSRemoveEntryDirtyList( Fcb,
1636 FileExtents[*ExtentCount].Flags |= AFS_EXTENT_FLAG_DIRTY;
1638 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
1640 *DirtyExtents = TRUE;
1643 AFSReleaseResource( &Fcb->NPFcb->Specific.File.DirtyExtentsListLock);
1647 // move forward all three cursors
1651 *ExtentCount = (*ExtentCount) + 1;
1656 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
1658 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
1660 RemoveEntryList( &pExtent->Lists[i] );
1664 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
1666 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
1671 AFSExFreePool( pExtent);
1673 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
1675 lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount);
1680 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
1695 AFSFindFcbToClean(ULONG IgnoreTime, AFSFcb *LastFcb, BOOLEAN Block)
1698 AFSFcb *pFcb = NULL;
1699 AFSVolumeCB *pVolumeCB = NULL;
1700 AFSDeviceExt *pRDRDeviceExt = NULL;
1701 AFSDeviceExt *pControlDeviceExt = NULL;
1702 BOOLEAN bLocatedEntry = FALSE;
1703 AFSObjectInfoCB *pCurrentObject = NULL;
1704 BOOLEAN bReleaseVolumeListLock = FALSE;
1707 pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1708 pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1710 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1711 AFS_TRACE_LEVEL_VERBOSE,
1712 "AFSFindFcbToClean Acquiring RDR VolumeListLock lock %08lX SHARED %08lX\n",
1713 &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1714 PsGetCurrentThread());
1716 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1719 bReleaseVolumeListLock = TRUE;
1721 pVolumeCB = pRDRDeviceExt->Specific.RDR.VolumeListHead;
1723 while( pVolumeCB != NULL)
1727 // The Volume list may move under our feet. Lock it.
1730 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1731 AFS_TRACE_LEVEL_VERBOSE,
1732 "AFSFindFcbToClean Acquiring VolumeRoot ObjectInfoTree lock %08lX SHARED %08lX\n",
1733 pVolumeCB->ObjectInfoTree.TreeLock,
1734 PsGetCurrentThread());
1736 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1738 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1740 bReleaseVolumeListLock = FALSE;
1742 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1745 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1747 if( NULL == LastFcb)
1750 pCurrentObject = pVolumeCB->ObjectInfoListHead;
1755 pCurrentObject = (AFSObjectInfoCB *)LastFcb->ObjectInformation->ListEntry.fLink;
1760 while( pCurrentObject != NULL)
1763 pFcb = (AFSFcb *)pCurrentObject->Fcb;
1766 // If the FCB is a candidate we try to lock it (but without waiting - which
1767 // means we are deadlock free
1771 pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
1777 AFSLockForExtentsTrim( pFcb);
1782 if( !AFSLockForExtentsTrimNoWait( pFcb))
1785 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1794 // Need to be sure there are no current flushes in the queue
1797 if( pFcb->Specific.File.ExtentCount == 0)
1800 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1801 AFS_TRACE_LEVEL_VERBOSE,
1802 "AFSFindFcbToClean Releasing Fcb extent lock %08lX thread %08lX\n",
1803 &pFcb->NPFcb->Specific.File.ExtentsResource,
1804 PsGetCurrentThread());
1806 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
1808 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1815 if( pFcb->Specific.File.QueuedFlushCount > 0)
1818 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1819 AFS_TRACE_LEVEL_VERBOSE,
1820 "AFSFindFcbToClean Releasing Fcb extent lock %08lX thread %08lX\n",
1821 &pFcb->NPFcb->Specific.File.ExtentsResource,
1822 PsGetCurrentThread());
1824 AFSReleaseResource(&pFcb->NPFcb->Specific.File.ExtentsResource);
1828 AFSWaitOnQueuedFlushes( pFcb);
1833 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1841 if( pFcb->OpenHandleCount > 0)
1844 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1845 AFS_TRACE_LEVEL_VERBOSE,
1846 "AFSFindFcbToClean Releasing Fcb extent lock %08lX thread %08lX\n",
1847 &pFcb->NPFcb->Specific.File.ExtentsResource,
1848 PsGetCurrentThread());
1850 AFSReleaseResource(&pFcb->NPFcb->Specific.File.ExtentsResource);
1852 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1860 // A hit a very palpable hit. Pin it
1863 lCount = InterlockedIncrement( &pCurrentObject->ObjectReferenceCount);
1865 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1866 AFS_TRACE_LEVEL_VERBOSE,
1867 "AFSFindFcbToClean Increment count on Fcb %08lX Cnt %d\n",
1871 bLocatedEntry = TRUE;
1876 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1881 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1888 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1891 bReleaseVolumeListLock = TRUE;
1893 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1896 if( bReleaseVolumeListLock)
1899 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1906 AFSProcessExtentFailure( PIRP Irp)
1908 AFSExtentFailureCB *pFailureCB = NULL;
1909 NTSTATUS ntStatus = STATUS_SUCCESS;
1910 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
1911 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1912 AFSVolumeCB *pVolumeCB = NULL;
1913 ULONGLONG ullIndex = 0;
1914 AFSObjectInfoCB *pObjectInfo = NULL;
1919 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSExtentFailureCB))
1922 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1923 AFS_TRACE_LEVEL_ERROR,
1924 "AFSProcessExtentFailure Input buffer too small\n");
1926 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1929 pFailureCB = (AFSExtentFailureCB *)Irp->AssociatedIrp.SystemBuffer;
1931 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1932 AFS_TRACE_LEVEL_ERROR,
1933 "AFSProcessExtentFailure Service Reports Failure fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1934 pFailureCB->FileId.Cell,
1935 pFailureCB->FileId.Volume,
1936 pFailureCB->FileId.Vnode,
1937 pFailureCB->FileId.Unique,
1938 pFailureCB->FailureStatus);
1940 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
1943 // Locate the volume node
1946 ullIndex = AFSCreateHighIndex( &pFailureCB->FileId);
1948 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
1950 (AFSBTreeEntry **)&pVolumeCB);
1952 if( pVolumeCB != NULL)
1955 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1956 AFS_TRACE_LEVEL_VERBOSE,
1957 "AFSProcessExtentFailure Acquiring VolumeRoot FileIDTree.TreeLock lock %08lX SHARED %08lX\n",
1958 pVolumeCB->ObjectInfoTree.TreeLock,
1959 PsGetCurrentThread());
1961 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1964 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
1966 if( !NT_SUCCESS( ntStatus) ||
1970 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1971 AFS_TRACE_LEVEL_ERROR,
1972 "AFSProcessExtentFailure Invalid volume index %I64X status %08X\n",
1973 ullIndex, ntStatus);
1975 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1978 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1981 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1984 // Now locate the Object in this volume
1987 ullIndex = AFSCreateLowIndex( &pFailureCB->FileId);
1989 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
1991 (AFSBTreeEntry **)&pObjectInfo);
1993 if( pObjectInfo != NULL &&
1994 pObjectInfo->Fcb != NULL)
1998 // Reference the node so it won't be torn down
2001 lCount = InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
2003 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2004 AFS_TRACE_LEVEL_VERBOSE,
2005 "AFSProcessExtentFailure Increment count on object %08lX Cnt %d\n",
2010 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2012 if( !NT_SUCCESS( ntStatus) ||
2013 pObjectInfo == NULL ||
2014 pObjectInfo->Fcb == NULL)
2017 if( pObjectInfo == NULL)
2019 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2020 AFS_TRACE_LEVEL_ERROR,
2021 "AFSProcessExtentFailure Invalid file index %I64X\n",
2026 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2027 AFS_TRACE_LEVEL_ERROR,
2028 "AFSProcessExtentFailure Fcb dealocated for %I64X\n",
2032 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2035 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2036 AFS_TRACE_LEVEL_VERBOSE,
2037 "AFSProcessExtentFailure Acquiring Fcb extent lock %08lX EXCL %08lX\n",
2038 &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2039 PsGetCurrentThread());
2041 AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2044 pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestStatus = pFailureCB->FailureStatus;
2046 RtlCopyMemory( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2047 &pFailureCB->AuthGroup,
2050 KeSetEvent( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
2054 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2055 AFS_TRACE_LEVEL_VERBOSE,
2056 "AFSProcessExtentFailure Releasing Fcb extent lock %08lX EXCL %08lX\n",
2057 &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2058 PsGetCurrentThread());
2060 AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource);
2062 lCount = InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
2064 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2065 AFS_TRACE_LEVEL_VERBOSE,
2066 "AFSProcessExtentFailure Decrement count on object %08lX Cnt %d\n",
2079 AFSProcessReleaseFileExtents( IN PIRP Irp)
2081 NTSTATUS ntStatus = STATUS_SUCCESS;
2082 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2083 PFILE_OBJECT pFileObject = pIrpSp->FileObject;
2084 AFSFcb *pFcb = NULL;
2085 AFSVolumeCB *pVolumeCB = NULL;
2086 AFSDeviceExt *pDevExt;
2087 AFSReleaseFileExtentsCB *pExtents;
2088 AFSReleaseFileExtentsResultCB *pResult = NULL;
2089 AFSReleaseFileExtentsResultFileCB *pFile = NULL;
2091 ULONGLONG ullIndex = 0;
2092 AFSObjectInfoCB *pObjectInfo = NULL;
2093 BOOLEAN bLocked = FALSE;
2094 BOOLEAN bDirtyExtents = FALSE;
2101 pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2103 pExtents = (AFSReleaseFileExtentsCB*) Irp->AssociatedIrp.SystemBuffer;
2105 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2106 sizeof( AFSReleaseFileExtentsCB))
2109 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2110 AFS_TRACE_LEVEL_ERROR,
2111 "AFSProcessReleaseFileExtents INPUT Buffer too small\n");
2113 try_return( ntStatus = STATUS_INVALID_PARAMETER );
2116 if ( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength <
2117 sizeof(AFSReleaseFileExtentsResultCB))
2120 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2121 AFS_TRACE_LEVEL_ERROR,
2122 "AFSProcessReleaseFileExtents OUTPUT Buffer too small [1]\n");
2125 // Must have space for one extent in one file
2128 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL);
2131 if (pExtents->ExtentCount == 0)
2134 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2135 AFS_TRACE_LEVEL_ERROR,
2136 "AFSProcessReleaseFileExtents Extent count zero\n");
2138 try_return( ntStatus = STATUS_INVALID_PARAMETER);
2141 if (pExtents->FileId.Cell != 0 ||
2142 pExtents->FileId.Volume != 0 ||
2143 pExtents->FileId.Vnode != 0 ||
2144 pExtents->FileId.Unique != 0)
2147 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2148 AFS_TRACE_LEVEL_VERBOSE,
2149 "AFSProcessReleaseFileExtents Processing FID %08lX:%08lX:%08lX:%08lX\n",
2150 pExtents->FileId.Cell,
2151 pExtents->FileId.Volume,
2152 pExtents->FileId.Vnode,
2153 pExtents->FileId.Unique);
2155 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2156 ( FIELD_OFFSET( AFSReleaseFileExtentsCB, ExtentCount) + sizeof(ULONG)) ||
2157 pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2158 ( FIELD_OFFSET( AFSReleaseFileExtentsCB, ExtentCount) + sizeof(ULONG) +
2159 sizeof (AFSFileExtentCB) * pExtents->ExtentCount))
2162 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2163 AFS_TRACE_LEVEL_ERROR,
2164 "AFSProcessReleaseFileExtents Buffer too small for FID %08lX:%08lx:%08lX:%08lX\n",
2165 pExtents->FileId.Cell,
2166 pExtents->FileId.Volume,
2167 pExtents->FileId.Vnode,
2168 pExtents->FileId.Unique);
2170 try_return( ntStatus = STATUS_INVALID_PARAMETER );
2173 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2174 AFS_TRACE_LEVEL_VERBOSE,
2175 "AFSProcessReleaseFileExtents Acquiring RDR VolumeTreeLock lock %08lX SHARED %08lX\n",
2176 &pDevExt->Specific.RDR.VolumeTreeLock,
2177 PsGetCurrentThread());
2179 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
2182 // Locate the volume node
2185 ullIndex = AFSCreateHighIndex( &pExtents->FileId);
2187 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
2189 (AFSBTreeEntry **)&pVolumeCB);
2191 if( pVolumeCB != NULL)
2194 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2195 AFS_TRACE_LEVEL_VERBOSE,
2196 "AFSProcessReleaseFileExtents Acquiring VolumeRoot FileIDTree.TreeLock lock %08lX SHARED %08lX\n",
2197 pVolumeCB->ObjectInfoTree.TreeLock,
2198 PsGetCurrentThread());
2200 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
2203 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
2205 if( !NT_SUCCESS( ntStatus) ||
2209 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2210 AFS_TRACE_LEVEL_ERROR,
2211 "AFSProcessReleaseFileExtents Invalid volume index %I64X status %08X\n",
2212 ullIndex, ntStatus);
2214 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2217 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
2220 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
2223 // Now locate the Object in this volume
2226 ullIndex = AFSCreateLowIndex( &pExtents->FileId);
2228 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
2230 (AFSBTreeEntry **)&pObjectInfo);
2232 if( pObjectInfo != NULL)
2236 // Reference the node so it won't be torn down
2239 lCount = InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
2241 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2242 AFS_TRACE_LEVEL_VERBOSE,
2243 "AFSProcessReleaseFileExtents Increment count on object %08lX Cnt %d\n",
2248 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2250 if( !NT_SUCCESS( ntStatus) ||
2251 pObjectInfo == NULL)
2254 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2255 AFS_TRACE_LEVEL_ERROR,
2256 "AFSProcessReleaseFileExtents Invalid file index %I64X\n",
2259 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2262 pFcb = pObjectInfo->Fcb;
2267 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2268 AFS_TRACE_LEVEL_ERROR,
2269 "AFSProcessReleaseFileExtents Fcb not initialied (NO EXTENTS) for FID %08lX:%08lx:%08lX:%08lX\n",
2270 pExtents->FileId.Cell,
2271 pExtents->FileId.Volume,
2272 pExtents->FileId.Vnode,
2273 pExtents->FileId.Unique);
2275 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2278 AFSLockForExtentsTrim( pFcb );
2286 // Locate an Fcb to trim down
2289 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2290 AFS_TRACE_LEVEL_VERBOSE,
2291 "AFSProcessReleaseFileExtents Searching for a Fcb to Trim Down\n");
2293 pFcb = AFSFindFcbToClean( 0, NULL, FALSE);
2298 pFcb = AFSFindFcbToClean( 0, NULL, TRUE);
2304 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2305 AFS_TRACE_LEVEL_ERROR,
2306 "AFSProcessReleaseFileExtents Failed to locate Fcb for release ...\n");
2308 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2311 pObjectInfo = pFcb->ObjectInformation;
2317 // Allocate a scratch buffer to move in the extent information
2320 ulSz = (pExtents->ExtentCount-1) * sizeof(AFSFileExtentCB);
2321 ulSz += sizeof(AFSReleaseFileExtentsResultCB);
2323 if (ulSz > pIrpSp->Parameters.DeviceIoControl.OutputBufferLength)
2325 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2326 AFS_TRACE_LEVEL_ERROR,
2327 "AFSProcessReleaseFileExtents OUTPUT Buffer too small [2]\n");
2329 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL );
2332 pResult = (AFSReleaseFileExtentsResultCB*) AFSExAllocatePoolWithTag( PagedPool,
2334 AFS_EXTENTS_RESULT_TAG);
2335 if (NULL == pResult)
2338 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2339 AFS_TRACE_LEVEL_ERROR,
2340 "AFSProcessReleaseFileExtents Failed to allocate result block\n");
2342 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2346 // Set up the header (for an array of one)
2348 pResult->FileCount = 1;
2349 pResult->Flags = AFS_EXTENT_FLAG_RELEASE;
2350 ulSz -= FIELD_OFFSET(AFSReleaseFileExtentsResultCB, Files);
2353 // Setup the first (and only) file
2355 pFile = pResult->Files;
2356 pFile->FileId = pObjectInfo->FileId;
2357 pFile->Flags = AFS_EXTENT_FLAG_RELEASE;
2360 // Stash away the auth group
2363 RtlZeroMemory( &stAuthGroup,
2366 ntStatus = AFSRetrieveValidAuthGroup( pFcb,
2371 if( !NT_SUCCESS( ntStatus))
2373 try_return( ntStatus);
2376 RtlCopyMemory( &pFile->AuthGroup,
2381 // Update the metadata for this call
2384 pFile->AllocationSize = pFcb->ObjectInformation->EndOfFile;
2385 pFile->CreateTime = pFcb->ObjectInformation->CreationTime;
2386 pFile->ChangeTime = pFcb->ObjectInformation->ChangeTime;
2387 pFile->LastAccessTime = pFcb->ObjectInformation->LastAccessTime;
2388 pFile->LastWriteTime = pFcb->ObjectInformation->LastWriteTime;
2390 ulSz -= FIELD_OFFSET(AFSReleaseFileExtentsResultFileCB, FileExtents);
2392 ntStatus = AFSReleaseSpecifiedExtents( pExtents,
2396 &pFile->ExtentCount,
2399 if (!NT_SUCCESS(ntStatus))
2402 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2403 AFS_TRACE_LEVEL_ERROR,
2404 "AFSProcessReleaseFileExtents Failed to release extents Status %08lX\n",
2407 try_return( ntStatus );
2410 if( pExtents->ExtentCount == 0)
2413 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2414 AFS_TRACE_LEVEL_WARNING,
2415 "AFSProcessReleaseFileExtents Failed to release ANY extents\n");
2418 ulSz = sizeof(AFSReleaseFileExtentsResultCB);
2420 if( pExtents->ExtentCount > 0)
2422 ulSz += ((pExtents->ExtentCount-1) * sizeof(AFSFileExtentCB));
2425 RtlCopyMemory( Irp->AssociatedIrp.SystemBuffer,
2434 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2435 AFS_TRACE_LEVEL_VERBOSE,
2436 "AFSProcessReleaseFileExtents Releasing Fcb extent lock %08lX thread %08lX\n",
2437 &pFcb->NPFcb->Specific.File.ExtentsResource,
2438 PsGetCurrentThread());
2440 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
2443 if( NULL != pResult &&
2444 Irp->AssociatedIrp.SystemBuffer != pResult)
2447 AFSExFreePool(pResult);
2450 if (NT_SUCCESS(ntStatus))
2452 Irp->IoStatus.Information = ulSz;
2456 Irp->IoStatus.Information = 0;
2459 Irp->IoStatus.Status = ntStatus;
2461 if( pObjectInfo != NULL)
2464 lCount = InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
2466 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2467 AFS_TRACE_LEVEL_VERBOSE,
2468 "AFSProcessReleaseFileExtents Decrement count on object %08lX Cnt %d\n",
2478 AFSWaitForExtentMapping( AFSFcb *Fcb,
2481 NTSTATUS ntStatus = STATUS_SUCCESS;
2482 LARGE_INTEGER liTimeOut;
2483 ULONGLONG ullProcessId = (ULONGLONG)PsGetCurrentProcessId();
2488 ASSERT( !ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
2490 if (!NT_SUCCESS( Fcb->NPFcb->Specific.File.ExtentsRequestStatus))
2494 // If this isn't the same authgroup which caused the failure
2495 // then try to request them again
2498 if( RtlCompareMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2500 sizeof( GUID)) == sizeof( GUID))
2503 ntStatus = Fcb->NPFcb->Specific.File.ExtentsRequestStatus;
2505 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
2507 RtlZeroMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2510 try_return( ntStatus);
2514 liTimeOut.QuadPart = -(1 * AFS_ONE_SECOND);
2516 ntStatus = KeWaitForSingleObject( &Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
2522 if (!NT_SUCCESS( Fcb->NPFcb->Specific.File.ExtentsRequestStatus))
2526 // If this isn't the same authgroup which caused the failure
2527 // or the System Process,
2528 // then try to request the extents again
2531 if( RtlCompareMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2533 sizeof( GUID)) == sizeof( GUID) ||
2534 ullProcessId == (ULONGLONG)AFSSysProcess)
2537 ntStatus = Fcb->NPFcb->Specific.File.ExtentsRequestStatus;
2539 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
2541 RtlZeroMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2544 try_return( ntStatus);
2548 if( ntStatus == STATUS_TIMEOUT)
2551 ntStatus = STATUS_SUCCESS;
2563 AFSFlushExtents( IN AFSFcb *Fcb,
2566 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
2567 AFSExtent *pExtent, *pNextExtent;
2569 AFSReleaseExtentsCB *pRelease = NULL;
2571 ULONG initialDirtyCount = 0;
2572 BOOLEAN bExtentsLocked = FALSE;
2575 NTSTATUS ntStatus = STATUS_SUCCESS;
2576 LARGE_INTEGER liLastFlush;
2577 AFSExtent *pDirtyListHead = NULL, *pDirtyListTail = NULL;
2578 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2579 GUID *pAuthGroup = AuthGroup;
2583 ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
2586 // Save, then reset the flush time
2589 liLastFlush = Fcb->Specific.File.LastServerFlush;
2591 KeQueryTickCount( &Fcb->Specific.File.LastServerFlush);
2596 if( pAuthGroup == NULL ||
2597 RtlCompareMemory( pAuthGroup,
2598 &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2599 sizeof( GUID)) == sizeof( GUID))
2602 RtlZeroMemory( &stAuthGroup,
2605 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
2610 if( !NT_SUCCESS( ntStatus))
2612 try_return( ntStatus);
2615 pAuthGroup = &stAuthGroup;
2619 // Lock extents while we count and set up the array to send to
2623 AFSLockForExtentsTrim( Fcb);
2625 bExtentsLocked = TRUE;
2627 lCount = InterlockedIncrement( &Fcb->Specific.File.QueuedFlushCount);
2630 // Clear our queued flush event
2633 KeClearEvent( &Fcb->NPFcb->Specific.File.QueuedFlushEvent);
2636 // Look for a start in the list to flush entries
2641 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
2643 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
2645 AFS_EXTENT_RELEASE_TAG);
2646 if( NULL == pRelease)
2649 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2652 initialDirtyCount = Fcb->Specific.File.ExtentsDirtyCount;
2654 while( Fcb->Specific.File.ExtentsDirtyCount > 0)
2657 pRelease->Flags = AFS_EXTENT_FLAG_DIRTY;
2659 if( BooleanFlagOn( Fcb->Flags, AFS_FCB_FILE_CLOSED))
2662 pRelease->Flags |= AFS_EXTENT_FLAG_FLUSH;
2666 // Update the metadata for this call
2669 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
2670 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
2671 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
2672 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
2673 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
2677 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
2680 pExtent = (AFSExtent *)pNPFcb->Specific.File.DirtyListHead;
2682 while( count < AFS_MAXIMUM_EXTENT_RELEASE_COUNT)
2685 if ( pExtent == NULL)
2691 pNextExtent = (AFSExtent *)pExtent->DirtyList.fLink;
2693 if ( pExtent->ActiveCount > 0)
2695 pExtent = pNextExtent;
2699 AFSRemoveEntryDirtyList( Fcb, pExtent);
2701 pExtent->DirtyList.fLink = NULL;
2702 pExtent->DirtyList.bLink = NULL;
2704 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
2707 // Clear the flag in advance of the write. If we do
2708 // things this was we know that the clear is
2709 // pessimistic (any write which happens from now on
2710 // will set the flag dirty again).
2713 pExtent->Flags &= ~AFS_EXTENT_DIRTY;
2715 pRelease->FileExtents[count].Flags = AFS_EXTENT_FLAG_DIRTY;
2717 pRelease->FileExtents[count].Length = pExtent->Size;
2718 pRelease->FileExtents[count].DirtyLength = pExtent->Size;
2719 pRelease->FileExtents[count].DirtyOffset = 0;
2720 pRelease->FileExtents[count].CacheOffset = pExtent->CacheOffset;
2721 pRelease->FileExtents[count].FileOffset = pExtent->FileOffset;
2724 RtlCopyMemory( pRelease->FileExtents[count].MD5,
2726 sizeof(pExtent->MD5));
2728 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_MD5_SET;
2731 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2732 AFS_TRACE_LEVEL_VERBOSE,
2733 "AFSFlushExtents Releasing DIRTY extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
2735 Fcb->ObjectInformation->FileId.Cell,
2736 Fcb->ObjectInformation->FileId.Volume,
2737 Fcb->ObjectInformation->FileId.Vnode,
2738 Fcb->ObjectInformation->FileId.Unique,
2739 pExtent->FileOffset.QuadPart,
2742 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_RELEASE;
2745 // Need to pull this extent from the main list as well
2748 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
2750 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
2752 RemoveEntryList( &pExtent->Lists[i] );
2756 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
2758 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
2760 AFSExFreePool( pExtent);
2762 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
2764 lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount);
2769 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
2776 pExtent = pNextExtent;
2779 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
2782 // If we are done then get out
2788 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2789 AFS_TRACE_LEVEL_VERBOSE,
2790 "AFSFlushExtents No more dirty extents found\n");
2796 // Fire off the request synchronously
2799 sz = sizeof( AFSReleaseExtentsCB ) + (count * sizeof ( AFSFileExtentCB ));
2801 pRelease->ExtentCount = count;
2803 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2804 AFS_TRACE_LEVEL_VERBOSE,
2805 "AFSFlushExtents Releasing(1) Fcb extents lock %08lX SHARED %08lX\n",
2806 &pNPFcb->Specific.File.ExtentsResource,
2807 PsGetCurrentThread());
2809 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource);
2810 bExtentsLocked = FALSE;
2812 KeSetEvent( &pNPFcb->Specific.File.FlushEvent,
2816 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
2817 AFS_REQUEST_FLAG_SYNCHRONOUS,
2820 &Fcb->ObjectInformation->FileId,
2826 if( !NT_SUCCESS(ntStatus))
2830 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
2831 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
2834 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2835 AFS_TRACE_LEVEL_ERROR,
2836 "AFSFlushExtents AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2837 Fcb->ObjectInformation->FileId.Cell,
2838 Fcb->ObjectInformation->FileId.Volume,
2839 Fcb->ObjectInformation->FileId.Vnode,
2840 Fcb->ObjectInformation->FileId.Unique,
2844 AFSLockForExtentsTrim( Fcb);
2846 bExtentsLocked = TRUE;
2851 lCount = InterlockedDecrement( &Fcb->Specific.File.QueuedFlushCount);
2856 KeSetEvent( &pNPFcb->Specific.File.QueuedFlushEvent,
2861 KeSetEvent( &pNPFcb->Specific.File.FlushEvent,
2868 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2869 AFS_TRACE_LEVEL_VERBOSE,
2870 "AFSFlushExtents Releasing(2) Fcb extents lock %08lX SHARED %08lX\n",
2871 &pNPFcb->Specific.File.ExtentsResource,
2872 PsGetCurrentThread());
2874 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
2879 AFSExFreePool( pRelease);
2887 AFSReleaseExtentsWithFlush( IN AFSFcb *Fcb,
2890 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
2893 AFSReleaseExtentsCB *pRelease = NULL;
2895 ULONG initialDirtyCount = 0;
2896 BOOLEAN bExtentsLocked = FALSE;
2899 NTSTATUS ntStatus = STATUS_SUCCESS;
2900 LARGE_INTEGER liLastFlush;
2901 ULONG ulRemainingExtentLength = 0;
2902 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2903 GUID *pAuthGroup = AuthGroup;
2907 ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
2910 // Save, then reset the flush time
2913 liLastFlush = Fcb->Specific.File.LastServerFlush;
2915 KeQueryTickCount( &Fcb->Specific.File.LastServerFlush);
2920 if( pAuthGroup == NULL ||
2921 RtlCompareMemory( pAuthGroup,
2922 &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2923 sizeof( GUID)) == sizeof( GUID))
2926 RtlZeroMemory( &stAuthGroup,
2929 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
2934 if( !NT_SUCCESS( ntStatus))
2936 try_return( ntStatus);
2939 pAuthGroup = &stAuthGroup;
2943 // Look for a start in the list to flush entries
2948 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
2950 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
2952 AFS_EXTENT_RELEASE_TAG);
2953 if( NULL == pRelease)
2956 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2959 if( Fcb->OpenHandleCount > 0)
2963 // Don't release everything ...
2967 // For now release everything
2970 //ulRemainingExtentLength = 1500;
2973 while( Fcb->Specific.File.ExtentLength > (LONG)ulRemainingExtentLength)
2976 AFSLockForExtentsTrim( Fcb);
2978 bExtentsLocked = TRUE;
2980 pRelease->Flags = AFS_EXTENT_FLAG_RELEASE;
2983 // Update the metadata for this call
2986 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
2987 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
2988 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
2989 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
2990 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
2994 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
2996 while( count < AFS_MAXIMUM_EXTENT_RELEASE_COUNT &&
2997 le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
3000 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3004 if( pExtent->ActiveCount > 0)
3010 pRelease->FileExtents[count].Flags = AFS_EXTENT_FLAG_RELEASE;
3012 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3013 AFS_TRACE_LEVEL_VERBOSE,
3014 "AFSReleaseExtentsWithFlush Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3016 Fcb->ObjectInformation->FileId.Cell,
3017 Fcb->ObjectInformation->FileId.Volume,
3018 Fcb->ObjectInformation->FileId.Vnode,
3019 Fcb->ObjectInformation->FileId.Unique,
3020 pExtent->FileOffset.QuadPart,
3023 pRelease->FileExtents[count].Length = pExtent->Size;
3024 pRelease->FileExtents[count].DirtyLength = pExtent->Size;
3025 pRelease->FileExtents[count].DirtyOffset = 0;
3026 pRelease->FileExtents[count].CacheOffset = pExtent->CacheOffset;
3027 pRelease->FileExtents[count].FileOffset = pExtent->FileOffset;
3030 RtlCopyMemory( pRelease->FileExtents[count].MD5,
3032 sizeof(pExtent->MD5));
3034 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_MD5_SET;
3037 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3040 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3043 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3046 AFSRemoveEntryDirtyList( Fcb,
3049 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_DIRTY;
3051 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
3054 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3058 // Need to pull this extent from the main list as well
3061 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
3063 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
3065 RemoveEntryList( &pExtent->Lists[i] );
3069 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
3071 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
3073 AFSExFreePool( pExtent);
3075 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
3077 lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount);
3082 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
3091 // If we are done then get out
3097 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3098 AFS_TRACE_LEVEL_VERBOSE,
3099 "AFSReleaseExtentsWithFlush No more dirty extents found\n");
3105 // Fire off the request synchronously
3108 sz = sizeof( AFSReleaseExtentsCB ) + (count * sizeof ( AFSFileExtentCB ));
3110 pRelease->ExtentCount = count;
3113 // Drop the extents lock for the duration of the call to
3114 // the network. We have pinned the extents so, even
3115 // though we might get extents added during this period,
3116 // but none will be removed. Hence we can carry on from
3120 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3121 AFS_TRACE_LEVEL_VERBOSE,
3122 "AFSReleaseExtentsWithFlush Releasing Fcb extents lock %08lX thread %08lX\n",
3123 &pNPFcb->Specific.File.ExtentsResource,
3124 PsGetCurrentThread());
3126 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource);
3127 bExtentsLocked = FALSE;
3129 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
3130 AFS_REQUEST_FLAG_SYNCHRONOUS,
3133 &Fcb->ObjectInformation->FileId,
3139 if( !NT_SUCCESS(ntStatus))
3143 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
3144 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
3147 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3148 AFS_TRACE_LEVEL_ERROR,
3149 "AFSReleaseExtentsWithFlush AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3150 Fcb->ObjectInformation->FileId.Cell,
3151 Fcb->ObjectInformation->FileId.Volume,
3152 Fcb->ObjectInformation->FileId.Vnode,
3153 Fcb->ObjectInformation->FileId.Unique,
3163 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3164 AFS_TRACE_LEVEL_VERBOSE,
3165 "AFSReleaseExtentsWithFlush Releasing Fcb extents lock %08lX thread %08lX\n",
3166 &pNPFcb->Specific.File.ExtentsResource,
3167 PsGetCurrentThread());
3169 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
3174 AFSExFreePool( pRelease);
3182 AFSReleaseCleanExtents( IN AFSFcb *Fcb,
3185 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3188 AFSReleaseExtentsCB *pRelease = NULL;
3190 ULONG initialDirtyCount = 0;
3191 BOOLEAN bExtentsLocked = FALSE;
3194 NTSTATUS ntStatus = STATUS_SUCCESS;
3195 LARGE_INTEGER liLastFlush;
3196 ULONG ulRemainingExtentLength = 0;
3197 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3198 GUID *pAuthGroup = AuthGroup;
3201 ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
3204 // Save, then reset the flush time
3207 liLastFlush = Fcb->Specific.File.LastServerFlush;
3209 KeQueryTickCount( &Fcb->Specific.File.LastServerFlush);
3214 if( pAuthGroup == NULL ||
3215 RtlCompareMemory( pAuthGroup,
3216 &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
3217 sizeof( GUID)) == sizeof( GUID))
3220 RtlZeroMemory( &stAuthGroup,
3223 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
3228 if( !NT_SUCCESS( ntStatus))
3230 try_return( ntStatus);
3233 pAuthGroup = &stAuthGroup;
3237 // Look for a start in the list to flush entries
3242 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
3244 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
3246 AFS_EXTENT_RELEASE_TAG);
3247 if( NULL == pRelease)
3250 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
3253 while( Fcb->Specific.File.ExtentLength > (LONG)ulRemainingExtentLength)
3256 AFSLockForExtentsTrim( Fcb);
3258 bExtentsLocked = TRUE;
3260 pRelease->Flags = AFS_EXTENT_FLAG_RELEASE;
3263 // Update the metadata for this call
3266 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
3267 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
3268 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
3269 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
3270 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
3274 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3276 while( count < AFS_MAXIMUM_EXTENT_RELEASE_COUNT &&
3277 le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
3280 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3284 if( pExtent->ActiveCount > 0 ||
3285 BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3290 pRelease->FileExtents[count].Flags = AFS_EXTENT_FLAG_RELEASE;
3292 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3293 AFS_TRACE_LEVEL_VERBOSE,
3294 "AFSReleaseCleanExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3296 Fcb->ObjectInformation->FileId.Cell,
3297 Fcb->ObjectInformation->FileId.Volume,
3298 Fcb->ObjectInformation->FileId.Vnode,
3299 Fcb->ObjectInformation->FileId.Unique,
3300 pExtent->FileOffset.QuadPart,
3303 pRelease->FileExtents[count].Length = pExtent->Size;
3304 pRelease->FileExtents[count].DirtyLength = pExtent->Size;
3305 pRelease->FileExtents[count].DirtyOffset = 0;
3306 pRelease->FileExtents[count].CacheOffset = pExtent->CacheOffset;
3307 pRelease->FileExtents[count].FileOffset = pExtent->FileOffset;
3310 RtlCopyMemory( pRelease->FileExtents[count].MD5,
3312 sizeof(pExtent->MD5));
3314 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_MD5_SET;
3318 // Need to pull this extent from the main list as well
3321 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
3323 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
3325 RemoveEntryList( &pExtent->Lists[i] );
3329 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
3331 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
3333 AFSExFreePool( pExtent);
3335 InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
3337 if( InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount) == 0)
3340 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
3349 // If we are done then get out
3355 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3356 AFS_TRACE_LEVEL_VERBOSE,
3357 "AFSReleaseCleanExtents No more dirty extents found\n");
3363 // Fire off the request synchronously
3366 sz = sizeof( AFSReleaseExtentsCB ) + (count * sizeof ( AFSFileExtentCB ));
3368 pRelease->ExtentCount = count;
3371 // Drop the extents lock for the duration of the call to
3372 // the network. We have pinned the extents so, even
3373 // though we might get extents added during this period,
3374 // but none will be removed. Hence we can carry on from
3378 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3379 AFS_TRACE_LEVEL_VERBOSE,
3380 "AFSReleaseCleanExtents Releasing Fcb extents lock %08lX thread %08lX\n",
3381 &pNPFcb->Specific.File.ExtentsResource,
3382 PsGetCurrentThread());
3384 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource);
3385 bExtentsLocked = FALSE;
3387 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
3388 AFS_REQUEST_FLAG_SYNCHRONOUS,
3391 &Fcb->ObjectInformation->FileId,
3397 if( !NT_SUCCESS(ntStatus))
3401 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
3402 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
3405 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3406 AFS_TRACE_LEVEL_ERROR,
3407 "AFSReleaseCleanExtents AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3408 Fcb->ObjectInformation->FileId.Cell,
3409 Fcb->ObjectInformation->FileId.Volume,
3410 Fcb->ObjectInformation->FileId.Vnode,
3411 Fcb->ObjectInformation->FileId.Unique,
3421 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3422 AFS_TRACE_LEVEL_VERBOSE,
3423 "AFSReleaseCleanExtents Releasing Fcb extents lock %08lX thread %08lX\n",
3424 &pNPFcb->Specific.File.ExtentsResource,
3425 PsGetCurrentThread());
3427 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
3432 AFSExFreePool( pRelease);
3440 AFSMarkDirty( IN AFSFcb *Fcb,
3441 IN AFSExtent *StartExtent,
3442 IN ULONG ExtentsCount,
3443 IN LARGE_INTEGER *StartingByte,
3444 IN BOOLEAN DerefExtents)
3447 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3448 AFSExtent *pExtent = StartExtent;
3449 AFSExtent *pNextExtent, *pCurrentExtent = NULL;
3451 BOOLEAN bInsertTail = FALSE, bInsertHead = FALSE;
3453 BOOLEAN bLocked = FALSE;
3455 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3456 AFS_TRACE_LEVEL_VERBOSE,
3457 "AFSMarkDirty Acquiring Fcb extents lock %08lX SHARED %08lX\n",
3458 &Fcb->NPFcb->Specific.File.ExtentsResource,
3459 PsGetCurrentThread());
3461 if( !ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource))
3463 AFSAcquireShared( &Fcb->NPFcb->Specific.File.ExtentsResource, TRUE);
3467 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3473 // Find the insertion point
3476 if( pNPFcb->Specific.File.DirtyListHead == NULL)
3481 else if( StartingByte->QuadPart == 0)
3489 pCurrentExtent = pNPFcb->Specific.File.DirtyListHead;
3491 while( pCurrentExtent != NULL)
3494 if( pCurrentExtent->FileOffset.QuadPart + pCurrentExtent->Size >= StartingByte->QuadPart ||
3495 pCurrentExtent->DirtyList.fLink == NULL)
3501 pCurrentExtent = (AFSExtent *)pCurrentExtent->DirtyList.fLink;
3505 while( ulCount < ExtentsCount)
3508 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
3510 if( !BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3513 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3514 AFS_TRACE_LEVEL_VERBOSE,
3515 "AFSMarkDirty Marking extent offset %I64X Length %08lX DIRTY\n",
3516 pExtent->FileOffset.QuadPart,
3519 pExtent->DirtyList.fLink = NULL;
3520 pExtent->DirtyList.bLink = NULL;
3525 pExtent->DirtyList.fLink = (void *)pNPFcb->Specific.File.DirtyListHead;
3527 pExtent->DirtyList.bLink = NULL;
3529 pNPFcb->Specific.File.DirtyListHead->DirtyList.bLink = (void *)pExtent;
3531 pNPFcb->Specific.File.DirtyListHead = pExtent;
3533 pCurrentExtent = pExtent;
3535 bInsertHead = FALSE;
3537 else if( bInsertTail)
3540 if( pNPFcb->Specific.File.DirtyListHead == NULL)
3543 pNPFcb->Specific.File.DirtyListHead = pExtent;
3548 pNPFcb->Specific.File.DirtyListTail->DirtyList.fLink = (void *)pExtent;
3550 pExtent->DirtyList.bLink = (void *)pNPFcb->Specific.File.DirtyListTail;
3553 pNPFcb->Specific.File.DirtyListTail = pExtent;
3558 pExtent->DirtyList.fLink = pCurrentExtent->DirtyList.fLink;
3560 pExtent->DirtyList.bLink = (void *)pCurrentExtent;
3562 if( pExtent->DirtyList.fLink == NULL)
3565 pNPFcb->Specific.File.DirtyListTail = pExtent;
3570 ((AFSExtent *)pExtent->DirtyList.fLink)->DirtyList.bLink = (void *)pExtent;
3573 pCurrentExtent->DirtyList.fLink = (void *)pExtent;
3575 pCurrentExtent = pExtent;
3578 pExtent->Flags |= AFS_EXTENT_DIRTY;
3581 // Up the dirty count
3584 lCount = InterlockedIncrement( &Fcb->Specific.File.ExtentsDirtyCount);
3589 pCurrentExtent = pExtent;
3592 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_ACTIVE_COUNTING,
3593 AFS_TRACE_LEVEL_VERBOSE,
3594 "AFSMarkDirty Decrement count on extent %08lX Cnt %d\n",
3596 pExtent->ActiveCount);
3600 ASSERT( pExtent->ActiveCount > 0);
3601 lCount = InterlockedDecrement( &pExtent->ActiveCount);
3604 pExtent = pNextExtent;
3609 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
3614 "EXCEPTION - AFSMarkDirty\n");
3616 AFSDumpTraceFilesFnc();
3619 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3621 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3622 AFS_TRACE_LEVEL_VERBOSE,
3623 "AFSMarkDirty Releasing Fcb extents lock %08lX SHARED %08lX\n",
3624 &Fcb->NPFcb->Specific.File.ExtentsResource,
3625 PsGetCurrentThread());
3629 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
3640 ExtentFor(PLIST_ENTRY le, ULONG SkipList)
3642 return CONTAINING_RECORD( le, AFSExtent, Lists[SkipList] );
3645 static AFSExtent *NextExtent(AFSExtent *Extent, ULONG SkipList)
3647 return ExtentFor(Extent->Lists[SkipList].Flink, SkipList);
3650 static AFSExtent *DirtyExtentFor(PLIST_ENTRY le)
3652 return CONTAINING_RECORD( le, AFSExtent, DirtyList );
3655 static VOID VerifyExtentsLists(AFSFcb *Fcb)
3659 // Check the ordering of the extents lists
3661 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
3663 ASSERT(Fcb->Specific.File.ExtentsLists[0].Flink != &Fcb->Specific.File.ExtentsLists[1]);
3665 for (ULONG listNo = 0; listNo < AFS_NUM_EXTENT_LISTS; listNo ++)
3667 LARGE_INTEGER lastOffset;
3669 lastOffset.QuadPart = 0;
3671 for (PLIST_ENTRY pLe = Fcb->Specific.File.ExtentsLists[listNo].Flink;
3672 pLe != &Fcb->Specific.File.ExtentsLists[listNo];
3677 pExtent = ExtentFor(pLe, listNo);
3680 ASSERT(pLe != &Fcb->Specific.File.ExtentsLists[1] &&
3681 pLe->Flink !=&Fcb->Specific.File.ExtentsLists[1] &&
3682 pLe->Blink !=&Fcb->Specific.File.ExtentsLists[1]);
3685 ASSERT(pLe->Flink->Blink == pLe);
3686 ASSERT(pLe->Blink->Flink == pLe);
3689 // Should follow on from previous
3691 ASSERT(pExtent->FileOffset.QuadPart >= lastOffset.QuadPart);
3692 lastOffset.QuadPart = pExtent->FileOffset.QuadPart + pExtent->Size;
3695 // Should match alignment criteria
3697 ASSERT( 0 == (pExtent->FileOffset.LowPart & ExtentsMasks[listNo]) );
3700 // "lower" lists should be populated
3702 for (LONG subListNo = listNo-1; subListNo > 0; subListNo --)
3704 ASSERT( !IsListEmpty(&pExtent->Lists[subListNo]));
3712 AFSTrimExtents( IN AFSFcb *Fcb,
3713 IN PLARGE_INTEGER FileSize)
3716 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3719 BOOLEAN locked = FALSE;
3720 NTSTATUS ntStatus = STATUS_SUCCESS;
3721 LARGE_INTEGER liAlignedOffset = {0,0};
3722 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
3723 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3730 // Get an aligned offset
3733 if( FileSize != NULL)
3736 liAlignedOffset = *FileSize;
3739 if( liAlignedOffset.QuadPart > 0 &&
3740 liAlignedOffset.QuadPart % pDevExt->Specific.RDR.CacheBlockSize != 0)
3744 // Align UP to the next cache block size
3747 liAlignedOffset.QuadPart = (ULONGLONG)( (ULONGLONG)((liAlignedOffset.QuadPart / pDevExt->Specific.RDR.CacheBlockSize) + 1) * (ULONGLONG)pDevExt->Specific.RDR.CacheBlockSize);
3751 // Ensure that no one is working with the extents and grab the
3755 AFSLockForExtentsTrim( Fcb);
3759 if( 0 == Fcb->Specific.File.ExtentCount)
3763 // Update the request extent status
3766 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
3768 try_return( ntStatus = STATUS_SUCCESS);
3772 // We are truncating from a specific length in the file. If the offset
3773 // is non-zero then go find the first extent to remove
3776 if( 0 == FileSize->QuadPart)
3779 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3784 pExtent = AFSExtentForOffset( Fcb,
3788 if( NULL == pExtent)
3791 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3795 le = &pExtent->Lists[AFS_EXTENTS_LIST];
3799 while( le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
3802 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3805 // Only trim down extents beyond the aligned offset
3810 if( pExtent->FileOffset.QuadPart >= liAlignedOffset.QuadPart)
3813 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3816 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3819 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3823 AFSRemoveEntryDirtyList( Fcb,
3826 dirtyCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
3828 ASSERT(dirtyCount >= 0);
3831 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3834 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
3836 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
3838 RemoveEntryList( &pExtent->Lists[i] );
3842 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3843 AFS_TRACE_LEVEL_VERBOSE,
3844 "AFSTrimExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3846 Fcb->ObjectInformation->FileId.Cell,
3847 Fcb->ObjectInformation->FileId.Volume,
3848 Fcb->ObjectInformation->FileId.Vnode,
3849 Fcb->ObjectInformation->FileId.Unique,
3850 pExtent->FileOffset.QuadPart,
3853 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
3855 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
3857 ASSERT( pExtent->ActiveCount == 0);
3862 AFSExFreePool( pExtent);
3864 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
3866 lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount);
3871 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
3879 // Update the request extent status
3882 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
3889 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3890 AFS_TRACE_LEVEL_VERBOSE,
3891 "AFSTrimExtents Releasing Fcb extents lock %08lX thread %08lX\n",
3892 &Fcb->NPFcb->Specific.File.ExtentsResource,
3893 PsGetCurrentThread());
3895 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
3903 AFSTrimSpecifiedExtents( IN AFSFcb *Fcb,
3905 IN AFSFileExtentCB *Result)
3908 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3911 AFSFileExtentCB *pFileExtents = Result;
3912 NTSTATUS ntStatus = STATUS_SUCCESS;
3913 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
3914 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3920 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3922 while( le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST] &&
3926 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3929 // Only trim down extents beyond the aligned offset
3934 if( pExtent->FileOffset.QuadPart == pFileExtents->FileOffset.QuadPart)
3937 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3940 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3943 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3948 AFSRemoveEntryDirtyList( Fcb,
3951 dirtyCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
3953 ASSERT( dirtyCount >= 0);
3957 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3961 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
3963 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
3965 RemoveEntryList( &pExtent->Lists[i] );
3969 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3970 AFS_TRACE_LEVEL_VERBOSE,
3971 "AFSTrimSpecifiedExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3973 Fcb->ObjectInformation->FileId.Cell,
3974 Fcb->ObjectInformation->FileId.Volume,
3975 Fcb->ObjectInformation->FileId.Vnode,
3976 Fcb->ObjectInformation->FileId.Unique,
3977 pExtent->FileOffset.QuadPart,
3980 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
3982 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
3984 ASSERT( pExtent->ActiveCount == 0);
3989 AFSExFreePool( pExtent);
3991 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
3993 lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount);
3998 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
4004 // Next extent we are looking for
4014 // Update the request extent status
4017 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
4024 AFSReferenceActiveExtents( IN AFSExtent *StartExtent,
4025 IN ULONG ExtentsCount)
4028 AFSExtent *pExtent = StartExtent;
4029 AFSExtent *pNextExtent;
4033 while( ulCount < ExtentsCount)
4036 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
4038 lCount = InterlockedIncrement( &pExtent->ActiveCount);
4040 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_ACTIVE_COUNTING,
4041 AFS_TRACE_LEVEL_VERBOSE,
4042 "AFSReferenceActiveExtents Increment count on extent %08lX Cnt %d\n",
4046 pExtent = pNextExtent;
4055 AFSDereferenceActiveExtents( IN AFSExtent *StartExtent,
4056 IN ULONG ExtentsCount)
4059 AFSExtent *pExtent = StartExtent;
4060 AFSExtent *pNextExtent;
4064 while( ulCount < ExtentsCount)
4067 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
4069 ASSERT( pExtent->ActiveCount > 0);
4071 lCount = InterlockedDecrement( &pExtent->ActiveCount);
4073 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_ACTIVE_COUNTING,
4074 AFS_TRACE_LEVEL_VERBOSE,
4075 "AFSDereferenceActiveExtents Decrement count on extent %08lX Cnt %d\n",
4079 pExtent = pNextExtent;
4088 AFSRemoveEntryDirtyList( IN AFSFcb *Fcb,
4089 IN AFSExtent *Extent)
4092 if( Extent->DirtyList.fLink == NULL)
4095 Fcb->NPFcb->Specific.File.DirtyListTail = (AFSExtent *)Extent->DirtyList.bLink;
4097 if( Fcb->NPFcb->Specific.File.DirtyListTail != NULL)
4100 Fcb->NPFcb->Specific.File.DirtyListTail->DirtyList.fLink = NULL;
4106 ((AFSExtent *)Extent->DirtyList.fLink)->DirtyList.bLink = Extent->DirtyList.bLink;
4109 if( Extent->DirtyList.bLink == NULL)
4112 Fcb->NPFcb->Specific.File.DirtyListHead = (AFSExtent *)Extent->DirtyList.fLink;
4114 if( Fcb->NPFcb->Specific.File.DirtyListHead != NULL)
4117 Fcb->NPFcb->Specific.File.DirtyListHead->DirtyList.bLink = NULL;
4123 ((AFSExtent *)Extent->DirtyList.bLink)->DirtyList.fLink = Extent->DirtyList.fLink;
4131 AFSConstructCleanByteRangeList( AFSFcb * pFcb,
4132 AFSByteRange ** pByteRangeList)
4135 ULONG ulByteRangeMax;
4136 ULONG ulByteRangeCount = 0;
4137 AFSByteRange *ByteRangeList;
4138 AFSExtent *pExtent, *pNextExtent;
4140 AFSAcquireShared( &pFcb->NPFcb->Specific.File.DirtyExtentsListLock, TRUE);
4142 ulByteRangeMax = pFcb->Specific.File.ExtentsDirtyCount + 1;
4144 ByteRangeList = (AFSByteRange *) AFSExAllocatePoolWithTag( PagedPool,
4145 ulByteRangeMax * sizeof( AFSByteRange),
4148 if ( ByteRangeList == NULL)
4151 (*pByteRangeList) = NULL;
4153 try_return( ulByteRangeCount = DWORD_MAX);
4156 RtlZeroMemory( ByteRangeList,
4157 ulByteRangeMax * sizeof( AFSByteRange));
4160 // The for loop populates the ByteRangeList entries with values that are
4161 // the gaps in the DirtyList. In other words, if a range is not present
4162 // in the DirtyList it will be represented in the ByteRangeList array.
4165 for ( ulByteRangeCount = 0,
4166 pExtent = (AFSExtent *)pFcb->NPFcb->Specific.File.DirtyListHead;
4167 ulByteRangeCount < ulByteRangeMax && pExtent != NULL;
4168 pExtent = pNextExtent)
4171 pNextExtent = (AFSExtent *)pExtent->DirtyList.fLink;
4174 // The first time the for() is entered the ulByteRangeCount will be zero and
4175 // ByteRangeList[0] FileOffset and Length will both be zero. If the first
4176 // extent is not for offset zero, the ByteRangeList[0] Length is set to the
4177 // FileOffset of the Extent.
4179 // Future passes through the loop behave in a similar fashion but
4180 // ByteRangeList[ulByteRangeCount] FileOffset will have been set below.
4183 if ( pExtent->FileOffset.QuadPart != ByteRangeList[ulByteRangeCount].FileOffset.QuadPart + ByteRangeList[ulByteRangeCount].Length.QuadPart)
4186 ByteRangeList[ulByteRangeCount].Length.QuadPart =
4187 pExtent->FileOffset.QuadPart - ByteRangeList[ulByteRangeCount].FileOffset.QuadPart;
4193 // Having processed the current dirty extent, the following while loop
4194 // searches for the next clean gap between dirty extents.
4197 while ( pNextExtent && pNextExtent->FileOffset.QuadPart == pExtent->FileOffset.QuadPart + pExtent->Size)
4200 pExtent = pNextExtent;
4202 pNextExtent = (AFSExtent *)pExtent->DirtyList.fLink;
4206 // Having found the next gap, the ByteRangeList[] FileOffset is set to the start of the gap.
4207 // The Length is left at zero and will be assigned either when the for loop continues or
4208 // when the for loop exits.
4211 ByteRangeList[ulByteRangeCount].FileOffset.QuadPart = pExtent->FileOffset.QuadPart + pExtent->Size;
4215 // Assign the Length of the final clean range to match the file length.
4218 ByteRangeList[ulByteRangeCount].Length.QuadPart =
4219 pFcb->ObjectInformation->EndOfFile.QuadPart - ByteRangeList[ulByteRangeCount].FileOffset.QuadPart;
4221 (*pByteRangeList) = ByteRangeList;
4225 AFSReleaseResource( &pFcb->NPFcb->Specific.File.DirtyExtentsListLock);
4227 return ulByteRangeCount;
4232 AFSSetupMD5Hash( IN AFSFcb *Fcb,
4233 IN AFSExtent *StartExtent,
4234 IN ULONG ExtentsCount,
4235 IN void *SystemBuffer,
4236 IN LARGE_INTEGER *ByteOffset,
4240 NTSTATUS ntStatus = STATUS_SUCCESS;
4241 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
4242 AFSExtent *pExtent = StartExtent;
4243 AFSExtent *pNextExtent, *pCurrentExtent = NULL;
4245 char *pCurrentBuffer = (char *)SystemBuffer;
4246 char *pMD5Buffer = NULL;
4247 ULONG ulCurrentLen = 0;
4248 void *pExtentBuffer = NULL;
4249 LARGE_INTEGER liByteOffset;
4250 ULONG ulBytesRead = 0;
4255 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4256 AFS_TRACE_LEVEL_VERBOSE,
4257 "AFSSetupMD5Hash Acquiring Fcb extents lock %08lX SHARED %08lX\n",
4258 &Fcb->NPFcb->Specific.File.ExtentsResource,
4259 PsGetCurrentThread());
4261 AFSAcquireShared( &Fcb->NPFcb->Specific.File.ExtentsResource, TRUE);
4265 liByteOffset.QuadPart = ByteOffset->QuadPart;
4267 while( ulCount < ExtentsCount)
4270 RtlZeroMemory( pExtent->MD5,
4271 sizeof( pExtent->MD5));
4273 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
4275 if( liByteOffset.QuadPart == pExtent->FileOffset.QuadPart &&
4276 ByteCount < pExtent->Size)
4279 if( pExtentBuffer == NULL)
4282 pExtentBuffer = AFSExAllocatePoolWithTag( PagedPool,
4284 AFS_GENERIC_MEMORY_9_TAG);
4286 if( pExtentBuffer == NULL)
4293 RtlZeroMemory( pExtentBuffer,
4296 RtlCopyMemory( pExtentBuffer,
4300 pMD5Buffer = (char *)pExtentBuffer;
4302 ulCurrentLen = ByteCount;
4304 else if( liByteOffset.QuadPart != pExtent->FileOffset.QuadPart)
4307 pExtentBuffer = AFSExAllocatePoolWithTag( PagedPool,
4309 AFS_GENERIC_MEMORY_10_TAG);
4311 if( pExtentBuffer == NULL)
4317 RtlZeroMemory( pExtentBuffer,
4320 if( BooleanFlagOn( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE))
4324 RtlCopyMemory( pExtentBuffer,
4325 ((char *)AFSLibCacheBaseAddress + pExtent->CacheOffset.QuadPart),
4328 ASSERT( pExtent->CacheOffset.HighPart == 0);
4329 RtlCopyMemory( pExtentBuffer,
4330 ((char *)AFSLibCacheBaseAddress + pExtent->CacheOffset.LowPart),
4334 ulBytesRead = pExtent->Size;
4339 ntStatus = AFSReadCacheFile( pExtentBuffer,
4340 &pExtent->CacheOffset,
4344 if( !NT_SUCCESS( ntStatus))
4351 pMD5Buffer = (char *)pExtentBuffer;
4353 ulCurrentLen = min( ByteCount, pExtent->Size - (ULONG)(liByteOffset.QuadPart - pExtent->FileOffset.QuadPart));
4355 RtlCopyMemory( (void *)((char *)pExtentBuffer + (ULONG)(liByteOffset.QuadPart - pExtent->FileOffset.QuadPart)),
4362 ulCurrentLen = pExtent->Size;
4364 pMD5Buffer = pCurrentBuffer;
4367 AFSGenerateMD5( pMD5Buffer,
4371 pExtent = pNextExtent;
4375 ByteCount -= ulCurrentLen;
4377 pCurrentBuffer += ulCurrentLen;
4379 liByteOffset.QuadPart += ulCurrentLen;
4382 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4383 AFS_TRACE_LEVEL_VERBOSE,
4384 "AFSSetupMD5Hash Releasing Fcb extents lock %08lX SHARED %08lX\n",
4385 &Fcb->NPFcb->Specific.File.ExtentsResource,
4386 PsGetCurrentThread());
4389 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
4394 "EXCEPTION - AFSSetupMD5Hash\n");
4396 AFSDumpTraceFilesFnc();
4399 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
4401 if( pExtentBuffer != NULL)
4404 AFSExFreePool( pExtentBuffer);