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 ULONG ExtentsMasks[AFS_NUM_EXTENT_LISTS] = AFS_EXTENTS_MASKS;
43 static VOID VerifyExtentsLists(AFSFcb *Fcb);
44 static AFSExtent *DirtyExtentFor(PLIST_ENTRY le);
47 AFSEntryForOffset( IN AFSFcb *Fcb,
48 IN PLARGE_INTEGER Offset);
52 // Returns with Extents lock EX and no one using them.
56 AFSLockForExtentsTrim( IN AFSFcb *Fcb)
59 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
60 AFS_TRACE_LEVEL_VERBOSE,
61 "AFSLockForExtentsTrim Acquiring Fcb extents lock %08lX EXCL %08lX\n",
62 &Fcb->NPFcb->Specific.File.ExtentsResource,
63 PsGetCurrentThread());
65 AFSAcquireExcl( &Fcb->NPFcb->Specific.File.ExtentsResource, TRUE );
71 // return FALSE *or* with Extents lock EX and noone using them
74 AFSLockForExtentsTrimNoWait( IN AFSFcb *Fcb)
77 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
78 AFS_TRACE_LEVEL_VERBOSE,
79 "AFSLockForExtentsTrimNoWait Attempting to acquire Fcb extent lock %08lX EXCL %08lX\n",
80 &Fcb->NPFcb->Specific.File.ExtentsResource,
81 PsGetCurrentThread());
83 if (!AFSAcquireExcl( &Fcb->NPFcb->Specific.File.ExtentsResource, FALSE ))
86 // Couldn't lock immediately
89 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
90 AFS_TRACE_LEVEL_VERBOSE,
91 "AFSLockForExtentsTrimNoWait Refused to wait for Fcb extent lock %08lX EXCL %08lX\n",
92 &Fcb->NPFcb->Specific.File.ExtentsResource,
93 PsGetCurrentThread());
102 AFSFreeExtent( IN AFSFcb *Fcb,
103 IN AFSExtent *pExtent)
105 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
108 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
110 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
112 RemoveEntryList( &pExtent->Lists[i] );
116 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
118 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
120 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
122 lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount);
127 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
132 AFSExFreePool( pExtent);
136 // AFSTearDownFcbExtents was originally written to
137 // remove all of the extents from an FCB. For that to happen
138 // it must be an invariant that the extent list cannot change
139 // from the moment the caller decides to execute AFSTearDownFcbExtents
140 // until it returns. This invariant does not hold because the
141 // the decision to call AFSTearDownFcbExtents is made without
142 // holding the ExtentsResource and it is possible that extents
143 // are in active use. Therefore, AFSTearDownFcbExtents now releases
144 // as many non-active extents as it can.
147 AFSTearDownFcbExtents( IN AFSFcb *Fcb,
150 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
151 LIST_ENTRY *le, *leNext;
153 LONG lExtentCount = 0;
154 ULONG ulReleaseCount = 0, ulProcessCount = 0;
156 AFSReleaseExtentsCB *pRelease = NULL;
157 BOOLEAN locked = FALSE;
159 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
160 GUID *pAuthGroup = AuthGroup;
167 if( pAuthGroup == NULL ||
168 RtlCompareMemory( pAuthGroup,
169 &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
170 sizeof( GUID)) == sizeof( GUID))
173 RtlZeroMemory( &stAuthGroup,
176 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
181 if( !NT_SUCCESS( ntStatus))
183 try_return( ntStatus);
186 pAuthGroup = &stAuthGroup;
190 // Ensure that no one is working with the extents and grab the
194 AFSLockForExtentsTrim( Fcb );
198 if (0 == Fcb->Specific.File.ExtentCount)
200 try_return ( ntStatus = STATUS_SUCCESS);
203 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
205 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
207 AFS_EXTENT_RELEASE_TAG);
208 if (NULL == pRelease)
211 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
214 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
217 for( le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink,
219 lExtentCount < Fcb->Specific.File.ExtentCount;
220 lExtentCount += ulProcessCount)
223 RtlZeroMemory( pRelease,
224 sizeof( AFSReleaseExtentsCB ) +
225 (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB )));
227 for( ulProcessCount = 0, ulReleaseCount = 0;
228 !IsListEmpty( le) && ulReleaseCount < AFS_MAXIMUM_EXTENT_RELEASE_COUNT;
229 ulProcessCount++, le = leNext)
234 pEntry = ExtentFor( le, AFS_EXTENTS_LIST );
236 if( pEntry->ActiveCount == 0)
239 pRelease->FileExtents[ulReleaseCount].Flags = AFS_EXTENT_FLAG_RELEASE;
242 RtlCopyMemory( pRelease->FileExtents[ulReleaseCount].MD5,
244 sizeof(pEntry->MD5));
246 pRelease->FileExtents[ulReleaseCount].Flags |= AFS_EXTENT_FLAG_MD5_SET;
249 if( BooleanFlagOn( pEntry->Flags, AFS_EXTENT_DIRTY))
254 AFSRemoveEntryDirtyList( Fcb,
257 pRelease->FileExtents[ulReleaseCount].Flags |= AFS_EXTENT_FLAG_DIRTY;
259 dirtyCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
261 ASSERT( dirtyCount >= 0);
264 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
265 AFS_TRACE_LEVEL_VERBOSE,
266 "AFSTearDownFcbExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %08lX-%08lX Len %08lX\n",
268 Fcb->ObjectInformation->FileId.Cell,
269 Fcb->ObjectInformation->FileId.Volume,
270 Fcb->ObjectInformation->FileId.Vnode,
271 Fcb->ObjectInformation->FileId.Unique,
272 pEntry->FileOffset.HighPart,
273 pEntry->FileOffset.LowPart,
276 pRelease->FileExtents[ulReleaseCount].Length = pEntry->Size;
277 pRelease->FileExtents[ulReleaseCount].DirtyLength = pEntry->Size;
278 pRelease->FileExtents[ulReleaseCount].DirtyOffset = 0;
279 pRelease->FileExtents[ulReleaseCount].CacheOffset = pEntry->CacheOffset;
280 pRelease->FileExtents[ulReleaseCount].FileOffset = pEntry->FileOffset;
289 if ( ulReleaseCount > 0)
292 pRelease->ExtentCount = ulReleaseCount;
294 pRelease->Flags = AFS_EXTENT_FLAG_RELEASE;
297 // Update the metadata for this call
300 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
301 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
302 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
303 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
304 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
307 // Send the request down. We cannot send this down
308 // asynchronously - if we did that we could request them
309 // back before the service got this request and then this
310 // request would be a corruption.
313 sz = sizeof( AFSReleaseExtentsCB ) + (ulProcessCount * sizeof ( AFSFileExtentCB ));
315 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
316 AFS_REQUEST_FLAG_SYNCHRONOUS,
319 &Fcb->ObjectInformation->FileId,
325 if( !NT_SUCCESS(ntStatus))
329 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
330 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
333 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
334 AFS_TRACE_LEVEL_ERROR,
335 "AFSTearDownFcbExtents AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
336 Fcb->ObjectInformation->FileId.Cell,
337 Fcb->ObjectInformation->FileId.Volume,
338 Fcb->ObjectInformation->FileId.Vnode,
339 Fcb->ObjectInformation->FileId.Unique,
346 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
349 // if all extents have been released, reinitialize the skip lists
352 if( Fcb->Specific.File.ExtentCount == 0)
355 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i++)
357 InitializeListHead(&Fcb->Specific.File.ExtentsLists[i]);
361 // Reinitialize the dirty list as well
364 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
367 ASSERT( Fcb->Specific.File.ExtentsDirtyCount == 0);
369 Fcb->NPFcb->Specific.File.DirtyListHead = NULL;
370 Fcb->NPFcb->Specific.File.DirtyListTail = NULL;
372 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
375 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
382 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
383 AFS_TRACE_LEVEL_VERBOSE,
384 "AFSTearDownFcbExtents Releasing Fcb extent lock %08lX thread %08lX\n",
385 &Fcb->NPFcb->Specific.File.ExtentsResource,
386 PsGetCurrentThread());
388 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
394 AFSExFreePool( pRelease);
400 ExtentForOffsetInList( IN AFSFcb *Fcb,
403 IN PLARGE_INTEGER Offset)
406 // Return the extent that maps the offset, that
407 // - Contains the offset
408 // - or is immediately ahead of the offset (in this list)
409 // - otherwise return NULL.
412 PLIST_ENTRY pLe = List;
413 AFSExtent *pPrevious = NULL;
415 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
417 while (pLe != &Fcb->Specific.File.ExtentsLists[ListNumber])
421 entry = ExtentFor( pLe, ListNumber );
428 if (Offset->QuadPart < entry->FileOffset.QuadPart)
431 // Offset is ahead of entry. Return previous
436 if (Offset->QuadPart >= (entry->FileOffset.QuadPart + entry->Size))
439 // We start after this extent - carry on round
447 // Otherwise its a match
454 // Got to the end. Return Previous
460 AFSExtentContains( IN AFSExtent *Extent, IN PLARGE_INTEGER Offset)
466 return (Extent->FileOffset.QuadPart <= Offset->QuadPart &&
467 (Extent->FileOffset.QuadPart + Extent->Size) > Offset->QuadPart);
472 // Return the extent that contains the offset
475 AFSExtentForOffsetHint( IN AFSFcb *Fcb,
476 IN PLARGE_INTEGER Offset,
477 IN BOOLEAN ReturnPrevious,
480 AFSExtent *pPrevious = Hint;
484 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
486 #if AFS_VALIDATE_EXTENTS
487 VerifyExtentsLists(Fcb);
491 // So we will go across the skip lists until we find an
492 // appropriate entry (previous or direct match). If it's a match
493 // we are done, other wise we start on the next layer down
495 for (i = AFS_NUM_EXTENT_LISTS-1; i >= AFS_EXTENTS_LIST; i--)
497 if (NULL == pPrevious)
500 // We haven't found anything in the previous layers
502 pLe = Fcb->Specific.File.ExtentsLists[i].Flink;
504 else if (NULL == pPrevious->Lists[i].Flink)
506 ASSERT(AFS_EXTENTS_LIST != i);
508 // The hint doesn't exist at this level, next one down
515 // take the previous into the next
517 pLe = &pPrevious->Lists[i];
520 pPrevious = ExtentForOffsetInList( Fcb, pLe, i, Offset);
522 if (NULL != pPrevious && AFSExtentContains(pPrevious, Offset))
525 // Found it immediately. Stop here
531 if (NULL == pPrevious || ReturnPrevious )
536 ASSERT( !AFSExtentContains(pPrevious, Offset) );
542 AFSEntryForOffset( IN AFSFcb *Fcb,
543 IN PLARGE_INTEGER Offset)
545 AFSExtent *pPrevious = NULL;
549 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
551 #if AFS_VALIDATE_EXTENTS
552 VerifyExtentsLists(Fcb);
556 // So we will go across the skip lists until we find an
557 // appropriate entry (previous or direct match). If it's a match
558 // we are done, other wise we start on the next layer down
560 for (i = AFS_NUM_EXTENT_LISTS-1; i >= AFS_EXTENTS_LIST; i--)
562 if (NULL == pPrevious)
565 // We haven't found anything in the previous layers
567 pLe = Fcb->Specific.File.ExtentsLists[i].Flink;
569 else if (NULL == pPrevious->Lists[i].Flink)
571 ASSERT(AFS_EXTENTS_LIST != i);
573 // The hint doesn't exist at this level, next one down
580 // take the previous into the next
582 pLe = &pPrevious->Lists[i];
585 pPrevious = ExtentForOffsetInList( Fcb, pLe, i, Offset);
587 if (NULL != pPrevious && AFSExtentContains(pPrevious, Offset))
590 // Found it immediately. Stop here
600 AFSExtentForOffset( IN AFSFcb *Fcb,
601 IN PLARGE_INTEGER Offset,
602 IN BOOLEAN ReturnPrevious)
604 return AFSExtentForOffsetHint(Fcb, Offset, ReturnPrevious, NULL);
608 BOOLEAN AFSDoExtentsMapRegion(IN AFSFcb *Fcb,
609 IN PLARGE_INTEGER Offset,
611 IN OUT AFSExtent **FirstExtent,
612 OUT AFSExtent **LastExtent)
615 // Return TRUE region is completely mapped. FALSE
616 // otherwise. If the region isn't mapped then the last
617 // extent to map part of the region is returned.
619 // *LastExtent as input is where to start looking.
620 // *LastExtent as output is either the extent which
621 // contains the Offset, or the last one which doesn't
625 BOOLEAN retVal = FALSE;
630 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
631 AFS_TRACE_LEVEL_VERBOSE,
632 "AFSDoExtentsMapRegion Acquiring Fcb extent lock %08lX SHARED %08lX\n",
633 &Fcb->NPFcb->Specific.File.ExtentsResource,
634 PsGetCurrentThread());
636 AFSAcquireShared( &Fcb->NPFcb->Specific.File.ExtentsResource, TRUE );
640 entry = AFSExtentForOffsetHint(Fcb, Offset, TRUE, *FirstExtent);
641 *FirstExtent = entry;
643 if (NULL == entry || !AFSExtentContains(entry, Offset))
645 try_return (retVal = FALSE);
648 ASSERT(Offset->QuadPart >= entry->FileOffset.QuadPart);
652 if ((entry->FileOffset.QuadPart + entry->Size) >=
653 (Offset->QuadPart + Size))
656 // The end is inside the extent
658 try_return (retVal = TRUE);
661 if (entry->Lists[AFS_EXTENTS_LIST].Flink == &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
664 // Run out of extents
666 try_return (retVal = FALSE);
669 newEntry = NextExtent( entry, AFS_EXTENTS_LIST );
671 if (newEntry->FileOffset.QuadPart !=
672 (entry->FileOffset.QuadPart + entry->Size))
677 try_return (retVal = FALSE);
683 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
688 "EXCEPTION - AFSDoExtentsMapRegion\n");
690 AFSDumpTraceFilesFnc();
695 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
696 AFS_TRACE_LEVEL_VERBOSE,
697 "AFSDoExtentsMapRegion Releasing Fcb extent lock %08lX SHARED %08lX\n",
698 &Fcb->NPFcb->Specific.File.ExtentsResource,
699 PsGetCurrentThread());
701 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
710 AFSRequestExtentsAsync( IN AFSFcb *Fcb,
712 IN PLARGE_INTEGER Offset,
716 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
717 NTSTATUS ntStatus = STATUS_SUCCESS;
718 AFSExtent *pExtent = NULL;
719 AFSRequestExtentsCB request;
720 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
721 AFSExtent *pFirstExtent = NULL;
722 LARGE_INTEGER liAlignedOffset;
723 ULONG ulAlignedLength = 0;
724 BOOLEAN bRegionMapped = FALSE;
725 ULONGLONG ullProcessId = (ULONGLONG)PsGetCurrentProcessId();
730 ASSERT( !ExIsResourceAcquiredLite( &pNPFcb->Specific.File.ExtentsResource ));
733 // If the service set a failure on the file since the last
734 // CreateFile was issued, return it now.
737 if (!NT_SUCCESS( pNPFcb->Specific.File.ExtentsRequestStatus))
741 // If this isn't the same authgroup which caused the failure
742 // then try to request them again
745 if( RtlCompareMemory( &pNPFcb->Specific.File.ExtentsRequestAuthGroup,
747 sizeof( GUID)) == sizeof( GUID))
750 ntStatus = pNPFcb->Specific.File.ExtentsRequestStatus;
752 pNPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
754 RtlZeroMemory( &pNPFcb->Specific.File.ExtentsRequestAuthGroup,
757 try_return( ntStatus);
762 // Check if we are already mapped
765 bRegionMapped = AFSDoExtentsMapRegion( Fcb, Offset, Size, &pFirstExtent, &pExtent);
770 try_return( ntStatus = STATUS_SUCCESS);
774 // Align our request on extent size boundary
777 ulAlignedLength = Size;
779 liAlignedOffset = *Offset;
781 if( liAlignedOffset.QuadPart % pDevExt->Specific.RDR.CacheBlockSize != 0)
784 liAlignedOffset.QuadPart = (ULONGLONG)( (ULONGLONG)(liAlignedOffset.QuadPart / pDevExt->Specific.RDR.CacheBlockSize) * (ULONGLONG)pDevExt->Specific.RDR.CacheBlockSize);
786 ulAlignedLength += (ULONG)(Offset->QuadPart - liAlignedOffset.QuadPart);
789 if( ulAlignedLength % pDevExt->Specific.RDR.CacheBlockSize != 0)
792 ulAlignedLength = (ULONG)(((ulAlignedLength / pDevExt->Specific.RDR.CacheBlockSize) + 1) * pDevExt->Specific.RDR.CacheBlockSize);
795 RtlZeroMemory( &request,
796 sizeof( AFSRequestExtentsCB));
798 request.ByteOffset = liAlignedOffset;
799 request.Length = ulAlignedLength;
801 if( !AFSIsExtentRequestQueued( &Fcb->ObjectInformation->FileId,
806 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
807 AFS_TRACE_LEVEL_VERBOSE,
808 "AFSRequestExtentsAsync Request extents for fid %08lX-%08lX-%08lX-%08lX Offset %08lX Len %08lX Thread %08lX\n",
809 Fcb->ObjectInformation->FileId.Cell,
810 Fcb->ObjectInformation->FileId.Volume,
811 Fcb->ObjectInformation->FileId.Vnode,
812 Fcb->ObjectInformation->FileId.Unique,
813 request.ByteOffset.LowPart,
815 PsGetCurrentThread());
817 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS,
821 &Fcb->ObjectInformation->FileId,
823 sizeof( AFSRequestExtentsCB ),
827 if ( ntStatus == STATUS_ACCESS_DENIED)
832 ntStatus2 = AFSRetrieveValidAuthGroup( Fcb,
837 if ( NT_SUCCESS( ntStatus2) &&
838 RtlCompareMemory( &stAuthGroup,
840 sizeof( GUID)) != sizeof( GUID))
843 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS,
847 &Fcb->ObjectInformation->FileId,
849 sizeof( AFSRequestExtentsCB ),
855 if( NT_SUCCESS( ntStatus))
858 KeClearEvent( &pNPFcb->Specific.File.ExtentsRequestComplete );
864 KeClearEvent( &pNPFcb->Specific.File.ExtentsRequestComplete );
876 AFSProcessExtentsResult( IN AFSFcb *Fcb,
878 IN AFSFileExtentCB *Result)
880 NTSTATUS ntStatus = STATUS_SUCCESS;
881 AFSFileExtentCB *pFileExtents = Result;
884 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
885 ULONG fileExtentsUsed = 0;
886 BOOLEAN bFoundExtent = FALSE;
887 LIST_ENTRY *pSkipEntries[AFS_NUM_EXTENT_LISTS] = { 0 };
888 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
892 // Grab the extents exclusive for the duration
895 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
896 AFS_TRACE_LEVEL_VERBOSE,
897 "AFSProcessExtentsResult Acquiring Fcb extent lock %08lX EXCL %08lX\n",
898 &pNPFcb->Specific.File.ExtentsResource,
899 PsGetCurrentThread());
901 AFSAcquireExcl( &pNPFcb->Specific.File.ExtentsResource, TRUE );
907 // Find where to put the extents
909 for (ULONG i = AFS_EXTENTS_LIST; i < AFS_NUM_EXTENT_LISTS; i++)
912 pSkipEntries[i] = Fcb->Specific.File.ExtentsLists[i].Flink;
915 le = pSkipEntries[AFS_EXTENTS_LIST];
917 if (le == &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
920 // No extents. Insert at head of list (which is where the skip lists point!)
924 else if (0 != pFileExtents->FileOffset.QuadPart)
927 // We want to find the best extents immediately *behind* this offset
929 LARGE_INTEGER offset = pFileExtents->FileOffset;
932 // Ask in the top skip list first, then work down
934 for (LONG i = AFS_NUM_EXTENT_LISTS-1; i >= AFS_EXTENTS_LIST; i--)
936 pExtent = ExtentForOffsetInList( Fcb,
944 // No dice. Header has to become the head of the list
946 pSkipEntries[i] = &Fcb->Specific.File.ExtentsLists[i];
948 // And as a loop invariant we should never have found an extent
950 ASSERT(!bFoundExtent);
955 // pExtent is where to start to insert at this level
957 pSkipEntries[i] = &pExtent->Lists[i];
960 // And also where to start to look at the next level
963 if (i > AFS_EXTENTS_LIST)
965 pSkipEntries[i-1] = &pExtent->Lists[i-1];
973 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
978 le = pExtent->Lists[AFS_EXTENTS_LIST].Blink;
984 // Looking at offset 0, so we must start at the beginning
987 pExtent = ExtentFor(le, AFS_EXTENTS_LIST);
991 // And set up the skip lists
994 for (ULONG i = AFS_EXTENTS_LIST; i < AFS_NUM_EXTENT_LISTS; i++)
996 pSkipEntries[i] = &Fcb->Specific.File.ExtentsLists[i];
1000 while (fileExtentsUsed < Count)
1004 // Loop invariant - le points to where to insert after and
1005 // pExtent points to le->fLink
1008 ASSERT (NULL == pExtent ||
1009 le->Flink == &pExtent->Lists[AFS_EXTENTS_LIST]);
1011 if (NULL == pExtent ||
1012 pExtent->FileOffset.QuadPart > pFileExtents->FileOffset.QuadPart)
1015 // We need to insert a new extent at le. Start with
1016 // some sanity check on spanning
1018 if (NULL != pExtent &&
1019 ((pFileExtents->FileOffset.QuadPart + pFileExtents->Length) >
1020 pExtent->FileOffset.QuadPart))
1023 // File Extents overlaps pExtent
1025 ASSERT( (pFileExtents->FileOffset.QuadPart + pFileExtents->Length) <=
1026 pExtent->FileOffset.QuadPart);
1028 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1032 // File offset is entirely in front of this extent. Create
1033 // a new one (remember le is the previous list entry)
1035 pExtent = (AFSExtent *) AFSExAllocatePoolWithTag( NonPagedPool,
1038 if (NULL == pExtent)
1041 try_return (ntStatus = STATUS_INSUFFICIENT_RESOURCES );
1044 RtlZeroMemory( pExtent, sizeof( AFSExtent ));
1046 pExtent->FileOffset = pFileExtents->FileOffset;
1047 pExtent->CacheOffset = pFileExtents->CacheOffset;
1048 pExtent->Size = pFileExtents->Length;
1050 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1051 AFS_TRACE_LEVEL_VERBOSE,
1052 "AFSProcessExtentsResult Received extent for fid %08lX-%08lX-%08lX-%08lX File Offset %I64X Cache Offset %I64X Len %08lX\n",
1053 Fcb->ObjectInformation->FileId.Cell,
1054 Fcb->ObjectInformation->FileId.Volume,
1055 Fcb->ObjectInformation->FileId.Vnode,
1056 Fcb->ObjectInformation->FileId.Unique,
1057 pFileExtents->FileOffset.QuadPart,
1058 pFileExtents->CacheOffset.QuadPart,
1059 pFileExtents->Length);
1061 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, (LONG)(pExtent->Size/1024));
1063 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, (LONG)(pExtent->Size/1024));
1065 lCount = InterlockedIncrement( &Fcb->Specific.File.ExtentCount);
1067 lCount = InterlockedIncrement( &pControlDevExt->Specific.Control.ExtentCount);
1072 KeClearEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent);
1078 InsertHeadList(le, &pExtent->Lists[AFS_EXTENTS_LIST]);
1079 ASSERT(le->Flink == &pExtent->Lists[AFS_EXTENTS_LIST]);
1080 ASSERT(0 == (pExtent->FileOffset.LowPart & ExtentsMasks[AFS_EXTENTS_LIST]));
1083 // Do not move the cursor - we will do it next time
1087 // And into the (upper) skip lists - Again, do not move the cursor
1089 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1091 if (0 == (pExtent->FileOffset.LowPart & ExtentsMasks[i]))
1093 InsertHeadList(pSkipEntries[i], &pExtent->Lists[i]);
1094 #if AFS_VALIDATE_EXTENTS
1095 VerifyExtentsLists(Fcb);
1100 else if (pExtent->FileOffset.QuadPart == pFileExtents->FileOffset.QuadPart)
1103 if (pExtent->Size != pFileExtents->Length)
1106 ASSERT (pExtent->Size == pFileExtents->Length);
1108 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1112 // Move both cursors forward.
1114 // First the extent pointer
1117 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1120 // Then the skip lists cursors forward if needed
1122 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1124 if (0 == (pExtent->FileOffset.LowPart & ExtentsMasks[i]))
1127 // Check sanity before
1129 #if AFS_VALIDATE_EXTENTS
1130 VerifyExtentsLists(Fcb);
1134 // Skip list should point to us
1136 //ASSERT(pSkipEntries[i] == &pExtent->Lists[i]);
1138 // Move forward cursor
1140 pSkipEntries[i] = pSkipEntries[i]->Flink;
1142 // Check sanity before
1144 #if AFS_VALIDATE_EXTENTS
1145 VerifyExtentsLists(Fcb);
1151 // And then the cursor in the supplied array
1157 // setup pExtent if there is one
1159 if (le->Flink != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
1161 pExtent = NextExtent( pExtent, AFS_EXTENTS_LIST ) ;
1171 ASSERT( pExtent->FileOffset.QuadPart < pFileExtents->FileOffset.QuadPart );
1174 // Sanity check on spanning
1176 if ((pExtent->FileOffset.QuadPart + pExtent->Size) >
1177 pFileExtents->FileOffset.QuadPart)
1180 ASSERT( (pExtent->FileOffset.QuadPart + pExtent->Size) <=
1181 pFileExtents->FileOffset.QuadPart);
1183 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1187 // Move le and pExtent forward
1189 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1193 // Then the check the skip lists cursors
1195 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1197 if (0 == (pFileExtents->FileOffset.LowPart & ExtentsMasks[i]))
1201 // - empty list (pSkipEntries[i]->Flink == pSkipEntries[i]->Flink == fcb->lists[i]
1202 // - We are the last on the list (pSkipEntries[i]->Flink == fcb->lists[i])
1203 // - We are not the last on the list. In that case we have to be strictly less than
1205 if (pSkipEntries[i]->Flink != &Fcb->Specific.File.ExtentsLists[i]) {
1207 AFSExtent *otherExtent = ExtentFor(pSkipEntries[i]->Flink, i);
1208 ASSERT(pFileExtents->FileOffset.QuadPart < otherExtent->FileOffset.QuadPart);
1215 // setup pExtent if there is one
1218 if (le->Flink != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
1220 pExtent = NextExtent( pExtent, AFS_EXTENTS_LIST ) ;
1230 // All done, signal that we are done drop the lock, exit
1235 if( !NT_SUCCESS( ntStatus))
1239 // If we failed the service is going to drop all extents so trim away the
1243 AFSTrimSpecifiedExtents( Fcb,
1248 #if AFS_VALIDATE_EXTENTS
1249 VerifyExtentsLists(Fcb);
1252 KeSetEvent( &pNPFcb->Specific.File.ExtentsRequestComplete,
1256 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1257 AFS_TRACE_LEVEL_VERBOSE,
1258 "AFSProcessExtentsResult Releasing Fcb extent lock %08lX EXCL %08lX\n",
1259 &pNPFcb->Specific.File.ExtentsResource,
1260 PsGetCurrentThread());
1262 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
1269 AFSProcessSetFileExtents( IN AFSSetFileExtentsCB *SetExtents )
1271 AFSFcb *pFcb = NULL;
1272 AFSVolumeCB *pVolumeCB = NULL;
1273 NTSTATUS ntStatus = STATUS_SUCCESS;
1274 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1275 ULONGLONG ullIndex = 0;
1276 AFSObjectInfoCB *pObjectInfo = NULL;
1282 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1283 AFS_TRACE_LEVEL_VERBOSE,
1284 "AFSProcessSetFileExtents Acquiring RDR VolumeTreeLock lock %08lX SHARED %08lX\n",
1285 &pDevExt->Specific.RDR.VolumeTreeLock,
1286 PsGetCurrentThread());
1288 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
1290 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1291 AFS_TRACE_LEVEL_VERBOSE,
1292 "AFSProcessSetFileExtents Set extents for fid %08lX-%08lX-%08lX-%08lX\n",
1293 SetExtents->FileId.Cell,
1294 SetExtents->FileId.Volume,
1295 SetExtents->FileId.Vnode,
1296 SetExtents->FileId.Unique);
1299 // Locate the volume node
1302 ullIndex = AFSCreateHighIndex( &SetExtents->FileId);
1304 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
1306 (AFSBTreeEntry **)&pVolumeCB);
1308 if( pVolumeCB != NULL)
1311 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1312 AFS_TRACE_LEVEL_VERBOSE,
1313 "AFSProcessSetFileExtents Acquiring VolumeRoot FileIDTree.TreeLock lock %08lX SHARED %08lX\n",
1314 pVolumeCB->ObjectInfoTree.TreeLock,
1315 PsGetCurrentThread());
1317 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1320 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
1322 if( !NT_SUCCESS( ntStatus) ||
1326 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1327 AFS_TRACE_LEVEL_ERROR,
1328 "AFSProcessSetFileExtents Set extents for fid %08lX-%08lX-%08lX-%08lX Failed to locate volume Status %08lX\n",
1329 SetExtents->FileId.Cell,
1330 SetExtents->FileId.Volume,
1331 SetExtents->FileId.Vnode,
1332 SetExtents->FileId.Unique,
1335 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1338 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1341 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1344 // Now locate the Object in this volume
1347 ullIndex = AFSCreateLowIndex( &SetExtents->FileId);
1349 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
1351 (AFSBTreeEntry **)&pObjectInfo);
1353 if( pObjectInfo != NULL)
1357 // Reference the node so it won't be torn down
1360 lCount = InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
1362 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1363 AFS_TRACE_LEVEL_VERBOSE,
1364 "AFSProcessSetFileExtents Increment count on object %08lX Cnt %d\n",
1369 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1371 if( !NT_SUCCESS( ntStatus) ||
1372 pObjectInfo == NULL)
1375 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1376 AFS_TRACE_LEVEL_ERROR,
1377 "AFSProcessSetFileExtents Set extents for hash %I64X fid %08lX-%08lX-%08lX-%08lX Failed to locate file in volume %08lX\n",
1379 SetExtents->FileId.Cell,
1380 SetExtents->FileId.Volume,
1381 SetExtents->FileId.Vnode,
1382 SetExtents->FileId.Unique,
1385 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1388 pFcb = pObjectInfo->Fcb;
1391 // If we have a result failure then don't bother trying to set the extents
1394 if( SetExtents->ResultStatus != STATUS_SUCCESS)
1397 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1398 AFS_TRACE_LEVEL_ERROR,
1399 "AFSProcessSetFileExtents Set extents failure fid %08lX-%08lX-%08lX-%08lX ResultStatus %08lX\n",
1400 SetExtents->FileId.Cell,
1401 SetExtents->FileId.Volume,
1402 SetExtents->FileId.Vnode,
1403 SetExtents->FileId.Unique,
1404 SetExtents->ResultStatus);
1406 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1407 AFS_TRACE_LEVEL_VERBOSE,
1408 "AFSProcessSetFileExtents Acquiring Fcb extents lock %08lX EXCL %08lX\n",
1409 &pFcb->NPFcb->Specific.File.ExtentsResource,
1410 PsGetCurrentThread());
1412 AFSAcquireExcl( &pFcb->NPFcb->Specific.File.ExtentsResource,
1415 pFcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_CANCELLED;
1417 KeSetEvent( &pFcb->NPFcb->Specific.File.ExtentsRequestComplete,
1421 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1422 AFS_TRACE_LEVEL_VERBOSE,
1423 "AFSProcessSetFileExtents Releasing Fcb extent lock %08lX EXCL %08lX\n",
1424 &pFcb->NPFcb->Specific.File.ExtentsResource,
1425 PsGetCurrentThread());
1427 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
1429 try_return( ntStatus);
1432 ntStatus = AFSProcessExtentsResult ( pFcb,
1433 SetExtents->ExtentCount,
1434 SetExtents->FileExtents );
1438 if( pObjectInfo != NULL)
1441 lCount = InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
1443 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1444 AFS_TRACE_LEVEL_VERBOSE,
1445 "AFSProcessSetFileExtents Decrement count on object %08lX Cnt %d\n",
1455 // Helper fuctions for Usermode initiation of release of extents
1458 AFSReleaseSpecifiedExtents( IN AFSReleaseFileExtentsCB *Extents,
1460 OUT AFSFileExtentCB *FileExtents,
1461 IN ULONG BufferSize,
1462 OUT ULONG *ExtentCount,
1463 OUT BOOLEAN *DirtyExtents)
1468 ULONG ulExtentCount = 0;
1469 NTSTATUS ntStatus = STATUS_SUCCESS;
1470 BOOLEAN bReleaseAll = FALSE;
1471 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1476 ASSERT( ExIsResourceAcquiredExclusiveLite( &Fcb->NPFcb->Specific.File.ExtentsResource));
1478 if (BufferSize < (Extents->ExtentCount * sizeof( AFSFileExtentCB)))
1481 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1482 AFS_TRACE_LEVEL_VERBOSE,
1483 "AFSReleaseSpecifiedExtents Buffer too small\n");
1485 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL);
1488 RtlZeroMemory( FileExtents, BufferSize);
1491 *DirtyExtents = FALSE;
1494 // iterate until we have dealt with all we were asked for or
1495 // are at the end of the list. Note that this deals (albeit
1496 // badly) with out of order extents
1499 pExtent = AFSExtentForOffset( Fcb,
1500 &Extents->FileExtents[0].FileOffset,
1503 if (NULL == pExtent)
1505 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1509 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1513 if( BooleanFlagOn( Extents->Flags, AFS_RELEASE_EXTENTS_FLAGS_RELEASE_ALL) ||
1514 ( Extents->FileId.Cell == 0 &&
1515 Extents->FileId.Volume == 0 &&
1516 Extents->FileId.Vnode == 0 &&
1517 Extents->FileId.Unique == 0))
1523 while( le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST] &&
1524 ulExtentCount < Extents->ExtentCount)
1528 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
1533 if( pExtent->FileOffset.QuadPart < Extents->FileExtents[ulExtentCount].FileOffset.QuadPart)
1536 // Skip forward through the extent list until we get
1537 // to the one we want
1543 else if (pExtent->FileOffset.QuadPart > Extents->FileExtents[ulExtentCount].FileOffset.QuadPart)
1546 // We don't have the extent asked for so return UNKNOWN
1549 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1550 AFS_TRACE_LEVEL_VERBOSE,
1551 "AFSReleaseSpecifiedExtents Located UNKNOWN extent Offset %I64X Len %08lX\n",
1552 Extents->FileExtents[ulExtentCount].FileOffset.QuadPart,
1553 Extents->FileExtents[ulExtentCount].Length);
1555 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_UNKNOWN;
1557 FileExtents[*ExtentCount].Length = 0;
1558 FileExtents[*ExtentCount].CacheOffset.QuadPart = 0;
1559 FileExtents[*ExtentCount].FileOffset = Extents->FileExtents[ulExtentCount].FileOffset;
1561 *ExtentCount = (*ExtentCount) + 1;
1566 // Reset where we are looking
1569 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1573 else if( pExtent->ActiveCount > 0)
1576 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1577 AFS_TRACE_LEVEL_VERBOSE,
1578 "AFSReleaseSpecifiedExtents Located IN_USE extent Offset %I64X Len %08lX\n",
1579 Extents->FileExtents[ulExtentCount].FileOffset.QuadPart,
1580 Extents->FileExtents[ulExtentCount].Length);
1582 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_IN_USE;
1584 FileExtents[*ExtentCount].Length = 0;
1585 FileExtents[*ExtentCount].CacheOffset.QuadPart = 0;
1586 FileExtents[*ExtentCount].FileOffset = Extents->FileExtents[ulExtentCount].FileOffset;
1588 *ExtentCount = (*ExtentCount) + 1;
1593 // Reset where we are looking
1596 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1605 // If the extent is currently active then skip it
1608 if( pExtent->ActiveCount > 0)
1617 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_RELEASE;
1619 FileExtents[*ExtentCount].Length = pExtent->Size;
1620 FileExtents[*ExtentCount].DirtyLength = pExtent->Size;
1621 FileExtents[*ExtentCount].DirtyOffset = 0;
1622 FileExtents[*ExtentCount].CacheOffset = pExtent->CacheOffset;
1623 FileExtents[*ExtentCount].FileOffset = pExtent->FileOffset;
1625 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1626 AFS_TRACE_LEVEL_VERBOSE,
1627 "AFSReleaseSpecifiedExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
1629 Fcb->ObjectInformation->FileId.Cell,
1630 Fcb->ObjectInformation->FileId.Volume,
1631 Fcb->ObjectInformation->FileId.Vnode,
1632 Fcb->ObjectInformation->FileId.Unique,
1633 FileExtents[*ExtentCount].FileOffset.QuadPart,
1634 FileExtents[*ExtentCount].Length);
1636 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
1639 AFSAcquireExcl( &Fcb->NPFcb->Specific.File.DirtyExtentsListLock,
1642 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
1645 AFSRemoveEntryDirtyList( Fcb,
1648 FileExtents[*ExtentCount].Flags |= AFS_EXTENT_FLAG_DIRTY;
1650 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
1652 *DirtyExtents = TRUE;
1655 AFSReleaseResource( &Fcb->NPFcb->Specific.File.DirtyExtentsListLock);
1659 // move forward all three cursors
1663 *ExtentCount = (*ExtentCount) + 1;
1678 AFSFindFcbToClean(ULONG IgnoreTime, AFSFcb *LastFcb, BOOLEAN Block)
1681 AFSFcb *pFcb = NULL;
1682 AFSVolumeCB *pVolumeCB = NULL;
1683 AFSDeviceExt *pRDRDeviceExt = NULL;
1684 AFSDeviceExt *pControlDeviceExt = NULL;
1685 BOOLEAN bLocatedEntry = FALSE;
1686 AFSObjectInfoCB *pCurrentObject = NULL;
1687 BOOLEAN bReleaseVolumeListLock = FALSE;
1690 pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1691 pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1693 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1694 AFS_TRACE_LEVEL_VERBOSE,
1695 "AFSFindFcbToClean Acquiring RDR VolumeListLock lock %08lX SHARED %08lX\n",
1696 &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1697 PsGetCurrentThread());
1699 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1702 bReleaseVolumeListLock = TRUE;
1704 pVolumeCB = pRDRDeviceExt->Specific.RDR.VolumeListHead;
1706 while( pVolumeCB != NULL)
1710 // The Volume list may move under our feet. Lock it.
1713 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1714 AFS_TRACE_LEVEL_VERBOSE,
1715 "AFSFindFcbToClean Acquiring VolumeRoot ObjectInfoTree lock %08lX SHARED %08lX\n",
1716 pVolumeCB->ObjectInfoTree.TreeLock,
1717 PsGetCurrentThread());
1719 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1721 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1723 bReleaseVolumeListLock = FALSE;
1725 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1728 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1730 if( NULL == LastFcb)
1733 pCurrentObject = pVolumeCB->ObjectInfoListHead;
1738 pCurrentObject = (AFSObjectInfoCB *)LastFcb->ObjectInformation->ListEntry.fLink;
1743 while( pCurrentObject != NULL)
1746 pFcb = (AFSFcb *)pCurrentObject->Fcb;
1749 // If the FCB is a candidate we try to lock it (but without waiting - which
1750 // means we are deadlock free
1754 pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
1760 AFSLockForExtentsTrim( pFcb);
1765 if( !AFSLockForExtentsTrimNoWait( pFcb))
1768 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1777 // Need to be sure there are no current flushes in the queue
1780 if( pFcb->Specific.File.ExtentCount == 0)
1783 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1784 AFS_TRACE_LEVEL_VERBOSE,
1785 "AFSFindFcbToClean Releasing Fcb extent lock %08lX thread %08lX\n",
1786 &pFcb->NPFcb->Specific.File.ExtentsResource,
1787 PsGetCurrentThread());
1789 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
1791 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1798 if( pFcb->Specific.File.QueuedFlushCount > 0)
1801 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1802 AFS_TRACE_LEVEL_VERBOSE,
1803 "AFSFindFcbToClean Releasing Fcb extent lock %08lX thread %08lX\n",
1804 &pFcb->NPFcb->Specific.File.ExtentsResource,
1805 PsGetCurrentThread());
1807 AFSReleaseResource(&pFcb->NPFcb->Specific.File.ExtentsResource);
1811 AFSWaitOnQueuedFlushes( pFcb);
1816 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1824 if( pFcb->OpenHandleCount > 0)
1827 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1828 AFS_TRACE_LEVEL_VERBOSE,
1829 "AFSFindFcbToClean Releasing Fcb extent lock %08lX thread %08lX\n",
1830 &pFcb->NPFcb->Specific.File.ExtentsResource,
1831 PsGetCurrentThread());
1833 AFSReleaseResource(&pFcb->NPFcb->Specific.File.ExtentsResource);
1835 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1843 // A hit a very palpable hit. Pin it
1846 lCount = InterlockedIncrement( &pCurrentObject->ObjectReferenceCount);
1848 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1849 AFS_TRACE_LEVEL_VERBOSE,
1850 "AFSFindFcbToClean Increment count on Fcb %08lX Cnt %d\n",
1854 bLocatedEntry = TRUE;
1859 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1864 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1871 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1874 bReleaseVolumeListLock = TRUE;
1876 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1879 if( bReleaseVolumeListLock)
1882 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1889 AFSProcessExtentFailure( PIRP Irp)
1891 AFSExtentFailureCB *pFailureCB = NULL;
1892 NTSTATUS ntStatus = STATUS_SUCCESS;
1893 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
1894 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1895 AFSVolumeCB *pVolumeCB = NULL;
1896 ULONGLONG ullIndex = 0;
1897 AFSObjectInfoCB *pObjectInfo = NULL;
1902 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSExtentFailureCB))
1905 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1906 AFS_TRACE_LEVEL_ERROR,
1907 "AFSProcessExtentFailure Input buffer too small\n");
1909 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1912 pFailureCB = (AFSExtentFailureCB *)Irp->AssociatedIrp.SystemBuffer;
1914 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1915 AFS_TRACE_LEVEL_ERROR,
1916 "AFSProcessExtentFailure Service Reports Failure fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1917 pFailureCB->FileId.Cell,
1918 pFailureCB->FileId.Volume,
1919 pFailureCB->FileId.Vnode,
1920 pFailureCB->FileId.Unique,
1921 pFailureCB->FailureStatus);
1923 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
1926 // Locate the volume node
1929 ullIndex = AFSCreateHighIndex( &pFailureCB->FileId);
1931 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
1933 (AFSBTreeEntry **)&pVolumeCB);
1935 if( pVolumeCB != NULL)
1938 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1939 AFS_TRACE_LEVEL_VERBOSE,
1940 "AFSProcessExtentFailure Acquiring VolumeRoot FileIDTree.TreeLock lock %08lX SHARED %08lX\n",
1941 pVolumeCB->ObjectInfoTree.TreeLock,
1942 PsGetCurrentThread());
1944 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1947 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
1949 if( !NT_SUCCESS( ntStatus) ||
1953 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1954 AFS_TRACE_LEVEL_ERROR,
1955 "AFSProcessExtentFailure Invalid volume index %I64X status %08X\n",
1956 ullIndex, ntStatus);
1958 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1961 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1964 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1967 // Now locate the Object in this volume
1970 ullIndex = AFSCreateLowIndex( &pFailureCB->FileId);
1972 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
1974 (AFSBTreeEntry **)&pObjectInfo);
1976 if( pObjectInfo != NULL &&
1977 pObjectInfo->Fcb != NULL)
1981 // Reference the node so it won't be torn down
1984 lCount = InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
1986 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1987 AFS_TRACE_LEVEL_VERBOSE,
1988 "AFSProcessExtentFailure Increment count on object %08lX Cnt %d\n",
1993 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1995 if( !NT_SUCCESS( ntStatus) ||
1996 pObjectInfo == NULL ||
1997 pObjectInfo->Fcb == NULL)
2000 if( pObjectInfo == NULL)
2002 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2003 AFS_TRACE_LEVEL_ERROR,
2004 "AFSProcessExtentFailure Invalid file index %I64X\n",
2009 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2010 AFS_TRACE_LEVEL_ERROR,
2011 "AFSProcessExtentFailure Fcb dealocated for %I64X\n",
2015 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2018 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2019 AFS_TRACE_LEVEL_VERBOSE,
2020 "AFSProcessExtentFailure Acquiring Fcb extent lock %08lX EXCL %08lX\n",
2021 &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2022 PsGetCurrentThread());
2024 AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2027 pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestStatus = pFailureCB->FailureStatus;
2029 RtlCopyMemory( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2030 &pFailureCB->AuthGroup,
2033 KeSetEvent( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
2037 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2038 AFS_TRACE_LEVEL_VERBOSE,
2039 "AFSProcessExtentFailure Releasing Fcb extent lock %08lX EXCL %08lX\n",
2040 &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2041 PsGetCurrentThread());
2043 AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource);
2045 lCount = InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
2047 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2048 AFS_TRACE_LEVEL_VERBOSE,
2049 "AFSProcessExtentFailure Decrement count on object %08lX Cnt %d\n",
2062 AFSProcessReleaseFileExtents( IN PIRP Irp)
2064 NTSTATUS ntStatus = STATUS_SUCCESS;
2065 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2066 PFILE_OBJECT pFileObject = pIrpSp->FileObject;
2067 AFSFcb *pFcb = NULL;
2068 AFSVolumeCB *pVolumeCB = NULL;
2069 AFSDeviceExt *pDevExt;
2070 AFSReleaseFileExtentsCB *pExtents;
2071 AFSReleaseFileExtentsResultCB *pResult = NULL;
2072 AFSReleaseFileExtentsResultFileCB *pFile = NULL;
2074 ULONGLONG ullIndex = 0;
2075 AFSObjectInfoCB *pObjectInfo = NULL;
2076 BOOLEAN bLocked = FALSE;
2077 BOOLEAN bDirtyExtents = FALSE;
2084 pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2086 pExtents = (AFSReleaseFileExtentsCB*) Irp->AssociatedIrp.SystemBuffer;
2088 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2089 sizeof( AFSReleaseFileExtentsCB))
2092 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2093 AFS_TRACE_LEVEL_ERROR,
2094 "AFSProcessReleaseFileExtents INPUT Buffer too small\n");
2096 try_return( ntStatus = STATUS_INVALID_PARAMETER );
2099 if ( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength <
2100 sizeof(AFSReleaseFileExtentsResultCB))
2103 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2104 AFS_TRACE_LEVEL_ERROR,
2105 "AFSProcessReleaseFileExtents OUTPUT Buffer too small [1]\n");
2108 // Must have space for one extent in one file
2111 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL);
2114 if (pExtents->ExtentCount == 0)
2117 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2118 AFS_TRACE_LEVEL_ERROR,
2119 "AFSProcessReleaseFileExtents Extent count zero\n");
2121 try_return( ntStatus = STATUS_INVALID_PARAMETER);
2124 if (pExtents->FileId.Cell != 0 ||
2125 pExtents->FileId.Volume != 0 ||
2126 pExtents->FileId.Vnode != 0 ||
2127 pExtents->FileId.Unique != 0)
2130 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2131 AFS_TRACE_LEVEL_VERBOSE,
2132 "AFSProcessReleaseFileExtents Processing FID %08lX:%08lX:%08lX:%08lX\n",
2133 pExtents->FileId.Cell,
2134 pExtents->FileId.Volume,
2135 pExtents->FileId.Vnode,
2136 pExtents->FileId.Unique);
2138 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2139 ( FIELD_OFFSET( AFSReleaseFileExtentsCB, ExtentCount) + sizeof(ULONG)) ||
2140 pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2141 ( FIELD_OFFSET( AFSReleaseFileExtentsCB, ExtentCount) + sizeof(ULONG) +
2142 sizeof (AFSFileExtentCB) * pExtents->ExtentCount))
2145 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2146 AFS_TRACE_LEVEL_ERROR,
2147 "AFSProcessReleaseFileExtents Buffer too small for FID %08lX:%08lx:%08lX:%08lX\n",
2148 pExtents->FileId.Cell,
2149 pExtents->FileId.Volume,
2150 pExtents->FileId.Vnode,
2151 pExtents->FileId.Unique);
2153 try_return( ntStatus = STATUS_INVALID_PARAMETER );
2156 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2157 AFS_TRACE_LEVEL_VERBOSE,
2158 "AFSProcessReleaseFileExtents Acquiring RDR VolumeTreeLock lock %08lX SHARED %08lX\n",
2159 &pDevExt->Specific.RDR.VolumeTreeLock,
2160 PsGetCurrentThread());
2162 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
2165 // Locate the volume node
2168 ullIndex = AFSCreateHighIndex( &pExtents->FileId);
2170 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
2172 (AFSBTreeEntry **)&pVolumeCB);
2174 if( pVolumeCB != NULL)
2177 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2178 AFS_TRACE_LEVEL_VERBOSE,
2179 "AFSProcessReleaseFileExtents Acquiring VolumeRoot FileIDTree.TreeLock lock %08lX SHARED %08lX\n",
2180 pVolumeCB->ObjectInfoTree.TreeLock,
2181 PsGetCurrentThread());
2183 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
2186 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
2188 if( !NT_SUCCESS( ntStatus) ||
2192 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2193 AFS_TRACE_LEVEL_ERROR,
2194 "AFSProcessReleaseFileExtents Invalid volume index %I64X status %08X\n",
2195 ullIndex, ntStatus);
2197 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2200 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
2203 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
2206 // Now locate the Object in this volume
2209 ullIndex = AFSCreateLowIndex( &pExtents->FileId);
2211 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
2213 (AFSBTreeEntry **)&pObjectInfo);
2215 if( pObjectInfo != NULL)
2219 // Reference the node so it won't be torn down
2222 lCount = InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
2224 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2225 AFS_TRACE_LEVEL_VERBOSE,
2226 "AFSProcessReleaseFileExtents Increment count on object %08lX Cnt %d\n",
2231 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2233 if( !NT_SUCCESS( ntStatus) ||
2234 pObjectInfo == NULL)
2237 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2238 AFS_TRACE_LEVEL_ERROR,
2239 "AFSProcessReleaseFileExtents Invalid file index %I64X\n",
2242 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2245 pFcb = pObjectInfo->Fcb;
2250 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2251 AFS_TRACE_LEVEL_ERROR,
2252 "AFSProcessReleaseFileExtents Fcb not initialied (NO EXTENTS) for FID %08lX:%08lx:%08lX:%08lX\n",
2253 pExtents->FileId.Cell,
2254 pExtents->FileId.Volume,
2255 pExtents->FileId.Vnode,
2256 pExtents->FileId.Unique);
2258 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2261 AFSLockForExtentsTrim( pFcb );
2269 // Locate an Fcb to trim down
2272 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2273 AFS_TRACE_LEVEL_VERBOSE,
2274 "AFSProcessReleaseFileExtents Searching for a Fcb to Trim Down\n");
2276 pFcb = AFSFindFcbToClean( 0, NULL, FALSE);
2281 pFcb = AFSFindFcbToClean( 0, NULL, TRUE);
2287 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2288 AFS_TRACE_LEVEL_ERROR,
2289 "AFSProcessReleaseFileExtents Failed to locate Fcb for release ...\n");
2291 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2294 pObjectInfo = pFcb->ObjectInformation;
2300 // Allocate a scratch buffer to move in the extent information
2303 ulSz = (pExtents->ExtentCount-1) * sizeof(AFSFileExtentCB);
2304 ulSz += sizeof(AFSReleaseFileExtentsResultCB);
2306 if (ulSz > pIrpSp->Parameters.DeviceIoControl.OutputBufferLength)
2308 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2309 AFS_TRACE_LEVEL_ERROR,
2310 "AFSProcessReleaseFileExtents OUTPUT Buffer too small [2]\n");
2312 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL );
2315 pResult = (AFSReleaseFileExtentsResultCB*) AFSExAllocatePoolWithTag( PagedPool,
2317 AFS_EXTENTS_RESULT_TAG);
2318 if (NULL == pResult)
2321 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2322 AFS_TRACE_LEVEL_ERROR,
2323 "AFSProcessReleaseFileExtents Failed to allocate result block\n");
2325 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2329 // Set up the header (for an array of one)
2331 pResult->FileCount = 1;
2332 pResult->Flags = AFS_EXTENT_FLAG_RELEASE;
2333 ulSz -= FIELD_OFFSET(AFSReleaseFileExtentsResultCB, Files);
2336 // Setup the first (and only) file
2338 pFile = pResult->Files;
2339 pFile->FileId = pObjectInfo->FileId;
2340 pFile->Flags = AFS_EXTENT_FLAG_RELEASE;
2343 // Stash away the auth group
2346 RtlZeroMemory( &stAuthGroup,
2349 ntStatus = AFSRetrieveValidAuthGroup( pFcb,
2354 if( !NT_SUCCESS( ntStatus))
2356 try_return( ntStatus);
2359 RtlCopyMemory( &pFile->AuthGroup,
2364 // Update the metadata for this call
2367 pFile->AllocationSize = pFcb->ObjectInformation->EndOfFile;
2368 pFile->CreateTime = pFcb->ObjectInformation->CreationTime;
2369 pFile->ChangeTime = pFcb->ObjectInformation->ChangeTime;
2370 pFile->LastAccessTime = pFcb->ObjectInformation->LastAccessTime;
2371 pFile->LastWriteTime = pFcb->ObjectInformation->LastWriteTime;
2373 ulSz -= FIELD_OFFSET(AFSReleaseFileExtentsResultFileCB, FileExtents);
2375 ntStatus = AFSReleaseSpecifiedExtents( pExtents,
2379 &pFile->ExtentCount,
2382 if (!NT_SUCCESS(ntStatus))
2385 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2386 AFS_TRACE_LEVEL_ERROR,
2387 "AFSProcessReleaseFileExtents Failed to release extents Status %08lX\n",
2390 try_return( ntStatus );
2393 if( pExtents->ExtentCount == 0)
2396 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2397 AFS_TRACE_LEVEL_WARNING,
2398 "AFSProcessReleaseFileExtents Failed to release ANY extents\n");
2401 ulSz = sizeof(AFSReleaseFileExtentsResultCB);
2403 if( pExtents->ExtentCount > 0)
2405 ulSz += ((pExtents->ExtentCount-1) * sizeof(AFSFileExtentCB));
2408 RtlCopyMemory( Irp->AssociatedIrp.SystemBuffer,
2417 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2418 AFS_TRACE_LEVEL_VERBOSE,
2419 "AFSProcessReleaseFileExtents Releasing Fcb extent lock %08lX thread %08lX\n",
2420 &pFcb->NPFcb->Specific.File.ExtentsResource,
2421 PsGetCurrentThread());
2423 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
2426 if( NULL != pResult &&
2427 Irp->AssociatedIrp.SystemBuffer != pResult)
2430 AFSExFreePool(pResult);
2433 if (NT_SUCCESS(ntStatus))
2435 Irp->IoStatus.Information = ulSz;
2439 Irp->IoStatus.Information = 0;
2442 Irp->IoStatus.Status = ntStatus;
2444 if( pObjectInfo != NULL)
2447 lCount = InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
2449 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2450 AFS_TRACE_LEVEL_VERBOSE,
2451 "AFSProcessReleaseFileExtents Decrement count on object %08lX Cnt %d\n",
2461 AFSWaitForExtentMapping( AFSFcb *Fcb,
2464 NTSTATUS ntStatus = STATUS_SUCCESS;
2465 LARGE_INTEGER liTimeOut;
2466 ULONGLONG ullProcessId = (ULONGLONG)PsGetCurrentProcessId();
2471 ASSERT( !ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
2473 if (!NT_SUCCESS( Fcb->NPFcb->Specific.File.ExtentsRequestStatus))
2477 // If this isn't the same authgroup which caused the failure
2478 // then try to request them again
2481 if( RtlCompareMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2483 sizeof( GUID)) == sizeof( GUID))
2486 ntStatus = Fcb->NPFcb->Specific.File.ExtentsRequestStatus;
2488 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
2490 RtlZeroMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2493 try_return( ntStatus);
2497 liTimeOut.QuadPart = -(1 * AFS_ONE_SECOND);
2499 ntStatus = KeWaitForSingleObject( &Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
2505 if (!NT_SUCCESS( Fcb->NPFcb->Specific.File.ExtentsRequestStatus))
2509 // If this isn't the same authgroup which caused the failure
2510 // or the System Process,
2511 // then try to request the extents again
2514 if( RtlCompareMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2516 sizeof( GUID)) == sizeof( GUID) ||
2517 ullProcessId == (ULONGLONG)AFSSysProcess)
2520 ntStatus = Fcb->NPFcb->Specific.File.ExtentsRequestStatus;
2522 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
2524 RtlZeroMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2527 try_return( ntStatus);
2531 if( ntStatus == STATUS_TIMEOUT)
2534 ntStatus = STATUS_SUCCESS;
2546 AFSFlushExtents( IN AFSFcb *Fcb,
2549 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
2550 AFSExtent *pExtent, *pNextExtent;
2552 AFSReleaseExtentsCB *pRelease = NULL;
2554 ULONG initialDirtyCount = 0;
2555 BOOLEAN bExtentsLocked = FALSE;
2558 NTSTATUS ntStatus = STATUS_SUCCESS;
2559 LARGE_INTEGER liLastFlush;
2560 AFSExtent *pDirtyListHead = NULL, *pDirtyListTail = NULL;
2561 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2562 GUID *pAuthGroup = AuthGroup;
2566 ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
2569 // Save, then reset the flush time
2572 liLastFlush = Fcb->Specific.File.LastServerFlush;
2574 KeQueryTickCount( &Fcb->Specific.File.LastServerFlush);
2579 if( pAuthGroup == NULL ||
2580 RtlCompareMemory( pAuthGroup,
2581 &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2582 sizeof( GUID)) == sizeof( GUID))
2585 RtlZeroMemory( &stAuthGroup,
2588 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
2593 if( !NT_SUCCESS( ntStatus))
2595 try_return( ntStatus);
2598 pAuthGroup = &stAuthGroup;
2602 // Lock extents while we count and set up the array to send to
2606 AFSLockForExtentsTrim( Fcb);
2608 bExtentsLocked = TRUE;
2610 lCount = InterlockedIncrement( &Fcb->Specific.File.QueuedFlushCount);
2613 // Clear our queued flush event
2616 KeClearEvent( &Fcb->NPFcb->Specific.File.QueuedFlushEvent);
2619 // Look for a start in the list to flush entries
2624 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
2626 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
2628 AFS_EXTENT_RELEASE_TAG);
2629 if( NULL == pRelease)
2632 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2635 initialDirtyCount = Fcb->Specific.File.ExtentsDirtyCount;
2637 while( Fcb->Specific.File.ExtentsDirtyCount > 0)
2640 pRelease->Flags = AFS_EXTENT_FLAG_DIRTY;
2642 if( BooleanFlagOn( Fcb->Flags, AFS_FCB_FILE_CLOSED))
2645 pRelease->Flags |= AFS_EXTENT_FLAG_FLUSH;
2649 // Update the metadata for this call
2652 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
2653 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
2654 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
2655 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
2656 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
2660 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
2663 pExtent = (AFSExtent *)pNPFcb->Specific.File.DirtyListHead;
2665 while( count < AFS_MAXIMUM_EXTENT_RELEASE_COUNT)
2668 if ( pExtent == NULL)
2674 pNextExtent = (AFSExtent *)pExtent->DirtyList.fLink;
2676 if ( pExtent->ActiveCount > 0)
2678 pExtent = pNextExtent;
2682 AFSRemoveEntryDirtyList( Fcb, pExtent);
2684 pExtent->DirtyList.fLink = NULL;
2685 pExtent->DirtyList.bLink = NULL;
2687 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
2690 // Clear the flag in advance of the write. If we do
2691 // things this was we know that the clear is
2692 // pessimistic (any write which happens from now on
2693 // will set the flag dirty again).
2696 pExtent->Flags &= ~AFS_EXTENT_DIRTY;
2698 pRelease->FileExtents[count].Flags = AFS_EXTENT_FLAG_DIRTY;
2700 pRelease->FileExtents[count].Length = pExtent->Size;
2701 pRelease->FileExtents[count].DirtyLength = pExtent->Size;
2702 pRelease->FileExtents[count].DirtyOffset = 0;
2703 pRelease->FileExtents[count].CacheOffset = pExtent->CacheOffset;
2704 pRelease->FileExtents[count].FileOffset = pExtent->FileOffset;
2707 RtlCopyMemory( pRelease->FileExtents[count].MD5,
2709 sizeof(pExtent->MD5));
2711 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_MD5_SET;
2714 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2715 AFS_TRACE_LEVEL_VERBOSE,
2716 "AFSFlushExtents Releasing DIRTY extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
2718 Fcb->ObjectInformation->FileId.Cell,
2719 Fcb->ObjectInformation->FileId.Volume,
2720 Fcb->ObjectInformation->FileId.Vnode,
2721 Fcb->ObjectInformation->FileId.Unique,
2722 pExtent->FileOffset.QuadPart,
2725 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_RELEASE;
2732 pExtent = pNextExtent;
2735 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
2738 // If we are done then get out
2744 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2745 AFS_TRACE_LEVEL_VERBOSE,
2746 "AFSFlushExtents No more dirty extents found\n");
2752 // Fire off the request synchronously
2755 sz = sizeof( AFSReleaseExtentsCB ) + (count * sizeof ( AFSFileExtentCB ));
2757 pRelease->ExtentCount = count;
2759 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2760 AFS_TRACE_LEVEL_VERBOSE,
2761 "AFSFlushExtents Releasing(1) Fcb extents lock %08lX SHARED %08lX\n",
2762 &pNPFcb->Specific.File.ExtentsResource,
2763 PsGetCurrentThread());
2765 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource);
2766 bExtentsLocked = FALSE;
2768 KeSetEvent( &pNPFcb->Specific.File.FlushEvent,
2772 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
2773 AFS_REQUEST_FLAG_SYNCHRONOUS,
2776 &Fcb->ObjectInformation->FileId,
2782 if( !NT_SUCCESS(ntStatus))
2786 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
2787 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
2790 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2791 AFS_TRACE_LEVEL_ERROR,
2792 "AFSFlushExtents AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2793 Fcb->ObjectInformation->FileId.Cell,
2794 Fcb->ObjectInformation->FileId.Volume,
2795 Fcb->ObjectInformation->FileId.Vnode,
2796 Fcb->ObjectInformation->FileId.Unique,
2800 AFSLockForExtentsTrim( Fcb);
2802 bExtentsLocked = TRUE;
2807 lCount = InterlockedDecrement( &Fcb->Specific.File.QueuedFlushCount);
2812 KeSetEvent( &pNPFcb->Specific.File.QueuedFlushEvent,
2817 KeSetEvent( &pNPFcb->Specific.File.FlushEvent,
2824 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2825 AFS_TRACE_LEVEL_VERBOSE,
2826 "AFSFlushExtents Releasing(2) Fcb extents lock %08lX SHARED %08lX\n",
2827 &pNPFcb->Specific.File.ExtentsResource,
2828 PsGetCurrentThread());
2830 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
2835 AFSExFreePool( pRelease);
2843 AFSReleaseExtentsWithFlush( IN AFSFcb *Fcb,
2845 IN BOOLEAN bReleaseAll)
2847 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
2850 AFSReleaseExtentsCB *pRelease = NULL;
2852 ULONG initialDirtyCount = 0;
2853 BOOLEAN bExtentsLocked = FALSE;
2856 NTSTATUS ntStatus = STATUS_SUCCESS;
2857 LARGE_INTEGER liLastFlush;
2858 ULONG ulRemainingExtentLength = 0;
2859 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2860 GUID *pAuthGroup = AuthGroup;
2864 ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
2867 // Save, then reset the flush time
2870 liLastFlush = Fcb->Specific.File.LastServerFlush;
2872 KeQueryTickCount( &Fcb->Specific.File.LastServerFlush);
2877 if( pAuthGroup == NULL ||
2878 RtlCompareMemory( pAuthGroup,
2879 &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2880 sizeof( GUID)) == sizeof( GUID))
2883 RtlZeroMemory( &stAuthGroup,
2886 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
2891 if( !NT_SUCCESS( ntStatus))
2893 try_return( ntStatus);
2896 pAuthGroup = &stAuthGroup;
2900 // Look for a start in the list to flush entries
2905 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
2907 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
2909 AFS_EXTENT_RELEASE_TAG);
2910 if( NULL == pRelease)
2913 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2916 if( Fcb->OpenHandleCount > 0 &&
2921 // Don't release everything ...
2924 ulRemainingExtentLength = 1024;
2927 while( Fcb->Specific.File.ExtentLength > (LONG)ulRemainingExtentLength)
2930 AFSLockForExtentsTrim( Fcb);
2932 bExtentsLocked = TRUE;
2934 pRelease->Flags = AFS_EXTENT_FLAG_RELEASE;
2937 // Update the metadata for this call
2940 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
2941 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
2942 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
2943 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
2944 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
2948 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
2950 while( count < AFS_MAXIMUM_EXTENT_RELEASE_COUNT &&
2951 le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
2954 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
2958 if( pExtent->ActiveCount > 0)
2964 pRelease->FileExtents[count].Flags = AFS_EXTENT_FLAG_RELEASE;
2966 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2967 AFS_TRACE_LEVEL_VERBOSE,
2968 "AFSReleaseExtentsWithFlush Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
2970 Fcb->ObjectInformation->FileId.Cell,
2971 Fcb->ObjectInformation->FileId.Volume,
2972 Fcb->ObjectInformation->FileId.Vnode,
2973 Fcb->ObjectInformation->FileId.Unique,
2974 pExtent->FileOffset.QuadPart,
2977 pRelease->FileExtents[count].Length = pExtent->Size;
2978 pRelease->FileExtents[count].DirtyLength = pExtent->Size;
2979 pRelease->FileExtents[count].DirtyOffset = 0;
2980 pRelease->FileExtents[count].CacheOffset = pExtent->CacheOffset;
2981 pRelease->FileExtents[count].FileOffset = pExtent->FileOffset;
2984 RtlCopyMemory( pRelease->FileExtents[count].MD5,
2986 sizeof(pExtent->MD5));
2988 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_MD5_SET;
2991 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
2994 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
2997 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3000 AFSRemoveEntryDirtyList( Fcb,
3003 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_DIRTY;
3005 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
3008 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3018 // If we are done then get out
3024 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3025 AFS_TRACE_LEVEL_VERBOSE,
3026 "AFSReleaseExtentsWithFlush No more dirty extents found\n");
3032 // Fire off the request synchronously
3035 sz = sizeof( AFSReleaseExtentsCB ) + (count * sizeof ( AFSFileExtentCB ));
3037 pRelease->ExtentCount = count;
3040 // Drop the extents lock for the duration of the call to
3041 // the network. We have pinned the extents so, even
3042 // though we might get extents added during this period,
3043 // but none will be removed. Hence we can carry on from
3047 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3048 AFS_TRACE_LEVEL_VERBOSE,
3049 "AFSReleaseExtentsWithFlush Releasing Fcb extents lock %08lX thread %08lX\n",
3050 &pNPFcb->Specific.File.ExtentsResource,
3051 PsGetCurrentThread());
3053 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource);
3054 bExtentsLocked = FALSE;
3056 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
3057 AFS_REQUEST_FLAG_SYNCHRONOUS,
3060 &Fcb->ObjectInformation->FileId,
3066 if( !NT_SUCCESS(ntStatus))
3070 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
3071 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
3074 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3075 AFS_TRACE_LEVEL_ERROR,
3076 "AFSReleaseExtentsWithFlush AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3077 Fcb->ObjectInformation->FileId.Cell,
3078 Fcb->ObjectInformation->FileId.Volume,
3079 Fcb->ObjectInformation->FileId.Vnode,
3080 Fcb->ObjectInformation->FileId.Unique,
3090 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3091 AFS_TRACE_LEVEL_VERBOSE,
3092 "AFSReleaseExtentsWithFlush Releasing Fcb extents lock %08lX thread %08lX\n",
3093 &pNPFcb->Specific.File.ExtentsResource,
3094 PsGetCurrentThread());
3096 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
3101 AFSExFreePool( pRelease);
3109 AFSReleaseCleanExtents( IN AFSFcb *Fcb,
3112 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3115 AFSReleaseExtentsCB *pRelease = NULL;
3117 ULONG initialDirtyCount = 0;
3118 BOOLEAN bExtentsLocked = FALSE;
3121 NTSTATUS ntStatus = STATUS_SUCCESS;
3122 LARGE_INTEGER liLastFlush;
3123 ULONG ulRemainingExtentLength = 0;
3124 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3125 GUID *pAuthGroup = AuthGroup;
3128 ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
3131 // Save, then reset the flush time
3134 liLastFlush = Fcb->Specific.File.LastServerFlush;
3136 KeQueryTickCount( &Fcb->Specific.File.LastServerFlush);
3141 if( pAuthGroup == NULL ||
3142 RtlCompareMemory( pAuthGroup,
3143 &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
3144 sizeof( GUID)) == sizeof( GUID))
3147 RtlZeroMemory( &stAuthGroup,
3150 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
3155 if( !NT_SUCCESS( ntStatus))
3157 try_return( ntStatus);
3160 pAuthGroup = &stAuthGroup;
3164 // Look for a start in the list to flush entries
3169 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
3171 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
3173 AFS_EXTENT_RELEASE_TAG);
3174 if( NULL == pRelease)
3177 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
3180 while( Fcb->Specific.File.ExtentLength > (LONG)ulRemainingExtentLength)
3183 AFSLockForExtentsTrim( Fcb);
3185 bExtentsLocked = TRUE;
3187 pRelease->Flags = AFS_EXTENT_FLAG_RELEASE;
3190 // Update the metadata for this call
3193 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
3194 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
3195 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
3196 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
3197 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
3201 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3203 while( count < AFS_MAXIMUM_EXTENT_RELEASE_COUNT &&
3204 le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
3207 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3211 if( pExtent->ActiveCount > 0 ||
3212 BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3217 pRelease->FileExtents[count].Flags = AFS_EXTENT_FLAG_RELEASE;
3219 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3220 AFS_TRACE_LEVEL_VERBOSE,
3221 "AFSReleaseCleanExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3223 Fcb->ObjectInformation->FileId.Cell,
3224 Fcb->ObjectInformation->FileId.Volume,
3225 Fcb->ObjectInformation->FileId.Vnode,
3226 Fcb->ObjectInformation->FileId.Unique,
3227 pExtent->FileOffset.QuadPart,
3230 pRelease->FileExtents[count].Length = pExtent->Size;
3231 pRelease->FileExtents[count].DirtyLength = pExtent->Size;
3232 pRelease->FileExtents[count].DirtyOffset = 0;
3233 pRelease->FileExtents[count].CacheOffset = pExtent->CacheOffset;
3234 pRelease->FileExtents[count].FileOffset = pExtent->FileOffset;
3237 RtlCopyMemory( pRelease->FileExtents[count].MD5,
3239 sizeof(pExtent->MD5));
3241 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_MD5_SET;
3251 // If we are done then get out
3257 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3258 AFS_TRACE_LEVEL_VERBOSE,
3259 "AFSReleaseCleanExtents No more dirty extents found\n");
3265 // Fire off the request synchronously
3268 sz = sizeof( AFSReleaseExtentsCB ) + (count * sizeof ( AFSFileExtentCB ));
3270 pRelease->ExtentCount = count;
3273 // Drop the extents lock for the duration of the call to
3274 // the network. We have pinned the extents so, even
3275 // though we might get extents added during this period,
3276 // but none will be removed. Hence we can carry on from
3280 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3281 AFS_TRACE_LEVEL_VERBOSE,
3282 "AFSReleaseCleanExtents Releasing Fcb extents lock %08lX thread %08lX\n",
3283 &pNPFcb->Specific.File.ExtentsResource,
3284 PsGetCurrentThread());
3286 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource);
3287 bExtentsLocked = FALSE;
3289 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
3290 AFS_REQUEST_FLAG_SYNCHRONOUS,
3293 &Fcb->ObjectInformation->FileId,
3299 if( !NT_SUCCESS(ntStatus))
3303 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
3304 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
3307 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3308 AFS_TRACE_LEVEL_ERROR,
3309 "AFSReleaseCleanExtents AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3310 Fcb->ObjectInformation->FileId.Cell,
3311 Fcb->ObjectInformation->FileId.Volume,
3312 Fcb->ObjectInformation->FileId.Vnode,
3313 Fcb->ObjectInformation->FileId.Unique,
3323 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3324 AFS_TRACE_LEVEL_VERBOSE,
3325 "AFSReleaseCleanExtents Releasing Fcb extents lock %08lX thread %08lX\n",
3326 &pNPFcb->Specific.File.ExtentsResource,
3327 PsGetCurrentThread());
3329 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
3334 AFSExFreePool( pRelease);
3342 AFSMarkDirty( IN AFSFcb *Fcb,
3343 IN AFSExtent *StartExtent,
3344 IN ULONG ExtentsCount,
3345 IN LARGE_INTEGER *StartingByte,
3346 IN BOOLEAN DerefExtents)
3349 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3350 AFSExtent *pExtent = StartExtent;
3351 AFSExtent *pNextExtent, *pCurrentExtent = NULL;
3353 BOOLEAN bInsertTail = FALSE, bInsertHead = FALSE;
3355 BOOLEAN bLocked = FALSE;
3357 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3358 AFS_TRACE_LEVEL_VERBOSE,
3359 "AFSMarkDirty Acquiring Fcb extents lock %08lX SHARED %08lX\n",
3360 &Fcb->NPFcb->Specific.File.ExtentsResource,
3361 PsGetCurrentThread());
3363 if( !ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource))
3365 AFSAcquireShared( &Fcb->NPFcb->Specific.File.ExtentsResource, TRUE);
3369 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3375 // Find the insertion point
3378 if( pNPFcb->Specific.File.DirtyListHead == NULL)
3383 else if( StartingByte->QuadPart == 0)
3391 pCurrentExtent = pNPFcb->Specific.File.DirtyListHead;
3393 while( pCurrentExtent != NULL)
3396 if( pCurrentExtent->FileOffset.QuadPart + pCurrentExtent->Size >= StartingByte->QuadPart ||
3397 pCurrentExtent->DirtyList.fLink == NULL)
3403 pCurrentExtent = (AFSExtent *)pCurrentExtent->DirtyList.fLink;
3407 while( ulCount < ExtentsCount)
3410 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
3412 if( !BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3415 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3416 AFS_TRACE_LEVEL_VERBOSE,
3417 "AFSMarkDirty Marking extent offset %I64X Length %08lX DIRTY\n",
3418 pExtent->FileOffset.QuadPart,
3421 pExtent->DirtyList.fLink = NULL;
3422 pExtent->DirtyList.bLink = NULL;
3427 pExtent->DirtyList.fLink = (void *)pNPFcb->Specific.File.DirtyListHead;
3429 pExtent->DirtyList.bLink = NULL;
3431 pNPFcb->Specific.File.DirtyListHead->DirtyList.bLink = (void *)pExtent;
3433 pNPFcb->Specific.File.DirtyListHead = pExtent;
3435 pCurrentExtent = pExtent;
3437 bInsertHead = FALSE;
3439 else if( bInsertTail)
3442 if( pNPFcb->Specific.File.DirtyListHead == NULL)
3445 pNPFcb->Specific.File.DirtyListHead = pExtent;
3450 pNPFcb->Specific.File.DirtyListTail->DirtyList.fLink = (void *)pExtent;
3452 pExtent->DirtyList.bLink = (void *)pNPFcb->Specific.File.DirtyListTail;
3455 pNPFcb->Specific.File.DirtyListTail = pExtent;
3460 pExtent->DirtyList.fLink = pCurrentExtent->DirtyList.fLink;
3462 pExtent->DirtyList.bLink = (void *)pCurrentExtent;
3464 if( pExtent->DirtyList.fLink == NULL)
3467 pNPFcb->Specific.File.DirtyListTail = pExtent;
3472 ((AFSExtent *)pExtent->DirtyList.fLink)->DirtyList.bLink = (void *)pExtent;
3475 pCurrentExtent->DirtyList.fLink = (void *)pExtent;
3477 pCurrentExtent = pExtent;
3480 pExtent->Flags |= AFS_EXTENT_DIRTY;
3483 // Up the dirty count
3486 lCount = InterlockedIncrement( &Fcb->Specific.File.ExtentsDirtyCount);
3491 pCurrentExtent = pExtent;
3494 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_ACTIVE_COUNTING,
3495 AFS_TRACE_LEVEL_VERBOSE,
3496 "AFSMarkDirty Decrement count on extent %08lX Cnt %d\n",
3498 pExtent->ActiveCount);
3502 ASSERT( pExtent->ActiveCount > 0);
3503 lCount = InterlockedDecrement( &pExtent->ActiveCount);
3506 pExtent = pNextExtent;
3511 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
3516 "EXCEPTION - AFSMarkDirty\n");
3518 AFSDumpTraceFilesFnc();
3521 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3523 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3524 AFS_TRACE_LEVEL_VERBOSE,
3525 "AFSMarkDirty Releasing Fcb extents lock %08lX SHARED %08lX\n",
3526 &Fcb->NPFcb->Specific.File.ExtentsResource,
3527 PsGetCurrentThread());
3531 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
3542 ExtentFor(PLIST_ENTRY le, ULONG SkipList)
3545 return CONTAINING_RECORD( le, AFSExtent, Lists[SkipList] );
3549 NextExtent(AFSExtent *Extent, ULONG SkipList)
3552 return ExtentFor(Extent->Lists[SkipList].Flink, SkipList);
3555 static AFSExtent *DirtyExtentFor(PLIST_ENTRY le)
3558 return CONTAINING_RECORD( le, AFSExtent, DirtyList );
3561 static VOID VerifyExtentsLists(AFSFcb *Fcb)
3565 // Check the ordering of the extents lists
3567 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
3569 ASSERT(Fcb->Specific.File.ExtentsLists[0].Flink != &Fcb->Specific.File.ExtentsLists[1]);
3571 for (ULONG listNo = 0; listNo < AFS_NUM_EXTENT_LISTS; listNo ++)
3573 LARGE_INTEGER lastOffset;
3575 lastOffset.QuadPart = 0;
3577 for (PLIST_ENTRY pLe = Fcb->Specific.File.ExtentsLists[listNo].Flink;
3578 pLe != &Fcb->Specific.File.ExtentsLists[listNo];
3583 pExtent = ExtentFor(pLe, listNo);
3586 ASSERT(pLe != &Fcb->Specific.File.ExtentsLists[1] &&
3587 pLe->Flink !=&Fcb->Specific.File.ExtentsLists[1] &&
3588 pLe->Blink !=&Fcb->Specific.File.ExtentsLists[1]);
3591 ASSERT(pLe->Flink->Blink == pLe);
3592 ASSERT(pLe->Blink->Flink == pLe);
3595 // Should follow on from previous
3597 ASSERT(pExtent->FileOffset.QuadPart >= lastOffset.QuadPart);
3598 lastOffset.QuadPart = pExtent->FileOffset.QuadPart + pExtent->Size;
3601 // Should match alignment criteria
3603 ASSERT( 0 == (pExtent->FileOffset.LowPart & ExtentsMasks[listNo]) );
3606 // "lower" lists should be populated
3608 for (LONG subListNo = listNo-1; subListNo > 0; subListNo --)
3610 ASSERT( !IsListEmpty(&pExtent->Lists[subListNo]));
3618 AFSTrimExtents( IN AFSFcb *Fcb,
3619 IN PLARGE_INTEGER FileSize)
3622 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3625 BOOLEAN locked = FALSE;
3626 NTSTATUS ntStatus = STATUS_SUCCESS;
3627 LARGE_INTEGER liAlignedOffset = {0,0};
3628 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
3629 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3636 // Get an aligned offset
3639 if( FileSize != NULL)
3642 liAlignedOffset = *FileSize;
3645 if( liAlignedOffset.QuadPart > 0 &&
3646 liAlignedOffset.QuadPart % pDevExt->Specific.RDR.CacheBlockSize != 0)
3650 // Align UP to the next cache block size
3653 liAlignedOffset.QuadPart = (ULONGLONG)( (ULONGLONG)((liAlignedOffset.QuadPart / pDevExt->Specific.RDR.CacheBlockSize) + 1) * (ULONGLONG)pDevExt->Specific.RDR.CacheBlockSize);
3657 // Ensure that no one is working with the extents and grab the
3661 AFSLockForExtentsTrim( Fcb);
3665 if( 0 == Fcb->Specific.File.ExtentCount)
3669 // Update the request extent status
3672 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
3674 try_return( ntStatus = STATUS_SUCCESS);
3678 // We are truncating from a specific length in the file. If the offset
3679 // is non-zero then go find the first extent to remove
3682 if( 0 == FileSize->QuadPart)
3685 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3690 pExtent = AFSExtentForOffset( Fcb,
3694 if( NULL == pExtent)
3697 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3701 le = &pExtent->Lists[AFS_EXTENTS_LIST];
3705 while( le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
3708 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3711 // Only trim down extents beyond the aligned offset
3716 if( pExtent->FileOffset.QuadPart >= liAlignedOffset.QuadPart)
3719 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3722 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3725 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3729 AFSRemoveEntryDirtyList( Fcb,
3732 dirtyCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
3734 ASSERT(dirtyCount >= 0);
3737 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3740 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3741 AFS_TRACE_LEVEL_VERBOSE,
3742 "AFSTrimExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3744 Fcb->ObjectInformation->FileId.Cell,
3745 Fcb->ObjectInformation->FileId.Volume,
3746 Fcb->ObjectInformation->FileId.Vnode,
3747 Fcb->ObjectInformation->FileId.Unique,
3748 pExtent->FileOffset.QuadPart,
3751 ASSERT( pExtent->ActiveCount == 0);
3759 // Update the request extent status
3762 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
3769 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3770 AFS_TRACE_LEVEL_VERBOSE,
3771 "AFSTrimExtents Releasing Fcb extents lock %08lX thread %08lX\n",
3772 &Fcb->NPFcb->Specific.File.ExtentsResource,
3773 PsGetCurrentThread());
3775 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
3783 AFSTrimSpecifiedExtents( IN AFSFcb *Fcb,
3785 IN AFSFileExtentCB *Result)
3788 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3791 AFSFileExtentCB *pFileExtents = Result;
3792 NTSTATUS ntStatus = STATUS_SUCCESS;
3793 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
3794 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3800 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3802 while( le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST] &&
3806 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3809 // Only trim down extents beyond the aligned offset
3814 if( pExtent->FileOffset.QuadPart == pFileExtents->FileOffset.QuadPart)
3817 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3820 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3823 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3828 AFSRemoveEntryDirtyList( Fcb,
3831 dirtyCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
3833 ASSERT( dirtyCount >= 0);
3837 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3841 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3842 AFS_TRACE_LEVEL_VERBOSE,
3843 "AFSTrimSpecifiedExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3845 Fcb->ObjectInformation->FileId.Cell,
3846 Fcb->ObjectInformation->FileId.Volume,
3847 Fcb->ObjectInformation->FileId.Vnode,
3848 Fcb->ObjectInformation->FileId.Unique,
3849 pExtent->FileOffset.QuadPart,
3852 ASSERT( pExtent->ActiveCount == 0);
3858 // Next extent we are looking for
3868 // Update the request extent status
3871 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
3878 AFSReferenceActiveExtents( IN AFSExtent *StartExtent,
3879 IN ULONG ExtentsCount)
3882 AFSExtent *pExtent = StartExtent;
3883 AFSExtent *pNextExtent;
3887 while( ulCount < ExtentsCount)
3890 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
3892 lCount = InterlockedIncrement( &pExtent->ActiveCount);
3894 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_ACTIVE_COUNTING,
3895 AFS_TRACE_LEVEL_VERBOSE,
3896 "AFSReferenceActiveExtents Increment count on extent %08lX Cnt %d\n",
3900 pExtent = pNextExtent;
3909 AFSDereferenceActiveExtents( IN AFSExtent *StartExtent,
3910 IN ULONG ExtentsCount)
3913 AFSExtent *pExtent = StartExtent;
3914 AFSExtent *pNextExtent;
3918 while( ulCount < ExtentsCount)
3921 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
3923 ASSERT( pExtent->ActiveCount > 0);
3925 lCount = InterlockedDecrement( &pExtent->ActiveCount);
3927 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_ACTIVE_COUNTING,
3928 AFS_TRACE_LEVEL_VERBOSE,
3929 "AFSDereferenceActiveExtents Decrement count on extent %08lX Cnt %d\n",
3933 pExtent = pNextExtent;
3942 AFSRemoveEntryDirtyList( IN AFSFcb *Fcb,
3943 IN AFSExtent *Extent)
3946 if( Extent->DirtyList.fLink == NULL)
3949 Fcb->NPFcb->Specific.File.DirtyListTail = (AFSExtent *)Extent->DirtyList.bLink;
3951 if( Fcb->NPFcb->Specific.File.DirtyListTail != NULL)
3954 Fcb->NPFcb->Specific.File.DirtyListTail->DirtyList.fLink = NULL;
3960 ((AFSExtent *)Extent->DirtyList.fLink)->DirtyList.bLink = Extent->DirtyList.bLink;
3963 if( Extent->DirtyList.bLink == NULL)
3966 Fcb->NPFcb->Specific.File.DirtyListHead = (AFSExtent *)Extent->DirtyList.fLink;
3968 if( Fcb->NPFcb->Specific.File.DirtyListHead != NULL)
3971 Fcb->NPFcb->Specific.File.DirtyListHead->DirtyList.bLink = NULL;
3977 ((AFSExtent *)Extent->DirtyList.bLink)->DirtyList.fLink = Extent->DirtyList.fLink;
3985 AFSConstructCleanByteRangeList( AFSFcb * pFcb,
3986 AFSByteRange ** pByteRangeList)
3989 ULONG ulByteRangeMax;
3990 ULONG ulByteRangeCount = 0;
3991 AFSByteRange *ByteRangeList;
3992 AFSExtent *pExtent, *pNextExtent;
3994 AFSAcquireShared( &pFcb->NPFcb->Specific.File.DirtyExtentsListLock, TRUE);
3996 ulByteRangeMax = pFcb->Specific.File.ExtentsDirtyCount + 1;
3998 ByteRangeList = (AFSByteRange *) AFSExAllocatePoolWithTag( PagedPool,
3999 ulByteRangeMax * sizeof( AFSByteRange),
4002 if ( ByteRangeList == NULL)
4005 (*pByteRangeList) = NULL;
4007 try_return( ulByteRangeCount = DWORD_MAX);
4010 RtlZeroMemory( ByteRangeList,
4011 ulByteRangeMax * sizeof( AFSByteRange));
4014 // The for loop populates the ByteRangeList entries with values that are
4015 // the gaps in the DirtyList. In other words, if a range is not present
4016 // in the DirtyList it will be represented in the ByteRangeList array.
4019 for ( ulByteRangeCount = 0,
4020 pExtent = (AFSExtent *)pFcb->NPFcb->Specific.File.DirtyListHead;
4021 ulByteRangeCount < ulByteRangeMax && pExtent != NULL;
4022 pExtent = pNextExtent)
4025 pNextExtent = (AFSExtent *)pExtent->DirtyList.fLink;
4028 // The first time the for() is entered the ulByteRangeCount will be zero and
4029 // ByteRangeList[0] FileOffset and Length will both be zero. If the first
4030 // extent is not for offset zero, the ByteRangeList[0] Length is set to the
4031 // FileOffset of the Extent.
4033 // Future passes through the loop behave in a similar fashion but
4034 // ByteRangeList[ulByteRangeCount] FileOffset will have been set below.
4037 if ( pExtent->FileOffset.QuadPart != ByteRangeList[ulByteRangeCount].FileOffset.QuadPart + ByteRangeList[ulByteRangeCount].Length.QuadPart)
4040 ByteRangeList[ulByteRangeCount].Length.QuadPart =
4041 pExtent->FileOffset.QuadPart - ByteRangeList[ulByteRangeCount].FileOffset.QuadPart;
4047 // Having processed the current dirty extent, the following while loop
4048 // searches for the next clean gap between dirty extents.
4051 while ( pNextExtent && pNextExtent->FileOffset.QuadPart == pExtent->FileOffset.QuadPart + pExtent->Size)
4054 pExtent = pNextExtent;
4056 pNextExtent = (AFSExtent *)pExtent->DirtyList.fLink;
4060 // Having found the next gap, the ByteRangeList[] FileOffset is set to the start of the gap.
4061 // The Length is left at zero and will be assigned either when the for loop continues or
4062 // when the for loop exits.
4065 ByteRangeList[ulByteRangeCount].FileOffset.QuadPart = pExtent->FileOffset.QuadPart + pExtent->Size;
4069 // Assign the Length of the final clean range to match the file length.
4072 ByteRangeList[ulByteRangeCount].Length.QuadPart =
4073 pFcb->ObjectInformation->EndOfFile.QuadPart - ByteRangeList[ulByteRangeCount].FileOffset.QuadPart;
4075 (*pByteRangeList) = ByteRangeList;
4079 AFSReleaseResource( &pFcb->NPFcb->Specific.File.DirtyExtentsListLock);
4081 return ulByteRangeCount;
4086 AFSSetupMD5Hash( IN AFSFcb *Fcb,
4087 IN AFSExtent *StartExtent,
4088 IN ULONG ExtentsCount,
4089 IN void *SystemBuffer,
4090 IN LARGE_INTEGER *ByteOffset,
4094 NTSTATUS ntStatus = STATUS_SUCCESS;
4095 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
4096 AFSExtent *pExtent = StartExtent;
4097 AFSExtent *pNextExtent, *pCurrentExtent = NULL;
4099 char *pCurrentBuffer = (char *)SystemBuffer;
4100 char *pMD5Buffer = NULL;
4101 ULONG ulCurrentLen = 0;
4102 void *pExtentBuffer = NULL;
4103 LARGE_INTEGER liByteOffset;
4104 ULONG ulBytesRead = 0;
4109 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4110 AFS_TRACE_LEVEL_VERBOSE,
4111 "AFSSetupMD5Hash Acquiring Fcb extents lock %08lX SHARED %08lX\n",
4112 &Fcb->NPFcb->Specific.File.ExtentsResource,
4113 PsGetCurrentThread());
4115 AFSAcquireShared( &Fcb->NPFcb->Specific.File.ExtentsResource, TRUE);
4119 liByteOffset.QuadPart = ByteOffset->QuadPart;
4121 while( ulCount < ExtentsCount)
4124 RtlZeroMemory( pExtent->MD5,
4125 sizeof( pExtent->MD5));
4127 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
4129 if( liByteOffset.QuadPart == pExtent->FileOffset.QuadPart &&
4130 ByteCount < pExtent->Size)
4133 if( pExtentBuffer == NULL)
4136 pExtentBuffer = AFSExAllocatePoolWithTag( PagedPool,
4138 AFS_GENERIC_MEMORY_9_TAG);
4140 if( pExtentBuffer == NULL)
4147 RtlZeroMemory( pExtentBuffer,
4150 RtlCopyMemory( pExtentBuffer,
4154 pMD5Buffer = (char *)pExtentBuffer;
4156 ulCurrentLen = ByteCount;
4158 else if( liByteOffset.QuadPart != pExtent->FileOffset.QuadPart)
4161 pExtentBuffer = AFSExAllocatePoolWithTag( PagedPool,
4163 AFS_GENERIC_MEMORY_10_TAG);
4165 if( pExtentBuffer == NULL)
4171 RtlZeroMemory( pExtentBuffer,
4174 if( BooleanFlagOn( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE))
4178 RtlCopyMemory( pExtentBuffer,
4179 ((char *)AFSLibCacheBaseAddress + pExtent->CacheOffset.QuadPart),
4182 ASSERT( pExtent->CacheOffset.HighPart == 0);
4183 RtlCopyMemory( pExtentBuffer,
4184 ((char *)AFSLibCacheBaseAddress + pExtent->CacheOffset.LowPart),
4188 ulBytesRead = pExtent->Size;
4193 ntStatus = AFSReadCacheFile( pExtentBuffer,
4194 &pExtent->CacheOffset,
4198 if( !NT_SUCCESS( ntStatus))
4205 pMD5Buffer = (char *)pExtentBuffer;
4207 ulCurrentLen = min( ByteCount, pExtent->Size - (ULONG)(liByteOffset.QuadPart - pExtent->FileOffset.QuadPart));
4209 RtlCopyMemory( (void *)((char *)pExtentBuffer + (ULONG)(liByteOffset.QuadPart - pExtent->FileOffset.QuadPart)),
4216 ulCurrentLen = pExtent->Size;
4218 pMD5Buffer = pCurrentBuffer;
4221 AFSGenerateMD5( pMD5Buffer,
4225 pExtent = pNextExtent;
4229 ByteCount -= ulCurrentLen;
4231 pCurrentBuffer += ulCurrentLen;
4233 liByteOffset.QuadPart += ulCurrentLen;
4236 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4237 AFS_TRACE_LEVEL_VERBOSE,
4238 "AFSSetupMD5Hash Releasing Fcb extents lock %08lX SHARED %08lX\n",
4239 &Fcb->NPFcb->Specific.File.ExtentsResource,
4240 PsGetCurrentThread());
4243 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
4248 "EXCEPTION - AFSSetupMD5Hash\n");
4250 AFSDumpTraceFilesFnc();
4253 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
4255 if( pExtentBuffer != NULL)
4258 AFSExFreePool( pExtentBuffer);