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);
164 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
166 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
168 AFS_EXTENT_RELEASE_TAG);
169 if (NULL == pRelease)
172 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
175 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
177 ulCount = Fcb->Specific.File.ExtentCount;
179 while( ulReleaseCount < ulCount)
182 bFoundExtents = TRUE;
184 RtlZeroMemory( pRelease,
185 sizeof( AFSReleaseExtentsCB ) +
186 (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB )));
188 if( ulCount - ulReleaseCount <= AFS_MAXIMUM_EXTENT_RELEASE_COUNT)
190 ulProcessCount = ulCount - ulReleaseCount;
194 ulProcessCount = AFS_MAXIMUM_EXTENT_RELEASE_COUNT;
197 pRelease->Flags = AFS_EXTENT_FLAG_RELEASE;
198 pRelease->ExtentCount = ulProcessCount;
201 // Update the metadata for this call
204 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
205 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
206 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
207 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
208 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
212 while (ulProcessCount < pRelease->ExtentCount)
214 pEntry = ExtentFor( le, AFS_EXTENTS_LIST );
216 pRelease->FileExtents[ulProcessCount].Flags = AFS_EXTENT_FLAG_RELEASE;
219 RtlCopyMemory( pRelease->FileExtents[ulProcessCount].MD5,
221 sizeof(pEntry->MD5));
223 pRelease->FileExtents[ulProcessCount].Flags |= AFS_EXTENT_FLAG_MD5_SET;
226 if( BooleanFlagOn( pEntry->Flags, AFS_EXTENT_DIRTY))
229 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
232 if( BooleanFlagOn( pEntry->Flags, AFS_EXTENT_DIRTY))
237 AFSRemoveEntryDirtyList( Fcb,
240 pRelease->FileExtents[ulProcessCount].Flags |= AFS_EXTENT_FLAG_DIRTY;
242 dirtyCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
244 ASSERT( dirtyCount >= 0);
247 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
250 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
251 AFS_TRACE_LEVEL_VERBOSE,
252 "AFSTearDownFcbExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %08lX-%08lX Len %08lX\n",
254 Fcb->ObjectInformation->FileId.Cell,
255 Fcb->ObjectInformation->FileId.Volume,
256 Fcb->ObjectInformation->FileId.Vnode,
257 Fcb->ObjectInformation->FileId.Unique,
258 pEntry->FileOffset.HighPart,
259 pEntry->FileOffset.LowPart,
262 pRelease->FileExtents[ulProcessCount].Length = pEntry->Size;
263 pRelease->FileExtents[ulProcessCount].DirtyLength = pEntry->Size;
264 pRelease->FileExtents[ulProcessCount].DirtyOffset = 0;
265 pRelease->FileExtents[ulProcessCount].CacheOffset = pEntry->CacheOffset;
266 pRelease->FileExtents[ulProcessCount].FileOffset = pEntry->FileOffset;
268 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pEntry->Size/1024)));
270 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pEntry->Size/1024)));
272 ASSERT( pEntry->ActiveCount == 0);
276 AFSExFreePool( pEntry);
278 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
280 lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount);
285 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
292 // Send the request down. We cannot send this down
293 // asynchronously - if we did that we could request them
294 // back before the service got this request and then this
295 // request would be a corruption.
298 sz = sizeof( AFSReleaseExtentsCB ) + (ulProcessCount * sizeof ( AFSFileExtentCB ));
300 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
301 AFS_REQUEST_FLAG_SYNCHRONOUS,
304 &Fcb->ObjectInformation->FileId,
310 if( !NT_SUCCESS(ntStatus))
314 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
315 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
318 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
319 AFS_TRACE_LEVEL_ERROR,
320 "AFSTearDownFcbExtents AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
321 Fcb->ObjectInformation->FileId.Cell,
322 Fcb->ObjectInformation->FileId.Volume,
323 Fcb->ObjectInformation->FileId.Vnode,
324 Fcb->ObjectInformation->FileId.Unique,
329 ulReleaseCount += ulProcessCount;
333 // Reinitialize the skip lists
336 ASSERT( Fcb->Specific.File.ExtentCount == 0);
338 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i++)
340 InitializeListHead(&Fcb->Specific.File.ExtentsLists[i]);
344 // Reinitialize the dirty list as well
347 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
350 ASSERT( Fcb->Specific.File.ExtentsDirtyCount == 0);
352 Fcb->NPFcb->Specific.File.DirtyListHead = NULL;
353 Fcb->NPFcb->Specific.File.DirtyListTail = NULL;
355 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
357 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
364 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
365 AFS_TRACE_LEVEL_VERBOSE,
366 "AFSTearDownFcbExtents Releasing Fcb extent lock %08lX thread %08lX\n",
367 &Fcb->NPFcb->Specific.File.ExtentsResource,
368 PsGetCurrentThread());
370 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
376 AFSExFreePool( pRelease);
380 return bFoundExtents;
384 ExtentForOffsetInList( IN AFSFcb *Fcb,
387 IN PLARGE_INTEGER Offset)
390 // Return the extent that maps the offset, that
391 // - Contains the offset
392 // - or is immediately ahead of the offset (in this list)
393 // - otherwise return NULL.
396 PLIST_ENTRY pLe = List;
397 AFSExtent *pPrevious = NULL;
399 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
401 while (pLe != &Fcb->Specific.File.ExtentsLists[ListNumber])
405 entry = ExtentFor( pLe, ListNumber );
412 if (Offset->QuadPart < entry->FileOffset.QuadPart)
415 // Offset is ahead of entry. Return previous
420 if (Offset->QuadPart >= (entry->FileOffset.QuadPart + entry->Size))
423 // We start after this extent - carry on round
431 // Otherwise its a match
438 // Got to the end. Return Previous
444 AFSExtentContains( IN AFSExtent *Extent, IN PLARGE_INTEGER Offset)
450 return (Extent->FileOffset.QuadPart <= Offset->QuadPart &&
451 (Extent->FileOffset.QuadPart + Extent->Size) > Offset->QuadPart);
456 // Return the extent that contains the offset
459 AFSExtentForOffsetHint( IN AFSFcb *Fcb,
460 IN PLARGE_INTEGER Offset,
461 IN BOOLEAN ReturnPrevious,
464 AFSExtent *pPrevious = Hint;
468 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
470 #if AFS_VALIDATE_EXTENTS
471 VerifyExtentsLists(Fcb);
475 // So we will go across the skip lists until we find an
476 // appropriate entry (previous or direct match). If it's a match
477 // we are done, other wise we start on the next layer down
479 for (i = AFS_NUM_EXTENT_LISTS-1; i >= AFS_EXTENTS_LIST; i--)
481 if (NULL == pPrevious)
484 // We haven't found anything in the previous layers
486 pLe = Fcb->Specific.File.ExtentsLists[i].Flink;
488 else if (NULL == pPrevious->Lists[i].Flink)
490 ASSERT(AFS_EXTENTS_LIST != i);
492 // The hint doesn't exist at this level, next one down
499 // take the previous into the next
501 pLe = &pPrevious->Lists[i];
504 pPrevious = ExtentForOffsetInList( Fcb, pLe, i, Offset);
506 if (NULL != pPrevious && AFSExtentContains(pPrevious, Offset))
509 // Found it immediately. Stop here
515 if (NULL == pPrevious || ReturnPrevious )
520 ASSERT( !AFSExtentContains(pPrevious, Offset) );
526 AFSEntryForOffset( IN AFSFcb *Fcb,
527 IN PLARGE_INTEGER Offset)
529 AFSExtent *pPrevious = NULL;
533 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
535 #if AFS_VALIDATE_EXTENTS
536 VerifyExtentsLists(Fcb);
540 // So we will go across the skip lists until we find an
541 // appropriate entry (previous or direct match). If it's a match
542 // we are done, other wise we start on the next layer down
544 for (i = AFS_NUM_EXTENT_LISTS-1; i >= AFS_EXTENTS_LIST; i--)
546 if (NULL == pPrevious)
549 // We haven't found anything in the previous layers
551 pLe = Fcb->Specific.File.ExtentsLists[i].Flink;
553 else if (NULL == pPrevious->Lists[i].Flink)
555 ASSERT(AFS_EXTENTS_LIST != i);
557 // The hint doesn't exist at this level, next one down
564 // take the previous into the next
566 pLe = &pPrevious->Lists[i];
569 pPrevious = ExtentForOffsetInList( Fcb, pLe, i, Offset);
571 if (NULL != pPrevious && AFSExtentContains(pPrevious, Offset))
574 // Found it immediately. Stop here
584 AFSExtentForOffset( IN AFSFcb *Fcb,
585 IN PLARGE_INTEGER Offset,
586 IN BOOLEAN ReturnPrevious)
588 return AFSExtentForOffsetHint(Fcb, Offset, ReturnPrevious, NULL);
592 BOOLEAN AFSDoExtentsMapRegion(IN AFSFcb *Fcb,
593 IN PLARGE_INTEGER Offset,
595 IN OUT AFSExtent **FirstExtent,
596 OUT AFSExtent **LastExtent)
599 // Return TRUE region is completely mapped. FALSE
600 // otherwise. If the region isn't mapped then the last
601 // extent to map part of the region is returned.
603 // *LastExtent as input is where to start looking.
604 // *LastExtent as output is either the extent which
605 // contains the Offset, or the last one which doesn't
609 BOOLEAN retVal = FALSE;
614 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
615 AFS_TRACE_LEVEL_VERBOSE,
616 "AFSDoExtentsMapRegion Acquiring Fcb extent lock %08lX SHARED %08lX\n",
617 &Fcb->NPFcb->Specific.File.ExtentsResource,
618 PsGetCurrentThread());
620 AFSAcquireShared( &Fcb->NPFcb->Specific.File.ExtentsResource, TRUE );
624 entry = AFSExtentForOffsetHint(Fcb, Offset, TRUE, *FirstExtent);
625 *FirstExtent = entry;
627 if (NULL == entry || !AFSExtentContains(entry, Offset))
629 try_return (retVal = FALSE);
632 ASSERT(Offset->QuadPart >= entry->FileOffset.QuadPart);
636 if ((entry->FileOffset.QuadPart + entry->Size) >=
637 (Offset->QuadPart + Size))
640 // The end is inside the extent
642 try_return (retVal = TRUE);
645 if (entry->Lists[AFS_EXTENTS_LIST].Flink == &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
648 // Run out of extents
650 try_return (retVal = FALSE);
653 newEntry = NextExtent( entry, AFS_EXTENTS_LIST );
655 if (newEntry->FileOffset.QuadPart !=
656 (entry->FileOffset.QuadPart + entry->Size))
661 try_return (retVal = FALSE);
667 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
672 "EXCEPTION - AFSDoExtentsMapRegion\n");
674 AFSDumpTraceFilesFnc();
679 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
680 AFS_TRACE_LEVEL_VERBOSE,
681 "AFSDoExtentsMapRegion Releasing Fcb extent lock %08lX SHARED %08lX\n",
682 &Fcb->NPFcb->Specific.File.ExtentsResource,
683 PsGetCurrentThread());
685 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
694 AFSRequestExtentsAsync( IN AFSFcb *Fcb,
696 IN PLARGE_INTEGER Offset,
700 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
701 NTSTATUS ntStatus = STATUS_SUCCESS;
702 AFSExtent *pExtent = NULL;
703 AFSRequestExtentsCB request;
704 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
705 AFSExtent *pFirstExtent = NULL;
706 LARGE_INTEGER liAlignedOffset;
707 ULONG ulAlignedLength = 0;
708 BOOLEAN bRegionMapped = FALSE;
709 ULONGLONG ullProcessId = (ULONGLONG)PsGetCurrentProcessId();
714 ASSERT( !ExIsResourceAcquiredLite( &pNPFcb->Specific.File.ExtentsResource ));
717 // If the service set a failure on the file since the last
718 // CreateFile was issued, return it now.
721 if (!NT_SUCCESS( pNPFcb->Specific.File.ExtentsRequestStatus))
725 // If this isn't the same authgroup which caused the failure
726 // then try to request them again
729 if( RtlCompareMemory( &pNPFcb->Specific.File.ExtentsRequestAuthGroup,
731 sizeof( GUID)) == sizeof( GUID))
734 ntStatus = pNPFcb->Specific.File.ExtentsRequestStatus;
736 pNPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
738 RtlZeroMemory( &pNPFcb->Specific.File.ExtentsRequestAuthGroup,
741 try_return( ntStatus);
746 // Check if we are already mapped
749 bRegionMapped = AFSDoExtentsMapRegion( Fcb, Offset, Size, &pFirstExtent, &pExtent);
754 try_return( ntStatus = STATUS_SUCCESS);
758 // Align our request on extent size boundary
761 ulAlignedLength = Size;
763 liAlignedOffset = *Offset;
765 if( liAlignedOffset.QuadPart % pDevExt->Specific.RDR.CacheBlockSize != 0)
768 liAlignedOffset.QuadPart = (ULONGLONG)( (ULONGLONG)(liAlignedOffset.QuadPart / pDevExt->Specific.RDR.CacheBlockSize) * (ULONGLONG)pDevExt->Specific.RDR.CacheBlockSize);
770 ulAlignedLength += (ULONG)(Offset->QuadPart - liAlignedOffset.QuadPart);
773 if( ulAlignedLength % pDevExt->Specific.RDR.CacheBlockSize != 0)
776 ulAlignedLength = (ULONG)(((ulAlignedLength / pDevExt->Specific.RDR.CacheBlockSize) + 1) * pDevExt->Specific.RDR.CacheBlockSize);
779 RtlZeroMemory( &request,
780 sizeof( AFSRequestExtentsCB));
782 request.ByteOffset = liAlignedOffset;
783 request.Length = ulAlignedLength;
785 if( !AFSIsExtentRequestQueued( &Fcb->ObjectInformation->FileId,
790 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
791 AFS_TRACE_LEVEL_VERBOSE,
792 "AFSRequestExtentsAsync Request extents for fid %08lX-%08lX-%08lX-%08lX Offset %08lX Len %08lX Thread %08lX\n",
793 Fcb->ObjectInformation->FileId.Cell,
794 Fcb->ObjectInformation->FileId.Volume,
795 Fcb->ObjectInformation->FileId.Vnode,
796 Fcb->ObjectInformation->FileId.Unique,
797 request.ByteOffset.LowPart,
799 PsGetCurrentThread());
801 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS,
805 &Fcb->ObjectInformation->FileId,
807 sizeof( AFSRequestExtentsCB ),
811 if ( ntStatus == STATUS_ACCESS_DENIED)
816 ntStatus2 = AFSRetrieveValidAuthGroup( Fcb,
821 if ( NT_SUCCESS( ntStatus2) &&
822 RtlCompareMemory( &stAuthGroup,
824 sizeof( GUID)) != sizeof( GUID))
827 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS,
831 &Fcb->ObjectInformation->FileId,
833 sizeof( AFSRequestExtentsCB ),
839 if( NT_SUCCESS( ntStatus))
842 KeClearEvent( &pNPFcb->Specific.File.ExtentsRequestComplete );
848 KeClearEvent( &pNPFcb->Specific.File.ExtentsRequestComplete );
860 AFSProcessExtentsResult( IN AFSFcb *Fcb,
862 IN AFSFileExtentCB *Result)
864 NTSTATUS ntStatus = STATUS_SUCCESS;
865 AFSFileExtentCB *pFileExtents = Result;
868 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
869 ULONG fileExtentsUsed = 0;
870 BOOLEAN bFoundExtent = FALSE;
871 LIST_ENTRY *pSkipEntries[AFS_NUM_EXTENT_LISTS] = { 0 };
872 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
876 // Grab the extents exclusive for the duration
879 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
880 AFS_TRACE_LEVEL_VERBOSE,
881 "AFSProcessExtentsResult Acquiring Fcb extent lock %08lX EXCL %08lX\n",
882 &pNPFcb->Specific.File.ExtentsResource,
883 PsGetCurrentThread());
885 AFSAcquireExcl( &pNPFcb->Specific.File.ExtentsResource, TRUE );
891 // Find where to put the extents
893 for (ULONG i = AFS_EXTENTS_LIST; i < AFS_NUM_EXTENT_LISTS; i++)
896 pSkipEntries[i] = Fcb->Specific.File.ExtentsLists[i].Flink;
899 le = pSkipEntries[AFS_EXTENTS_LIST];
901 if (le == &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
904 // No extents. Insert at head of list (which is where the skip lists point!)
908 else if (0 != pFileExtents->FileOffset.QuadPart)
911 // We want to find the best extents immediately *behind* this offset
913 LARGE_INTEGER offset = pFileExtents->FileOffset;
916 // Ask in the top skip list first, then work down
918 for (LONG i = AFS_NUM_EXTENT_LISTS-1; i >= AFS_EXTENTS_LIST; i--)
920 pExtent = ExtentForOffsetInList( Fcb,
928 // No dice. Header has to become the head of the list
930 pSkipEntries[i] = &Fcb->Specific.File.ExtentsLists[i];
932 // And as a loop invariant we should never have found an extent
934 ASSERT(!bFoundExtent);
939 // pExtent is where to start to insert at this level
941 pSkipEntries[i] = &pExtent->Lists[i];
944 // And also where to start to look at the next level
947 if (i > AFS_EXTENTS_LIST)
949 pSkipEntries[i-1] = &pExtent->Lists[i-1];
957 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
962 le = pExtent->Lists[AFS_EXTENTS_LIST].Blink;
968 // Looking at offset 0, so we must start at the beginning
971 pExtent = ExtentFor(le, AFS_EXTENTS_LIST);
975 // And set up the skip lists
978 for (ULONG i = AFS_EXTENTS_LIST; i < AFS_NUM_EXTENT_LISTS; i++)
980 pSkipEntries[i] = &Fcb->Specific.File.ExtentsLists[i];
984 while (fileExtentsUsed < Count)
988 // Loop invariant - le points to where to insert after and
989 // pExtent points to le->fLink
992 ASSERT (NULL == pExtent ||
993 le->Flink == &pExtent->Lists[AFS_EXTENTS_LIST]);
995 if (NULL == pExtent ||
996 pExtent->FileOffset.QuadPart > pFileExtents->FileOffset.QuadPart)
999 // We need to insert a new extent at le. Start with
1000 // some sanity check on spanning
1002 if (NULL != pExtent &&
1003 ((pFileExtents->FileOffset.QuadPart + pFileExtents->Length) >
1004 pExtent->FileOffset.QuadPart))
1007 // File Extents overlaps pExtent
1009 ASSERT( (pFileExtents->FileOffset.QuadPart + pFileExtents->Length) <=
1010 pExtent->FileOffset.QuadPart);
1012 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1016 // File offset is entirely in front of this extent. Create
1017 // a new one (remember le is the previous list entry)
1019 pExtent = (AFSExtent *) AFSExAllocatePoolWithTag( NonPagedPool,
1022 if (NULL == pExtent)
1025 try_return (ntStatus = STATUS_INSUFFICIENT_RESOURCES );
1028 RtlZeroMemory( pExtent, sizeof( AFSExtent ));
1030 pExtent->FileOffset = pFileExtents->FileOffset;
1031 pExtent->CacheOffset = pFileExtents->CacheOffset;
1032 pExtent->Size = pFileExtents->Length;
1034 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1035 AFS_TRACE_LEVEL_VERBOSE,
1036 "AFSProcessExtentsResult Received extent for fid %08lX-%08lX-%08lX-%08lX File Offset %I64X Cache Offset %I64X Len %08lX\n",
1037 Fcb->ObjectInformation->FileId.Cell,
1038 Fcb->ObjectInformation->FileId.Volume,
1039 Fcb->ObjectInformation->FileId.Vnode,
1040 Fcb->ObjectInformation->FileId.Unique,
1041 pFileExtents->FileOffset.QuadPart,
1042 pFileExtents->CacheOffset.QuadPart,
1043 pFileExtents->Length);
1045 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, (LONG)(pExtent->Size/1024));
1047 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, (LONG)(pExtent->Size/1024));
1049 lCount = InterlockedIncrement( &Fcb->Specific.File.ExtentCount);
1051 lCount = InterlockedIncrement( &pControlDevExt->Specific.Control.ExtentCount);
1056 KeClearEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent);
1062 InsertHeadList(le, &pExtent->Lists[AFS_EXTENTS_LIST]);
1063 ASSERT(le->Flink == &pExtent->Lists[AFS_EXTENTS_LIST]);
1064 ASSERT(0 == (pExtent->FileOffset.LowPart & ExtentsMasks[AFS_EXTENTS_LIST]));
1067 // Do not move the cursor - we will do it next time
1071 // And into the (upper) skip lists - Again, do not move the cursor
1073 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1075 if (0 == (pExtent->FileOffset.LowPart & ExtentsMasks[i]))
1077 InsertHeadList(pSkipEntries[i], &pExtent->Lists[i]);
1078 #if AFS_VALIDATE_EXTENTS
1079 VerifyExtentsLists(Fcb);
1084 else if (pExtent->FileOffset.QuadPart == pFileExtents->FileOffset.QuadPart)
1087 if (pExtent->Size != pFileExtents->Length)
1090 ASSERT (pExtent->Size == pFileExtents->Length);
1092 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1096 // Move both cursors forward.
1098 // First the extent pointer
1101 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1104 // Then the skip lists cursors forward if needed
1106 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1108 if (0 == (pExtent->FileOffset.LowPart & ExtentsMasks[i]))
1111 // Check sanity before
1113 #if AFS_VALIDATE_EXTENTS
1114 VerifyExtentsLists(Fcb);
1118 // Skip list should point to us
1120 //ASSERT(pSkipEntries[i] == &pExtent->Lists[i]);
1122 // Move forward cursor
1124 pSkipEntries[i] = pSkipEntries[i]->Flink;
1126 // Check sanity before
1128 #if AFS_VALIDATE_EXTENTS
1129 VerifyExtentsLists(Fcb);
1135 // And then the cursor in the supplied array
1141 // setup pExtent if there is one
1143 if (le->Flink != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
1145 pExtent = NextExtent( pExtent, AFS_EXTENTS_LIST ) ;
1155 ASSERT( pExtent->FileOffset.QuadPart < pFileExtents->FileOffset.QuadPart );
1158 // Sanity check on spanning
1160 if ((pExtent->FileOffset.QuadPart + pExtent->Size) >
1161 pFileExtents->FileOffset.QuadPart)
1164 ASSERT( (pExtent->FileOffset.QuadPart + pExtent->Size) <=
1165 pFileExtents->FileOffset.QuadPart);
1167 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1171 // Move le and pExtent forward
1173 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1177 // Then the check the skip lists cursors
1179 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1181 if (0 == (pFileExtents->FileOffset.LowPart & ExtentsMasks[i]))
1185 // - empty list (pSkipEntries[i]->Flink == pSkipEntries[i]->Flink == fcb->lists[i]
1186 // - We are the last on the list (pSkipEntries[i]->Flink == fcb->lists[i])
1187 // - We are not the last on the list. In that case we have to be strictly less than
1189 if (pSkipEntries[i]->Flink != &Fcb->Specific.File.ExtentsLists[i]) {
1191 AFSExtent *otherExtent = ExtentFor(pSkipEntries[i]->Flink, i);
1192 ASSERT(pFileExtents->FileOffset.QuadPart < otherExtent->FileOffset.QuadPart);
1199 // setup pExtent if there is one
1202 if (le->Flink != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
1204 pExtent = NextExtent( pExtent, AFS_EXTENTS_LIST ) ;
1214 // All done, signal that we are done drop the lock, exit
1219 if( !NT_SUCCESS( ntStatus))
1223 // If we failed the service is going to drop all extents so trim away the
1227 AFSTrimSpecifiedExtents( Fcb,
1232 #if AFS_VALIDATE_EXTENTS
1233 VerifyExtentsLists(Fcb);
1236 KeSetEvent( &pNPFcb->Specific.File.ExtentsRequestComplete,
1240 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1241 AFS_TRACE_LEVEL_VERBOSE,
1242 "AFSProcessExtentsResult Releasing Fcb extent lock %08lX EXCL %08lX\n",
1243 &pNPFcb->Specific.File.ExtentsResource,
1244 PsGetCurrentThread());
1246 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
1253 AFSProcessSetFileExtents( IN AFSSetFileExtentsCB *SetExtents )
1255 AFSFcb *pFcb = NULL;
1256 AFSVolumeCB *pVolumeCB = NULL;
1257 NTSTATUS ntStatus = STATUS_SUCCESS;
1258 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1259 ULONGLONG ullIndex = 0;
1260 AFSObjectInfoCB *pObjectInfo = NULL;
1266 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1267 AFS_TRACE_LEVEL_VERBOSE,
1268 "AFSProcessSetFileExtents Acquiring RDR VolumeTreeLock lock %08lX SHARED %08lX\n",
1269 &pDevExt->Specific.RDR.VolumeTreeLock,
1270 PsGetCurrentThread());
1272 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
1274 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1275 AFS_TRACE_LEVEL_VERBOSE,
1276 "AFSProcessSetFileExtents Set extents for fid %08lX-%08lX-%08lX-%08lX\n",
1277 SetExtents->FileId.Cell,
1278 SetExtents->FileId.Volume,
1279 SetExtents->FileId.Vnode,
1280 SetExtents->FileId.Unique);
1283 // Locate the volume node
1286 ullIndex = AFSCreateHighIndex( &SetExtents->FileId);
1288 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
1290 (AFSBTreeEntry **)&pVolumeCB);
1292 if( pVolumeCB != NULL)
1295 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1296 AFS_TRACE_LEVEL_VERBOSE,
1297 "AFSProcessSetFileExtents Acquiring VolumeRoot FileIDTree.TreeLock lock %08lX SHARED %08lX\n",
1298 pVolumeCB->ObjectInfoTree.TreeLock,
1299 PsGetCurrentThread());
1301 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1304 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
1306 if( !NT_SUCCESS( ntStatus) ||
1310 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1311 AFS_TRACE_LEVEL_ERROR,
1312 "AFSProcessSetFileExtents Set extents for fid %08lX-%08lX-%08lX-%08lX Failed to locate volume Status %08lX\n",
1313 SetExtents->FileId.Cell,
1314 SetExtents->FileId.Volume,
1315 SetExtents->FileId.Vnode,
1316 SetExtents->FileId.Unique,
1319 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1322 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1325 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1328 // Now locate the Object in this volume
1331 ullIndex = AFSCreateLowIndex( &SetExtents->FileId);
1333 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
1335 (AFSBTreeEntry **)&pObjectInfo);
1337 if( pObjectInfo != NULL)
1341 // Reference the node so it won't be torn down
1344 lCount = InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
1346 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1347 AFS_TRACE_LEVEL_VERBOSE,
1348 "AFSProcessSetFileExtents Increment count on object %08lX Cnt %d\n",
1353 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1355 if( !NT_SUCCESS( ntStatus) ||
1356 pObjectInfo == NULL)
1359 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1360 AFS_TRACE_LEVEL_ERROR,
1361 "AFSProcessSetFileExtents Set extents for hash %I64X fid %08lX-%08lX-%08lX-%08lX Failed to locate file in volume %08lX\n",
1363 SetExtents->FileId.Cell,
1364 SetExtents->FileId.Volume,
1365 SetExtents->FileId.Vnode,
1366 SetExtents->FileId.Unique,
1369 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1372 pFcb = pObjectInfo->Fcb;
1375 // If we have a result failure then don't bother trying to set the extents
1378 if( SetExtents->ResultStatus != STATUS_SUCCESS)
1381 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1382 AFS_TRACE_LEVEL_ERROR,
1383 "AFSProcessSetFileExtents Set extents failure fid %08lX-%08lX-%08lX-%08lX ResultStatus %08lX\n",
1384 SetExtents->FileId.Cell,
1385 SetExtents->FileId.Volume,
1386 SetExtents->FileId.Vnode,
1387 SetExtents->FileId.Unique,
1388 SetExtents->ResultStatus);
1390 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1391 AFS_TRACE_LEVEL_VERBOSE,
1392 "AFSProcessSetFileExtents Acquiring Fcb extents lock %08lX EXCL %08lX\n",
1393 &pFcb->NPFcb->Specific.File.ExtentsResource,
1394 PsGetCurrentThread());
1396 AFSAcquireExcl( &pFcb->NPFcb->Specific.File.ExtentsResource,
1399 pFcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_CANCELLED;
1401 KeSetEvent( &pFcb->NPFcb->Specific.File.ExtentsRequestComplete,
1405 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1406 AFS_TRACE_LEVEL_VERBOSE,
1407 "AFSProcessSetFileExtents Releasing Fcb extent lock %08lX EXCL %08lX\n",
1408 &pFcb->NPFcb->Specific.File.ExtentsResource,
1409 PsGetCurrentThread());
1411 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
1413 try_return( ntStatus);
1416 ntStatus = AFSProcessExtentsResult ( pFcb,
1417 SetExtents->ExtentCount,
1418 SetExtents->FileExtents );
1422 if( pObjectInfo != NULL)
1425 lCount = InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
1427 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1428 AFS_TRACE_LEVEL_VERBOSE,
1429 "AFSProcessSetFileExtents Decrement count on object %08lX Cnt %d\n",
1439 // Helper fuctions for Usermode initiation of release of extents
1442 AFSReleaseSpecifiedExtents( IN AFSReleaseFileExtentsCB *Extents,
1444 OUT AFSFileExtentCB *FileExtents,
1445 IN ULONG BufferSize,
1446 OUT ULONG *ExtentCount,
1447 OUT BOOLEAN *DirtyExtents)
1452 ULONG ulExtentCount = 0;
1453 NTSTATUS ntStatus = STATUS_SUCCESS;
1454 BOOLEAN bReleaseAll = FALSE;
1455 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1460 ASSERT( ExIsResourceAcquiredExclusiveLite( &Fcb->NPFcb->Specific.File.ExtentsResource));
1462 if (BufferSize < (Extents->ExtentCount * sizeof( AFSFileExtentCB)))
1465 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1466 AFS_TRACE_LEVEL_VERBOSE,
1467 "AFSReleaseSpecifiedExtents Buffer too small\n");
1469 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL);
1472 RtlZeroMemory( FileExtents, BufferSize);
1475 *DirtyExtents = FALSE;
1478 // iterate until we have dealt with all we were asked for or
1479 // are at the end of the list. Note that this deals (albeit
1480 // badly) with out of order extents
1483 pExtent = AFSExtentForOffset( Fcb,
1484 &Extents->FileExtents[0].FileOffset,
1487 if (NULL == pExtent)
1489 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1493 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1497 if( BooleanFlagOn( Extents->Flags, AFS_RELEASE_EXTENTS_FLAGS_RELEASE_ALL) ||
1498 ( Extents->FileId.Cell == 0 &&
1499 Extents->FileId.Volume == 0 &&
1500 Extents->FileId.Vnode == 0 &&
1501 Extents->FileId.Unique == 0))
1507 while( le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST] &&
1508 ulExtentCount < Extents->ExtentCount)
1512 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
1517 if( pExtent->FileOffset.QuadPart < Extents->FileExtents[ulExtentCount].FileOffset.QuadPart)
1520 // Skip forward through the extent list until we get
1521 // to the one we want
1527 else if (pExtent->FileOffset.QuadPart > Extents->FileExtents[ulExtentCount].FileOffset.QuadPart)
1530 // We don't have the extent asked for so return UNKNOWN
1533 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1534 AFS_TRACE_LEVEL_VERBOSE,
1535 "AFSReleaseSpecifiedExtents Located UNKNOWN extent Offset %I64X Len %08lX\n",
1536 Extents->FileExtents[ulExtentCount].FileOffset.QuadPart,
1537 Extents->FileExtents[ulExtentCount].Length);
1539 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_UNKNOWN;
1541 FileExtents[*ExtentCount].Length = 0;
1542 FileExtents[*ExtentCount].CacheOffset.QuadPart = 0;
1543 FileExtents[*ExtentCount].FileOffset = Extents->FileExtents[ulExtentCount].FileOffset;
1545 *ExtentCount = (*ExtentCount) + 1;
1550 // Reset where we are looking
1553 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1557 else if( pExtent->ActiveCount > 0)
1560 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1561 AFS_TRACE_LEVEL_VERBOSE,
1562 "AFSReleaseSpecifiedExtents Located IN_USE extent Offset %I64X Len %08lX\n",
1563 Extents->FileExtents[ulExtentCount].FileOffset.QuadPart,
1564 Extents->FileExtents[ulExtentCount].Length);
1566 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_IN_USE;
1568 FileExtents[*ExtentCount].Length = 0;
1569 FileExtents[*ExtentCount].CacheOffset.QuadPart = 0;
1570 FileExtents[*ExtentCount].FileOffset = Extents->FileExtents[ulExtentCount].FileOffset;
1572 *ExtentCount = (*ExtentCount) + 1;
1577 // Reset where we are looking
1580 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1589 // If the extent is currently active then skip it
1592 if( pExtent->ActiveCount > 0)
1601 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_RELEASE;
1603 FileExtents[*ExtentCount].Length = pExtent->Size;
1604 FileExtents[*ExtentCount].DirtyLength = pExtent->Size;
1605 FileExtents[*ExtentCount].DirtyOffset = 0;
1606 FileExtents[*ExtentCount].CacheOffset = pExtent->CacheOffset;
1607 FileExtents[*ExtentCount].FileOffset = pExtent->FileOffset;
1609 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1610 AFS_TRACE_LEVEL_VERBOSE,
1611 "AFSReleaseSpecifiedExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
1613 Fcb->ObjectInformation->FileId.Cell,
1614 Fcb->ObjectInformation->FileId.Volume,
1615 Fcb->ObjectInformation->FileId.Vnode,
1616 Fcb->ObjectInformation->FileId.Unique,
1617 FileExtents[*ExtentCount].FileOffset.QuadPart,
1618 FileExtents[*ExtentCount].Length);
1620 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
1623 AFSAcquireExcl( &Fcb->NPFcb->Specific.File.DirtyExtentsListLock,
1626 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
1629 AFSRemoveEntryDirtyList( Fcb,
1632 FileExtents[*ExtentCount].Flags |= AFS_EXTENT_FLAG_DIRTY;
1634 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
1636 *DirtyExtents = TRUE;
1639 AFSReleaseResource( &Fcb->NPFcb->Specific.File.DirtyExtentsListLock);
1643 // move forward all three cursors
1647 *ExtentCount = (*ExtentCount) + 1;
1652 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
1654 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
1656 RemoveEntryList( &pExtent->Lists[i] );
1660 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
1662 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
1667 AFSExFreePool( pExtent);
1669 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
1671 lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount);
1676 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
1691 AFSFindFcbToClean(ULONG IgnoreTime, AFSFcb *LastFcb, BOOLEAN Block)
1694 AFSFcb *pFcb = NULL;
1695 AFSVolumeCB *pVolumeCB = NULL;
1696 AFSDeviceExt *pRDRDeviceExt = NULL;
1697 AFSDeviceExt *pControlDeviceExt = NULL;
1698 BOOLEAN bLocatedEntry = FALSE;
1699 AFSObjectInfoCB *pCurrentObject = NULL;
1700 BOOLEAN bReleaseVolumeListLock = FALSE;
1703 pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1704 pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1706 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1707 AFS_TRACE_LEVEL_VERBOSE,
1708 "AFSFindFcbToClean Acquiring RDR VolumeListLock lock %08lX SHARED %08lX\n",
1709 &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1710 PsGetCurrentThread());
1712 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1715 bReleaseVolumeListLock = TRUE;
1717 pVolumeCB = pRDRDeviceExt->Specific.RDR.VolumeListHead;
1719 while( pVolumeCB != NULL)
1723 // The Volume list may move under our feet. Lock it.
1726 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1727 AFS_TRACE_LEVEL_VERBOSE,
1728 "AFSFindFcbToClean Acquiring VolumeRoot ObjectInfoTree lock %08lX SHARED %08lX\n",
1729 pVolumeCB->ObjectInfoTree.TreeLock,
1730 PsGetCurrentThread());
1732 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1734 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1736 bReleaseVolumeListLock = FALSE;
1738 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1741 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1743 if( NULL == LastFcb)
1746 pCurrentObject = pVolumeCB->ObjectInfoListHead;
1751 pCurrentObject = (AFSObjectInfoCB *)LastFcb->ObjectInformation->ListEntry.fLink;
1756 while( pCurrentObject != NULL)
1759 pFcb = (AFSFcb *)pCurrentObject->Fcb;
1762 // If the FCB is a candidate we try to lock it (but without waiting - which
1763 // means we are deadlock free
1767 pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
1773 AFSLockForExtentsTrim( pFcb);
1778 if( !AFSLockForExtentsTrimNoWait( pFcb))
1781 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1790 // Need to be sure there are no current flushes in the queue
1793 if( pFcb->Specific.File.ExtentCount == 0)
1796 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1797 AFS_TRACE_LEVEL_VERBOSE,
1798 "AFSFindFcbToClean Releasing Fcb extent lock %08lX thread %08lX\n",
1799 &pFcb->NPFcb->Specific.File.ExtentsResource,
1800 PsGetCurrentThread());
1802 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
1804 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1811 if( pFcb->Specific.File.QueuedFlushCount > 0)
1814 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1815 AFS_TRACE_LEVEL_VERBOSE,
1816 "AFSFindFcbToClean Releasing Fcb extent lock %08lX thread %08lX\n",
1817 &pFcb->NPFcb->Specific.File.ExtentsResource,
1818 PsGetCurrentThread());
1820 AFSReleaseResource(&pFcb->NPFcb->Specific.File.ExtentsResource);
1824 AFSWaitOnQueuedFlushes( pFcb);
1829 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1837 if( pFcb->OpenHandleCount > 0)
1840 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1841 AFS_TRACE_LEVEL_VERBOSE,
1842 "AFSFindFcbToClean Releasing Fcb extent lock %08lX thread %08lX\n",
1843 &pFcb->NPFcb->Specific.File.ExtentsResource,
1844 PsGetCurrentThread());
1846 AFSReleaseResource(&pFcb->NPFcb->Specific.File.ExtentsResource);
1848 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1856 // A hit a very palpable hit. Pin it
1859 lCount = InterlockedIncrement( &pCurrentObject->ObjectReferenceCount);
1861 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1862 AFS_TRACE_LEVEL_VERBOSE,
1863 "AFSFindFcbToClean Increment count on Fcb %08lX Cnt %d\n",
1867 bLocatedEntry = TRUE;
1872 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1877 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1884 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1887 bReleaseVolumeListLock = TRUE;
1889 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1892 if( bReleaseVolumeListLock)
1895 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1902 AFSProcessExtentFailure( PIRP Irp)
1904 AFSExtentFailureCB *pFailureCB = NULL;
1905 NTSTATUS ntStatus = STATUS_SUCCESS;
1906 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
1907 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1908 AFSVolumeCB *pVolumeCB = NULL;
1909 ULONGLONG ullIndex = 0;
1910 AFSObjectInfoCB *pObjectInfo = NULL;
1915 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSExtentFailureCB))
1918 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1919 AFS_TRACE_LEVEL_ERROR,
1920 "AFSProcessExtentFailure Input buffer too small\n");
1922 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1925 pFailureCB = (AFSExtentFailureCB *)Irp->AssociatedIrp.SystemBuffer;
1927 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1928 AFS_TRACE_LEVEL_ERROR,
1929 "AFSProcessExtentFailure Service Reports Failure fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1930 pFailureCB->FileId.Cell,
1931 pFailureCB->FileId.Volume,
1932 pFailureCB->FileId.Vnode,
1933 pFailureCB->FileId.Unique,
1934 pFailureCB->FailureStatus);
1936 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
1939 // Locate the volume node
1942 ullIndex = AFSCreateHighIndex( &pFailureCB->FileId);
1944 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
1946 (AFSBTreeEntry **)&pVolumeCB);
1948 if( pVolumeCB != NULL)
1951 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1952 AFS_TRACE_LEVEL_VERBOSE,
1953 "AFSProcessExtentFailure Acquiring VolumeRoot FileIDTree.TreeLock lock %08lX SHARED %08lX\n",
1954 pVolumeCB->ObjectInfoTree.TreeLock,
1955 PsGetCurrentThread());
1957 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1960 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
1962 if( !NT_SUCCESS( ntStatus) ||
1966 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1967 AFS_TRACE_LEVEL_ERROR,
1968 "AFSProcessExtentFailure Invalid volume index %I64X status %08X\n",
1969 ullIndex, ntStatus);
1971 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1974 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1977 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1980 // Now locate the Object in this volume
1983 ullIndex = AFSCreateLowIndex( &pFailureCB->FileId);
1985 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
1987 (AFSBTreeEntry **)&pObjectInfo);
1989 if( pObjectInfo != NULL &&
1990 pObjectInfo->Fcb != NULL)
1994 // Reference the node so it won't be torn down
1997 lCount = InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
1999 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2000 AFS_TRACE_LEVEL_VERBOSE,
2001 "AFSProcessExtentFailure Increment count on object %08lX Cnt %d\n",
2006 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2008 if( !NT_SUCCESS( ntStatus) ||
2009 pObjectInfo == NULL ||
2010 pObjectInfo->Fcb == NULL)
2013 if( pObjectInfo == NULL)
2015 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2016 AFS_TRACE_LEVEL_ERROR,
2017 "AFSProcessExtentFailure Invalid file index %I64X\n",
2022 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2023 AFS_TRACE_LEVEL_ERROR,
2024 "AFSProcessExtentFailure Fcb dealocated for %I64X\n",
2028 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2031 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2032 AFS_TRACE_LEVEL_VERBOSE,
2033 "AFSProcessExtentFailure Acquiring Fcb extent lock %08lX EXCL %08lX\n",
2034 &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2035 PsGetCurrentThread());
2037 AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2040 pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestStatus = pFailureCB->FailureStatus;
2042 RtlCopyMemory( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2043 &pFailureCB->AuthGroup,
2046 KeSetEvent( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
2050 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2051 AFS_TRACE_LEVEL_VERBOSE,
2052 "AFSProcessExtentFailure Releasing Fcb extent lock %08lX EXCL %08lX\n",
2053 &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2054 PsGetCurrentThread());
2056 AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource);
2058 lCount = InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
2060 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2061 AFS_TRACE_LEVEL_VERBOSE,
2062 "AFSProcessExtentFailure Decrement count on object %08lX Cnt %d\n",
2075 AFSProcessReleaseFileExtents( IN PIRP Irp)
2077 NTSTATUS ntStatus = STATUS_SUCCESS;
2078 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2079 PFILE_OBJECT pFileObject = pIrpSp->FileObject;
2080 AFSFcb *pFcb = NULL;
2081 AFSVolumeCB *pVolumeCB = NULL;
2082 AFSDeviceExt *pDevExt;
2083 AFSReleaseFileExtentsCB *pExtents;
2084 AFSReleaseFileExtentsResultCB *pResult = NULL;
2085 AFSReleaseFileExtentsResultFileCB *pFile = NULL;
2087 ULONGLONG ullIndex = 0;
2088 AFSObjectInfoCB *pObjectInfo = NULL;
2089 BOOLEAN bLocked = FALSE;
2090 BOOLEAN bDirtyExtents = FALSE;
2097 pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2099 pExtents = (AFSReleaseFileExtentsCB*) Irp->AssociatedIrp.SystemBuffer;
2101 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2102 sizeof( AFSReleaseFileExtentsCB))
2105 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2106 AFS_TRACE_LEVEL_ERROR,
2107 "AFSProcessReleaseFileExtents INPUT Buffer too small\n");
2109 try_return( ntStatus = STATUS_INVALID_PARAMETER );
2112 if ( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength <
2113 sizeof(AFSReleaseFileExtentsResultCB))
2116 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2117 AFS_TRACE_LEVEL_ERROR,
2118 "AFSProcessReleaseFileExtents OUTPUT Buffer too small [1]\n");
2121 // Must have space for one extent in one file
2124 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL);
2127 if (pExtents->ExtentCount == 0)
2130 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2131 AFS_TRACE_LEVEL_ERROR,
2132 "AFSProcessReleaseFileExtents Extent count zero\n");
2134 try_return( ntStatus = STATUS_INVALID_PARAMETER);
2137 if (pExtents->FileId.Cell != 0 ||
2138 pExtents->FileId.Volume != 0 ||
2139 pExtents->FileId.Vnode != 0 ||
2140 pExtents->FileId.Unique != 0)
2143 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2144 AFS_TRACE_LEVEL_VERBOSE,
2145 "AFSProcessReleaseFileExtents Processing FID %08lX:%08lX:%08lX:%08lX\n",
2146 pExtents->FileId.Cell,
2147 pExtents->FileId.Volume,
2148 pExtents->FileId.Vnode,
2149 pExtents->FileId.Unique);
2151 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2152 ( FIELD_OFFSET( AFSReleaseFileExtentsCB, ExtentCount) + sizeof(ULONG)) ||
2153 pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2154 ( FIELD_OFFSET( AFSReleaseFileExtentsCB, ExtentCount) + sizeof(ULONG) +
2155 sizeof (AFSFileExtentCB) * pExtents->ExtentCount))
2158 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2159 AFS_TRACE_LEVEL_ERROR,
2160 "AFSProcessReleaseFileExtents Buffer too small for FID %08lX:%08lx:%08lX:%08lX\n",
2161 pExtents->FileId.Cell,
2162 pExtents->FileId.Volume,
2163 pExtents->FileId.Vnode,
2164 pExtents->FileId.Unique);
2166 try_return( ntStatus = STATUS_INVALID_PARAMETER );
2169 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2170 AFS_TRACE_LEVEL_VERBOSE,
2171 "AFSProcessReleaseFileExtents Acquiring RDR VolumeTreeLock lock %08lX SHARED %08lX\n",
2172 &pDevExt->Specific.RDR.VolumeTreeLock,
2173 PsGetCurrentThread());
2175 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
2178 // Locate the volume node
2181 ullIndex = AFSCreateHighIndex( &pExtents->FileId);
2183 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
2185 (AFSBTreeEntry **)&pVolumeCB);
2187 if( pVolumeCB != NULL)
2190 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2191 AFS_TRACE_LEVEL_VERBOSE,
2192 "AFSProcessReleaseFileExtents Acquiring VolumeRoot FileIDTree.TreeLock lock %08lX SHARED %08lX\n",
2193 pVolumeCB->ObjectInfoTree.TreeLock,
2194 PsGetCurrentThread());
2196 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
2199 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
2201 if( !NT_SUCCESS( ntStatus) ||
2205 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2206 AFS_TRACE_LEVEL_ERROR,
2207 "AFSProcessReleaseFileExtents Invalid volume index %I64X status %08X\n",
2208 ullIndex, ntStatus);
2210 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2213 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
2216 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
2219 // Now locate the Object in this volume
2222 ullIndex = AFSCreateLowIndex( &pExtents->FileId);
2224 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
2226 (AFSBTreeEntry **)&pObjectInfo);
2228 if( pObjectInfo != NULL)
2232 // Reference the node so it won't be torn down
2235 lCount = InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
2237 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2238 AFS_TRACE_LEVEL_VERBOSE,
2239 "AFSProcessReleaseFileExtents Increment count on object %08lX Cnt %d\n",
2244 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2246 if( !NT_SUCCESS( ntStatus) ||
2247 pObjectInfo == NULL)
2250 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2251 AFS_TRACE_LEVEL_ERROR,
2252 "AFSProcessReleaseFileExtents Invalid file index %I64X\n",
2255 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2258 pFcb = pObjectInfo->Fcb;
2263 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2264 AFS_TRACE_LEVEL_ERROR,
2265 "AFSProcessReleaseFileExtents Fcb not initialied (NO EXTENTS) for FID %08lX:%08lx:%08lX:%08lX\n",
2266 pExtents->FileId.Cell,
2267 pExtents->FileId.Volume,
2268 pExtents->FileId.Vnode,
2269 pExtents->FileId.Unique);
2271 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2274 AFSLockForExtentsTrim( pFcb );
2282 // Locate an Fcb to trim down
2285 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2286 AFS_TRACE_LEVEL_VERBOSE,
2287 "AFSProcessReleaseFileExtents Searching for a Fcb to Trim Down\n");
2289 pFcb = AFSFindFcbToClean( 0, NULL, FALSE);
2294 pFcb = AFSFindFcbToClean( 0, NULL, TRUE);
2300 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2301 AFS_TRACE_LEVEL_ERROR,
2302 "AFSProcessReleaseFileExtents Failed to locate Fcb for release ...\n");
2304 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2307 pObjectInfo = pFcb->ObjectInformation;
2313 // Allocate a scratch buffer to move in the extent information
2316 ulSz = (pExtents->ExtentCount-1) * sizeof(AFSFileExtentCB);
2317 ulSz += sizeof(AFSReleaseFileExtentsResultCB);
2319 if (ulSz > pIrpSp->Parameters.DeviceIoControl.OutputBufferLength)
2321 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2322 AFS_TRACE_LEVEL_ERROR,
2323 "AFSProcessReleaseFileExtents OUTPUT Buffer too small [2]\n");
2325 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL );
2328 pResult = (AFSReleaseFileExtentsResultCB*) AFSExAllocatePoolWithTag( PagedPool,
2330 AFS_EXTENTS_RESULT_TAG);
2331 if (NULL == pResult)
2334 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2335 AFS_TRACE_LEVEL_ERROR,
2336 "AFSProcessReleaseFileExtents Failed to allocate result block\n");
2338 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2342 // Set up the header (for an array of one)
2344 pResult->FileCount = 1;
2345 pResult->Flags = AFS_EXTENT_FLAG_RELEASE;
2346 ulSz -= FIELD_OFFSET(AFSReleaseFileExtentsResultCB, Files);
2349 // Setup the first (and only) file
2351 pFile = pResult->Files;
2352 pFile->FileId = pObjectInfo->FileId;
2353 pFile->Flags = AFS_EXTENT_FLAG_RELEASE;
2356 // Stash away the auth group
2359 RtlZeroMemory( &stAuthGroup,
2362 ntStatus = AFSRetrieveValidAuthGroup( pFcb,
2367 if( !NT_SUCCESS( ntStatus))
2369 try_return( ntStatus);
2372 RtlCopyMemory( &pFile->AuthGroup,
2377 // Update the metadata for this call
2380 pFile->AllocationSize = pFcb->ObjectInformation->EndOfFile;
2381 pFile->CreateTime = pFcb->ObjectInformation->CreationTime;
2382 pFile->ChangeTime = pFcb->ObjectInformation->ChangeTime;
2383 pFile->LastAccessTime = pFcb->ObjectInformation->LastAccessTime;
2384 pFile->LastWriteTime = pFcb->ObjectInformation->LastWriteTime;
2386 ulSz -= FIELD_OFFSET(AFSReleaseFileExtentsResultFileCB, FileExtents);
2388 ntStatus = AFSReleaseSpecifiedExtents( pExtents,
2392 &pFile->ExtentCount,
2395 if (!NT_SUCCESS(ntStatus))
2398 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2399 AFS_TRACE_LEVEL_ERROR,
2400 "AFSProcessReleaseFileExtents Failed to release extents Status %08lX\n",
2403 try_return( ntStatus );
2406 if( pExtents->ExtentCount == 0)
2409 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2410 AFS_TRACE_LEVEL_WARNING,
2411 "AFSProcessReleaseFileExtents Failed to release ANY extents\n");
2414 ulSz = sizeof(AFSReleaseFileExtentsResultCB);
2416 if( pExtents->ExtentCount > 0)
2418 ulSz += ((pExtents->ExtentCount-1) * sizeof(AFSFileExtentCB));
2421 RtlCopyMemory( Irp->AssociatedIrp.SystemBuffer,
2430 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2431 AFS_TRACE_LEVEL_VERBOSE,
2432 "AFSProcessReleaseFileExtents Releasing Fcb extent lock %08lX thread %08lX\n",
2433 &pFcb->NPFcb->Specific.File.ExtentsResource,
2434 PsGetCurrentThread());
2436 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
2439 if( NULL != pResult &&
2440 Irp->AssociatedIrp.SystemBuffer != pResult)
2443 AFSExFreePool(pResult);
2446 if (NT_SUCCESS(ntStatus))
2448 Irp->IoStatus.Information = ulSz;
2452 Irp->IoStatus.Information = 0;
2455 Irp->IoStatus.Status = ntStatus;
2457 if( pObjectInfo != NULL)
2460 lCount = InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
2462 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2463 AFS_TRACE_LEVEL_VERBOSE,
2464 "AFSProcessReleaseFileExtents Decrement count on object %08lX Cnt %d\n",
2474 AFSWaitForExtentMapping( AFSFcb *Fcb,
2477 NTSTATUS ntStatus = STATUS_SUCCESS;
2478 LARGE_INTEGER liTimeOut;
2479 ULONGLONG ullProcessId = (ULONGLONG)PsGetCurrentProcessId();
2484 ASSERT( !ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
2486 if (!NT_SUCCESS( Fcb->NPFcb->Specific.File.ExtentsRequestStatus))
2490 // If this isn't the same authgroup which caused the failure
2491 // then try to request them again
2494 if( RtlCompareMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2496 sizeof( GUID)) == sizeof( GUID))
2499 ntStatus = Fcb->NPFcb->Specific.File.ExtentsRequestStatus;
2501 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
2503 RtlZeroMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2506 try_return( ntStatus);
2510 liTimeOut.QuadPart = -(1 * AFS_ONE_SECOND);
2512 ntStatus = KeWaitForSingleObject( &Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
2518 if (!NT_SUCCESS( Fcb->NPFcb->Specific.File.ExtentsRequestStatus))
2522 // If this isn't the same authgroup which caused the failure
2523 // or the System Process,
2524 // then try to request the extents again
2527 if( RtlCompareMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2529 sizeof( GUID)) == sizeof( GUID) ||
2530 ullProcessId == (ULONGLONG)AFSSysProcess)
2533 ntStatus = Fcb->NPFcb->Specific.File.ExtentsRequestStatus;
2535 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
2537 RtlZeroMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2540 try_return( ntStatus);
2544 if( ntStatus == STATUS_TIMEOUT)
2547 ntStatus = STATUS_SUCCESS;
2559 AFSFlushExtents( IN AFSFcb *Fcb,
2562 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
2563 AFSExtent *pExtent, *pNextExtent;
2565 AFSReleaseExtentsCB *pRelease = NULL;
2567 ULONG initialDirtyCount = 0;
2568 BOOLEAN bExtentsLocked = FALSE;
2571 NTSTATUS ntStatus = STATUS_SUCCESS;
2572 LARGE_INTEGER liLastFlush;
2573 AFSExtent *pDirtyListHead = NULL, *pDirtyListTail = NULL;
2574 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2575 GUID *pAuthGroup = AuthGroup;
2579 ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
2582 // Save, then reset the flush time
2585 liLastFlush = Fcb->Specific.File.LastServerFlush;
2587 KeQueryTickCount( &Fcb->Specific.File.LastServerFlush);
2592 if( pAuthGroup == NULL ||
2593 RtlCompareMemory( pAuthGroup,
2594 &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2595 sizeof( GUID)) == sizeof( GUID))
2598 RtlZeroMemory( &stAuthGroup,
2601 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
2606 if( !NT_SUCCESS( ntStatus))
2608 try_return( ntStatus);
2611 pAuthGroup = &stAuthGroup;
2615 // Lock extents while we count and set up the array to send to
2619 AFSLockForExtentsTrim( Fcb);
2621 bExtentsLocked = TRUE;
2623 lCount = InterlockedIncrement( &Fcb->Specific.File.QueuedFlushCount);
2626 // Clear our queued flush event
2629 KeClearEvent( &Fcb->NPFcb->Specific.File.QueuedFlushEvent);
2632 // Look for a start in the list to flush entries
2637 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
2639 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
2641 AFS_EXTENT_RELEASE_TAG);
2642 if( NULL == pRelease)
2645 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2648 initialDirtyCount = Fcb->Specific.File.ExtentsDirtyCount;
2650 while( Fcb->Specific.File.ExtentsDirtyCount > 0)
2653 pRelease->Flags = AFS_EXTENT_FLAG_DIRTY;
2655 if( BooleanFlagOn( Fcb->Flags, AFS_FCB_FILE_CLOSED))
2658 pRelease->Flags |= AFS_EXTENT_FLAG_FLUSH;
2662 // Update the metadata for this call
2665 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
2666 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
2667 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
2668 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
2669 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
2673 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
2676 pExtent = (AFSExtent *)pNPFcb->Specific.File.DirtyListHead;
2678 while( count < AFS_MAXIMUM_EXTENT_RELEASE_COUNT)
2681 if ( pExtent == NULL)
2687 pNextExtent = (AFSExtent *)pExtent->DirtyList.fLink;
2689 if ( pExtent->ActiveCount > 0)
2691 pExtent = pNextExtent;
2695 AFSRemoveEntryDirtyList( Fcb, pExtent);
2697 pExtent->DirtyList.fLink = NULL;
2698 pExtent->DirtyList.bLink = NULL;
2700 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
2703 // Clear the flag in advance of the write. If we do
2704 // things this was we know that the clear is
2705 // pessimistic (any write which happens from now on
2706 // will set the flag dirty again).
2709 pExtent->Flags &= ~AFS_EXTENT_DIRTY;
2711 pRelease->FileExtents[count].Flags = AFS_EXTENT_FLAG_DIRTY;
2713 pRelease->FileExtents[count].Length = pExtent->Size;
2714 pRelease->FileExtents[count].DirtyLength = pExtent->Size;
2715 pRelease->FileExtents[count].DirtyOffset = 0;
2716 pRelease->FileExtents[count].CacheOffset = pExtent->CacheOffset;
2717 pRelease->FileExtents[count].FileOffset = pExtent->FileOffset;
2720 RtlCopyMemory( pRelease->FileExtents[count].MD5,
2722 sizeof(pExtent->MD5));
2724 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_MD5_SET;
2727 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2728 AFS_TRACE_LEVEL_VERBOSE,
2729 "AFSFlushExtents Releasing DIRTY extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
2731 Fcb->ObjectInformation->FileId.Cell,
2732 Fcb->ObjectInformation->FileId.Volume,
2733 Fcb->ObjectInformation->FileId.Vnode,
2734 Fcb->ObjectInformation->FileId.Unique,
2735 pExtent->FileOffset.QuadPart,
2738 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_RELEASE;
2741 // Need to pull this extent from the main list as well
2744 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
2746 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
2748 RemoveEntryList( &pExtent->Lists[i] );
2752 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
2754 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
2756 AFSExFreePool( pExtent);
2758 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
2760 lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount);
2765 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
2772 pExtent = pNextExtent;
2775 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
2778 // If we are done then get out
2784 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2785 AFS_TRACE_LEVEL_VERBOSE,
2786 "AFSFlushExtents No more dirty extents found\n");
2792 // Fire off the request synchronously
2795 sz = sizeof( AFSReleaseExtentsCB ) + (count * sizeof ( AFSFileExtentCB ));
2797 pRelease->ExtentCount = count;
2799 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2800 AFS_TRACE_LEVEL_VERBOSE,
2801 "AFSFlushExtents Releasing(1) Fcb extents lock %08lX SHARED %08lX\n",
2802 &pNPFcb->Specific.File.ExtentsResource,
2803 PsGetCurrentThread());
2805 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource);
2806 bExtentsLocked = FALSE;
2808 KeSetEvent( &pNPFcb->Specific.File.FlushEvent,
2812 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
2813 AFS_REQUEST_FLAG_SYNCHRONOUS,
2816 &Fcb->ObjectInformation->FileId,
2822 if( !NT_SUCCESS(ntStatus))
2826 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
2827 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
2830 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2831 AFS_TRACE_LEVEL_ERROR,
2832 "AFSFlushExtents AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2833 Fcb->ObjectInformation->FileId.Cell,
2834 Fcb->ObjectInformation->FileId.Volume,
2835 Fcb->ObjectInformation->FileId.Vnode,
2836 Fcb->ObjectInformation->FileId.Unique,
2840 AFSLockForExtentsTrim( Fcb);
2842 bExtentsLocked = TRUE;
2847 lCount = InterlockedDecrement( &Fcb->Specific.File.QueuedFlushCount);
2852 KeSetEvent( &pNPFcb->Specific.File.QueuedFlushEvent,
2857 KeSetEvent( &pNPFcb->Specific.File.FlushEvent,
2864 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2865 AFS_TRACE_LEVEL_VERBOSE,
2866 "AFSFlushExtents Releasing(2) Fcb extents lock %08lX SHARED %08lX\n",
2867 &pNPFcb->Specific.File.ExtentsResource,
2868 PsGetCurrentThread());
2870 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
2875 AFSExFreePool( pRelease);
2883 AFSReleaseExtentsWithFlush( IN AFSFcb *Fcb,
2886 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
2889 AFSReleaseExtentsCB *pRelease = NULL;
2891 ULONG initialDirtyCount = 0;
2892 BOOLEAN bExtentsLocked = FALSE;
2895 NTSTATUS ntStatus = STATUS_SUCCESS;
2896 LARGE_INTEGER liLastFlush;
2897 ULONG ulRemainingExtentLength = 0;
2898 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2899 GUID *pAuthGroup = AuthGroup;
2903 ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
2906 // Save, then reset the flush time
2909 liLastFlush = Fcb->Specific.File.LastServerFlush;
2911 KeQueryTickCount( &Fcb->Specific.File.LastServerFlush);
2916 if( pAuthGroup == NULL ||
2917 RtlCompareMemory( pAuthGroup,
2918 &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2919 sizeof( GUID)) == sizeof( GUID))
2922 RtlZeroMemory( &stAuthGroup,
2925 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
2930 if( !NT_SUCCESS( ntStatus))
2932 try_return( ntStatus);
2935 pAuthGroup = &stAuthGroup;
2939 // Look for a start in the list to flush entries
2944 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
2946 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
2948 AFS_EXTENT_RELEASE_TAG);
2949 if( NULL == pRelease)
2952 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2955 if( Fcb->OpenHandleCount > 0)
2959 // Don't release everything ...
2963 // For now release everything
2966 //ulRemainingExtentLength = 1500;
2969 while( Fcb->Specific.File.ExtentLength > (LONG)ulRemainingExtentLength)
2972 AFSLockForExtentsTrim( Fcb);
2974 bExtentsLocked = TRUE;
2976 pRelease->Flags = AFS_EXTENT_FLAG_RELEASE;
2979 // Update the metadata for this call
2982 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
2983 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
2984 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
2985 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
2986 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
2990 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
2992 while( count < AFS_MAXIMUM_EXTENT_RELEASE_COUNT &&
2993 le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
2996 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3000 if( pExtent->ActiveCount > 0)
3006 pRelease->FileExtents[count].Flags = AFS_EXTENT_FLAG_RELEASE;
3008 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3009 AFS_TRACE_LEVEL_VERBOSE,
3010 "AFSReleaseExtentsWithFlush Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3012 Fcb->ObjectInformation->FileId.Cell,
3013 Fcb->ObjectInformation->FileId.Volume,
3014 Fcb->ObjectInformation->FileId.Vnode,
3015 Fcb->ObjectInformation->FileId.Unique,
3016 pExtent->FileOffset.QuadPart,
3019 pRelease->FileExtents[count].Length = pExtent->Size;
3020 pRelease->FileExtents[count].DirtyLength = pExtent->Size;
3021 pRelease->FileExtents[count].DirtyOffset = 0;
3022 pRelease->FileExtents[count].CacheOffset = pExtent->CacheOffset;
3023 pRelease->FileExtents[count].FileOffset = pExtent->FileOffset;
3026 RtlCopyMemory( pRelease->FileExtents[count].MD5,
3028 sizeof(pExtent->MD5));
3030 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_MD5_SET;
3033 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3036 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3039 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3042 AFSRemoveEntryDirtyList( Fcb,
3045 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_DIRTY;
3047 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
3050 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3054 // Need to pull this extent from the main list as well
3057 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
3059 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
3061 RemoveEntryList( &pExtent->Lists[i] );
3065 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
3067 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
3069 AFSExFreePool( pExtent);
3071 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
3073 lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount);
3078 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
3087 // If we are done then get out
3093 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3094 AFS_TRACE_LEVEL_VERBOSE,
3095 "AFSReleaseExtentsWithFlush No more dirty extents found\n");
3101 // Fire off the request synchronously
3104 sz = sizeof( AFSReleaseExtentsCB ) + (count * sizeof ( AFSFileExtentCB ));
3106 pRelease->ExtentCount = count;
3109 // Drop the extents lock for the duration of the call to
3110 // the network. We have pinned the extents so, even
3111 // though we might get extents added during this period,
3112 // but none will be removed. Hence we can carry on from
3116 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3117 AFS_TRACE_LEVEL_VERBOSE,
3118 "AFSReleaseExtentsWithFlush Releasing Fcb extents lock %08lX thread %08lX\n",
3119 &pNPFcb->Specific.File.ExtentsResource,
3120 PsGetCurrentThread());
3122 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource);
3123 bExtentsLocked = FALSE;
3125 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
3126 AFS_REQUEST_FLAG_SYNCHRONOUS,
3129 &Fcb->ObjectInformation->FileId,
3135 if( !NT_SUCCESS(ntStatus))
3139 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
3140 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
3143 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3144 AFS_TRACE_LEVEL_ERROR,
3145 "AFSReleaseExtentsWithFlush AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3146 Fcb->ObjectInformation->FileId.Cell,
3147 Fcb->ObjectInformation->FileId.Volume,
3148 Fcb->ObjectInformation->FileId.Vnode,
3149 Fcb->ObjectInformation->FileId.Unique,
3159 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3160 AFS_TRACE_LEVEL_VERBOSE,
3161 "AFSReleaseExtentsWithFlush Releasing Fcb extents lock %08lX thread %08lX\n",
3162 &pNPFcb->Specific.File.ExtentsResource,
3163 PsGetCurrentThread());
3165 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
3170 AFSExFreePool( pRelease);
3178 AFSReleaseCleanExtents( IN AFSFcb *Fcb,
3181 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3184 AFSReleaseExtentsCB *pRelease = NULL;
3186 ULONG initialDirtyCount = 0;
3187 BOOLEAN bExtentsLocked = FALSE;
3190 NTSTATUS ntStatus = STATUS_SUCCESS;
3191 LARGE_INTEGER liLastFlush;
3192 ULONG ulRemainingExtentLength = 0;
3193 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3194 GUID *pAuthGroup = AuthGroup;
3197 ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
3200 // Save, then reset the flush time
3203 liLastFlush = Fcb->Specific.File.LastServerFlush;
3205 KeQueryTickCount( &Fcb->Specific.File.LastServerFlush);
3210 if( pAuthGroup == NULL ||
3211 RtlCompareMemory( pAuthGroup,
3212 &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
3213 sizeof( GUID)) == sizeof( GUID))
3216 RtlZeroMemory( &stAuthGroup,
3219 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
3224 if( !NT_SUCCESS( ntStatus))
3226 try_return( ntStatus);
3229 pAuthGroup = &stAuthGroup;
3233 // Look for a start in the list to flush entries
3238 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
3240 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
3242 AFS_EXTENT_RELEASE_TAG);
3243 if( NULL == pRelease)
3246 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
3249 while( Fcb->Specific.File.ExtentLength > (LONG)ulRemainingExtentLength)
3252 AFSLockForExtentsTrim( Fcb);
3254 bExtentsLocked = TRUE;
3256 pRelease->Flags = AFS_EXTENT_FLAG_RELEASE;
3259 // Update the metadata for this call
3262 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
3263 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
3264 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
3265 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
3266 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
3270 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3272 while( count < AFS_MAXIMUM_EXTENT_RELEASE_COUNT &&
3273 le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
3276 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3280 if( pExtent->ActiveCount > 0 ||
3281 BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3286 pRelease->FileExtents[count].Flags = AFS_EXTENT_FLAG_RELEASE;
3288 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3289 AFS_TRACE_LEVEL_VERBOSE,
3290 "AFSReleaseCleanExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3292 Fcb->ObjectInformation->FileId.Cell,
3293 Fcb->ObjectInformation->FileId.Volume,
3294 Fcb->ObjectInformation->FileId.Vnode,
3295 Fcb->ObjectInformation->FileId.Unique,
3296 pExtent->FileOffset.QuadPart,
3299 pRelease->FileExtents[count].Length = pExtent->Size;
3300 pRelease->FileExtents[count].DirtyLength = pExtent->Size;
3301 pRelease->FileExtents[count].DirtyOffset = 0;
3302 pRelease->FileExtents[count].CacheOffset = pExtent->CacheOffset;
3303 pRelease->FileExtents[count].FileOffset = pExtent->FileOffset;
3306 RtlCopyMemory( pRelease->FileExtents[count].MD5,
3308 sizeof(pExtent->MD5));
3310 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_MD5_SET;
3314 // Need to pull this extent from the main list as well
3317 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
3319 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
3321 RemoveEntryList( &pExtent->Lists[i] );
3325 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
3327 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
3329 AFSExFreePool( pExtent);
3331 InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
3333 if( InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount) == 0)
3336 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
3345 // If we are done then get out
3351 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3352 AFS_TRACE_LEVEL_VERBOSE,
3353 "AFSReleaseCleanExtents No more dirty extents found\n");
3359 // Fire off the request synchronously
3362 sz = sizeof( AFSReleaseExtentsCB ) + (count * sizeof ( AFSFileExtentCB ));
3364 pRelease->ExtentCount = count;
3367 // Drop the extents lock for the duration of the call to
3368 // the network. We have pinned the extents so, even
3369 // though we might get extents added during this period,
3370 // but none will be removed. Hence we can carry on from
3374 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3375 AFS_TRACE_LEVEL_VERBOSE,
3376 "AFSReleaseCleanExtents Releasing Fcb extents lock %08lX thread %08lX\n",
3377 &pNPFcb->Specific.File.ExtentsResource,
3378 PsGetCurrentThread());
3380 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource);
3381 bExtentsLocked = FALSE;
3383 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
3384 AFS_REQUEST_FLAG_SYNCHRONOUS,
3387 &Fcb->ObjectInformation->FileId,
3393 if( !NT_SUCCESS(ntStatus))
3397 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
3398 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
3401 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3402 AFS_TRACE_LEVEL_ERROR,
3403 "AFSReleaseCleanExtents AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3404 Fcb->ObjectInformation->FileId.Cell,
3405 Fcb->ObjectInformation->FileId.Volume,
3406 Fcb->ObjectInformation->FileId.Vnode,
3407 Fcb->ObjectInformation->FileId.Unique,
3417 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3418 AFS_TRACE_LEVEL_VERBOSE,
3419 "AFSReleaseCleanExtents Releasing Fcb extents lock %08lX thread %08lX\n",
3420 &pNPFcb->Specific.File.ExtentsResource,
3421 PsGetCurrentThread());
3423 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
3428 AFSExFreePool( pRelease);
3436 AFSMarkDirty( IN AFSFcb *Fcb,
3437 IN AFSExtent *StartExtent,
3438 IN ULONG ExtentsCount,
3439 IN LARGE_INTEGER *StartingByte,
3440 IN BOOLEAN DerefExtents)
3443 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3444 AFSExtent *pExtent = StartExtent;
3445 AFSExtent *pNextExtent, *pCurrentExtent = NULL;
3447 BOOLEAN bInsertTail = FALSE, bInsertHead = FALSE;
3449 BOOLEAN bLocked = FALSE;
3451 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3452 AFS_TRACE_LEVEL_VERBOSE,
3453 "AFSMarkDirty Acquiring Fcb extents lock %08lX SHARED %08lX\n",
3454 &Fcb->NPFcb->Specific.File.ExtentsResource,
3455 PsGetCurrentThread());
3457 if( !ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource))
3459 AFSAcquireShared( &Fcb->NPFcb->Specific.File.ExtentsResource, TRUE);
3463 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3469 // Find the insertion point
3472 if( pNPFcb->Specific.File.DirtyListHead == NULL)
3477 else if( StartingByte->QuadPart == 0)
3485 pCurrentExtent = pNPFcb->Specific.File.DirtyListHead;
3487 while( pCurrentExtent != NULL)
3490 if( pCurrentExtent->FileOffset.QuadPart + pCurrentExtent->Size >= StartingByte->QuadPart ||
3491 pCurrentExtent->DirtyList.fLink == NULL)
3497 pCurrentExtent = (AFSExtent *)pCurrentExtent->DirtyList.fLink;
3501 while( ulCount < ExtentsCount)
3504 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
3506 if( !BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3509 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3510 AFS_TRACE_LEVEL_VERBOSE,
3511 "AFSMarkDirty Marking extent offset %I64X Length %08lX DIRTY\n",
3512 pExtent->FileOffset.QuadPart,
3515 pExtent->DirtyList.fLink = NULL;
3516 pExtent->DirtyList.bLink = NULL;
3521 pExtent->DirtyList.fLink = (void *)pNPFcb->Specific.File.DirtyListHead;
3523 pExtent->DirtyList.bLink = NULL;
3525 pNPFcb->Specific.File.DirtyListHead->DirtyList.bLink = (void *)pExtent;
3527 pNPFcb->Specific.File.DirtyListHead = pExtent;
3529 pCurrentExtent = pExtent;
3531 bInsertHead = FALSE;
3533 else if( bInsertTail)
3536 if( pNPFcb->Specific.File.DirtyListHead == NULL)
3539 pNPFcb->Specific.File.DirtyListHead = pExtent;
3544 pNPFcb->Specific.File.DirtyListTail->DirtyList.fLink = (void *)pExtent;
3546 pExtent->DirtyList.bLink = (void *)pNPFcb->Specific.File.DirtyListTail;
3549 pNPFcb->Specific.File.DirtyListTail = pExtent;
3554 pExtent->DirtyList.fLink = pCurrentExtent->DirtyList.fLink;
3556 pExtent->DirtyList.bLink = (void *)pCurrentExtent;
3558 if( pExtent->DirtyList.fLink == NULL)
3561 pNPFcb->Specific.File.DirtyListTail = pExtent;
3566 ((AFSExtent *)pExtent->DirtyList.fLink)->DirtyList.bLink = (void *)pExtent;
3569 pCurrentExtent->DirtyList.fLink = (void *)pExtent;
3571 pCurrentExtent = pExtent;
3574 pExtent->Flags |= AFS_EXTENT_DIRTY;
3577 // Up the dirty count
3580 lCount = InterlockedIncrement( &Fcb->Specific.File.ExtentsDirtyCount);
3585 pCurrentExtent = pExtent;
3588 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_ACTIVE_COUNTING,
3589 AFS_TRACE_LEVEL_VERBOSE,
3590 "AFSMarkDirty Decrement count on extent %08lX Cnt %d\n",
3592 pExtent->ActiveCount);
3596 ASSERT( pExtent->ActiveCount > 0);
3597 lCount = InterlockedDecrement( &pExtent->ActiveCount);
3600 pExtent = pNextExtent;
3605 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
3610 "EXCEPTION - AFSMarkDirty\n");
3612 AFSDumpTraceFilesFnc();
3615 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3617 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3618 AFS_TRACE_LEVEL_VERBOSE,
3619 "AFSMarkDirty Releasing Fcb extents lock %08lX SHARED %08lX\n",
3620 &Fcb->NPFcb->Specific.File.ExtentsResource,
3621 PsGetCurrentThread());
3625 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
3636 ExtentFor(PLIST_ENTRY le, ULONG SkipList)
3638 return CONTAINING_RECORD( le, AFSExtent, Lists[SkipList] );
3641 static AFSExtent *NextExtent(AFSExtent *Extent, ULONG SkipList)
3643 return ExtentFor(Extent->Lists[SkipList].Flink, SkipList);
3646 static AFSExtent *DirtyExtentFor(PLIST_ENTRY le)
3648 return CONTAINING_RECORD( le, AFSExtent, DirtyList );
3651 static VOID VerifyExtentsLists(AFSFcb *Fcb)
3655 // Check the ordering of the extents lists
3657 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
3659 ASSERT(Fcb->Specific.File.ExtentsLists[0].Flink != &Fcb->Specific.File.ExtentsLists[1]);
3661 for (ULONG listNo = 0; listNo < AFS_NUM_EXTENT_LISTS; listNo ++)
3663 LARGE_INTEGER lastOffset;
3665 lastOffset.QuadPart = 0;
3667 for (PLIST_ENTRY pLe = Fcb->Specific.File.ExtentsLists[listNo].Flink;
3668 pLe != &Fcb->Specific.File.ExtentsLists[listNo];
3673 pExtent = ExtentFor(pLe, listNo);
3676 ASSERT(pLe != &Fcb->Specific.File.ExtentsLists[1] &&
3677 pLe->Flink !=&Fcb->Specific.File.ExtentsLists[1] &&
3678 pLe->Blink !=&Fcb->Specific.File.ExtentsLists[1]);
3681 ASSERT(pLe->Flink->Blink == pLe);
3682 ASSERT(pLe->Blink->Flink == pLe);
3685 // Should follow on from previous
3687 ASSERT(pExtent->FileOffset.QuadPart >= lastOffset.QuadPart);
3688 lastOffset.QuadPart = pExtent->FileOffset.QuadPart + pExtent->Size;
3691 // Should match alignment criteria
3693 ASSERT( 0 == (pExtent->FileOffset.LowPart & ExtentsMasks[listNo]) );
3696 // "lower" lists should be populated
3698 for (LONG subListNo = listNo-1; subListNo > 0; subListNo --)
3700 ASSERT( !IsListEmpty(&pExtent->Lists[subListNo]));
3708 AFSTrimExtents( IN AFSFcb *Fcb,
3709 IN PLARGE_INTEGER FileSize)
3712 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3715 BOOLEAN locked = FALSE;
3716 NTSTATUS ntStatus = STATUS_SUCCESS;
3717 LARGE_INTEGER liAlignedOffset = {0,0};
3718 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
3719 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3726 // Get an aligned offset
3729 if( FileSize != NULL)
3732 liAlignedOffset = *FileSize;
3735 if( liAlignedOffset.QuadPart > 0 &&
3736 liAlignedOffset.QuadPart % pDevExt->Specific.RDR.CacheBlockSize != 0)
3740 // Align UP to the next cache block size
3743 liAlignedOffset.QuadPart = (ULONGLONG)( (ULONGLONG)((liAlignedOffset.QuadPart / pDevExt->Specific.RDR.CacheBlockSize) + 1) * (ULONGLONG)pDevExt->Specific.RDR.CacheBlockSize);
3747 // Ensure that no one is working with the extents and grab the
3751 AFSLockForExtentsTrim( Fcb);
3755 if( 0 == Fcb->Specific.File.ExtentCount)
3759 // Update the request extent status
3762 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
3764 try_return( ntStatus = STATUS_SUCCESS);
3768 // We are truncating from a specific length in the file. If the offset
3769 // is non-zero then go find the first extent to remove
3772 if( 0 == FileSize->QuadPart)
3775 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3780 pExtent = AFSExtentForOffset( Fcb,
3784 if( NULL == pExtent)
3787 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3791 le = &pExtent->Lists[AFS_EXTENTS_LIST];
3795 while( le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
3798 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3801 // Only trim down extents beyond the aligned offset
3806 if( pExtent->FileOffset.QuadPart >= liAlignedOffset.QuadPart)
3809 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3812 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3815 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3819 AFSRemoveEntryDirtyList( Fcb,
3822 dirtyCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
3824 ASSERT(dirtyCount >= 0);
3827 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3830 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
3832 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
3834 RemoveEntryList( &pExtent->Lists[i] );
3838 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3839 AFS_TRACE_LEVEL_VERBOSE,
3840 "AFSTrimExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3842 Fcb->ObjectInformation->FileId.Cell,
3843 Fcb->ObjectInformation->FileId.Volume,
3844 Fcb->ObjectInformation->FileId.Vnode,
3845 Fcb->ObjectInformation->FileId.Unique,
3846 pExtent->FileOffset.QuadPart,
3849 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
3851 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
3853 ASSERT( pExtent->ActiveCount == 0);
3858 AFSExFreePool( pExtent);
3860 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
3862 lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount);
3867 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
3875 // Update the request extent status
3878 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
3885 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3886 AFS_TRACE_LEVEL_VERBOSE,
3887 "AFSTrimExtents Releasing Fcb extents lock %08lX thread %08lX\n",
3888 &Fcb->NPFcb->Specific.File.ExtentsResource,
3889 PsGetCurrentThread());
3891 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
3899 AFSTrimSpecifiedExtents( IN AFSFcb *Fcb,
3901 IN AFSFileExtentCB *Result)
3904 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3907 AFSFileExtentCB *pFileExtents = Result;
3908 NTSTATUS ntStatus = STATUS_SUCCESS;
3909 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
3910 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3916 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3918 while( le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST] &&
3922 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3925 // Only trim down extents beyond the aligned offset
3930 if( pExtent->FileOffset.QuadPart == pFileExtents->FileOffset.QuadPart)
3933 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3936 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3939 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3944 AFSRemoveEntryDirtyList( Fcb,
3947 dirtyCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
3949 ASSERT( dirtyCount >= 0);
3953 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3957 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
3959 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
3961 RemoveEntryList( &pExtent->Lists[i] );
3965 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3966 AFS_TRACE_LEVEL_VERBOSE,
3967 "AFSTrimSpecifiedExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3969 Fcb->ObjectInformation->FileId.Cell,
3970 Fcb->ObjectInformation->FileId.Volume,
3971 Fcb->ObjectInformation->FileId.Vnode,
3972 Fcb->ObjectInformation->FileId.Unique,
3973 pExtent->FileOffset.QuadPart,
3976 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
3978 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
3980 ASSERT( pExtent->ActiveCount == 0);
3985 AFSExFreePool( pExtent);
3987 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
3989 lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount);
3994 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
4000 // Next extent we are looking for
4010 // Update the request extent status
4013 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
4020 AFSReferenceActiveExtents( IN AFSExtent *StartExtent,
4021 IN ULONG ExtentsCount)
4024 AFSExtent *pExtent = StartExtent;
4025 AFSExtent *pNextExtent;
4029 while( ulCount < ExtentsCount)
4032 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
4034 lCount = InterlockedIncrement( &pExtent->ActiveCount);
4036 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_ACTIVE_COUNTING,
4037 AFS_TRACE_LEVEL_VERBOSE,
4038 "AFSReferenceActiveExtents Increment count on extent %08lX Cnt %d\n",
4042 pExtent = pNextExtent;
4051 AFSDereferenceActiveExtents( IN AFSExtent *StartExtent,
4052 IN ULONG ExtentsCount)
4055 AFSExtent *pExtent = StartExtent;
4056 AFSExtent *pNextExtent;
4060 while( ulCount < ExtentsCount)
4063 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
4065 ASSERT( pExtent->ActiveCount > 0);
4067 lCount = InterlockedDecrement( &pExtent->ActiveCount);
4069 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_ACTIVE_COUNTING,
4070 AFS_TRACE_LEVEL_VERBOSE,
4071 "AFSDereferenceActiveExtents Decrement count on extent %08lX Cnt %d\n",
4075 pExtent = pNextExtent;
4084 AFSRemoveEntryDirtyList( IN AFSFcb *Fcb,
4085 IN AFSExtent *Extent)
4088 if( Extent->DirtyList.fLink == NULL)
4091 Fcb->NPFcb->Specific.File.DirtyListTail = (AFSExtent *)Extent->DirtyList.bLink;
4093 if( Fcb->NPFcb->Specific.File.DirtyListTail != NULL)
4096 Fcb->NPFcb->Specific.File.DirtyListTail->DirtyList.fLink = NULL;
4102 ((AFSExtent *)Extent->DirtyList.fLink)->DirtyList.bLink = Extent->DirtyList.bLink;
4105 if( Extent->DirtyList.bLink == NULL)
4108 Fcb->NPFcb->Specific.File.DirtyListHead = (AFSExtent *)Extent->DirtyList.fLink;
4110 if( Fcb->NPFcb->Specific.File.DirtyListHead != NULL)
4113 Fcb->NPFcb->Specific.File.DirtyListHead->DirtyList.bLink = NULL;
4119 ((AFSExtent *)Extent->DirtyList.bLink)->DirtyList.fLink = Extent->DirtyList.fLink;
4127 AFSConstructCleanByteRangeList( AFSFcb * pFcb,
4128 AFSByteRange ** pByteRangeList)
4131 ULONG ulByteRangeMax;
4132 ULONG ulByteRangeCount = 0;
4133 AFSByteRange *ByteRangeList;
4134 AFSExtent *pExtent, *pNextExtent;
4136 AFSAcquireShared( &pFcb->NPFcb->Specific.File.DirtyExtentsListLock, TRUE);
4138 ulByteRangeMax = pFcb->Specific.File.ExtentsDirtyCount + 1;
4140 ByteRangeList = (AFSByteRange *) AFSExAllocatePoolWithTag( PagedPool,
4141 ulByteRangeMax * sizeof( AFSByteRange),
4144 if ( ByteRangeList == NULL)
4147 (*pByteRangeList) = NULL;
4149 try_return( ulByteRangeCount = DWORD_MAX);
4152 RtlZeroMemory( ByteRangeList,
4153 ulByteRangeMax * sizeof( AFSByteRange));
4156 // The for loop populates the ByteRangeList entries with values that are
4157 // the gaps in the DirtyList. In other words, if a range is not present
4158 // in the DirtyList it will be represented in the ByteRangeList array.
4161 for ( ulByteRangeCount = 0,
4162 pExtent = (AFSExtent *)pFcb->NPFcb->Specific.File.DirtyListHead;
4163 ulByteRangeCount < ulByteRangeMax && pExtent != NULL;
4164 pExtent = pNextExtent)
4167 pNextExtent = (AFSExtent *)pExtent->DirtyList.fLink;
4170 // The first time the for() is entered the ulByteRangeCount will be zero and
4171 // ByteRangeList[0] FileOffset and Length will both be zero. If the first
4172 // extent is not for offset zero, the ByteRangeList[0] Length is set to the
4173 // FileOffset of the Extent.
4175 // Future passes through the loop behave in a similar fashion but
4176 // ByteRangeList[ulByteRangeCount] FileOffset will have been set below.
4179 if ( pExtent->FileOffset.QuadPart != ByteRangeList[ulByteRangeCount].FileOffset.QuadPart + ByteRangeList[ulByteRangeCount].Length.QuadPart)
4182 ByteRangeList[ulByteRangeCount].Length.QuadPart =
4183 pExtent->FileOffset.QuadPart - ByteRangeList[ulByteRangeCount].FileOffset.QuadPart;
4189 // Having processed the current dirty extent, the following while loop
4190 // searches for the next clean gap between dirty extents.
4193 while ( pNextExtent && pNextExtent->FileOffset.QuadPart == pExtent->FileOffset.QuadPart + pExtent->Size)
4196 pExtent = pNextExtent;
4198 pNextExtent = (AFSExtent *)pExtent->DirtyList.fLink;
4202 // Having found the next gap, the ByteRangeList[] FileOffset is set to the start of the gap.
4203 // The Length is left at zero and will be assigned either when the for loop continues or
4204 // when the for loop exits.
4207 ByteRangeList[ulByteRangeCount].FileOffset.QuadPart = pExtent->FileOffset.QuadPart + pExtent->Size;
4211 // Assign the Length of the final clean range to match the file length.
4214 ByteRangeList[ulByteRangeCount].Length.QuadPart =
4215 pFcb->ObjectInformation->EndOfFile.QuadPart - ByteRangeList[ulByteRangeCount].FileOffset.QuadPart;
4217 (*pByteRangeList) = ByteRangeList;
4221 AFSReleaseResource( &pFcb->NPFcb->Specific.File.DirtyExtentsListLock);
4223 return ulByteRangeCount;
4228 AFSSetupMD5Hash( IN AFSFcb *Fcb,
4229 IN AFSExtent *StartExtent,
4230 IN ULONG ExtentsCount,
4231 IN void *SystemBuffer,
4232 IN LARGE_INTEGER *ByteOffset,
4236 NTSTATUS ntStatus = STATUS_SUCCESS;
4237 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
4238 AFSExtent *pExtent = StartExtent;
4239 AFSExtent *pNextExtent, *pCurrentExtent = NULL;
4241 char *pCurrentBuffer = (char *)SystemBuffer;
4242 char *pMD5Buffer = NULL;
4243 ULONG ulCurrentLen = 0;
4244 void *pExtentBuffer = NULL;
4245 LARGE_INTEGER liByteOffset;
4246 ULONG ulBytesRead = 0;
4251 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4252 AFS_TRACE_LEVEL_VERBOSE,
4253 "AFSSetupMD5Hash Acquiring Fcb extents lock %08lX SHARED %08lX\n",
4254 &Fcb->NPFcb->Specific.File.ExtentsResource,
4255 PsGetCurrentThread());
4257 AFSAcquireShared( &Fcb->NPFcb->Specific.File.ExtentsResource, TRUE);
4261 liByteOffset.QuadPart = ByteOffset->QuadPart;
4263 while( ulCount < ExtentsCount)
4266 RtlZeroMemory( pExtent->MD5,
4267 sizeof( pExtent->MD5));
4269 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
4271 if( liByteOffset.QuadPart == pExtent->FileOffset.QuadPart &&
4272 ByteCount < pExtent->Size)
4275 if( pExtentBuffer == NULL)
4278 pExtentBuffer = AFSExAllocatePoolWithTag( PagedPool,
4280 AFS_GENERIC_MEMORY_9_TAG);
4282 if( pExtentBuffer == NULL)
4289 RtlZeroMemory( pExtentBuffer,
4292 RtlCopyMemory( pExtentBuffer,
4296 pMD5Buffer = (char *)pExtentBuffer;
4298 ulCurrentLen = ByteCount;
4300 else if( liByteOffset.QuadPart != pExtent->FileOffset.QuadPart)
4303 pExtentBuffer = AFSExAllocatePoolWithTag( PagedPool,
4305 AFS_GENERIC_MEMORY_10_TAG);
4307 if( pExtentBuffer == NULL)
4313 RtlZeroMemory( pExtentBuffer,
4316 if( BooleanFlagOn( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE))
4320 RtlCopyMemory( pExtentBuffer,
4321 ((char *)AFSLibCacheBaseAddress + pExtent->CacheOffset.QuadPart),
4324 ASSERT( pExtent->CacheOffset.HighPart == 0);
4325 RtlCopyMemory( pExtentBuffer,
4326 ((char *)AFSLibCacheBaseAddress + pExtent->CacheOffset.LowPart),
4330 ulBytesRead = pExtent->Size;
4335 ntStatus = AFSReadCacheFile( pExtentBuffer,
4336 &pExtent->CacheOffset,
4340 if( !NT_SUCCESS( ntStatus))
4347 pMD5Buffer = (char *)pExtentBuffer;
4349 ulCurrentLen = min( ByteCount, pExtent->Size - (ULONG)(liByteOffset.QuadPart - pExtent->FileOffset.QuadPart));
4351 RtlCopyMemory( (void *)((char *)pExtentBuffer + (ULONG)(liByteOffset.QuadPart - pExtent->FileOffset.QuadPart)),
4358 ulCurrentLen = pExtent->Size;
4360 pMD5Buffer = pCurrentBuffer;
4363 AFSGenerateMD5( pMD5Buffer,
4367 pExtent = pNextExtent;
4371 ByteCount -= ulCurrentLen;
4373 pCurrentBuffer += ulCurrentLen;
4375 liByteOffset.QuadPart += ulCurrentLen;
4378 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4379 AFS_TRACE_LEVEL_VERBOSE,
4380 "AFSSetupMD5Hash Releasing Fcb extents lock %08lX SHARED %08lX\n",
4381 &Fcb->NPFcb->Specific.File.ExtentsResource,
4382 PsGetCurrentThread());
4385 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
4390 "EXCEPTION - AFSSetupMD5Hash\n");
4392 AFSDumpTraceFilesFnc();
4395 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
4397 if( pExtentBuffer != NULL)
4400 AFSExFreePool( pExtentBuffer);