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 Acuiring 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 acquiring Fcb extent lock %08lX EXCL %08lX\n",
84 &pNPFcb->Specific.File.ExtentsResource,
85 PsGetCurrentThread());
87 if (!AFSAcquireExcl( &pNPFcb->Specific.File.ExtentsResource, FALSE ))
90 // Couldn't lock immediately
93 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
94 AFS_TRACE_LEVEL_VERBOSE,
95 "AFSLockForExtentsTrimNoWait Refused to wait for Fcb extent lock %08lX EXCL %08lX\n",
96 &pNPFcb->Specific.File.ExtentsResource,
97 PsGetCurrentThread());
105 // Pull all the extents away from the FCB.
108 AFSTearDownFcbExtents( IN AFSFcb *Fcb,
111 BOOLEAN bFoundExtents = FALSE;
112 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
115 ULONG ulCount = 0, ulReleaseCount = 0, ulProcessCount = 0;
117 AFSReleaseExtentsCB *pRelease = NULL;
118 BOOLEAN locked = FALSE;
120 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
121 GUID *pAuthGroup = AuthGroup;
128 if( pAuthGroup == NULL ||
129 RtlCompareMemory( pAuthGroup,
130 &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
131 sizeof( GUID)) == sizeof( GUID))
134 RtlZeroMemory( &stAuthGroup,
137 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
142 if( !NT_SUCCESS( ntStatus))
144 try_return( ntStatus);
147 pAuthGroup = &stAuthGroup;
151 // Ensure that no one is working with the extents and grab the
155 AFSLockForExtentsTrim( Fcb );
159 if (0 == Fcb->Specific.File.ExtentCount)
161 try_return ( ntStatus = STATUS_SUCCESS);
165 // Release a max of 100 extents at a time
168 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
170 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
172 AFS_EXTENT_RELEASE_TAG);
173 if (NULL == pRelease)
176 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
179 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
181 ulCount = Fcb->Specific.File.ExtentCount;
183 while( ulReleaseCount < ulCount)
186 bFoundExtents = TRUE;
188 RtlZeroMemory( pRelease,
189 sizeof( AFSReleaseExtentsCB ) +
190 (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB )));
192 if( ulCount - ulReleaseCount <= AFS_MAXIMUM_EXTENT_RELEASE_COUNT)
194 ulProcessCount = ulCount - ulReleaseCount;
198 ulProcessCount = AFS_MAXIMUM_EXTENT_RELEASE_COUNT;
201 pRelease->Flags = AFS_EXTENT_FLAG_RELEASE;
202 pRelease->ExtentCount = ulProcessCount;
205 // Update the metadata for this call
208 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
209 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
210 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
211 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
212 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
216 while (ulProcessCount < pRelease->ExtentCount)
218 pEntry = ExtentFor( le, AFS_EXTENTS_LIST );
220 pRelease->FileExtents[ulProcessCount].Flags = AFS_EXTENT_FLAG_RELEASE;
223 RtlCopyMemory( pRelease->FileExtents[ulProcessCount].MD5,
225 sizeof(pEntry->MD5));
227 pRelease->FileExtents[ulProcessCount].Flags |= AFS_EXTENT_FLAG_MD5_SET;
230 if( BooleanFlagOn( pEntry->Flags, AFS_EXTENT_DIRTY))
233 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
236 if( BooleanFlagOn( pEntry->Flags, AFS_EXTENT_DIRTY))
241 AFSRemoveEntryDirtyList( Fcb,
244 pRelease->FileExtents[ulProcessCount].Flags |= AFS_EXTENT_FLAG_DIRTY;
246 dirtyCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
248 ASSERT( dirtyCount >= 0);
251 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
254 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
255 AFS_TRACE_LEVEL_VERBOSE,
256 "AFSTearDownFcbExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %08lX-%08lX Len %08lX\n",
258 Fcb->ObjectInformation->FileId.Cell,
259 Fcb->ObjectInformation->FileId.Volume,
260 Fcb->ObjectInformation->FileId.Vnode,
261 Fcb->ObjectInformation->FileId.Unique,
262 pEntry->FileOffset.HighPart,
263 pEntry->FileOffset.LowPart,
266 pRelease->FileExtents[ulProcessCount].Length = pEntry->Size;
267 pRelease->FileExtents[ulProcessCount].DirtyLength = pEntry->Size;
268 pRelease->FileExtents[ulProcessCount].DirtyOffset = 0;
269 pRelease->FileExtents[ulProcessCount].CacheOffset = pEntry->CacheOffset;
270 pRelease->FileExtents[ulProcessCount].FileOffset = pEntry->FileOffset;
272 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pEntry->Size/1024)));
274 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pEntry->Size/1024)));
276 ASSERT( pEntry->ActiveCount == 0);
280 AFSExFreePool( pEntry);
282 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
284 lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount);
289 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
296 // Send the request down. We cannot send this down
297 // asynchronously - if we did that we could request them
298 // back before the service got this request and then this
299 // request would be a corruption.
302 sz = sizeof( AFSReleaseExtentsCB ) + (ulProcessCount * sizeof ( AFSFileExtentCB ));
304 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
305 AFS_REQUEST_FLAG_SYNCHRONOUS,
308 &Fcb->ObjectInformation->FileId,
314 if( !NT_SUCCESS(ntStatus))
318 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
319 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
322 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
323 AFS_TRACE_LEVEL_ERROR,
324 "AFSTearDownFcbExtents AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
325 Fcb->ObjectInformation->FileId.Cell,
326 Fcb->ObjectInformation->FileId.Volume,
327 Fcb->ObjectInformation->FileId.Vnode,
328 Fcb->ObjectInformation->FileId.Unique,
333 ulReleaseCount += ulProcessCount;
337 // Reinitialize the skip lists
340 ASSERT( Fcb->Specific.File.ExtentCount == 0);
342 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i++)
344 InitializeListHead(&Fcb->Specific.File.ExtentsLists[i]);
348 // Reinitialize the dirty list as well
351 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
354 ASSERT( Fcb->Specific.File.ExtentsDirtyCount == 0);
356 Fcb->NPFcb->Specific.File.DirtyListHead = NULL;
357 Fcb->NPFcb->Specific.File.DirtyListTail = NULL;
359 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
361 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
368 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
369 AFS_TRACE_LEVEL_VERBOSE,
370 "AFSTearDownFcbExtents Releasing Fcb extent lock %08lX thread %08lX\n",
371 &Fcb->NPFcb->Specific.File.ExtentsResource,
372 PsGetCurrentThread());
374 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
380 AFSExFreePool( pRelease);
384 return bFoundExtents;
388 ExtentForOffsetInList( IN AFSFcb *Fcb,
391 IN PLARGE_INTEGER Offset)
394 // Return the extent that maps the offset, that
395 // - Contains the offset
396 // - or is immediately ahead of the offset (in this list)
397 // - otherwise return NULL.
400 PLIST_ENTRY pLe = List;
401 AFSExtent *pPrevious = NULL;
403 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
405 while (pLe != &Fcb->Specific.File.ExtentsLists[ListNumber])
409 entry = ExtentFor( pLe, ListNumber );
416 if (Offset->QuadPart < entry->FileOffset.QuadPart)
419 // Offset is ahead of entry. Return previous
424 if (Offset->QuadPart >= (entry->FileOffset.QuadPart + entry->Size))
427 // We start after this extent - carry on round
435 // Otherwise its a match
442 // Got to the end. Return Previous
448 AFSExtentContains( IN AFSExtent *Extent, IN PLARGE_INTEGER Offset)
454 return (Extent->FileOffset.QuadPart <= Offset->QuadPart &&
455 (Extent->FileOffset.QuadPart + Extent->Size) > Offset->QuadPart);
460 // Return the extent that contains the offset
463 AFSExtentForOffsetHint( IN AFSFcb *Fcb,
464 IN PLARGE_INTEGER Offset,
465 IN BOOLEAN ReturnPrevious,
468 AFSExtent *pPrevious = Hint;
472 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
474 #if AFS_VALIDATE_EXTENTS
475 VerifyExtentsLists(Fcb);
479 // So we will go across the skip lists until we find an
480 // appropriate entry (previous or direct match). If it's a match
481 // we are done, other wise we start on the next layer down
483 for (i = AFS_NUM_EXTENT_LISTS-1; i >= AFS_EXTENTS_LIST; i--)
485 if (NULL == pPrevious)
488 // We haven't found anything in the previous layers
490 pLe = Fcb->Specific.File.ExtentsLists[i].Flink;
492 else if (NULL == pPrevious->Lists[i].Flink)
494 ASSERT(AFS_EXTENTS_LIST != i);
496 // The hint doesn't exist at this level, next one down
503 // take the previous into the next
505 pLe = &pPrevious->Lists[i];
508 pPrevious = ExtentForOffsetInList( Fcb, pLe, i, Offset);
510 if (NULL != pPrevious && AFSExtentContains(pPrevious, Offset))
513 // Found it immediately. Stop here
519 if (NULL == pPrevious || ReturnPrevious )
524 ASSERT( !AFSExtentContains(pPrevious, Offset) );
530 AFSEntryForOffset( IN AFSFcb *Fcb,
531 IN PLARGE_INTEGER Offset)
533 AFSExtent *pPrevious = NULL;
537 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
539 #if AFS_VALIDATE_EXTENTS
540 VerifyExtentsLists(Fcb);
544 // So we will go across the skip lists until we find an
545 // appropriate entry (previous or direct match). If it's a match
546 // we are done, other wise we start on the next layer down
548 for (i = AFS_NUM_EXTENT_LISTS-1; i >= AFS_EXTENTS_LIST; i--)
550 if (NULL == pPrevious)
553 // We haven't found anything in the previous layers
555 pLe = Fcb->Specific.File.ExtentsLists[i].Flink;
557 else if (NULL == pPrevious->Lists[i].Flink)
559 ASSERT(AFS_EXTENTS_LIST != i);
561 // The hint doesn't exist at this level, next one down
568 // take the previous into the next
570 pLe = &pPrevious->Lists[i];
573 pPrevious = ExtentForOffsetInList( Fcb, pLe, i, Offset);
575 if (NULL != pPrevious && AFSExtentContains(pPrevious, Offset))
578 // Found it immediately. Stop here
588 AFSExtentForOffset( IN AFSFcb *Fcb,
589 IN PLARGE_INTEGER Offset,
590 IN BOOLEAN ReturnPrevious)
592 return AFSExtentForOffsetHint(Fcb, Offset, ReturnPrevious, NULL);
596 BOOLEAN AFSDoExtentsMapRegion(IN AFSFcb *Fcb,
597 IN PLARGE_INTEGER Offset,
599 IN OUT AFSExtent **FirstExtent,
600 OUT AFSExtent **LastExtent)
603 // Return TRUE region is completely mapped. FALSE
604 // otherwise. If the region isn't mapped then the last
605 // extent to map part of the region is returned.
607 // *LastExtent as input is where to start looking.
608 // *LastExtent as output is either the extent which
609 // contains the Offset, or the last one which doesn't
613 BOOLEAN retVal = FALSE;
618 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
619 AFS_TRACE_LEVEL_VERBOSE,
620 "AFSDoExtentsMapRegion Acquiring Fcb extent lock %08lX SHARED %08lX\n",
621 &Fcb->NPFcb->Specific.File.ExtentsResource,
622 PsGetCurrentThread());
624 AFSAcquireShared( &Fcb->NPFcb->Specific.File.ExtentsResource, TRUE );
626 entry = AFSExtentForOffsetHint(Fcb, Offset, TRUE, *FirstExtent);
627 *FirstExtent = entry;
629 if (NULL == entry || !AFSExtentContains(entry, Offset))
631 try_return (retVal = FALSE);
634 ASSERT(Offset->QuadPart >= entry->FileOffset.QuadPart);
638 if ((entry->FileOffset.QuadPart + entry->Size) >=
639 (Offset->QuadPart + Size))
642 // The end is inside the extent
644 try_return (retVal = TRUE);
647 if (entry->Lists[AFS_EXTENTS_LIST].Flink == &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
650 // Run out of extents
652 try_return (retVal = FALSE);
655 newEntry = NextExtent( entry, AFS_EXTENTS_LIST );
657 if (newEntry->FileOffset.QuadPart !=
658 (entry->FileOffset.QuadPart + entry->Size))
663 try_return (retVal = FALSE);
671 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
672 AFS_TRACE_LEVEL_VERBOSE,
673 "AFSDoExtentsMapRegion Releasing Fcb extent lock %08lX SHARED %08lX\n",
674 &Fcb->NPFcb->Specific.File.ExtentsResource,
675 PsGetCurrentThread());
677 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
686 AFSRequestExtentsAsync( IN AFSFcb *Fcb,
688 IN PLARGE_INTEGER Offset,
692 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
693 NTSTATUS ntStatus = STATUS_SUCCESS;
694 AFSExtent *pExtent = NULL;
695 AFSRequestExtentsCB request;
696 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
697 AFSExtent *pFirstExtent = NULL;
698 LARGE_INTEGER liAlignedOffset;
699 ULONG ulAlignedLength = 0;
700 BOOLEAN bRegionMapped = FALSE;
701 ULONGLONG ullProcessId = (ULONGLONG)PsGetCurrentProcessId();
706 ASSERT( !ExIsResourceAcquiredLite( &pNPFcb->Specific.File.ExtentsResource ));
709 // If the service set a failure on the file since the last
710 // CreateFile was issued, return it now.
713 if (!NT_SUCCESS( pNPFcb->Specific.File.ExtentsRequestStatus))
717 // If this isn't the same authgroup which caused the failure
718 // then try to request them again
721 if( RtlCompareMemory( &pNPFcb->Specific.File.ExtentsRequestAuthGroup,
723 sizeof( GUID)) == sizeof( GUID))
726 ntStatus = pNPFcb->Specific.File.ExtentsRequestStatus;
728 pNPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
730 RtlZeroMemory( &pNPFcb->Specific.File.ExtentsRequestAuthGroup,
733 try_return( ntStatus);
738 // Check if we are already mapped
741 bRegionMapped = AFSDoExtentsMapRegion( Fcb, Offset, Size, &pFirstExtent, &pExtent);
746 try_return( ntStatus = STATUS_SUCCESS);
750 // Align our request on extent size boundary
753 ulAlignedLength = Size;
755 liAlignedOffset = *Offset;
757 if( liAlignedOffset.QuadPart % pDevExt->Specific.RDR.CacheBlockSize != 0)
760 liAlignedOffset.QuadPart = (ULONGLONG)( (ULONGLONG)(liAlignedOffset.QuadPart / pDevExt->Specific.RDR.CacheBlockSize) * (ULONGLONG)pDevExt->Specific.RDR.CacheBlockSize);
762 ulAlignedLength += (ULONG)(Offset->QuadPart - liAlignedOffset.QuadPart);
765 if( ulAlignedLength % pDevExt->Specific.RDR.CacheBlockSize != 0)
768 ulAlignedLength = (ULONG)(((ulAlignedLength / pDevExt->Specific.RDR.CacheBlockSize) + 1) * pDevExt->Specific.RDR.CacheBlockSize);
771 RtlZeroMemory( &request,
772 sizeof( AFSRequestExtentsCB));
774 request.ByteOffset = liAlignedOffset;
775 request.Length = ulAlignedLength;
777 if( !AFSIsExtentRequestQueued( &Fcb->ObjectInformation->FileId,
782 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
783 AFS_TRACE_LEVEL_VERBOSE,
784 "AFSRequestExtentsAsync Request extents for fid %08lX-%08lX-%08lX-%08lX Offset %08lX Len %08lX Thread %08lX\n",
785 Fcb->ObjectInformation->FileId.Cell,
786 Fcb->ObjectInformation->FileId.Volume,
787 Fcb->ObjectInformation->FileId.Vnode,
788 Fcb->ObjectInformation->FileId.Unique,
789 request.ByteOffset.LowPart,
791 PsGetCurrentThread());
793 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS,
797 &Fcb->ObjectInformation->FileId,
799 sizeof( AFSRequestExtentsCB ),
803 if ( ntStatus == STATUS_ACCESS_DENIED)
808 ntStatus2 = AFSRetrieveValidAuthGroup( Fcb,
813 if ( NT_SUCCESS( ntStatus2) &&
814 RtlCompareMemory( &stAuthGroup,
816 sizeof( GUID)) != sizeof( GUID))
819 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS,
823 &Fcb->ObjectInformation->FileId,
825 sizeof( AFSRequestExtentsCB ),
831 if( NT_SUCCESS( ntStatus))
834 KeClearEvent( &pNPFcb->Specific.File.ExtentsRequestComplete );
840 KeClearEvent( &pNPFcb->Specific.File.ExtentsRequestComplete );
852 AFSProcessExtentsResult( IN AFSFcb *Fcb,
854 IN AFSFileExtentCB *Result)
856 NTSTATUS ntStatus = STATUS_SUCCESS;
857 AFSFileExtentCB *pFileExtents = Result;
860 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
861 ULONG fileExtentsUsed = 0;
862 BOOLEAN bFoundExtent = FALSE;
863 LIST_ENTRY *pSkipEntries[AFS_NUM_EXTENT_LISTS] = { 0 };
864 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
868 // Grab the extents exclusive for the duration
871 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
872 AFS_TRACE_LEVEL_VERBOSE,
873 "AFSProcessExtentsResult Acquiring Fcb extent lock %08lX EXCL %08lX\n",
874 &pNPFcb->Specific.File.ExtentsResource,
875 PsGetCurrentThread());
877 AFSAcquireExcl( &pNPFcb->Specific.File.ExtentsResource, TRUE );
883 // Find where to put the extents
885 for (ULONG i = AFS_EXTENTS_LIST; i < AFS_NUM_EXTENT_LISTS; i++)
888 pSkipEntries[i] = Fcb->Specific.File.ExtentsLists[i].Flink;
891 le = pSkipEntries[AFS_EXTENTS_LIST];
893 if (le == &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
896 // No extents. Insert at head of list (which is where the skip lists point!)
900 else if (0 != pFileExtents->FileOffset.QuadPart)
903 // We want to find the best extents immediately *behind* this offset
905 LARGE_INTEGER offset = pFileExtents->FileOffset;
908 // Ask in the top skip list first, then work down
910 for (LONG i = AFS_NUM_EXTENT_LISTS-1; i >= AFS_EXTENTS_LIST; i--)
912 pExtent = ExtentForOffsetInList( Fcb,
920 // No dice. Header has to become the head of the list
922 pSkipEntries[i] = &Fcb->Specific.File.ExtentsLists[i];
924 // And as a loop invariant we should never have found an extent
926 ASSERT(!bFoundExtent);
931 // pExtent is where to start to insert at this level
933 pSkipEntries[i] = &pExtent->Lists[i];
936 // And also where to start to look at the next level
939 if (i > AFS_EXTENTS_LIST)
941 pSkipEntries[i-1] = &pExtent->Lists[i-1];
949 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
954 le = pExtent->Lists[AFS_EXTENTS_LIST].Blink;
960 // Looking at offset 0, so we must start at the beginning
963 pExtent = ExtentFor(le, AFS_EXTENTS_LIST);
967 // And set up the skip lists
970 for (ULONG i = AFS_EXTENTS_LIST; i < AFS_NUM_EXTENT_LISTS; i++)
972 pSkipEntries[i] = &Fcb->Specific.File.ExtentsLists[i];
976 while (fileExtentsUsed < Count)
980 // Loop invariant - le points to where to insert after and
981 // pExtent points to le->fLink
984 ASSERT (NULL == pExtent ||
985 le->Flink == &pExtent->Lists[AFS_EXTENTS_LIST]);
987 if (NULL == pExtent ||
988 pExtent->FileOffset.QuadPart > pFileExtents->FileOffset.QuadPart)
991 // We need to insert a new extent at le. Start with
992 // some sanity check on spanning
994 if (NULL != pExtent &&
995 ((pFileExtents->FileOffset.QuadPart + pFileExtents->Length) >
996 pExtent->FileOffset.QuadPart))
999 // File Extents overlaps pExtent
1001 ASSERT( (pFileExtents->FileOffset.QuadPart + pFileExtents->Length) <=
1002 pExtent->FileOffset.QuadPart);
1004 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1008 // File offset is entirely in front of this extent. Create
1009 // a new one (remember le is the previous list entry)
1011 pExtent = (AFSExtent *) AFSExAllocatePoolWithTag( NonPagedPool,
1014 if (NULL == pExtent)
1019 try_return (ntStatus = STATUS_INSUFFICIENT_RESOURCES );
1022 RtlZeroMemory( pExtent, sizeof( AFSExtent ));
1024 pExtent->FileOffset = pFileExtents->FileOffset;
1025 pExtent->CacheOffset = pFileExtents->CacheOffset;
1026 pExtent->Size = pFileExtents->Length;
1028 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1029 AFS_TRACE_LEVEL_VERBOSE,
1030 "AFSProcessExtentsResult Received extent for fid %08lX-%08lX-%08lX-%08lX File Offset %I64X Cache Offset %I64X Len %08lX\n",
1031 Fcb->ObjectInformation->FileId.Cell,
1032 Fcb->ObjectInformation->FileId.Volume,
1033 Fcb->ObjectInformation->FileId.Vnode,
1034 Fcb->ObjectInformation->FileId.Unique,
1035 pFileExtents->FileOffset.QuadPart,
1036 pFileExtents->CacheOffset.QuadPart,
1037 pFileExtents->Length);
1039 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, (LONG)(pExtent->Size/1024));
1041 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, (LONG)(pExtent->Size/1024));
1043 lCount = InterlockedIncrement( &Fcb->Specific.File.ExtentCount);
1045 lCount = InterlockedIncrement( &pControlDevExt->Specific.Control.ExtentCount);
1050 KeClearEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent);
1056 InsertHeadList(le, &pExtent->Lists[AFS_EXTENTS_LIST]);
1057 ASSERT(le->Flink == &pExtent->Lists[AFS_EXTENTS_LIST]);
1058 ASSERT(0 == (pExtent->FileOffset.LowPart & ExtentsMasks[AFS_EXTENTS_LIST]));
1061 // Do not move the cursor - we will do it next time
1065 // And into the (upper) skip lists - Again, do not move the cursor
1067 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1069 if (0 == (pExtent->FileOffset.LowPart & ExtentsMasks[i]))
1071 InsertHeadList(pSkipEntries[i], &pExtent->Lists[i]);
1072 #if AFS_VALIDATE_EXTENTS
1073 VerifyExtentsLists(Fcb);
1078 else if (pExtent->FileOffset.QuadPart == pFileExtents->FileOffset.QuadPart)
1081 if (pExtent->Size != pFileExtents->Length)
1084 ASSERT (pExtent->Size == pFileExtents->Length);
1086 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1090 // Move both cursors forward.
1092 // First the extent pointer
1095 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1098 // Then the skip lists cursors forward if needed
1100 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1102 if (0 == (pExtent->FileOffset.LowPart & ExtentsMasks[i]))
1105 // Check sanity before
1107 #if AFS_VALIDATE_EXTENTS
1108 VerifyExtentsLists(Fcb);
1112 // Skip list should point to us
1114 //ASSERT(pSkipEntries[i] == &pExtent->Lists[i]);
1116 // Move forward cursor
1118 pSkipEntries[i] = pSkipEntries[i]->Flink;
1120 // Check sanity before
1122 #if AFS_VALIDATE_EXTENTS
1123 VerifyExtentsLists(Fcb);
1129 // And then the cursor in the supplied array
1135 // setup pExtent if there is one
1137 if (le->Flink != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
1139 pExtent = NextExtent( pExtent, AFS_EXTENTS_LIST ) ;
1149 ASSERT( pExtent->FileOffset.QuadPart < pFileExtents->FileOffset.QuadPart );
1152 // Sanity check on spanning
1154 if ((pExtent->FileOffset.QuadPart + pExtent->Size) >
1155 pFileExtents->FileOffset.QuadPart)
1158 ASSERT( (pExtent->FileOffset.QuadPart + pExtent->Size) <=
1159 pFileExtents->FileOffset.QuadPart);
1161 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1165 // Move le and pExtent forward
1167 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1171 // Then the check the skip lists cursors
1173 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1175 if (0 == (pFileExtents->FileOffset.LowPart & ExtentsMasks[i]))
1179 // - empty list (pSkipEntries[i]->Flink == pSkipEntries[i]->Flink == fcb->lists[i]
1180 // - We are the last on the list (pSkipEntries[i]->Flink == fcb->lists[i])
1181 // - We are not the last on the list. In that case we have to be strictly less than
1183 if (pSkipEntries[i]->Flink != &Fcb->Specific.File.ExtentsLists[i]) {
1185 AFSExtent *otherExtent = ExtentFor(pSkipEntries[i]->Flink, i);
1186 ASSERT(pFileExtents->FileOffset.QuadPart < otherExtent->FileOffset.QuadPart);
1193 // setup pExtent if there is one
1196 if (le->Flink != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
1198 pExtent = NextExtent( pExtent, AFS_EXTENTS_LIST ) ;
1208 // All done, signal that we are done drop the lock, exit
1213 if( !NT_SUCCESS( ntStatus))
1217 // If we failed the service is going to drop all extents so trim away the
1221 AFSTrimSpecifiedExtents( Fcb,
1226 #if AFS_VALIDATE_EXTENTS
1227 VerifyExtentsLists(Fcb);
1230 KeSetEvent( &pNPFcb->Specific.File.ExtentsRequestComplete,
1234 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1235 AFS_TRACE_LEVEL_VERBOSE,
1236 "AFSProcessExtentsResult Releasing Fcb extent lock %08lX EXCL %08lX\n",
1237 &pNPFcb->Specific.File.ExtentsResource,
1238 PsGetCurrentThread());
1240 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
1247 AFSProcessSetFileExtents( IN AFSSetFileExtentsCB *SetExtents )
1249 AFSFcb *pFcb = NULL;
1250 AFSVolumeCB *pVolumeCB = NULL;
1251 NTSTATUS ntStatus = STATUS_SUCCESS;
1252 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1253 ULONGLONG ullIndex = 0;
1254 AFSObjectInfoCB *pObjectInfo = NULL;
1260 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1261 AFS_TRACE_LEVEL_VERBOSE,
1262 "AFSProcessSetFileExtents Acquiring RDR VolumeTreeLock lock %08lX SHARED %08lX\n",
1263 &pDevExt->Specific.RDR.VolumeTreeLock,
1264 PsGetCurrentThread());
1266 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
1268 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1269 AFS_TRACE_LEVEL_VERBOSE,
1270 "AFSProcessSetFileExtents Set extents for fid %08lX-%08lX-%08lX-%08lX\n",
1271 SetExtents->FileId.Cell,
1272 SetExtents->FileId.Volume,
1273 SetExtents->FileId.Vnode,
1274 SetExtents->FileId.Unique);
1277 // Locate the volume node
1280 ullIndex = AFSCreateHighIndex( &SetExtents->FileId);
1282 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
1284 (AFSBTreeEntry **)&pVolumeCB);
1286 if( pVolumeCB != NULL)
1289 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1290 AFS_TRACE_LEVEL_VERBOSE,
1291 "AFSProcessSetFileExtents Acquiring VolumeRoot FileIDTree.TreeLock lock %08lX SHARED %08lX\n",
1292 pVolumeCB->ObjectInfoTree.TreeLock,
1293 PsGetCurrentThread());
1295 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1298 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
1300 if( !NT_SUCCESS( ntStatus) ||
1304 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1305 AFS_TRACE_LEVEL_ERROR,
1306 "AFSProcessSetFileExtents Set extents for fid %08lX-%08lX-%08lX-%08lX Failed to locate volume Status %08lX\n",
1307 SetExtents->FileId.Cell,
1308 SetExtents->FileId.Volume,
1309 SetExtents->FileId.Vnode,
1310 SetExtents->FileId.Unique,
1313 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1316 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1319 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1322 // Now locate the Object in this volume
1325 ullIndex = AFSCreateLowIndex( &SetExtents->FileId);
1327 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
1329 (AFSBTreeEntry **)&pObjectInfo);
1331 if( pObjectInfo != NULL)
1335 // Reference the node so it won't be torn down
1338 lCount = InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
1340 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1341 AFS_TRACE_LEVEL_VERBOSE,
1342 "AFSProcessSetFileExtents Increment count on object %08lX Cnt %d\n",
1347 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1349 if( !NT_SUCCESS( ntStatus) ||
1350 pObjectInfo == NULL)
1353 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1354 AFS_TRACE_LEVEL_ERROR,
1355 "AFSProcessSetFileExtents Set extents for hash %I64X fid %08lX-%08lX-%08lX-%08lX Failed to locate file in volume %08lX\n",
1357 SetExtents->FileId.Cell,
1358 SetExtents->FileId.Volume,
1359 SetExtents->FileId.Vnode,
1360 SetExtents->FileId.Unique,
1363 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1366 pFcb = pObjectInfo->Fcb;
1369 // If we have a result failure then don't bother trying to set the extents
1372 if( SetExtents->ResultStatus != STATUS_SUCCESS)
1375 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1376 AFS_TRACE_LEVEL_ERROR,
1377 "AFSProcessSetFileExtents Set extents failure fid %08lX-%08lX-%08lX-%08lX ResultStatus %08lX\n",
1378 SetExtents->FileId.Cell,
1379 SetExtents->FileId.Volume,
1380 SetExtents->FileId.Vnode,
1381 SetExtents->FileId.Unique,
1382 SetExtents->ResultStatus);
1384 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1385 AFS_TRACE_LEVEL_VERBOSE,
1386 "AFSProcessSetFileExtents Acquiring Fcb extents lock %08lX EXCL %08lX\n",
1387 &pFcb->NPFcb->Specific.File.ExtentsResource,
1388 PsGetCurrentThread());
1390 AFSAcquireExcl( &pFcb->NPFcb->Specific.File.ExtentsResource,
1393 pFcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_CANCELLED;
1395 KeSetEvent( &pFcb->NPFcb->Specific.File.ExtentsRequestComplete,
1399 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1400 AFS_TRACE_LEVEL_VERBOSE,
1401 "AFSProcessSetFileExtents Releasing Fcb extent lock %08lX EXCL %08lX\n",
1402 &pFcb->NPFcb->Specific.File.ExtentsResource,
1403 PsGetCurrentThread());
1405 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
1407 try_return( ntStatus);
1410 ntStatus = AFSProcessExtentsResult ( pFcb,
1411 SetExtents->ExtentCount,
1412 SetExtents->FileExtents );
1416 if( pObjectInfo != NULL)
1419 lCount = InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
1421 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1422 AFS_TRACE_LEVEL_VERBOSE,
1423 "AFSProcessSetFileExtents Decrement count on object %08lX Cnt %d\n",
1433 // Helper fuctions for Usermode initiation of release of extents
1436 AFSReleaseSpecifiedExtents( IN AFSReleaseFileExtentsCB *Extents,
1438 OUT AFSFileExtentCB *FileExtents,
1439 IN ULONG BufferSize,
1440 OUT ULONG *ExtentCount,
1441 OUT BOOLEAN *DirtyExtents)
1446 ULONG ulExtentCount = 0;
1447 NTSTATUS ntStatus = STATUS_SUCCESS;
1448 BOOLEAN bReleaseAll = FALSE;
1449 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1454 ASSERT( ExIsResourceAcquiredExclusiveLite( &Fcb->NPFcb->Specific.File.ExtentsResource));
1456 if (BufferSize < (Extents->ExtentCount * sizeof( AFSFileExtentCB)))
1459 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1460 AFS_TRACE_LEVEL_VERBOSE,
1461 "AFSReleaseSpecifiedExtents Buffer too small\n");
1463 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL);
1466 RtlZeroMemory( FileExtents, BufferSize);
1469 *DirtyExtents = FALSE;
1472 // iterate until we have dealt with all we were asked for or
1473 // are at the end of the list. Note that this deals (albeit
1474 // badly) with out of order extents
1477 pExtent = AFSExtentForOffset( Fcb,
1478 &Extents->FileExtents[0].FileOffset,
1481 if (NULL == pExtent)
1483 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1487 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1491 if( BooleanFlagOn( Extents->Flags, AFS_RELEASE_EXTENTS_FLAGS_RELEASE_ALL) ||
1492 ( Extents->FileId.Cell == 0 &&
1493 Extents->FileId.Volume == 0 &&
1494 Extents->FileId.Vnode == 0 &&
1495 Extents->FileId.Unique == 0))
1501 while( le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST] &&
1502 ulExtentCount < Extents->ExtentCount)
1506 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
1511 if( pExtent->FileOffset.QuadPart < Extents->FileExtents[ulExtentCount].FileOffset.QuadPart)
1514 // Skip forward through the extent list until we get
1515 // to the one we want
1521 else if (pExtent->FileOffset.QuadPart > Extents->FileExtents[ulExtentCount].FileOffset.QuadPart)
1524 // We don't have the extent asked for so return UNKNOWN
1527 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1528 AFS_TRACE_LEVEL_VERBOSE,
1529 "AFSReleaseSpecifiedExtents Located UNKNOWN extent Offset %I64X Len %08lX\n",
1530 Extents->FileExtents[ulExtentCount].FileOffset.QuadPart,
1531 Extents->FileExtents[ulExtentCount].Length);
1533 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_UNKNOWN;
1535 FileExtents[*ExtentCount].Length = 0;
1536 FileExtents[*ExtentCount].CacheOffset.QuadPart = 0;
1537 FileExtents[*ExtentCount].FileOffset = Extents->FileExtents[ulExtentCount].FileOffset;
1539 *ExtentCount = (*ExtentCount) + 1;
1544 // Reset where we are looking
1547 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1551 else if( pExtent->ActiveCount > 0)
1554 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1555 AFS_TRACE_LEVEL_VERBOSE,
1556 "AFSReleaseSpecifiedExtents Located IN_USE extent Offset %I64X Len %08lX\n",
1557 Extents->FileExtents[ulExtentCount].FileOffset.QuadPart,
1558 Extents->FileExtents[ulExtentCount].Length);
1560 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_IN_USE;
1562 FileExtents[*ExtentCount].Length = 0;
1563 FileExtents[*ExtentCount].CacheOffset.QuadPart = 0;
1564 FileExtents[*ExtentCount].FileOffset = Extents->FileExtents[ulExtentCount].FileOffset;
1566 *ExtentCount = (*ExtentCount) + 1;
1571 // Reset where we are looking
1574 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1583 // If the extent is currently active then skip it
1586 if( pExtent->ActiveCount > 0)
1595 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_RELEASE;
1597 FileExtents[*ExtentCount].Length = pExtent->Size;
1598 FileExtents[*ExtentCount].DirtyLength = pExtent->Size;
1599 FileExtents[*ExtentCount].DirtyOffset = 0;
1600 FileExtents[*ExtentCount].CacheOffset = pExtent->CacheOffset;
1601 FileExtents[*ExtentCount].FileOffset = pExtent->FileOffset;
1603 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1604 AFS_TRACE_LEVEL_VERBOSE,
1605 "AFSReleaseSpecifiedExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
1607 Fcb->ObjectInformation->FileId.Cell,
1608 Fcb->ObjectInformation->FileId.Volume,
1609 Fcb->ObjectInformation->FileId.Vnode,
1610 Fcb->ObjectInformation->FileId.Unique,
1611 FileExtents[*ExtentCount].FileOffset.QuadPart,
1612 FileExtents[*ExtentCount].Length);
1614 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
1617 AFSAcquireExcl( &Fcb->NPFcb->Specific.File.DirtyExtentsListLock,
1620 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
1623 AFSRemoveEntryDirtyList( Fcb,
1626 FileExtents[*ExtentCount].Flags |= AFS_EXTENT_FLAG_DIRTY;
1628 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
1630 *DirtyExtents = TRUE;
1633 AFSReleaseResource( &Fcb->NPFcb->Specific.File.DirtyExtentsListLock);
1637 // move forward all three cursors
1641 *ExtentCount = (*ExtentCount) + 1;
1646 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
1648 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
1650 RemoveEntryList( &pExtent->Lists[i] );
1654 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
1656 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
1661 AFSExFreePool( pExtent);
1663 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
1665 lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount);
1670 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
1685 AFSFindFcbToClean(ULONG IgnoreTime, AFSFcb *LastFcb, BOOLEAN Block)
1688 AFSFcb *pFcb = NULL;
1689 AFSVolumeCB *pVolumeCB = NULL;
1690 AFSDeviceExt *pRDRDeviceExt = NULL;
1691 AFSDeviceExt *pControlDeviceExt = NULL;
1692 BOOLEAN bLocatedEntry = FALSE;
1693 AFSObjectInfoCB *pCurrentObject = NULL;
1694 BOOLEAN bReleaseVolumeListLock = FALSE;
1697 pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1698 pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1700 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1701 AFS_TRACE_LEVEL_VERBOSE,
1702 "AFSFindFcbToClean Acquiring RDR VolumeListLock lock %08lX SHARED %08lX\n",
1703 &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1704 PsGetCurrentThread());
1706 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1709 bReleaseVolumeListLock = TRUE;
1711 pVolumeCB = pRDRDeviceExt->Specific.RDR.VolumeListHead;
1713 while( pVolumeCB != NULL)
1717 // The Volume list may move under our feet. Lock it.
1720 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1721 AFS_TRACE_LEVEL_VERBOSE,
1722 "AFSFindFcbToClean Acquiring VolumeRoot ObjectInfoTree lock %08lX SHARED %08lX\n",
1723 pVolumeCB->ObjectInfoTree.TreeLock,
1724 PsGetCurrentThread());
1726 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1728 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1730 bReleaseVolumeListLock = FALSE;
1732 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1735 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1737 if( NULL == LastFcb)
1740 pCurrentObject = pVolumeCB->ObjectInfoListHead;
1745 pCurrentObject = (AFSObjectInfoCB *)LastFcb->ObjectInformation->ListEntry.fLink;
1750 while( pCurrentObject != NULL)
1753 pFcb = (AFSFcb *)pCurrentObject->Fcb;
1756 // If the FCB is a candidate we try to lock it (but without waiting - which
1757 // means we are deadlock free
1761 pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
1767 AFSLockForExtentsTrim( pFcb);
1772 if( !AFSLockForExtentsTrimNoWait( pFcb))
1775 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1784 // Need to be sure there are no current flushes in the queue
1787 if( pFcb->Specific.File.ExtentCount == 0)
1790 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1791 AFS_TRACE_LEVEL_VERBOSE,
1792 "AFSFindFcbToClean Releasing Fcb extent lock %08lX thread %08lX\n",
1793 &pFcb->NPFcb->Specific.File.ExtentsResource,
1794 PsGetCurrentThread());
1796 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
1798 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1805 if( pFcb->Specific.File.QueuedFlushCount > 0)
1808 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1809 AFS_TRACE_LEVEL_VERBOSE,
1810 "AFSFindFcbToClean Releasing Fcb extent lock %08lX thread %08lX\n",
1811 &pFcb->NPFcb->Specific.File.ExtentsResource,
1812 PsGetCurrentThread());
1814 AFSReleaseResource(&pFcb->NPFcb->Specific.File.ExtentsResource);
1818 AFSWaitOnQueuedFlushes( pFcb);
1823 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1831 if( pFcb->OpenHandleCount > 0)
1834 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1835 AFS_TRACE_LEVEL_VERBOSE,
1836 "AFSFindFcbToClean Releasing Fcb extent lock %08lX thread %08lX\n",
1837 &pFcb->NPFcb->Specific.File.ExtentsResource,
1838 PsGetCurrentThread());
1840 AFSReleaseResource(&pFcb->NPFcb->Specific.File.ExtentsResource);
1842 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1850 // A hit a very palpable hit. Pin it
1853 lCount = InterlockedIncrement( &pCurrentObject->ObjectReferenceCount);
1855 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1856 AFS_TRACE_LEVEL_VERBOSE,
1857 "AFSFindFcbToClean Increment count on Fcb %08lX Cnt %d\n",
1861 bLocatedEntry = TRUE;
1866 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1871 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1878 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1881 bReleaseVolumeListLock = TRUE;
1883 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1886 if( bReleaseVolumeListLock)
1889 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1896 AFSProcessExtentFailure( PIRP Irp)
1898 AFSExtentFailureCB *pFailureCB = NULL;
1899 NTSTATUS ntStatus = STATUS_SUCCESS;
1900 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
1901 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1902 AFSVolumeCB *pVolumeCB = NULL;
1903 ULONGLONG ullIndex = 0;
1904 AFSObjectInfoCB *pObjectInfo = NULL;
1909 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSExtentFailureCB))
1912 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1913 AFS_TRACE_LEVEL_ERROR,
1914 "AFSProcessExtentFailure Input buffer too small\n");
1916 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1919 pFailureCB = (AFSExtentFailureCB *)Irp->AssociatedIrp.SystemBuffer;
1921 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1922 AFS_TRACE_LEVEL_ERROR,
1923 "AFSProcessExtentFailure Service Reports Failure fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1924 pFailureCB->FileId.Cell,
1925 pFailureCB->FileId.Volume,
1926 pFailureCB->FileId.Vnode,
1927 pFailureCB->FileId.Unique,
1928 pFailureCB->FailureStatus);
1930 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
1933 // Locate the volume node
1936 ullIndex = AFSCreateHighIndex( &pFailureCB->FileId);
1938 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
1940 (AFSBTreeEntry **)&pVolumeCB);
1942 if( pVolumeCB != NULL)
1945 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1946 AFS_TRACE_LEVEL_VERBOSE,
1947 "AFSProcessExtentFailure Acquiring VolumeRoot FileIDTree.TreeLock lock %08lX SHARED %08lX\n",
1948 pVolumeCB->ObjectInfoTree.TreeLock,
1949 PsGetCurrentThread());
1951 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1954 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
1956 if( !NT_SUCCESS( ntStatus) ||
1960 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1961 AFS_TRACE_LEVEL_ERROR,
1962 "AFSProcessExtentFailure Invalid volume index %I64X status %08X\n",
1963 ullIndex, ntStatus);
1965 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1968 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1971 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1974 // Now locate the Object in this volume
1977 ullIndex = AFSCreateLowIndex( &pFailureCB->FileId);
1979 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
1981 (AFSBTreeEntry **)&pObjectInfo);
1983 if( pObjectInfo != NULL &&
1984 pObjectInfo->Fcb != NULL)
1988 // Reference the node so it won't be torn down
1991 lCount = InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
1993 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1994 AFS_TRACE_LEVEL_VERBOSE,
1995 "AFSProcessExtentFailure Increment count on object %08lX Cnt %d\n",
2000 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2002 if( !NT_SUCCESS( ntStatus) ||
2003 pObjectInfo == NULL ||
2004 pObjectInfo->Fcb == NULL)
2007 if( pObjectInfo == NULL)
2009 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2010 AFS_TRACE_LEVEL_ERROR,
2011 "AFSProcessExtentFailure Invalid file index %I64X\n",
2016 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2017 AFS_TRACE_LEVEL_ERROR,
2018 "AFSProcessExtentFailure Fcb dealocated for %I64X\n",
2022 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2025 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2026 AFS_TRACE_LEVEL_VERBOSE,
2027 "AFSProcessExtentFailure Acquiring Fcb extent lock %08lX EXCL %08lX\n",
2028 &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2029 PsGetCurrentThread());
2031 AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2034 pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestStatus = pFailureCB->FailureStatus;
2036 RtlCopyMemory( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2037 &pFailureCB->AuthGroup,
2040 KeSetEvent( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
2044 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2045 AFS_TRACE_LEVEL_VERBOSE,
2046 "AFSProcessExtentFailure Releasing Fcb extent lock %08lX EXCL %08lX\n",
2047 &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2048 PsGetCurrentThread());
2050 AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource);
2052 lCount = InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
2054 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2055 AFS_TRACE_LEVEL_VERBOSE,
2056 "AFSProcessExtentFailure Decrement count on object %08lX Cnt %d\n",
2069 AFSProcessReleaseFileExtents( IN PIRP Irp)
2071 NTSTATUS ntStatus = STATUS_SUCCESS;
2072 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2073 PFILE_OBJECT pFileObject = pIrpSp->FileObject;
2074 AFSFcb *pFcb = NULL;
2075 AFSVolumeCB *pVolumeCB = NULL;
2076 AFSDeviceExt *pDevExt;
2077 AFSReleaseFileExtentsCB *pExtents;
2078 AFSReleaseFileExtentsResultCB *pResult = NULL;
2079 AFSReleaseFileExtentsResultFileCB *pFile = NULL;
2081 ULONGLONG ullIndex = 0;
2082 AFSObjectInfoCB *pObjectInfo = NULL;
2083 BOOLEAN bLocked = FALSE;
2084 BOOLEAN bDirtyExtents = FALSE;
2091 pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2093 pExtents = (AFSReleaseFileExtentsCB*) Irp->AssociatedIrp.SystemBuffer;
2095 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2096 sizeof( AFSReleaseFileExtentsCB))
2099 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2100 AFS_TRACE_LEVEL_ERROR,
2101 "AFSProcessReleaseFileExtents INPUT Buffer too small\n");
2103 try_return( ntStatus = STATUS_INVALID_PARAMETER );
2106 if ( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength <
2107 sizeof(AFSReleaseFileExtentsResultCB))
2110 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2111 AFS_TRACE_LEVEL_ERROR,
2112 "AFSProcessReleaseFileExtents OUTPUT Buffer too small [1]\n");
2115 // Must have space for one extent in one file
2118 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL);
2121 if (pExtents->ExtentCount == 0)
2124 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2125 AFS_TRACE_LEVEL_ERROR,
2126 "AFSProcessReleaseFileExtents Extent count zero\n");
2128 try_return( ntStatus = STATUS_INVALID_PARAMETER);
2131 if (pExtents->FileId.Cell != 0 ||
2132 pExtents->FileId.Volume != 0 ||
2133 pExtents->FileId.Vnode != 0 ||
2134 pExtents->FileId.Unique != 0)
2137 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2138 AFS_TRACE_LEVEL_VERBOSE,
2139 "AFSProcessReleaseFileExtents Processing FID %08lX:%08lX:%08lX:%08lX\n",
2140 pExtents->FileId.Cell,
2141 pExtents->FileId.Volume,
2142 pExtents->FileId.Vnode,
2143 pExtents->FileId.Unique);
2145 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2146 ( FIELD_OFFSET( AFSReleaseFileExtentsCB, ExtentCount) + sizeof(ULONG)) ||
2147 pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2148 ( FIELD_OFFSET( AFSReleaseFileExtentsCB, ExtentCount) + sizeof(ULONG) +
2149 sizeof (AFSFileExtentCB) * pExtents->ExtentCount))
2152 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2153 AFS_TRACE_LEVEL_ERROR,
2154 "AFSProcessReleaseFileExtents Buffer too small for FID %08lX:%08lx:%08lX:%08lX\n",
2155 pExtents->FileId.Cell,
2156 pExtents->FileId.Volume,
2157 pExtents->FileId.Vnode,
2158 pExtents->FileId.Unique);
2160 try_return( ntStatus = STATUS_INVALID_PARAMETER );
2163 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2164 AFS_TRACE_LEVEL_VERBOSE,
2165 "AFSProcessReleaseFileExtents Acquiring RDR VolumeTreeLock lock %08lX SHARED %08lX\n",
2166 &pDevExt->Specific.RDR.VolumeTreeLock,
2167 PsGetCurrentThread());
2169 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
2172 // Locate the volume node
2175 ullIndex = AFSCreateHighIndex( &pExtents->FileId);
2177 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
2179 (AFSBTreeEntry **)&pVolumeCB);
2181 if( pVolumeCB != NULL)
2184 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2185 AFS_TRACE_LEVEL_VERBOSE,
2186 "AFSProcessReleaseFileExtents Acquiring VolumeRoot FileIDTree.TreeLock lock %08lX SHARED %08lX\n",
2187 pVolumeCB->ObjectInfoTree.TreeLock,
2188 PsGetCurrentThread());
2190 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
2193 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
2195 if( !NT_SUCCESS( ntStatus) ||
2199 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2200 AFS_TRACE_LEVEL_ERROR,
2201 "AFSProcessReleaseFileExtents Invalid volume index %I64X status %08X\n",
2202 ullIndex, ntStatus);
2204 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2207 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
2210 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
2213 // Now locate the Object in this volume
2216 ullIndex = AFSCreateLowIndex( &pExtents->FileId);
2218 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
2220 (AFSBTreeEntry **)&pObjectInfo);
2222 if( pObjectInfo != NULL)
2226 // Reference the node so it won't be torn down
2229 lCount = InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
2231 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2232 AFS_TRACE_LEVEL_VERBOSE,
2233 "AFSProcessReleaseFileExtents Increment count on object %08lX Cnt %d\n",
2238 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2240 if( !NT_SUCCESS( ntStatus) ||
2241 pObjectInfo == NULL)
2244 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2245 AFS_TRACE_LEVEL_ERROR,
2246 "AFSProcessReleaseFileExtents Invalid file index %I64X\n",
2249 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2252 pFcb = pObjectInfo->Fcb;
2257 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2258 AFS_TRACE_LEVEL_ERROR,
2259 "AFSProcessReleaseFileExtents Fcb not initialied (NO EXTENTS) for FID %08lX:%08lx:%08lX:%08lX\n",
2260 pExtents->FileId.Cell,
2261 pExtents->FileId.Volume,
2262 pExtents->FileId.Vnode,
2263 pExtents->FileId.Unique);
2265 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2268 AFSLockForExtentsTrim( pFcb );
2276 // Locate an Fcb to trim down
2279 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2280 AFS_TRACE_LEVEL_VERBOSE,
2281 "AFSProcessReleaseFileExtents Searching for a Fcb to Trim Down\n");
2283 pFcb = AFSFindFcbToClean( 0, NULL, FALSE);
2288 pFcb = AFSFindFcbToClean( 0, NULL, TRUE);
2294 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2295 AFS_TRACE_LEVEL_ERROR,
2296 "AFSProcessReleaseFileExtents Failed to locate Fcb for release ...\n");
2298 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2301 pObjectInfo = pFcb->ObjectInformation;
2307 // Allocate a scratch buffer to move in the extent information
2310 ulSz = (pExtents->ExtentCount-1) * sizeof(AFSFileExtentCB);
2311 ulSz += sizeof(AFSReleaseFileExtentsResultCB);
2313 if (ulSz > pIrpSp->Parameters.DeviceIoControl.OutputBufferLength)
2315 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2316 AFS_TRACE_LEVEL_ERROR,
2317 "AFSProcessReleaseFileExtents OUTPUT Buffer too small [2]\n");
2319 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL );
2322 pResult = (AFSReleaseFileExtentsResultCB*) AFSExAllocatePoolWithTag( PagedPool,
2324 AFS_EXTENTS_RESULT_TAG);
2325 if (NULL == pResult)
2328 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2329 AFS_TRACE_LEVEL_ERROR,
2330 "AFSProcessReleaseFileExtents Failed to allocate result block\n");
2332 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2336 // Set up the header (for an array of one)
2338 pResult->FileCount = 1;
2339 pResult->Flags = AFS_EXTENT_FLAG_RELEASE;
2340 ulSz -= FIELD_OFFSET(AFSReleaseFileExtentsResultCB, Files);
2343 // Setup the first (and only) file
2345 pFile = pResult->Files;
2346 pFile->FileId = pObjectInfo->FileId;
2347 pFile->Flags = AFS_EXTENT_FLAG_RELEASE;
2350 // Stash away the auth group
2353 RtlZeroMemory( &stAuthGroup,
2356 ntStatus = AFSRetrieveValidAuthGroup( pFcb,
2361 if( !NT_SUCCESS( ntStatus))
2363 try_return( ntStatus);
2366 RtlCopyMemory( &pFile->AuthGroup,
2371 // Update the metadata for this call
2374 pFile->AllocationSize = pFcb->ObjectInformation->EndOfFile;
2375 pFile->CreateTime = pFcb->ObjectInformation->CreationTime;
2376 pFile->ChangeTime = pFcb->ObjectInformation->ChangeTime;
2377 pFile->LastAccessTime = pFcb->ObjectInformation->LastAccessTime;
2378 pFile->LastWriteTime = pFcb->ObjectInformation->LastWriteTime;
2380 ulSz -= FIELD_OFFSET(AFSReleaseFileExtentsResultFileCB, FileExtents);
2382 ntStatus = AFSReleaseSpecifiedExtents( pExtents,
2386 &pFile->ExtentCount,
2389 if (!NT_SUCCESS(ntStatus))
2392 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2393 AFS_TRACE_LEVEL_ERROR,
2394 "AFSProcessReleaseFileExtents Failed to release extents Status %08lX\n",
2397 try_return( ntStatus );
2400 if( pExtents->ExtentCount == 0)
2403 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2404 AFS_TRACE_LEVEL_WARNING,
2405 "AFSProcessReleaseFileExtents Failed to release ANY extents\n");
2408 ulSz = sizeof(AFSReleaseFileExtentsResultCB);
2410 if( pExtents->ExtentCount > 0)
2412 ulSz += ((pExtents->ExtentCount-1) * sizeof(AFSFileExtentCB));
2415 RtlCopyMemory( Irp->AssociatedIrp.SystemBuffer,
2424 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2425 AFS_TRACE_LEVEL_VERBOSE,
2426 "AFSProcessReleaseFileExtents Releasing Fcb extent lock %08lX thread %08lX\n",
2427 &pFcb->NPFcb->Specific.File.ExtentsResource,
2428 PsGetCurrentThread());
2430 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
2433 if( NULL != pResult &&
2434 Irp->AssociatedIrp.SystemBuffer != pResult)
2437 AFSExFreePool(pResult);
2440 if (NT_SUCCESS(ntStatus))
2442 Irp->IoStatus.Information = ulSz;
2446 Irp->IoStatus.Information = 0;
2449 Irp->IoStatus.Status = ntStatus;
2451 if( pObjectInfo != NULL)
2454 lCount = InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
2456 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2457 AFS_TRACE_LEVEL_VERBOSE,
2458 "AFSProcessReleaseFileExtents Decrement count on object %08lX Cnt %d\n",
2468 AFSWaitForExtentMapping( AFSFcb *Fcb,
2471 NTSTATUS ntStatus = STATUS_SUCCESS;
2472 LARGE_INTEGER liTimeOut;
2473 ULONGLONG ullProcessId = (ULONGLONG)PsGetCurrentProcessId();
2478 ASSERT( !ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
2480 if (!NT_SUCCESS( Fcb->NPFcb->Specific.File.ExtentsRequestStatus))
2484 // If this isn't the same authgroup which caused the failure
2485 // then try to request them again
2488 if( RtlCompareMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2490 sizeof( GUID)) == sizeof( GUID))
2493 ntStatus = Fcb->NPFcb->Specific.File.ExtentsRequestStatus;
2495 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
2497 RtlZeroMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2500 try_return( ntStatus);
2504 liTimeOut.QuadPart = -(1 * AFS_ONE_SECOND);
2506 ntStatus = KeWaitForSingleObject( &Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
2512 if (!NT_SUCCESS( Fcb->NPFcb->Specific.File.ExtentsRequestStatus))
2516 // If this isn't the same authgroup which caused the failure
2517 // or the System Process,
2518 // then try to request the extents again
2521 if( RtlCompareMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2523 sizeof( GUID)) == sizeof( GUID) ||
2524 ullProcessId == (ULONGLONG)AFSSysProcess)
2527 ntStatus = Fcb->NPFcb->Specific.File.ExtentsRequestStatus;
2529 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
2531 RtlZeroMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2534 try_return( ntStatus);
2538 if( ntStatus == STATUS_TIMEOUT)
2541 ntStatus = STATUS_SUCCESS;
2553 AFSFlushExtents( IN AFSFcb *Fcb,
2556 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
2557 AFSExtent *pExtent, *pNextExtent;
2559 AFSReleaseExtentsCB *pRelease = NULL;
2561 ULONG initialDirtyCount = 0;
2562 BOOLEAN bExtentsLocked = FALSE;
2565 NTSTATUS ntStatus = STATUS_SUCCESS;
2566 LARGE_INTEGER liLastFlush;
2567 AFSExtent *pDirtyListHead = NULL, *pDirtyListTail = NULL;
2568 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2569 GUID *pAuthGroup = AuthGroup;
2573 ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
2576 // Save, then reset the flush time
2579 liLastFlush = Fcb->Specific.File.LastServerFlush;
2581 KeQueryTickCount( &Fcb->Specific.File.LastServerFlush);
2586 if( pAuthGroup == NULL ||
2587 RtlCompareMemory( pAuthGroup,
2588 &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2589 sizeof( GUID)) == sizeof( GUID))
2592 RtlZeroMemory( &stAuthGroup,
2595 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
2600 if( !NT_SUCCESS( ntStatus))
2602 try_return( ntStatus);
2605 pAuthGroup = &stAuthGroup;
2609 // Lock extents while we count and set up the array to send to
2613 AFSLockForExtentsTrim( Fcb);
2615 bExtentsLocked = TRUE;
2617 lCount = InterlockedIncrement( &Fcb->Specific.File.QueuedFlushCount);
2620 // Clear our queued flush event
2623 KeClearEvent( &Fcb->NPFcb->Specific.File.QueuedFlushEvent);
2626 // Look for a start in the list to flush entries
2631 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
2633 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
2635 AFS_EXTENT_RELEASE_TAG);
2636 if( NULL == pRelease)
2639 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2642 initialDirtyCount = Fcb->Specific.File.ExtentsDirtyCount;
2644 while( Fcb->Specific.File.ExtentsDirtyCount > 0)
2647 pRelease->Flags = AFS_EXTENT_FLAG_DIRTY;
2649 if( BooleanFlagOn( Fcb->Flags, AFS_FCB_FILE_CLOSED))
2652 pRelease->Flags |= AFS_EXTENT_FLAG_FLUSH;
2656 // Update the metadata for this call
2659 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
2660 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
2661 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
2662 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
2663 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
2667 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
2670 pExtent = (AFSExtent *)pNPFcb->Specific.File.DirtyListHead;
2672 while( count < AFS_MAXIMUM_EXTENT_RELEASE_COUNT)
2675 if ( pExtent == NULL)
2681 pNextExtent = (AFSExtent *)pExtent->DirtyList.fLink;
2683 if ( pExtent->ActiveCount > 0)
2685 pExtent = pNextExtent;
2689 AFSRemoveEntryDirtyList( Fcb, pExtent);
2691 pExtent->DirtyList.fLink = NULL;
2692 pExtent->DirtyList.bLink = NULL;
2694 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
2697 // Clear the flag in advance of the write. If we do
2698 // things this was we know that the clear is
2699 // pessimistic (any write which happens from now on
2700 // will set the flag dirty again).
2703 pExtent->Flags &= ~AFS_EXTENT_DIRTY;
2705 pRelease->FileExtents[count].Flags = AFS_EXTENT_FLAG_DIRTY;
2707 pRelease->FileExtents[count].Length = pExtent->Size;
2708 pRelease->FileExtents[count].DirtyLength = pExtent->Size;
2709 pRelease->FileExtents[count].DirtyOffset = 0;
2710 pRelease->FileExtents[count].CacheOffset = pExtent->CacheOffset;
2711 pRelease->FileExtents[count].FileOffset = pExtent->FileOffset;
2714 RtlCopyMemory( pRelease->FileExtents[count].MD5,
2716 sizeof(pExtent->MD5));
2718 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_MD5_SET;
2721 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2722 AFS_TRACE_LEVEL_VERBOSE,
2723 "AFSFlushExtents Releasing DIRTY extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
2725 Fcb->ObjectInformation->FileId.Cell,
2726 Fcb->ObjectInformation->FileId.Volume,
2727 Fcb->ObjectInformation->FileId.Vnode,
2728 Fcb->ObjectInformation->FileId.Unique,
2729 pExtent->FileOffset.QuadPart,
2732 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_RELEASE;
2735 // Need to pull this extent from the main list as well
2738 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
2740 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
2742 RemoveEntryList( &pExtent->Lists[i] );
2746 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
2748 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
2750 AFSExFreePool( pExtent);
2752 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
2754 lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount);
2759 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
2766 pExtent = pNextExtent;
2769 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
2772 // If we are done then get out
2778 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2779 AFS_TRACE_LEVEL_VERBOSE,
2780 "AFSFlushExtents No more dirty extents found\n");
2786 // Fire off the request synchronously
2789 sz = sizeof( AFSReleaseExtentsCB ) + (count * sizeof ( AFSFileExtentCB ));
2791 pRelease->ExtentCount = count;
2793 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2794 AFS_TRACE_LEVEL_VERBOSE,
2795 "AFSFlushExtents Releasing(1) Fcb extents lock %08lX SHARED %08lX\n",
2796 &pNPFcb->Specific.File.ExtentsResource,
2797 PsGetCurrentThread());
2799 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource);
2800 bExtentsLocked = FALSE;
2802 KeSetEvent( &pNPFcb->Specific.File.FlushEvent,
2806 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
2807 AFS_REQUEST_FLAG_SYNCHRONOUS,
2810 &Fcb->ObjectInformation->FileId,
2816 if( !NT_SUCCESS(ntStatus))
2820 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
2821 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
2824 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2825 AFS_TRACE_LEVEL_ERROR,
2826 "AFSFlushExtents AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2827 Fcb->ObjectInformation->FileId.Cell,
2828 Fcb->ObjectInformation->FileId.Volume,
2829 Fcb->ObjectInformation->FileId.Vnode,
2830 Fcb->ObjectInformation->FileId.Unique,
2834 AFSLockForExtentsTrim( Fcb);
2836 bExtentsLocked = TRUE;
2841 lCount = InterlockedDecrement( &Fcb->Specific.File.QueuedFlushCount);
2846 KeSetEvent( &pNPFcb->Specific.File.QueuedFlushEvent,
2851 KeSetEvent( &pNPFcb->Specific.File.FlushEvent,
2858 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2859 AFS_TRACE_LEVEL_VERBOSE,
2860 "AFSFlushExtents Releasing(2) Fcb extents lock %08lX SHARED %08lX\n",
2861 &pNPFcb->Specific.File.ExtentsResource,
2862 PsGetCurrentThread());
2864 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
2869 AFSExFreePool( pRelease);
2877 AFSReleaseExtentsWithFlush( IN AFSFcb *Fcb,
2880 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
2883 AFSReleaseExtentsCB *pRelease = NULL;
2885 ULONG initialDirtyCount = 0;
2886 BOOLEAN bExtentsLocked = FALSE;
2889 NTSTATUS ntStatus = STATUS_SUCCESS;
2890 LARGE_INTEGER liLastFlush;
2891 ULONG ulRemainingExtentLength = 0;
2892 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2893 GUID *pAuthGroup = AuthGroup;
2897 ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
2900 // Save, then reset the flush time
2903 liLastFlush = Fcb->Specific.File.LastServerFlush;
2905 KeQueryTickCount( &Fcb->Specific.File.LastServerFlush);
2910 if( pAuthGroup == NULL ||
2911 RtlCompareMemory( pAuthGroup,
2912 &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2913 sizeof( GUID)) == sizeof( GUID))
2916 RtlZeroMemory( &stAuthGroup,
2919 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
2924 if( !NT_SUCCESS( ntStatus))
2926 try_return( ntStatus);
2929 pAuthGroup = &stAuthGroup;
2933 // Look for a start in the list to flush entries
2938 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
2940 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
2942 AFS_EXTENT_RELEASE_TAG);
2943 if( NULL == pRelease)
2946 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2949 if( Fcb->OpenHandleCount > 0)
2953 // Don't release everything ...
2957 // For now release everything
2960 //ulRemainingExtentLength = 1500;
2963 while( Fcb->Specific.File.ExtentLength > (LONG)ulRemainingExtentLength)
2966 AFSLockForExtentsTrim( Fcb);
2968 bExtentsLocked = TRUE;
2970 pRelease->Flags = AFS_EXTENT_FLAG_RELEASE;
2973 // Update the metadata for this call
2976 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
2977 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
2978 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
2979 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
2980 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
2984 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
2986 while( count < AFS_MAXIMUM_EXTENT_RELEASE_COUNT &&
2987 le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
2990 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
2994 if( pExtent->ActiveCount > 0)
3000 pRelease->FileExtents[count].Flags = AFS_EXTENT_FLAG_RELEASE;
3002 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3003 AFS_TRACE_LEVEL_VERBOSE,
3004 "AFSReleaseExtentsWithFlush Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3006 Fcb->ObjectInformation->FileId.Cell,
3007 Fcb->ObjectInformation->FileId.Volume,
3008 Fcb->ObjectInformation->FileId.Vnode,
3009 Fcb->ObjectInformation->FileId.Unique,
3010 pExtent->FileOffset.QuadPart,
3013 pRelease->FileExtents[count].Length = pExtent->Size;
3014 pRelease->FileExtents[count].DirtyLength = pExtent->Size;
3015 pRelease->FileExtents[count].DirtyOffset = 0;
3016 pRelease->FileExtents[count].CacheOffset = pExtent->CacheOffset;
3017 pRelease->FileExtents[count].FileOffset = pExtent->FileOffset;
3020 RtlCopyMemory( pRelease->FileExtents[count].MD5,
3022 sizeof(pExtent->MD5));
3024 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_MD5_SET;
3027 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3030 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3033 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3036 AFSRemoveEntryDirtyList( Fcb,
3039 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_DIRTY;
3041 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
3044 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3048 // Need to pull this extent from the main list as well
3051 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
3053 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
3055 RemoveEntryList( &pExtent->Lists[i] );
3059 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
3061 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
3063 AFSExFreePool( pExtent);
3065 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
3067 lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount);
3072 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
3081 // If we are done then get out
3087 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3088 AFS_TRACE_LEVEL_VERBOSE,
3089 "AFSReleaseExtentsWithFlush No more dirty extents found\n");
3095 // Fire off the request synchronously
3098 sz = sizeof( AFSReleaseExtentsCB ) + (count * sizeof ( AFSFileExtentCB ));
3100 pRelease->ExtentCount = count;
3103 // Drop the extents lock for the duration of the call to
3104 // the network. We have pinned the extents so, even
3105 // though we might get extents added during this period,
3106 // but none will be removed. Hence we can carry on from
3110 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3111 AFS_TRACE_LEVEL_VERBOSE,
3112 "AFSReleaseExtentsWithFlush Releasing Fcb extents lock %08lX thread %08lX\n",
3113 &pNPFcb->Specific.File.ExtentsResource,
3114 PsGetCurrentThread());
3116 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource);
3117 bExtentsLocked = FALSE;
3119 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
3120 AFS_REQUEST_FLAG_SYNCHRONOUS,
3123 &Fcb->ObjectInformation->FileId,
3129 if( !NT_SUCCESS(ntStatus))
3133 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
3134 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
3137 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3138 AFS_TRACE_LEVEL_ERROR,
3139 "AFSReleaseExtentsWithFlush AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3140 Fcb->ObjectInformation->FileId.Cell,
3141 Fcb->ObjectInformation->FileId.Volume,
3142 Fcb->ObjectInformation->FileId.Vnode,
3143 Fcb->ObjectInformation->FileId.Unique,
3153 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3154 AFS_TRACE_LEVEL_VERBOSE,
3155 "AFSReleaseExtentsWithFlush Releasing Fcb extents lock %08lX thread %08lX\n",
3156 &pNPFcb->Specific.File.ExtentsResource,
3157 PsGetCurrentThread());
3159 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
3164 AFSExFreePool( pRelease);
3172 AFSReleaseCleanExtents( IN AFSFcb *Fcb,
3175 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3178 AFSReleaseExtentsCB *pRelease = NULL;
3180 ULONG initialDirtyCount = 0;
3181 BOOLEAN bExtentsLocked = FALSE;
3184 NTSTATUS ntStatus = STATUS_SUCCESS;
3185 LARGE_INTEGER liLastFlush;
3186 ULONG ulRemainingExtentLength = 0;
3187 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3188 GUID *pAuthGroup = AuthGroup;
3191 ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
3194 // Save, then reset the flush time
3197 liLastFlush = Fcb->Specific.File.LastServerFlush;
3199 KeQueryTickCount( &Fcb->Specific.File.LastServerFlush);
3204 if( pAuthGroup == NULL ||
3205 RtlCompareMemory( pAuthGroup,
3206 &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
3207 sizeof( GUID)) == sizeof( GUID))
3210 RtlZeroMemory( &stAuthGroup,
3213 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
3218 if( !NT_SUCCESS( ntStatus))
3220 try_return( ntStatus);
3223 pAuthGroup = &stAuthGroup;
3227 // Look for a start in the list to flush entries
3232 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
3234 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
3236 AFS_EXTENT_RELEASE_TAG);
3237 if( NULL == pRelease)
3240 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
3243 while( Fcb->Specific.File.ExtentLength > (LONG)ulRemainingExtentLength)
3246 AFSLockForExtentsTrim( Fcb);
3248 bExtentsLocked = TRUE;
3250 pRelease->Flags = AFS_EXTENT_FLAG_RELEASE;
3253 // Update the metadata for this call
3256 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
3257 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
3258 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
3259 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
3260 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
3264 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3266 while( count < AFS_MAXIMUM_EXTENT_RELEASE_COUNT &&
3267 le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
3270 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3274 if( pExtent->ActiveCount > 0 ||
3275 BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3280 pRelease->FileExtents[count].Flags = AFS_EXTENT_FLAG_RELEASE;
3282 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3283 AFS_TRACE_LEVEL_VERBOSE,
3284 "AFSReleaseCleanExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3286 Fcb->ObjectInformation->FileId.Cell,
3287 Fcb->ObjectInformation->FileId.Volume,
3288 Fcb->ObjectInformation->FileId.Vnode,
3289 Fcb->ObjectInformation->FileId.Unique,
3290 pExtent->FileOffset.QuadPart,
3293 pRelease->FileExtents[count].Length = pExtent->Size;
3294 pRelease->FileExtents[count].DirtyLength = pExtent->Size;
3295 pRelease->FileExtents[count].DirtyOffset = 0;
3296 pRelease->FileExtents[count].CacheOffset = pExtent->CacheOffset;
3297 pRelease->FileExtents[count].FileOffset = pExtent->FileOffset;
3300 RtlCopyMemory( pRelease->FileExtents[count].MD5,
3302 sizeof(pExtent->MD5));
3304 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_MD5_SET;
3308 // Need to pull this extent from the main list as well
3311 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
3313 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
3315 RemoveEntryList( &pExtent->Lists[i] );
3319 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
3321 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
3323 AFSExFreePool( pExtent);
3325 InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
3327 if( InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount) == 0)
3330 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
3339 // If we are done then get out
3345 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3346 AFS_TRACE_LEVEL_VERBOSE,
3347 "AFSReleaseCleanExtents No more dirty extents found\n");
3353 // Fire off the request synchronously
3356 sz = sizeof( AFSReleaseExtentsCB ) + (count * sizeof ( AFSFileExtentCB ));
3358 pRelease->ExtentCount = count;
3361 // Drop the extents lock for the duration of the call to
3362 // the network. We have pinned the extents so, even
3363 // though we might get extents added during this period,
3364 // but none will be removed. Hence we can carry on from
3368 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3369 AFS_TRACE_LEVEL_VERBOSE,
3370 "AFSReleaseCleanExtents Releasing Fcb extents lock %08lX thread %08lX\n",
3371 &pNPFcb->Specific.File.ExtentsResource,
3372 PsGetCurrentThread());
3374 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource);
3375 bExtentsLocked = FALSE;
3377 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
3378 AFS_REQUEST_FLAG_SYNCHRONOUS,
3381 &Fcb->ObjectInformation->FileId,
3387 if( !NT_SUCCESS(ntStatus))
3391 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
3392 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
3395 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3396 AFS_TRACE_LEVEL_ERROR,
3397 "AFSReleaseCleanExtents AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3398 Fcb->ObjectInformation->FileId.Cell,
3399 Fcb->ObjectInformation->FileId.Volume,
3400 Fcb->ObjectInformation->FileId.Vnode,
3401 Fcb->ObjectInformation->FileId.Unique,
3411 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3412 AFS_TRACE_LEVEL_VERBOSE,
3413 "AFSReleaseCleanExtents Releasing Fcb extents lock %08lX thread %08lX\n",
3414 &pNPFcb->Specific.File.ExtentsResource,
3415 PsGetCurrentThread());
3417 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
3422 AFSExFreePool( pRelease);
3430 AFSMarkDirty( IN AFSFcb *Fcb,
3431 IN AFSExtent *StartExtent,
3432 IN ULONG ExtentsCount,
3433 IN LARGE_INTEGER *StartingByte)
3436 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3437 AFSExtent *pExtent = StartExtent;
3438 AFSExtent *pNextExtent, *pCurrentExtent = NULL;
3440 BOOLEAN bInsertTail = FALSE, bInsertHead = FALSE;
3443 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3444 AFS_TRACE_LEVEL_VERBOSE,
3445 "AFSMarkDirty Acquiring Fcb extents lock %08lX SHARED %08lX\n",
3446 &Fcb->NPFcb->Specific.File.ExtentsResource,
3447 PsGetCurrentThread());
3449 AFSAcquireShared( &Fcb->NPFcb->Specific.File.ExtentsResource, TRUE);
3451 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3455 // Find the insertion point
3458 if( pNPFcb->Specific.File.DirtyListHead == NULL)
3463 else if( StartingByte->QuadPart == 0)
3471 pCurrentExtent = pNPFcb->Specific.File.DirtyListHead;
3473 while( pCurrentExtent != NULL)
3476 if( pCurrentExtent->FileOffset.QuadPart + pCurrentExtent->Size >= StartingByte->QuadPart ||
3477 pCurrentExtent->DirtyList.fLink == NULL)
3483 pCurrentExtent = (AFSExtent *)pCurrentExtent->DirtyList.fLink;
3487 while( ulCount < ExtentsCount)
3490 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
3492 if( !BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3495 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3496 AFS_TRACE_LEVEL_VERBOSE,
3497 "AFSMarkDirty Marking extent offset %I64X Length %08lX DIRTY\n",
3498 pExtent->FileOffset.QuadPart,
3501 pExtent->DirtyList.fLink = NULL;
3502 pExtent->DirtyList.bLink = NULL;
3507 pExtent->DirtyList.fLink = (void *)pNPFcb->Specific.File.DirtyListHead;
3509 pExtent->DirtyList.bLink = NULL;
3511 pNPFcb->Specific.File.DirtyListHead->DirtyList.bLink = (void *)pExtent;
3513 pNPFcb->Specific.File.DirtyListHead = pExtent;
3515 pCurrentExtent = pExtent;
3517 bInsertHead = FALSE;
3519 else if( bInsertTail)
3522 if( pNPFcb->Specific.File.DirtyListHead == NULL)
3525 pNPFcb->Specific.File.DirtyListHead = pExtent;
3530 pNPFcb->Specific.File.DirtyListTail->DirtyList.fLink = (void *)pExtent;
3532 pExtent->DirtyList.bLink = (void *)pNPFcb->Specific.File.DirtyListTail;
3535 pNPFcb->Specific.File.DirtyListTail = pExtent;
3540 pExtent->DirtyList.fLink = pCurrentExtent->DirtyList.fLink;
3541 pExtent->DirtyList.bLink = (void *)pCurrentExtent;
3543 if( pExtent->DirtyList.fLink == NULL)
3546 pNPFcb->Specific.File.DirtyListTail = pExtent;
3551 ((AFSExtent *)pExtent->DirtyList.fLink)->DirtyList.bLink = (void *)pExtent;
3554 pCurrentExtent->DirtyList.fLink = (void *)pExtent;
3556 pCurrentExtent = pExtent;
3559 pExtent->Flags |= AFS_EXTENT_DIRTY;
3562 // Up the dirty count
3565 lCount = InterlockedIncrement( &Fcb->Specific.File.ExtentsDirtyCount);
3570 pCurrentExtent = pExtent;
3573 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_ACTIVE_COUNTING,
3574 AFS_TRACE_LEVEL_VERBOSE,
3575 "AFSMarkDirty Decrement count on extent %08lX Cnt %d\n",
3577 pExtent->ActiveCount);
3579 ASSERT( pExtent->ActiveCount > 0);
3581 lCount = InterlockedDecrement( &pExtent->ActiveCount);
3583 pExtent = pNextExtent;
3588 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3590 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3591 AFS_TRACE_LEVEL_VERBOSE,
3592 "AFSMarkDirty Releasing Fcb extents lock %08lX SHARED %08lX\n",
3593 &Fcb->NPFcb->Specific.File.ExtentsResource,
3594 PsGetCurrentThread());
3596 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
3606 ExtentFor(PLIST_ENTRY le, ULONG SkipList)
3608 return CONTAINING_RECORD( le, AFSExtent, Lists[SkipList] );
3611 static AFSExtent *NextExtent(AFSExtent *Extent, ULONG SkipList)
3613 return ExtentFor(Extent->Lists[SkipList].Flink, SkipList);
3616 static AFSExtent *DirtyExtentFor(PLIST_ENTRY le)
3618 return CONTAINING_RECORD( le, AFSExtent, DirtyList );
3621 static VOID VerifyExtentsLists(AFSFcb *Fcb)
3625 // Check the ordering of the extents lists
3627 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
3629 ASSERT(Fcb->Specific.File.ExtentsLists[0].Flink != &Fcb->Specific.File.ExtentsLists[1]);
3631 for (ULONG listNo = 0; listNo < AFS_NUM_EXTENT_LISTS; listNo ++)
3633 LARGE_INTEGER lastOffset;
3635 lastOffset.QuadPart = 0;
3637 for (PLIST_ENTRY pLe = Fcb->Specific.File.ExtentsLists[listNo].Flink;
3638 pLe != &Fcb->Specific.File.ExtentsLists[listNo];
3643 pExtent = ExtentFor(pLe, listNo);
3646 ASSERT(pLe != &Fcb->Specific.File.ExtentsLists[1] &&
3647 pLe->Flink !=&Fcb->Specific.File.ExtentsLists[1] &&
3648 pLe->Blink !=&Fcb->Specific.File.ExtentsLists[1]);
3651 ASSERT(pLe->Flink->Blink == pLe);
3652 ASSERT(pLe->Blink->Flink == pLe);
3655 // Should follow on from previous
3657 ASSERT(pExtent->FileOffset.QuadPart >= lastOffset.QuadPart);
3658 lastOffset.QuadPart = pExtent->FileOffset.QuadPart + pExtent->Size;
3661 // Should match alignment criteria
3663 ASSERT( 0 == (pExtent->FileOffset.LowPart & ExtentsMasks[listNo]) );
3666 // "lower" lists should be populated
3668 for (LONG subListNo = listNo-1; subListNo > 0; subListNo --)
3670 ASSERT( !IsListEmpty(&pExtent->Lists[subListNo]));
3678 AFSTrimExtents( IN AFSFcb *Fcb,
3679 IN PLARGE_INTEGER FileSize)
3682 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3685 BOOLEAN locked = FALSE;
3686 NTSTATUS ntStatus = STATUS_SUCCESS;
3687 LARGE_INTEGER liAlignedOffset = {0,0};
3688 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
3689 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3696 // Get an aligned offset
3699 if( FileSize != NULL)
3702 liAlignedOffset = *FileSize;
3705 if( liAlignedOffset.QuadPart > 0 &&
3706 liAlignedOffset.QuadPart % pDevExt->Specific.RDR.CacheBlockSize != 0)
3710 // Align UP to the next cache block size
3713 liAlignedOffset.QuadPart = (ULONGLONG)( (ULONGLONG)((liAlignedOffset.QuadPart / pDevExt->Specific.RDR.CacheBlockSize) + 1) * (ULONGLONG)pDevExt->Specific.RDR.CacheBlockSize);
3717 // Ensure that no one is working with the extents and grab the
3721 AFSLockForExtentsTrim( Fcb);
3725 if( 0 == Fcb->Specific.File.ExtentCount)
3729 // Update the request extent status
3732 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
3734 try_return( ntStatus = STATUS_SUCCESS);
3738 // We are truncating from a specific length in the file. If the offset
3739 // is non-zero then go find the first extent to remove
3742 if( 0 == FileSize->QuadPart)
3745 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3750 pExtent = AFSExtentForOffset( Fcb,
3754 if( NULL == pExtent)
3757 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3761 le = &pExtent->Lists[AFS_EXTENTS_LIST];
3765 while( le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
3768 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3771 // Only trim down extents beyond the aligned offset
3776 if( pExtent->FileOffset.QuadPart >= liAlignedOffset.QuadPart)
3779 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3782 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3785 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3789 AFSRemoveEntryDirtyList( Fcb,
3792 dirtyCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
3794 ASSERT(dirtyCount >= 0);
3797 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3800 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
3802 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
3804 RemoveEntryList( &pExtent->Lists[i] );
3808 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3809 AFS_TRACE_LEVEL_VERBOSE,
3810 "AFSTrimExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3812 Fcb->ObjectInformation->FileId.Cell,
3813 Fcb->ObjectInformation->FileId.Volume,
3814 Fcb->ObjectInformation->FileId.Vnode,
3815 Fcb->ObjectInformation->FileId.Unique,
3816 pExtent->FileOffset.QuadPart,
3819 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
3821 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
3823 ASSERT( pExtent->ActiveCount == 0);
3828 AFSExFreePool( pExtent);
3830 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
3832 lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount);
3837 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
3845 // Update the request extent status
3848 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
3855 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3856 AFS_TRACE_LEVEL_VERBOSE,
3857 "AFSTrimExtents Releasing Fcb extents lock %08lX thread %08lX\n",
3858 &Fcb->NPFcb->Specific.File.ExtentsResource,
3859 PsGetCurrentThread());
3861 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
3869 AFSTrimSpecifiedExtents( IN AFSFcb *Fcb,
3871 IN AFSFileExtentCB *Result)
3874 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3877 AFSFileExtentCB *pFileExtents = Result;
3878 NTSTATUS ntStatus = STATUS_SUCCESS;
3879 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
3880 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3886 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3888 while( le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST] &&
3892 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3895 // Only trim down extents beyond the aligned offset
3900 if( pExtent->FileOffset.QuadPart == pFileExtents->FileOffset.QuadPart)
3903 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3906 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3909 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3914 AFSRemoveEntryDirtyList( Fcb,
3917 dirtyCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
3919 ASSERT( dirtyCount >= 0);
3923 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3927 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
3929 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
3931 RemoveEntryList( &pExtent->Lists[i] );
3935 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3936 AFS_TRACE_LEVEL_VERBOSE,
3937 "AFSTrimSpecifiedExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3939 Fcb->ObjectInformation->FileId.Cell,
3940 Fcb->ObjectInformation->FileId.Volume,
3941 Fcb->ObjectInformation->FileId.Vnode,
3942 Fcb->ObjectInformation->FileId.Unique,
3943 pExtent->FileOffset.QuadPart,
3946 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
3948 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
3950 ASSERT( pExtent->ActiveCount == 0);
3955 AFSExFreePool( pExtent);
3957 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
3959 lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount);
3964 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
3970 // Next extent we are looking for
3980 // Update the request extent status
3983 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
3990 AFSReferenceActiveExtents( IN AFSExtent *StartExtent,
3991 IN ULONG ExtentsCount)
3994 AFSExtent *pExtent = StartExtent;
3995 AFSExtent *pNextExtent;
3999 while( ulCount < ExtentsCount)
4002 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
4004 lCount = InterlockedIncrement( &pExtent->ActiveCount);
4006 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_ACTIVE_COUNTING,
4007 AFS_TRACE_LEVEL_VERBOSE,
4008 "AFSReferenceActiveExtents Increment count on extent %08lX Cnt %d\n",
4012 pExtent = pNextExtent;
4021 AFSDereferenceActiveExtents( IN AFSExtent *StartExtent,
4022 IN ULONG ExtentsCount)
4025 AFSExtent *pExtent = StartExtent;
4026 AFSExtent *pNextExtent;
4030 while( ulCount < ExtentsCount)
4033 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
4035 ASSERT( pExtent->ActiveCount > 0);
4037 lCount = InterlockedDecrement( &pExtent->ActiveCount);
4039 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_ACTIVE_COUNTING,
4040 AFS_TRACE_LEVEL_VERBOSE,
4041 "AFSDereferenceActiveExtents Decrement count on extent %08lX Cnt %d\n",
4045 pExtent = pNextExtent;
4054 AFSRemoveEntryDirtyList( IN AFSFcb *Fcb,
4055 IN AFSExtent *Extent)
4058 if( Extent->DirtyList.fLink == NULL)
4061 Fcb->NPFcb->Specific.File.DirtyListTail = (AFSExtent *)Extent->DirtyList.bLink;
4063 if( Fcb->NPFcb->Specific.File.DirtyListTail != NULL)
4066 Fcb->NPFcb->Specific.File.DirtyListTail->DirtyList.fLink = NULL;
4072 ((AFSExtent *)Extent->DirtyList.fLink)->DirtyList.bLink = Extent->DirtyList.bLink;
4075 if( Extent->DirtyList.bLink == NULL)
4078 Fcb->NPFcb->Specific.File.DirtyListHead = (AFSExtent *)Extent->DirtyList.fLink;
4080 if( Fcb->NPFcb->Specific.File.DirtyListHead != NULL)
4083 Fcb->NPFcb->Specific.File.DirtyListHead->DirtyList.bLink = NULL;
4089 ((AFSExtent *)Extent->DirtyList.bLink)->DirtyList.fLink = Extent->DirtyList.fLink;
4098 AFSSetupMD5Hash( IN AFSFcb *Fcb,
4099 IN AFSExtent *StartExtent,
4100 IN ULONG ExtentsCount,
4101 IN void *SystemBuffer,
4102 IN LARGE_INTEGER *ByteOffset,
4106 NTSTATUS ntStatus = STATUS_SUCCESS;
4107 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
4108 AFSExtent *pExtent = StartExtent;
4109 AFSExtent *pNextExtent, *pCurrentExtent = NULL;
4111 char *pCurrentBuffer = (char *)SystemBuffer;
4112 char *pMD5Buffer = NULL;
4113 ULONG ulCurrentLen = 0;
4114 void *pExtentBuffer = NULL;
4115 LARGE_INTEGER liByteOffset;
4116 ULONG ulBytesRead = 0;
4121 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4122 AFS_TRACE_LEVEL_VERBOSE,
4123 "AFSSetupMD5Hash Acquiring Fcb extents lock %08lX SHARED %08lX\n",
4124 &Fcb->NPFcb->Specific.File.ExtentsResource,
4125 PsGetCurrentThread());
4127 AFSAcquireShared( &Fcb->NPFcb->Specific.File.ExtentsResource, TRUE);
4129 liByteOffset.QuadPart = ByteOffset->QuadPart;
4131 while( ulCount < ExtentsCount)
4134 RtlZeroMemory( pExtent->MD5,
4135 sizeof( pExtent->MD5));
4137 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
4139 if( liByteOffset.QuadPart == pExtent->FileOffset.QuadPart &&
4140 ByteCount < pExtent->Size)
4143 if( pExtentBuffer == NULL)
4146 pExtentBuffer = AFSExAllocatePoolWithTag( PagedPool,
4148 AFS_GENERIC_MEMORY_9_TAG);
4150 if( pExtentBuffer == NULL)
4157 RtlZeroMemory( pExtentBuffer,
4160 RtlCopyMemory( pExtentBuffer,
4164 pMD5Buffer = (char *)pExtentBuffer;
4166 ulCurrentLen = ByteCount;
4168 else if( liByteOffset.QuadPart != pExtent->FileOffset.QuadPart)
4171 pExtentBuffer = AFSExAllocatePoolWithTag( PagedPool,
4173 AFS_GENERIC_MEMORY_10_TAG);
4175 if( pExtentBuffer == NULL)
4181 RtlZeroMemory( pExtentBuffer,
4184 if( BooleanFlagOn( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE))
4188 RtlCopyMemory( pExtentBuffer,
4189 ((char *)AFSLibCacheBaseAddress + pExtent->CacheOffset.QuadPart),
4192 ASSERT( pExtent->CacheOffset.HighPart == 0);
4193 RtlCopyMemory( pExtentBuffer,
4194 ((char *)AFSLibCacheBaseAddress + pExtent->CacheOffset.LowPart),
4198 ulBytesRead = pExtent->Size;
4203 ntStatus = AFSReadCacheFile( pExtentBuffer,
4204 &pExtent->CacheOffset,
4208 if( !NT_SUCCESS( ntStatus))
4214 pMD5Buffer = (char *)pExtentBuffer;
4216 ulCurrentLen = min( ByteCount, pExtent->Size - (ULONG)(liByteOffset.QuadPart - pExtent->FileOffset.QuadPart));
4218 RtlCopyMemory( (void *)((char *)pExtentBuffer + (ULONG)(liByteOffset.QuadPart - pExtent->FileOffset.QuadPart)),
4225 ulCurrentLen = pExtent->Size;
4227 pMD5Buffer = pCurrentBuffer;
4230 AFSGenerateMD5( pMD5Buffer,
4234 pExtent = pNextExtent;
4238 ByteCount -= ulCurrentLen;
4240 pCurrentBuffer += ulCurrentLen;
4242 liByteOffset.QuadPart += ulCurrentLen;
4245 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4246 AFS_TRACE_LEVEL_VERBOSE,
4247 "AFSSetupMD5Hash Releasing Fcb extents lock %08lX SHARED %08lX\n",
4248 &Fcb->NPFcb->Specific.File.ExtentsResource,
4249 PsGetCurrentThread());
4251 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
4253 if( pExtentBuffer != NULL)
4256 AFSExFreePool( pExtentBuffer);