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 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
61 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
62 AFS_TRACE_LEVEL_VERBOSE,
63 "AFSLockForExtentsTrim Acquiring Fcb extents lock %08lX EXCL %08lX\n",
64 &pNPFcb->Specific.File.ExtentsResource,
65 PsGetCurrentThread());
67 AFSAcquireExcl( &pNPFcb->Specific.File.ExtentsResource, TRUE );
73 // return FALSE *or* with Extents lock EX and noone using them
76 AFSLockForExtentsTrimNoWait( IN AFSFcb *Fcb)
78 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
80 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
81 AFS_TRACE_LEVEL_VERBOSE,
82 "AFSLockForExtentsTrimNoWait Attempting to acquire Fcb extent lock %08lX EXCL %08lX\n",
83 &pNPFcb->Specific.File.ExtentsResource,
84 PsGetCurrentThread());
86 if (!AFSAcquireExcl( &pNPFcb->Specific.File.ExtentsResource, FALSE ))
89 // Couldn't lock immediately
92 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
93 AFS_TRACE_LEVEL_VERBOSE,
94 "AFSLockForExtentsTrimNoWait Refused to wait for Fcb extent lock %08lX EXCL %08lX\n",
95 &pNPFcb->Specific.File.ExtentsResource,
96 PsGetCurrentThread());
104 // AFSTearDownFcbExtents was originally written to
105 // remove all of the extents from an FCB. For that to happen
106 // it must be an invariant that the extent list cannot change
107 // from the moment the caller decides to execute AFSTearDownFcbExtents
108 // until it returns. This invariant does not hold because the
109 // the decision to call AFSTearDownFcbExtents is made without
110 // holding the ExtentsResource and it is possible that extents
111 // are in active use. Therefore, AFSTearDownFcbExtents now releases
112 // as many non-active extents as it can.
115 AFSTearDownFcbExtents( IN AFSFcb *Fcb,
118 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
119 LIST_ENTRY *le, *leNext;
121 LONG lExtentCount = 0;
122 ULONG ulReleaseCount = 0, ulProcessCount = 0;
124 AFSReleaseExtentsCB *pRelease = NULL;
125 BOOLEAN locked = FALSE;
127 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
128 GUID *pAuthGroup = AuthGroup;
135 if( pAuthGroup == NULL ||
136 RtlCompareMemory( pAuthGroup,
137 &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
138 sizeof( GUID)) == sizeof( GUID))
141 RtlZeroMemory( &stAuthGroup,
144 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
149 if( !NT_SUCCESS( ntStatus))
151 try_return( ntStatus);
154 pAuthGroup = &stAuthGroup;
158 // Ensure that no one is working with the extents and grab the
162 AFSLockForExtentsTrim( Fcb );
166 if (0 == Fcb->Specific.File.ExtentCount)
168 try_return ( ntStatus = STATUS_SUCCESS);
171 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
173 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
175 AFS_EXTENT_RELEASE_TAG);
176 if (NULL == pRelease)
179 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
182 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
185 for( le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink,
187 lExtentCount < Fcb->Specific.File.ExtentCount;
188 lExtentCount += ulProcessCount)
191 RtlZeroMemory( pRelease,
192 sizeof( AFSReleaseExtentsCB ) +
193 (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB )));
195 for( ulProcessCount = 0, ulReleaseCount = 0;
196 !IsListEmpty( le) && ulReleaseCount < AFS_MAXIMUM_EXTENT_RELEASE_COUNT;
197 ulProcessCount++, le = leNext)
202 pEntry = ExtentFor( le, AFS_EXTENTS_LIST );
204 if( pEntry->ActiveCount == 0)
209 pRelease->FileExtents[ulProcessCount].Flags = AFS_EXTENT_FLAG_RELEASE;
212 RtlCopyMemory( pRelease->FileExtents[ulProcessCount].MD5,
214 sizeof(pEntry->MD5));
216 pRelease->FileExtents[ulProcessCount].Flags |= AFS_EXTENT_FLAG_MD5_SET;
219 if( BooleanFlagOn( pEntry->Flags, AFS_EXTENT_DIRTY))
224 AFSRemoveEntryDirtyList( Fcb,
227 pRelease->FileExtents[ulProcessCount].Flags |= AFS_EXTENT_FLAG_DIRTY;
229 dirtyCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
231 ASSERT( dirtyCount >= 0);
234 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
235 AFS_TRACE_LEVEL_VERBOSE,
236 "AFSTearDownFcbExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %08lX-%08lX Len %08lX\n",
238 Fcb->ObjectInformation->FileId.Cell,
239 Fcb->ObjectInformation->FileId.Volume,
240 Fcb->ObjectInformation->FileId.Vnode,
241 Fcb->ObjectInformation->FileId.Unique,
242 pEntry->FileOffset.HighPart,
243 pEntry->FileOffset.LowPart,
246 pRelease->FileExtents[ulProcessCount].Length = pEntry->Size;
247 pRelease->FileExtents[ulProcessCount].DirtyLength = pEntry->Size;
248 pRelease->FileExtents[ulProcessCount].DirtyOffset = 0;
249 pRelease->FileExtents[ulProcessCount].CacheOffset = pEntry->CacheOffset;
250 pRelease->FileExtents[ulProcessCount].FileOffset = pEntry->FileOffset;
252 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pEntry->Size/1024)));
254 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pEntry->Size/1024)));
256 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
258 if (NULL != pEntry->Lists[i].Flink && !IsListEmpty(&pEntry->Lists[i]))
260 RemoveEntryList( &pEntry->Lists[i] );
264 AFSExFreePool( pEntry);
266 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
268 lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount);
273 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
280 if ( ulReleaseCount > 0)
283 pRelease->ExtentCount = ulReleaseCount;
285 pRelease->Flags = AFS_EXTENT_FLAG_RELEASE;
288 // Update the metadata for this call
291 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
292 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
293 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
294 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
295 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
298 // Send the request down. We cannot send this down
299 // asynchronously - if we did that we could request them
300 // back before the service got this request and then this
301 // request would be a corruption.
304 sz = sizeof( AFSReleaseExtentsCB ) + (ulProcessCount * sizeof ( AFSFileExtentCB ));
306 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
307 AFS_REQUEST_FLAG_SYNCHRONOUS,
310 &Fcb->ObjectInformation->FileId,
316 if( !NT_SUCCESS(ntStatus))
320 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
321 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
324 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
325 AFS_TRACE_LEVEL_ERROR,
326 "AFSTearDownFcbExtents AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
327 Fcb->ObjectInformation->FileId.Cell,
328 Fcb->ObjectInformation->FileId.Volume,
329 Fcb->ObjectInformation->FileId.Vnode,
330 Fcb->ObjectInformation->FileId.Unique,
337 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
340 // if all extents have been released, reinitialize the skip lists
343 if( Fcb->Specific.File.ExtentCount == 0)
346 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i++)
348 InitializeListHead(&Fcb->Specific.File.ExtentsLists[i]);
352 // Reinitialize the dirty list as well
355 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
358 ASSERT( Fcb->Specific.File.ExtentsDirtyCount == 0);
360 Fcb->NPFcb->Specific.File.DirtyListHead = NULL;
361 Fcb->NPFcb->Specific.File.DirtyListTail = NULL;
363 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
366 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
373 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
374 AFS_TRACE_LEVEL_VERBOSE,
375 "AFSTearDownFcbExtents Releasing Fcb extent lock %08lX thread %08lX\n",
376 &Fcb->NPFcb->Specific.File.ExtentsResource,
377 PsGetCurrentThread());
379 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
385 AFSExFreePool( pRelease);
391 ExtentForOffsetInList( IN AFSFcb *Fcb,
394 IN PLARGE_INTEGER Offset)
397 // Return the extent that maps the offset, that
398 // - Contains the offset
399 // - or is immediately ahead of the offset (in this list)
400 // - otherwise return NULL.
403 PLIST_ENTRY pLe = List;
404 AFSExtent *pPrevious = NULL;
406 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
408 while (pLe != &Fcb->Specific.File.ExtentsLists[ListNumber])
412 entry = ExtentFor( pLe, ListNumber );
419 if (Offset->QuadPart < entry->FileOffset.QuadPart)
422 // Offset is ahead of entry. Return previous
427 if (Offset->QuadPart >= (entry->FileOffset.QuadPart + entry->Size))
430 // We start after this extent - carry on round
438 // Otherwise its a match
445 // Got to the end. Return Previous
451 AFSExtentContains( IN AFSExtent *Extent, IN PLARGE_INTEGER Offset)
457 return (Extent->FileOffset.QuadPart <= Offset->QuadPart &&
458 (Extent->FileOffset.QuadPart + Extent->Size) > Offset->QuadPart);
463 // Return the extent that contains the offset
466 AFSExtentForOffsetHint( IN AFSFcb *Fcb,
467 IN PLARGE_INTEGER Offset,
468 IN BOOLEAN ReturnPrevious,
471 AFSExtent *pPrevious = Hint;
475 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
477 #if AFS_VALIDATE_EXTENTS
478 VerifyExtentsLists(Fcb);
482 // So we will go across the skip lists until we find an
483 // appropriate entry (previous or direct match). If it's a match
484 // we are done, other wise we start on the next layer down
486 for (i = AFS_NUM_EXTENT_LISTS-1; i >= AFS_EXTENTS_LIST; i--)
488 if (NULL == pPrevious)
491 // We haven't found anything in the previous layers
493 pLe = Fcb->Specific.File.ExtentsLists[i].Flink;
495 else if (NULL == pPrevious->Lists[i].Flink)
497 ASSERT(AFS_EXTENTS_LIST != i);
499 // The hint doesn't exist at this level, next one down
506 // take the previous into the next
508 pLe = &pPrevious->Lists[i];
511 pPrevious = ExtentForOffsetInList( Fcb, pLe, i, Offset);
513 if (NULL != pPrevious && AFSExtentContains(pPrevious, Offset))
516 // Found it immediately. Stop here
522 if (NULL == pPrevious || ReturnPrevious )
527 ASSERT( !AFSExtentContains(pPrevious, Offset) );
533 AFSEntryForOffset( IN AFSFcb *Fcb,
534 IN PLARGE_INTEGER Offset)
536 AFSExtent *pPrevious = NULL;
540 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
542 #if AFS_VALIDATE_EXTENTS
543 VerifyExtentsLists(Fcb);
547 // So we will go across the skip lists until we find an
548 // appropriate entry (previous or direct match). If it's a match
549 // we are done, other wise we start on the next layer down
551 for (i = AFS_NUM_EXTENT_LISTS-1; i >= AFS_EXTENTS_LIST; i--)
553 if (NULL == pPrevious)
556 // We haven't found anything in the previous layers
558 pLe = Fcb->Specific.File.ExtentsLists[i].Flink;
560 else if (NULL == pPrevious->Lists[i].Flink)
562 ASSERT(AFS_EXTENTS_LIST != i);
564 // The hint doesn't exist at this level, next one down
571 // take the previous into the next
573 pLe = &pPrevious->Lists[i];
576 pPrevious = ExtentForOffsetInList( Fcb, pLe, i, Offset);
578 if (NULL != pPrevious && AFSExtentContains(pPrevious, Offset))
581 // Found it immediately. Stop here
591 AFSExtentForOffset( IN AFSFcb *Fcb,
592 IN PLARGE_INTEGER Offset,
593 IN BOOLEAN ReturnPrevious)
595 return AFSExtentForOffsetHint(Fcb, Offset, ReturnPrevious, NULL);
599 BOOLEAN AFSDoExtentsMapRegion(IN AFSFcb *Fcb,
600 IN PLARGE_INTEGER Offset,
602 IN OUT AFSExtent **FirstExtent,
603 OUT AFSExtent **LastExtent)
606 // Return TRUE region is completely mapped. FALSE
607 // otherwise. If the region isn't mapped then the last
608 // extent to map part of the region is returned.
610 // *LastExtent as input is where to start looking.
611 // *LastExtent as output is either the extent which
612 // contains the Offset, or the last one which doesn't
616 BOOLEAN retVal = FALSE;
621 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
622 AFS_TRACE_LEVEL_VERBOSE,
623 "AFSDoExtentsMapRegion Acquiring Fcb extent lock %08lX SHARED %08lX\n",
624 &Fcb->NPFcb->Specific.File.ExtentsResource,
625 PsGetCurrentThread());
627 AFSAcquireShared( &Fcb->NPFcb->Specific.File.ExtentsResource, TRUE );
631 entry = AFSExtentForOffsetHint(Fcb, Offset, TRUE, *FirstExtent);
632 *FirstExtent = entry;
634 if (NULL == entry || !AFSExtentContains(entry, Offset))
636 try_return (retVal = FALSE);
639 ASSERT(Offset->QuadPart >= entry->FileOffset.QuadPart);
643 if ((entry->FileOffset.QuadPart + entry->Size) >=
644 (Offset->QuadPart + Size))
647 // The end is inside the extent
649 try_return (retVal = TRUE);
652 if (entry->Lists[AFS_EXTENTS_LIST].Flink == &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
655 // Run out of extents
657 try_return (retVal = FALSE);
660 newEntry = NextExtent( entry, AFS_EXTENTS_LIST );
662 if (newEntry->FileOffset.QuadPart !=
663 (entry->FileOffset.QuadPart + entry->Size))
668 try_return (retVal = FALSE);
674 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
679 "EXCEPTION - AFSDoExtentsMapRegion\n");
681 AFSDumpTraceFilesFnc();
686 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
687 AFS_TRACE_LEVEL_VERBOSE,
688 "AFSDoExtentsMapRegion Releasing Fcb extent lock %08lX SHARED %08lX\n",
689 &Fcb->NPFcb->Specific.File.ExtentsResource,
690 PsGetCurrentThread());
692 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
701 AFSRequestExtentsAsync( IN AFSFcb *Fcb,
703 IN PLARGE_INTEGER Offset,
707 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
708 NTSTATUS ntStatus = STATUS_SUCCESS;
709 AFSExtent *pExtent = NULL;
710 AFSRequestExtentsCB request;
711 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
712 AFSExtent *pFirstExtent = NULL;
713 LARGE_INTEGER liAlignedOffset;
714 ULONG ulAlignedLength = 0;
715 BOOLEAN bRegionMapped = FALSE;
716 ULONGLONG ullProcessId = (ULONGLONG)PsGetCurrentProcessId();
721 ASSERT( !ExIsResourceAcquiredLite( &pNPFcb->Specific.File.ExtentsResource ));
724 // If the service set a failure on the file since the last
725 // CreateFile was issued, return it now.
728 if (!NT_SUCCESS( pNPFcb->Specific.File.ExtentsRequestStatus))
732 // If this isn't the same authgroup which caused the failure
733 // then try to request them again
736 if( RtlCompareMemory( &pNPFcb->Specific.File.ExtentsRequestAuthGroup,
738 sizeof( GUID)) == sizeof( GUID))
741 ntStatus = pNPFcb->Specific.File.ExtentsRequestStatus;
743 pNPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
745 RtlZeroMemory( &pNPFcb->Specific.File.ExtentsRequestAuthGroup,
748 try_return( ntStatus);
753 // Check if we are already mapped
756 bRegionMapped = AFSDoExtentsMapRegion( Fcb, Offset, Size, &pFirstExtent, &pExtent);
761 try_return( ntStatus = STATUS_SUCCESS);
765 // Align our request on extent size boundary
768 ulAlignedLength = Size;
770 liAlignedOffset = *Offset;
772 if( liAlignedOffset.QuadPart % pDevExt->Specific.RDR.CacheBlockSize != 0)
775 liAlignedOffset.QuadPart = (ULONGLONG)( (ULONGLONG)(liAlignedOffset.QuadPart / pDevExt->Specific.RDR.CacheBlockSize) * (ULONGLONG)pDevExt->Specific.RDR.CacheBlockSize);
777 ulAlignedLength += (ULONG)(Offset->QuadPart - liAlignedOffset.QuadPart);
780 if( ulAlignedLength % pDevExt->Specific.RDR.CacheBlockSize != 0)
783 ulAlignedLength = (ULONG)(((ulAlignedLength / pDevExt->Specific.RDR.CacheBlockSize) + 1) * pDevExt->Specific.RDR.CacheBlockSize);
786 RtlZeroMemory( &request,
787 sizeof( AFSRequestExtentsCB));
789 request.ByteOffset = liAlignedOffset;
790 request.Length = ulAlignedLength;
792 if( !AFSIsExtentRequestQueued( &Fcb->ObjectInformation->FileId,
797 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
798 AFS_TRACE_LEVEL_VERBOSE,
799 "AFSRequestExtentsAsync Request extents for fid %08lX-%08lX-%08lX-%08lX Offset %08lX Len %08lX Thread %08lX\n",
800 Fcb->ObjectInformation->FileId.Cell,
801 Fcb->ObjectInformation->FileId.Volume,
802 Fcb->ObjectInformation->FileId.Vnode,
803 Fcb->ObjectInformation->FileId.Unique,
804 request.ByteOffset.LowPart,
806 PsGetCurrentThread());
808 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS,
812 &Fcb->ObjectInformation->FileId,
814 sizeof( AFSRequestExtentsCB ),
818 if ( ntStatus == STATUS_ACCESS_DENIED)
823 ntStatus2 = AFSRetrieveValidAuthGroup( Fcb,
828 if ( NT_SUCCESS( ntStatus2) &&
829 RtlCompareMemory( &stAuthGroup,
831 sizeof( GUID)) != sizeof( GUID))
834 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS,
838 &Fcb->ObjectInformation->FileId,
840 sizeof( AFSRequestExtentsCB ),
846 if( NT_SUCCESS( ntStatus))
849 KeClearEvent( &pNPFcb->Specific.File.ExtentsRequestComplete );
855 KeClearEvent( &pNPFcb->Specific.File.ExtentsRequestComplete );
867 AFSProcessExtentsResult( IN AFSFcb *Fcb,
869 IN AFSFileExtentCB *Result)
871 NTSTATUS ntStatus = STATUS_SUCCESS;
872 AFSFileExtentCB *pFileExtents = Result;
875 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
876 ULONG fileExtentsUsed = 0;
877 BOOLEAN bFoundExtent = FALSE;
878 LIST_ENTRY *pSkipEntries[AFS_NUM_EXTENT_LISTS] = { 0 };
879 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
883 // Grab the extents exclusive for the duration
886 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
887 AFS_TRACE_LEVEL_VERBOSE,
888 "AFSProcessExtentsResult Acquiring Fcb extent lock %08lX EXCL %08lX\n",
889 &pNPFcb->Specific.File.ExtentsResource,
890 PsGetCurrentThread());
892 AFSAcquireExcl( &pNPFcb->Specific.File.ExtentsResource, TRUE );
898 // Find where to put the extents
900 for (ULONG i = AFS_EXTENTS_LIST; i < AFS_NUM_EXTENT_LISTS; i++)
903 pSkipEntries[i] = Fcb->Specific.File.ExtentsLists[i].Flink;
906 le = pSkipEntries[AFS_EXTENTS_LIST];
908 if (le == &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
911 // No extents. Insert at head of list (which is where the skip lists point!)
915 else if (0 != pFileExtents->FileOffset.QuadPart)
918 // We want to find the best extents immediately *behind* this offset
920 LARGE_INTEGER offset = pFileExtents->FileOffset;
923 // Ask in the top skip list first, then work down
925 for (LONG i = AFS_NUM_EXTENT_LISTS-1; i >= AFS_EXTENTS_LIST; i--)
927 pExtent = ExtentForOffsetInList( Fcb,
935 // No dice. Header has to become the head of the list
937 pSkipEntries[i] = &Fcb->Specific.File.ExtentsLists[i];
939 // And as a loop invariant we should never have found an extent
941 ASSERT(!bFoundExtent);
946 // pExtent is where to start to insert at this level
948 pSkipEntries[i] = &pExtent->Lists[i];
951 // And also where to start to look at the next level
954 if (i > AFS_EXTENTS_LIST)
956 pSkipEntries[i-1] = &pExtent->Lists[i-1];
964 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
969 le = pExtent->Lists[AFS_EXTENTS_LIST].Blink;
975 // Looking at offset 0, so we must start at the beginning
978 pExtent = ExtentFor(le, AFS_EXTENTS_LIST);
982 // And set up the skip lists
985 for (ULONG i = AFS_EXTENTS_LIST; i < AFS_NUM_EXTENT_LISTS; i++)
987 pSkipEntries[i] = &Fcb->Specific.File.ExtentsLists[i];
991 while (fileExtentsUsed < Count)
995 // Loop invariant - le points to where to insert after and
996 // pExtent points to le->fLink
999 ASSERT (NULL == pExtent ||
1000 le->Flink == &pExtent->Lists[AFS_EXTENTS_LIST]);
1002 if (NULL == pExtent ||
1003 pExtent->FileOffset.QuadPart > pFileExtents->FileOffset.QuadPart)
1006 // We need to insert a new extent at le. Start with
1007 // some sanity check on spanning
1009 if (NULL != pExtent &&
1010 ((pFileExtents->FileOffset.QuadPart + pFileExtents->Length) >
1011 pExtent->FileOffset.QuadPart))
1014 // File Extents overlaps pExtent
1016 ASSERT( (pFileExtents->FileOffset.QuadPart + pFileExtents->Length) <=
1017 pExtent->FileOffset.QuadPart);
1019 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1023 // File offset is entirely in front of this extent. Create
1024 // a new one (remember le is the previous list entry)
1026 pExtent = (AFSExtent *) AFSExAllocatePoolWithTag( NonPagedPool,
1029 if (NULL == pExtent)
1032 try_return (ntStatus = STATUS_INSUFFICIENT_RESOURCES );
1035 RtlZeroMemory( pExtent, sizeof( AFSExtent ));
1037 pExtent->FileOffset = pFileExtents->FileOffset;
1038 pExtent->CacheOffset = pFileExtents->CacheOffset;
1039 pExtent->Size = pFileExtents->Length;
1041 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1042 AFS_TRACE_LEVEL_VERBOSE,
1043 "AFSProcessExtentsResult Received extent for fid %08lX-%08lX-%08lX-%08lX File Offset %I64X Cache Offset %I64X Len %08lX\n",
1044 Fcb->ObjectInformation->FileId.Cell,
1045 Fcb->ObjectInformation->FileId.Volume,
1046 Fcb->ObjectInformation->FileId.Vnode,
1047 Fcb->ObjectInformation->FileId.Unique,
1048 pFileExtents->FileOffset.QuadPart,
1049 pFileExtents->CacheOffset.QuadPart,
1050 pFileExtents->Length);
1052 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, (LONG)(pExtent->Size/1024));
1054 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, (LONG)(pExtent->Size/1024));
1056 lCount = InterlockedIncrement( &Fcb->Specific.File.ExtentCount);
1058 lCount = InterlockedIncrement( &pControlDevExt->Specific.Control.ExtentCount);
1063 KeClearEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent);
1069 InsertHeadList(le, &pExtent->Lists[AFS_EXTENTS_LIST]);
1070 ASSERT(le->Flink == &pExtent->Lists[AFS_EXTENTS_LIST]);
1071 ASSERT(0 == (pExtent->FileOffset.LowPart & ExtentsMasks[AFS_EXTENTS_LIST]));
1074 // Do not move the cursor - we will do it next time
1078 // And into the (upper) skip lists - Again, do not move the cursor
1080 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1082 if (0 == (pExtent->FileOffset.LowPart & ExtentsMasks[i]))
1084 InsertHeadList(pSkipEntries[i], &pExtent->Lists[i]);
1085 #if AFS_VALIDATE_EXTENTS
1086 VerifyExtentsLists(Fcb);
1091 else if (pExtent->FileOffset.QuadPart == pFileExtents->FileOffset.QuadPart)
1094 if (pExtent->Size != pFileExtents->Length)
1097 ASSERT (pExtent->Size == pFileExtents->Length);
1099 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1103 // Move both cursors forward.
1105 // First the extent pointer
1108 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1111 // Then the skip lists cursors forward if needed
1113 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1115 if (0 == (pExtent->FileOffset.LowPart & ExtentsMasks[i]))
1118 // Check sanity before
1120 #if AFS_VALIDATE_EXTENTS
1121 VerifyExtentsLists(Fcb);
1125 // Skip list should point to us
1127 //ASSERT(pSkipEntries[i] == &pExtent->Lists[i]);
1129 // Move forward cursor
1131 pSkipEntries[i] = pSkipEntries[i]->Flink;
1133 // Check sanity before
1135 #if AFS_VALIDATE_EXTENTS
1136 VerifyExtentsLists(Fcb);
1142 // And then the cursor in the supplied array
1148 // setup pExtent if there is one
1150 if (le->Flink != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
1152 pExtent = NextExtent( pExtent, AFS_EXTENTS_LIST ) ;
1162 ASSERT( pExtent->FileOffset.QuadPart < pFileExtents->FileOffset.QuadPart );
1165 // Sanity check on spanning
1167 if ((pExtent->FileOffset.QuadPart + pExtent->Size) >
1168 pFileExtents->FileOffset.QuadPart)
1171 ASSERT( (pExtent->FileOffset.QuadPart + pExtent->Size) <=
1172 pFileExtents->FileOffset.QuadPart);
1174 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1178 // Move le and pExtent forward
1180 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1184 // Then the check the skip lists cursors
1186 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1188 if (0 == (pFileExtents->FileOffset.LowPart & ExtentsMasks[i]))
1192 // - empty list (pSkipEntries[i]->Flink == pSkipEntries[i]->Flink == fcb->lists[i]
1193 // - We are the last on the list (pSkipEntries[i]->Flink == fcb->lists[i])
1194 // - We are not the last on the list. In that case we have to be strictly less than
1196 if (pSkipEntries[i]->Flink != &Fcb->Specific.File.ExtentsLists[i]) {
1198 AFSExtent *otherExtent = ExtentFor(pSkipEntries[i]->Flink, i);
1199 ASSERT(pFileExtents->FileOffset.QuadPart < otherExtent->FileOffset.QuadPart);
1206 // setup pExtent if there is one
1209 if (le->Flink != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
1211 pExtent = NextExtent( pExtent, AFS_EXTENTS_LIST ) ;
1221 // All done, signal that we are done drop the lock, exit
1226 if( !NT_SUCCESS( ntStatus))
1230 // If we failed the service is going to drop all extents so trim away the
1234 AFSTrimSpecifiedExtents( Fcb,
1239 #if AFS_VALIDATE_EXTENTS
1240 VerifyExtentsLists(Fcb);
1243 KeSetEvent( &pNPFcb->Specific.File.ExtentsRequestComplete,
1247 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1248 AFS_TRACE_LEVEL_VERBOSE,
1249 "AFSProcessExtentsResult Releasing Fcb extent lock %08lX EXCL %08lX\n",
1250 &pNPFcb->Specific.File.ExtentsResource,
1251 PsGetCurrentThread());
1253 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
1260 AFSProcessSetFileExtents( IN AFSSetFileExtentsCB *SetExtents )
1262 AFSFcb *pFcb = NULL;
1263 AFSVolumeCB *pVolumeCB = NULL;
1264 NTSTATUS ntStatus = STATUS_SUCCESS;
1265 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1266 ULONGLONG ullIndex = 0;
1267 AFSObjectInfoCB *pObjectInfo = NULL;
1273 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1274 AFS_TRACE_LEVEL_VERBOSE,
1275 "AFSProcessSetFileExtents Acquiring RDR VolumeTreeLock lock %08lX SHARED %08lX\n",
1276 &pDevExt->Specific.RDR.VolumeTreeLock,
1277 PsGetCurrentThread());
1279 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
1281 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1282 AFS_TRACE_LEVEL_VERBOSE,
1283 "AFSProcessSetFileExtents Set extents for fid %08lX-%08lX-%08lX-%08lX\n",
1284 SetExtents->FileId.Cell,
1285 SetExtents->FileId.Volume,
1286 SetExtents->FileId.Vnode,
1287 SetExtents->FileId.Unique);
1290 // Locate the volume node
1293 ullIndex = AFSCreateHighIndex( &SetExtents->FileId);
1295 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
1297 (AFSBTreeEntry **)&pVolumeCB);
1299 if( pVolumeCB != NULL)
1302 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1303 AFS_TRACE_LEVEL_VERBOSE,
1304 "AFSProcessSetFileExtents Acquiring VolumeRoot FileIDTree.TreeLock lock %08lX SHARED %08lX\n",
1305 pVolumeCB->ObjectInfoTree.TreeLock,
1306 PsGetCurrentThread());
1308 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1311 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
1313 if( !NT_SUCCESS( ntStatus) ||
1317 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1318 AFS_TRACE_LEVEL_ERROR,
1319 "AFSProcessSetFileExtents Set extents for fid %08lX-%08lX-%08lX-%08lX Failed to locate volume Status %08lX\n",
1320 SetExtents->FileId.Cell,
1321 SetExtents->FileId.Volume,
1322 SetExtents->FileId.Vnode,
1323 SetExtents->FileId.Unique,
1326 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1329 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1332 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1335 // Now locate the Object in this volume
1338 ullIndex = AFSCreateLowIndex( &SetExtents->FileId);
1340 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
1342 (AFSBTreeEntry **)&pObjectInfo);
1344 if( pObjectInfo != NULL)
1348 // Reference the node so it won't be torn down
1351 lCount = InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
1353 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1354 AFS_TRACE_LEVEL_VERBOSE,
1355 "AFSProcessSetFileExtents Increment count on object %08lX Cnt %d\n",
1360 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1362 if( !NT_SUCCESS( ntStatus) ||
1363 pObjectInfo == NULL)
1366 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1367 AFS_TRACE_LEVEL_ERROR,
1368 "AFSProcessSetFileExtents Set extents for hash %I64X fid %08lX-%08lX-%08lX-%08lX Failed to locate file in volume %08lX\n",
1370 SetExtents->FileId.Cell,
1371 SetExtents->FileId.Volume,
1372 SetExtents->FileId.Vnode,
1373 SetExtents->FileId.Unique,
1376 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1379 pFcb = pObjectInfo->Fcb;
1382 // If we have a result failure then don't bother trying to set the extents
1385 if( SetExtents->ResultStatus != STATUS_SUCCESS)
1388 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1389 AFS_TRACE_LEVEL_ERROR,
1390 "AFSProcessSetFileExtents Set extents failure fid %08lX-%08lX-%08lX-%08lX ResultStatus %08lX\n",
1391 SetExtents->FileId.Cell,
1392 SetExtents->FileId.Volume,
1393 SetExtents->FileId.Vnode,
1394 SetExtents->FileId.Unique,
1395 SetExtents->ResultStatus);
1397 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1398 AFS_TRACE_LEVEL_VERBOSE,
1399 "AFSProcessSetFileExtents Acquiring Fcb extents lock %08lX EXCL %08lX\n",
1400 &pFcb->NPFcb->Specific.File.ExtentsResource,
1401 PsGetCurrentThread());
1403 AFSAcquireExcl( &pFcb->NPFcb->Specific.File.ExtentsResource,
1406 pFcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_CANCELLED;
1408 KeSetEvent( &pFcb->NPFcb->Specific.File.ExtentsRequestComplete,
1412 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1413 AFS_TRACE_LEVEL_VERBOSE,
1414 "AFSProcessSetFileExtents Releasing Fcb extent lock %08lX EXCL %08lX\n",
1415 &pFcb->NPFcb->Specific.File.ExtentsResource,
1416 PsGetCurrentThread());
1418 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
1420 try_return( ntStatus);
1423 ntStatus = AFSProcessExtentsResult ( pFcb,
1424 SetExtents->ExtentCount,
1425 SetExtents->FileExtents );
1429 if( pObjectInfo != NULL)
1432 lCount = InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
1434 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1435 AFS_TRACE_LEVEL_VERBOSE,
1436 "AFSProcessSetFileExtents Decrement count on object %08lX Cnt %d\n",
1446 // Helper fuctions for Usermode initiation of release of extents
1449 AFSReleaseSpecifiedExtents( IN AFSReleaseFileExtentsCB *Extents,
1451 OUT AFSFileExtentCB *FileExtents,
1452 IN ULONG BufferSize,
1453 OUT ULONG *ExtentCount,
1454 OUT BOOLEAN *DirtyExtents)
1459 ULONG ulExtentCount = 0;
1460 NTSTATUS ntStatus = STATUS_SUCCESS;
1461 BOOLEAN bReleaseAll = FALSE;
1462 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1467 ASSERT( ExIsResourceAcquiredExclusiveLite( &Fcb->NPFcb->Specific.File.ExtentsResource));
1469 if (BufferSize < (Extents->ExtentCount * sizeof( AFSFileExtentCB)))
1472 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1473 AFS_TRACE_LEVEL_VERBOSE,
1474 "AFSReleaseSpecifiedExtents Buffer too small\n");
1476 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL);
1479 RtlZeroMemory( FileExtents, BufferSize);
1482 *DirtyExtents = FALSE;
1485 // iterate until we have dealt with all we were asked for or
1486 // are at the end of the list. Note that this deals (albeit
1487 // badly) with out of order extents
1490 pExtent = AFSExtentForOffset( Fcb,
1491 &Extents->FileExtents[0].FileOffset,
1494 if (NULL == pExtent)
1496 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1500 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1504 if( BooleanFlagOn( Extents->Flags, AFS_RELEASE_EXTENTS_FLAGS_RELEASE_ALL) ||
1505 ( Extents->FileId.Cell == 0 &&
1506 Extents->FileId.Volume == 0 &&
1507 Extents->FileId.Vnode == 0 &&
1508 Extents->FileId.Unique == 0))
1514 while( le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST] &&
1515 ulExtentCount < Extents->ExtentCount)
1519 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
1524 if( pExtent->FileOffset.QuadPart < Extents->FileExtents[ulExtentCount].FileOffset.QuadPart)
1527 // Skip forward through the extent list until we get
1528 // to the one we want
1534 else if (pExtent->FileOffset.QuadPart > Extents->FileExtents[ulExtentCount].FileOffset.QuadPart)
1537 // We don't have the extent asked for so return UNKNOWN
1540 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1541 AFS_TRACE_LEVEL_VERBOSE,
1542 "AFSReleaseSpecifiedExtents Located UNKNOWN extent Offset %I64X Len %08lX\n",
1543 Extents->FileExtents[ulExtentCount].FileOffset.QuadPart,
1544 Extents->FileExtents[ulExtentCount].Length);
1546 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_UNKNOWN;
1548 FileExtents[*ExtentCount].Length = 0;
1549 FileExtents[*ExtentCount].CacheOffset.QuadPart = 0;
1550 FileExtents[*ExtentCount].FileOffset = Extents->FileExtents[ulExtentCount].FileOffset;
1552 *ExtentCount = (*ExtentCount) + 1;
1557 // Reset where we are looking
1560 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1564 else if( pExtent->ActiveCount > 0)
1567 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1568 AFS_TRACE_LEVEL_VERBOSE,
1569 "AFSReleaseSpecifiedExtents Located IN_USE extent Offset %I64X Len %08lX\n",
1570 Extents->FileExtents[ulExtentCount].FileOffset.QuadPart,
1571 Extents->FileExtents[ulExtentCount].Length);
1573 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_IN_USE;
1575 FileExtents[*ExtentCount].Length = 0;
1576 FileExtents[*ExtentCount].CacheOffset.QuadPart = 0;
1577 FileExtents[*ExtentCount].FileOffset = Extents->FileExtents[ulExtentCount].FileOffset;
1579 *ExtentCount = (*ExtentCount) + 1;
1584 // Reset where we are looking
1587 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1596 // If the extent is currently active then skip it
1599 if( pExtent->ActiveCount > 0)
1608 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_RELEASE;
1610 FileExtents[*ExtentCount].Length = pExtent->Size;
1611 FileExtents[*ExtentCount].DirtyLength = pExtent->Size;
1612 FileExtents[*ExtentCount].DirtyOffset = 0;
1613 FileExtents[*ExtentCount].CacheOffset = pExtent->CacheOffset;
1614 FileExtents[*ExtentCount].FileOffset = pExtent->FileOffset;
1616 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1617 AFS_TRACE_LEVEL_VERBOSE,
1618 "AFSReleaseSpecifiedExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
1620 Fcb->ObjectInformation->FileId.Cell,
1621 Fcb->ObjectInformation->FileId.Volume,
1622 Fcb->ObjectInformation->FileId.Vnode,
1623 Fcb->ObjectInformation->FileId.Unique,
1624 FileExtents[*ExtentCount].FileOffset.QuadPart,
1625 FileExtents[*ExtentCount].Length);
1627 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
1630 AFSAcquireExcl( &Fcb->NPFcb->Specific.File.DirtyExtentsListLock,
1633 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
1636 AFSRemoveEntryDirtyList( Fcb,
1639 FileExtents[*ExtentCount].Flags |= AFS_EXTENT_FLAG_DIRTY;
1641 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
1643 *DirtyExtents = TRUE;
1646 AFSReleaseResource( &Fcb->NPFcb->Specific.File.DirtyExtentsListLock);
1650 // move forward all three cursors
1654 *ExtentCount = (*ExtentCount) + 1;
1659 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
1661 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
1663 RemoveEntryList( &pExtent->Lists[i] );
1667 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
1669 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
1674 AFSExFreePool( pExtent);
1676 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
1678 lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount);
1683 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
1698 AFSFindFcbToClean(ULONG IgnoreTime, AFSFcb *LastFcb, BOOLEAN Block)
1701 AFSFcb *pFcb = NULL;
1702 AFSVolumeCB *pVolumeCB = NULL;
1703 AFSDeviceExt *pRDRDeviceExt = NULL;
1704 AFSDeviceExt *pControlDeviceExt = NULL;
1705 BOOLEAN bLocatedEntry = FALSE;
1706 AFSObjectInfoCB *pCurrentObject = NULL;
1707 BOOLEAN bReleaseVolumeListLock = FALSE;
1710 pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1711 pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1713 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1714 AFS_TRACE_LEVEL_VERBOSE,
1715 "AFSFindFcbToClean Acquiring RDR VolumeListLock lock %08lX SHARED %08lX\n",
1716 &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1717 PsGetCurrentThread());
1719 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1722 bReleaseVolumeListLock = TRUE;
1724 pVolumeCB = pRDRDeviceExt->Specific.RDR.VolumeListHead;
1726 while( pVolumeCB != NULL)
1730 // The Volume list may move under our feet. Lock it.
1733 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1734 AFS_TRACE_LEVEL_VERBOSE,
1735 "AFSFindFcbToClean Acquiring VolumeRoot ObjectInfoTree lock %08lX SHARED %08lX\n",
1736 pVolumeCB->ObjectInfoTree.TreeLock,
1737 PsGetCurrentThread());
1739 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1741 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1743 bReleaseVolumeListLock = FALSE;
1745 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1748 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1750 if( NULL == LastFcb)
1753 pCurrentObject = pVolumeCB->ObjectInfoListHead;
1758 pCurrentObject = (AFSObjectInfoCB *)LastFcb->ObjectInformation->ListEntry.fLink;
1763 while( pCurrentObject != NULL)
1766 pFcb = (AFSFcb *)pCurrentObject->Fcb;
1769 // If the FCB is a candidate we try to lock it (but without waiting - which
1770 // means we are deadlock free
1774 pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
1780 AFSLockForExtentsTrim( pFcb);
1785 if( !AFSLockForExtentsTrimNoWait( pFcb))
1788 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1797 // Need to be sure there are no current flushes in the queue
1800 if( pFcb->Specific.File.ExtentCount == 0)
1803 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1804 AFS_TRACE_LEVEL_VERBOSE,
1805 "AFSFindFcbToClean Releasing Fcb extent lock %08lX thread %08lX\n",
1806 &pFcb->NPFcb->Specific.File.ExtentsResource,
1807 PsGetCurrentThread());
1809 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
1811 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1818 if( pFcb->Specific.File.QueuedFlushCount > 0)
1821 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1822 AFS_TRACE_LEVEL_VERBOSE,
1823 "AFSFindFcbToClean Releasing Fcb extent lock %08lX thread %08lX\n",
1824 &pFcb->NPFcb->Specific.File.ExtentsResource,
1825 PsGetCurrentThread());
1827 AFSReleaseResource(&pFcb->NPFcb->Specific.File.ExtentsResource);
1831 AFSWaitOnQueuedFlushes( pFcb);
1836 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1844 if( pFcb->OpenHandleCount > 0)
1847 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1848 AFS_TRACE_LEVEL_VERBOSE,
1849 "AFSFindFcbToClean Releasing Fcb extent lock %08lX thread %08lX\n",
1850 &pFcb->NPFcb->Specific.File.ExtentsResource,
1851 PsGetCurrentThread());
1853 AFSReleaseResource(&pFcb->NPFcb->Specific.File.ExtentsResource);
1855 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1863 // A hit a very palpable hit. Pin it
1866 lCount = InterlockedIncrement( &pCurrentObject->ObjectReferenceCount);
1868 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1869 AFS_TRACE_LEVEL_VERBOSE,
1870 "AFSFindFcbToClean Increment count on Fcb %08lX Cnt %d\n",
1874 bLocatedEntry = TRUE;
1879 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1884 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1891 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1894 bReleaseVolumeListLock = TRUE;
1896 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1899 if( bReleaseVolumeListLock)
1902 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1909 AFSProcessExtentFailure( PIRP Irp)
1911 AFSExtentFailureCB *pFailureCB = NULL;
1912 NTSTATUS ntStatus = STATUS_SUCCESS;
1913 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
1914 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1915 AFSVolumeCB *pVolumeCB = NULL;
1916 ULONGLONG ullIndex = 0;
1917 AFSObjectInfoCB *pObjectInfo = NULL;
1922 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSExtentFailureCB))
1925 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1926 AFS_TRACE_LEVEL_ERROR,
1927 "AFSProcessExtentFailure Input buffer too small\n");
1929 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1932 pFailureCB = (AFSExtentFailureCB *)Irp->AssociatedIrp.SystemBuffer;
1934 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1935 AFS_TRACE_LEVEL_ERROR,
1936 "AFSProcessExtentFailure Service Reports Failure fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1937 pFailureCB->FileId.Cell,
1938 pFailureCB->FileId.Volume,
1939 pFailureCB->FileId.Vnode,
1940 pFailureCB->FileId.Unique,
1941 pFailureCB->FailureStatus);
1943 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
1946 // Locate the volume node
1949 ullIndex = AFSCreateHighIndex( &pFailureCB->FileId);
1951 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
1953 (AFSBTreeEntry **)&pVolumeCB);
1955 if( pVolumeCB != NULL)
1958 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1959 AFS_TRACE_LEVEL_VERBOSE,
1960 "AFSProcessExtentFailure Acquiring VolumeRoot FileIDTree.TreeLock lock %08lX SHARED %08lX\n",
1961 pVolumeCB->ObjectInfoTree.TreeLock,
1962 PsGetCurrentThread());
1964 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1967 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
1969 if( !NT_SUCCESS( ntStatus) ||
1973 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1974 AFS_TRACE_LEVEL_ERROR,
1975 "AFSProcessExtentFailure Invalid volume index %I64X status %08X\n",
1976 ullIndex, ntStatus);
1978 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1981 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1984 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1987 // Now locate the Object in this volume
1990 ullIndex = AFSCreateLowIndex( &pFailureCB->FileId);
1992 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
1994 (AFSBTreeEntry **)&pObjectInfo);
1996 if( pObjectInfo != NULL &&
1997 pObjectInfo->Fcb != NULL)
2001 // Reference the node so it won't be torn down
2004 lCount = InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
2006 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2007 AFS_TRACE_LEVEL_VERBOSE,
2008 "AFSProcessExtentFailure Increment count on object %08lX Cnt %d\n",
2013 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2015 if( !NT_SUCCESS( ntStatus) ||
2016 pObjectInfo == NULL ||
2017 pObjectInfo->Fcb == NULL)
2020 if( pObjectInfo == NULL)
2022 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2023 AFS_TRACE_LEVEL_ERROR,
2024 "AFSProcessExtentFailure Invalid file index %I64X\n",
2029 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2030 AFS_TRACE_LEVEL_ERROR,
2031 "AFSProcessExtentFailure Fcb dealocated for %I64X\n",
2035 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2038 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2039 AFS_TRACE_LEVEL_VERBOSE,
2040 "AFSProcessExtentFailure Acquiring Fcb extent lock %08lX EXCL %08lX\n",
2041 &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2042 PsGetCurrentThread());
2044 AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2047 pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestStatus = pFailureCB->FailureStatus;
2049 RtlCopyMemory( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2050 &pFailureCB->AuthGroup,
2053 KeSetEvent( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
2057 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2058 AFS_TRACE_LEVEL_VERBOSE,
2059 "AFSProcessExtentFailure Releasing Fcb extent lock %08lX EXCL %08lX\n",
2060 &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2061 PsGetCurrentThread());
2063 AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource);
2065 lCount = InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
2067 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2068 AFS_TRACE_LEVEL_VERBOSE,
2069 "AFSProcessExtentFailure Decrement count on object %08lX Cnt %d\n",
2082 AFSProcessReleaseFileExtents( IN PIRP Irp)
2084 NTSTATUS ntStatus = STATUS_SUCCESS;
2085 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2086 PFILE_OBJECT pFileObject = pIrpSp->FileObject;
2087 AFSFcb *pFcb = NULL;
2088 AFSVolumeCB *pVolumeCB = NULL;
2089 AFSDeviceExt *pDevExt;
2090 AFSReleaseFileExtentsCB *pExtents;
2091 AFSReleaseFileExtentsResultCB *pResult = NULL;
2092 AFSReleaseFileExtentsResultFileCB *pFile = NULL;
2094 ULONGLONG ullIndex = 0;
2095 AFSObjectInfoCB *pObjectInfo = NULL;
2096 BOOLEAN bLocked = FALSE;
2097 BOOLEAN bDirtyExtents = FALSE;
2104 pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2106 pExtents = (AFSReleaseFileExtentsCB*) Irp->AssociatedIrp.SystemBuffer;
2108 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2109 sizeof( AFSReleaseFileExtentsCB))
2112 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2113 AFS_TRACE_LEVEL_ERROR,
2114 "AFSProcessReleaseFileExtents INPUT Buffer too small\n");
2116 try_return( ntStatus = STATUS_INVALID_PARAMETER );
2119 if ( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength <
2120 sizeof(AFSReleaseFileExtentsResultCB))
2123 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2124 AFS_TRACE_LEVEL_ERROR,
2125 "AFSProcessReleaseFileExtents OUTPUT Buffer too small [1]\n");
2128 // Must have space for one extent in one file
2131 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL);
2134 if (pExtents->ExtentCount == 0)
2137 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2138 AFS_TRACE_LEVEL_ERROR,
2139 "AFSProcessReleaseFileExtents Extent count zero\n");
2141 try_return( ntStatus = STATUS_INVALID_PARAMETER);
2144 if (pExtents->FileId.Cell != 0 ||
2145 pExtents->FileId.Volume != 0 ||
2146 pExtents->FileId.Vnode != 0 ||
2147 pExtents->FileId.Unique != 0)
2150 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2151 AFS_TRACE_LEVEL_VERBOSE,
2152 "AFSProcessReleaseFileExtents Processing FID %08lX:%08lX:%08lX:%08lX\n",
2153 pExtents->FileId.Cell,
2154 pExtents->FileId.Volume,
2155 pExtents->FileId.Vnode,
2156 pExtents->FileId.Unique);
2158 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2159 ( FIELD_OFFSET( AFSReleaseFileExtentsCB, ExtentCount) + sizeof(ULONG)) ||
2160 pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2161 ( FIELD_OFFSET( AFSReleaseFileExtentsCB, ExtentCount) + sizeof(ULONG) +
2162 sizeof (AFSFileExtentCB) * pExtents->ExtentCount))
2165 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2166 AFS_TRACE_LEVEL_ERROR,
2167 "AFSProcessReleaseFileExtents Buffer too small for FID %08lX:%08lx:%08lX:%08lX\n",
2168 pExtents->FileId.Cell,
2169 pExtents->FileId.Volume,
2170 pExtents->FileId.Vnode,
2171 pExtents->FileId.Unique);
2173 try_return( ntStatus = STATUS_INVALID_PARAMETER );
2176 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2177 AFS_TRACE_LEVEL_VERBOSE,
2178 "AFSProcessReleaseFileExtents Acquiring RDR VolumeTreeLock lock %08lX SHARED %08lX\n",
2179 &pDevExt->Specific.RDR.VolumeTreeLock,
2180 PsGetCurrentThread());
2182 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
2185 // Locate the volume node
2188 ullIndex = AFSCreateHighIndex( &pExtents->FileId);
2190 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
2192 (AFSBTreeEntry **)&pVolumeCB);
2194 if( pVolumeCB != NULL)
2197 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2198 AFS_TRACE_LEVEL_VERBOSE,
2199 "AFSProcessReleaseFileExtents Acquiring VolumeRoot FileIDTree.TreeLock lock %08lX SHARED %08lX\n",
2200 pVolumeCB->ObjectInfoTree.TreeLock,
2201 PsGetCurrentThread());
2203 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
2206 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
2208 if( !NT_SUCCESS( ntStatus) ||
2212 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2213 AFS_TRACE_LEVEL_ERROR,
2214 "AFSProcessReleaseFileExtents Invalid volume index %I64X status %08X\n",
2215 ullIndex, ntStatus);
2217 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2220 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
2223 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
2226 // Now locate the Object in this volume
2229 ullIndex = AFSCreateLowIndex( &pExtents->FileId);
2231 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
2233 (AFSBTreeEntry **)&pObjectInfo);
2235 if( pObjectInfo != NULL)
2239 // Reference the node so it won't be torn down
2242 lCount = InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
2244 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2245 AFS_TRACE_LEVEL_VERBOSE,
2246 "AFSProcessReleaseFileExtents Increment count on object %08lX Cnt %d\n",
2251 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2253 if( !NT_SUCCESS( ntStatus) ||
2254 pObjectInfo == NULL)
2257 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2258 AFS_TRACE_LEVEL_ERROR,
2259 "AFSProcessReleaseFileExtents Invalid file index %I64X\n",
2262 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2265 pFcb = pObjectInfo->Fcb;
2270 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2271 AFS_TRACE_LEVEL_ERROR,
2272 "AFSProcessReleaseFileExtents Fcb not initialied (NO EXTENTS) for FID %08lX:%08lx:%08lX:%08lX\n",
2273 pExtents->FileId.Cell,
2274 pExtents->FileId.Volume,
2275 pExtents->FileId.Vnode,
2276 pExtents->FileId.Unique);
2278 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2281 AFSLockForExtentsTrim( pFcb );
2289 // Locate an Fcb to trim down
2292 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2293 AFS_TRACE_LEVEL_VERBOSE,
2294 "AFSProcessReleaseFileExtents Searching for a Fcb to Trim Down\n");
2296 pFcb = AFSFindFcbToClean( 0, NULL, FALSE);
2301 pFcb = AFSFindFcbToClean( 0, NULL, TRUE);
2307 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2308 AFS_TRACE_LEVEL_ERROR,
2309 "AFSProcessReleaseFileExtents Failed to locate Fcb for release ...\n");
2311 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2314 pObjectInfo = pFcb->ObjectInformation;
2320 // Allocate a scratch buffer to move in the extent information
2323 ulSz = (pExtents->ExtentCount-1) * sizeof(AFSFileExtentCB);
2324 ulSz += sizeof(AFSReleaseFileExtentsResultCB);
2326 if (ulSz > pIrpSp->Parameters.DeviceIoControl.OutputBufferLength)
2328 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2329 AFS_TRACE_LEVEL_ERROR,
2330 "AFSProcessReleaseFileExtents OUTPUT Buffer too small [2]\n");
2332 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL );
2335 pResult = (AFSReleaseFileExtentsResultCB*) AFSExAllocatePoolWithTag( PagedPool,
2337 AFS_EXTENTS_RESULT_TAG);
2338 if (NULL == pResult)
2341 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2342 AFS_TRACE_LEVEL_ERROR,
2343 "AFSProcessReleaseFileExtents Failed to allocate result block\n");
2345 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2349 // Set up the header (for an array of one)
2351 pResult->FileCount = 1;
2352 pResult->Flags = AFS_EXTENT_FLAG_RELEASE;
2353 ulSz -= FIELD_OFFSET(AFSReleaseFileExtentsResultCB, Files);
2356 // Setup the first (and only) file
2358 pFile = pResult->Files;
2359 pFile->FileId = pObjectInfo->FileId;
2360 pFile->Flags = AFS_EXTENT_FLAG_RELEASE;
2363 // Stash away the auth group
2366 RtlZeroMemory( &stAuthGroup,
2369 ntStatus = AFSRetrieveValidAuthGroup( pFcb,
2374 if( !NT_SUCCESS( ntStatus))
2376 try_return( ntStatus);
2379 RtlCopyMemory( &pFile->AuthGroup,
2384 // Update the metadata for this call
2387 pFile->AllocationSize = pFcb->ObjectInformation->EndOfFile;
2388 pFile->CreateTime = pFcb->ObjectInformation->CreationTime;
2389 pFile->ChangeTime = pFcb->ObjectInformation->ChangeTime;
2390 pFile->LastAccessTime = pFcb->ObjectInformation->LastAccessTime;
2391 pFile->LastWriteTime = pFcb->ObjectInformation->LastWriteTime;
2393 ulSz -= FIELD_OFFSET(AFSReleaseFileExtentsResultFileCB, FileExtents);
2395 ntStatus = AFSReleaseSpecifiedExtents( pExtents,
2399 &pFile->ExtentCount,
2402 if (!NT_SUCCESS(ntStatus))
2405 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2406 AFS_TRACE_LEVEL_ERROR,
2407 "AFSProcessReleaseFileExtents Failed to release extents Status %08lX\n",
2410 try_return( ntStatus );
2413 if( pExtents->ExtentCount == 0)
2416 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2417 AFS_TRACE_LEVEL_WARNING,
2418 "AFSProcessReleaseFileExtents Failed to release ANY extents\n");
2421 ulSz = sizeof(AFSReleaseFileExtentsResultCB);
2423 if( pExtents->ExtentCount > 0)
2425 ulSz += ((pExtents->ExtentCount-1) * sizeof(AFSFileExtentCB));
2428 RtlCopyMemory( Irp->AssociatedIrp.SystemBuffer,
2437 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2438 AFS_TRACE_LEVEL_VERBOSE,
2439 "AFSProcessReleaseFileExtents Releasing Fcb extent lock %08lX thread %08lX\n",
2440 &pFcb->NPFcb->Specific.File.ExtentsResource,
2441 PsGetCurrentThread());
2443 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
2446 if( NULL != pResult &&
2447 Irp->AssociatedIrp.SystemBuffer != pResult)
2450 AFSExFreePool(pResult);
2453 if (NT_SUCCESS(ntStatus))
2455 Irp->IoStatus.Information = ulSz;
2459 Irp->IoStatus.Information = 0;
2462 Irp->IoStatus.Status = ntStatus;
2464 if( pObjectInfo != NULL)
2467 lCount = InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
2469 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2470 AFS_TRACE_LEVEL_VERBOSE,
2471 "AFSProcessReleaseFileExtents Decrement count on object %08lX Cnt %d\n",
2481 AFSWaitForExtentMapping( AFSFcb *Fcb,
2484 NTSTATUS ntStatus = STATUS_SUCCESS;
2485 LARGE_INTEGER liTimeOut;
2486 ULONGLONG ullProcessId = (ULONGLONG)PsGetCurrentProcessId();
2491 ASSERT( !ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
2493 if (!NT_SUCCESS( Fcb->NPFcb->Specific.File.ExtentsRequestStatus))
2497 // If this isn't the same authgroup which caused the failure
2498 // then try to request them again
2501 if( RtlCompareMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2503 sizeof( GUID)) == sizeof( GUID))
2506 ntStatus = Fcb->NPFcb->Specific.File.ExtentsRequestStatus;
2508 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
2510 RtlZeroMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2513 try_return( ntStatus);
2517 liTimeOut.QuadPart = -(1 * AFS_ONE_SECOND);
2519 ntStatus = KeWaitForSingleObject( &Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
2525 if (!NT_SUCCESS( Fcb->NPFcb->Specific.File.ExtentsRequestStatus))
2529 // If this isn't the same authgroup which caused the failure
2530 // or the System Process,
2531 // then try to request the extents again
2534 if( RtlCompareMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2536 sizeof( GUID)) == sizeof( GUID) ||
2537 ullProcessId == (ULONGLONG)AFSSysProcess)
2540 ntStatus = Fcb->NPFcb->Specific.File.ExtentsRequestStatus;
2542 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
2544 RtlZeroMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2547 try_return( ntStatus);
2551 if( ntStatus == STATUS_TIMEOUT)
2554 ntStatus = STATUS_SUCCESS;
2566 AFSFlushExtents( IN AFSFcb *Fcb,
2569 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
2570 AFSExtent *pExtent, *pNextExtent;
2572 AFSReleaseExtentsCB *pRelease = NULL;
2574 ULONG initialDirtyCount = 0;
2575 BOOLEAN bExtentsLocked = FALSE;
2578 NTSTATUS ntStatus = STATUS_SUCCESS;
2579 LARGE_INTEGER liLastFlush;
2580 AFSExtent *pDirtyListHead = NULL, *pDirtyListTail = NULL;
2581 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2582 GUID *pAuthGroup = AuthGroup;
2586 ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
2589 // Save, then reset the flush time
2592 liLastFlush = Fcb->Specific.File.LastServerFlush;
2594 KeQueryTickCount( &Fcb->Specific.File.LastServerFlush);
2599 if( pAuthGroup == NULL ||
2600 RtlCompareMemory( pAuthGroup,
2601 &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2602 sizeof( GUID)) == sizeof( GUID))
2605 RtlZeroMemory( &stAuthGroup,
2608 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
2613 if( !NT_SUCCESS( ntStatus))
2615 try_return( ntStatus);
2618 pAuthGroup = &stAuthGroup;
2622 // Lock extents while we count and set up the array to send to
2626 AFSLockForExtentsTrim( Fcb);
2628 bExtentsLocked = TRUE;
2630 lCount = InterlockedIncrement( &Fcb->Specific.File.QueuedFlushCount);
2633 // Clear our queued flush event
2636 KeClearEvent( &Fcb->NPFcb->Specific.File.QueuedFlushEvent);
2639 // Look for a start in the list to flush entries
2644 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
2646 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
2648 AFS_EXTENT_RELEASE_TAG);
2649 if( NULL == pRelease)
2652 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2655 initialDirtyCount = Fcb->Specific.File.ExtentsDirtyCount;
2657 while( Fcb->Specific.File.ExtentsDirtyCount > 0)
2660 pRelease->Flags = AFS_EXTENT_FLAG_DIRTY;
2662 if( BooleanFlagOn( Fcb->Flags, AFS_FCB_FILE_CLOSED))
2665 pRelease->Flags |= AFS_EXTENT_FLAG_FLUSH;
2669 // Update the metadata for this call
2672 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
2673 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
2674 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
2675 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
2676 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
2680 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
2683 pExtent = (AFSExtent *)pNPFcb->Specific.File.DirtyListHead;
2685 while( count < AFS_MAXIMUM_EXTENT_RELEASE_COUNT)
2688 if ( pExtent == NULL)
2694 pNextExtent = (AFSExtent *)pExtent->DirtyList.fLink;
2696 if ( pExtent->ActiveCount > 0)
2698 pExtent = pNextExtent;
2702 AFSRemoveEntryDirtyList( Fcb, pExtent);
2704 pExtent->DirtyList.fLink = NULL;
2705 pExtent->DirtyList.bLink = NULL;
2707 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
2710 // Clear the flag in advance of the write. If we do
2711 // things this was we know that the clear is
2712 // pessimistic (any write which happens from now on
2713 // will set the flag dirty again).
2716 pExtent->Flags &= ~AFS_EXTENT_DIRTY;
2718 pRelease->FileExtents[count].Flags = AFS_EXTENT_FLAG_DIRTY;
2720 pRelease->FileExtents[count].Length = pExtent->Size;
2721 pRelease->FileExtents[count].DirtyLength = pExtent->Size;
2722 pRelease->FileExtents[count].DirtyOffset = 0;
2723 pRelease->FileExtents[count].CacheOffset = pExtent->CacheOffset;
2724 pRelease->FileExtents[count].FileOffset = pExtent->FileOffset;
2727 RtlCopyMemory( pRelease->FileExtents[count].MD5,
2729 sizeof(pExtent->MD5));
2731 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_MD5_SET;
2734 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2735 AFS_TRACE_LEVEL_VERBOSE,
2736 "AFSFlushExtents Releasing DIRTY extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
2738 Fcb->ObjectInformation->FileId.Cell,
2739 Fcb->ObjectInformation->FileId.Volume,
2740 Fcb->ObjectInformation->FileId.Vnode,
2741 Fcb->ObjectInformation->FileId.Unique,
2742 pExtent->FileOffset.QuadPart,
2745 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_RELEASE;
2748 // Need to pull this extent from the main list as well
2751 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
2753 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
2755 RemoveEntryList( &pExtent->Lists[i] );
2759 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
2761 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
2763 AFSExFreePool( pExtent);
2765 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
2767 lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount);
2772 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
2779 pExtent = pNextExtent;
2782 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
2785 // If we are done then get out
2791 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2792 AFS_TRACE_LEVEL_VERBOSE,
2793 "AFSFlushExtents No more dirty extents found\n");
2799 // Fire off the request synchronously
2802 sz = sizeof( AFSReleaseExtentsCB ) + (count * sizeof ( AFSFileExtentCB ));
2804 pRelease->ExtentCount = count;
2806 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2807 AFS_TRACE_LEVEL_VERBOSE,
2808 "AFSFlushExtents Releasing(1) Fcb extents lock %08lX SHARED %08lX\n",
2809 &pNPFcb->Specific.File.ExtentsResource,
2810 PsGetCurrentThread());
2812 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource);
2813 bExtentsLocked = FALSE;
2815 KeSetEvent( &pNPFcb->Specific.File.FlushEvent,
2819 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
2820 AFS_REQUEST_FLAG_SYNCHRONOUS,
2823 &Fcb->ObjectInformation->FileId,
2829 if( !NT_SUCCESS(ntStatus))
2833 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
2834 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
2837 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2838 AFS_TRACE_LEVEL_ERROR,
2839 "AFSFlushExtents AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2840 Fcb->ObjectInformation->FileId.Cell,
2841 Fcb->ObjectInformation->FileId.Volume,
2842 Fcb->ObjectInformation->FileId.Vnode,
2843 Fcb->ObjectInformation->FileId.Unique,
2847 AFSLockForExtentsTrim( Fcb);
2849 bExtentsLocked = TRUE;
2854 lCount = InterlockedDecrement( &Fcb->Specific.File.QueuedFlushCount);
2859 KeSetEvent( &pNPFcb->Specific.File.QueuedFlushEvent,
2864 KeSetEvent( &pNPFcb->Specific.File.FlushEvent,
2871 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2872 AFS_TRACE_LEVEL_VERBOSE,
2873 "AFSFlushExtents Releasing(2) Fcb extents lock %08lX SHARED %08lX\n",
2874 &pNPFcb->Specific.File.ExtentsResource,
2875 PsGetCurrentThread());
2877 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
2882 AFSExFreePool( pRelease);
2890 AFSReleaseExtentsWithFlush( IN AFSFcb *Fcb,
2893 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
2896 AFSReleaseExtentsCB *pRelease = NULL;
2898 ULONG initialDirtyCount = 0;
2899 BOOLEAN bExtentsLocked = FALSE;
2902 NTSTATUS ntStatus = STATUS_SUCCESS;
2903 LARGE_INTEGER liLastFlush;
2904 ULONG ulRemainingExtentLength = 0;
2905 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2906 GUID *pAuthGroup = AuthGroup;
2910 ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
2913 // Save, then reset the flush time
2916 liLastFlush = Fcb->Specific.File.LastServerFlush;
2918 KeQueryTickCount( &Fcb->Specific.File.LastServerFlush);
2923 if( pAuthGroup == NULL ||
2924 RtlCompareMemory( pAuthGroup,
2925 &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2926 sizeof( GUID)) == sizeof( GUID))
2929 RtlZeroMemory( &stAuthGroup,
2932 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
2937 if( !NT_SUCCESS( ntStatus))
2939 try_return( ntStatus);
2942 pAuthGroup = &stAuthGroup;
2946 // Look for a start in the list to flush entries
2951 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
2953 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
2955 AFS_EXTENT_RELEASE_TAG);
2956 if( NULL == pRelease)
2959 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2962 if( Fcb->OpenHandleCount > 0)
2966 // Don't release everything ...
2970 // For now release everything
2973 //ulRemainingExtentLength = 1500;
2976 while( Fcb->Specific.File.ExtentLength > (LONG)ulRemainingExtentLength)
2979 AFSLockForExtentsTrim( Fcb);
2981 bExtentsLocked = TRUE;
2983 pRelease->Flags = AFS_EXTENT_FLAG_RELEASE;
2986 // Update the metadata for this call
2989 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
2990 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
2991 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
2992 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
2993 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
2997 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
2999 while( count < AFS_MAXIMUM_EXTENT_RELEASE_COUNT &&
3000 le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
3003 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3007 if( pExtent->ActiveCount > 0)
3013 pRelease->FileExtents[count].Flags = AFS_EXTENT_FLAG_RELEASE;
3015 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3016 AFS_TRACE_LEVEL_VERBOSE,
3017 "AFSReleaseExtentsWithFlush Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3019 Fcb->ObjectInformation->FileId.Cell,
3020 Fcb->ObjectInformation->FileId.Volume,
3021 Fcb->ObjectInformation->FileId.Vnode,
3022 Fcb->ObjectInformation->FileId.Unique,
3023 pExtent->FileOffset.QuadPart,
3026 pRelease->FileExtents[count].Length = pExtent->Size;
3027 pRelease->FileExtents[count].DirtyLength = pExtent->Size;
3028 pRelease->FileExtents[count].DirtyOffset = 0;
3029 pRelease->FileExtents[count].CacheOffset = pExtent->CacheOffset;
3030 pRelease->FileExtents[count].FileOffset = pExtent->FileOffset;
3033 RtlCopyMemory( pRelease->FileExtents[count].MD5,
3035 sizeof(pExtent->MD5));
3037 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_MD5_SET;
3040 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3043 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3046 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3049 AFSRemoveEntryDirtyList( Fcb,
3052 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_DIRTY;
3054 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
3057 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3061 // Need to pull this extent from the main list as well
3064 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
3066 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
3068 RemoveEntryList( &pExtent->Lists[i] );
3072 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
3074 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
3076 AFSExFreePool( pExtent);
3078 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
3080 lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount);
3085 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
3094 // If we are done then get out
3100 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3101 AFS_TRACE_LEVEL_VERBOSE,
3102 "AFSReleaseExtentsWithFlush No more dirty extents found\n");
3108 // Fire off the request synchronously
3111 sz = sizeof( AFSReleaseExtentsCB ) + (count * sizeof ( AFSFileExtentCB ));
3113 pRelease->ExtentCount = count;
3116 // Drop the extents lock for the duration of the call to
3117 // the network. We have pinned the extents so, even
3118 // though we might get extents added during this period,
3119 // but none will be removed. Hence we can carry on from
3123 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3124 AFS_TRACE_LEVEL_VERBOSE,
3125 "AFSReleaseExtentsWithFlush Releasing Fcb extents lock %08lX thread %08lX\n",
3126 &pNPFcb->Specific.File.ExtentsResource,
3127 PsGetCurrentThread());
3129 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource);
3130 bExtentsLocked = FALSE;
3132 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
3133 AFS_REQUEST_FLAG_SYNCHRONOUS,
3136 &Fcb->ObjectInformation->FileId,
3142 if( !NT_SUCCESS(ntStatus))
3146 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
3147 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
3150 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3151 AFS_TRACE_LEVEL_ERROR,
3152 "AFSReleaseExtentsWithFlush AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3153 Fcb->ObjectInformation->FileId.Cell,
3154 Fcb->ObjectInformation->FileId.Volume,
3155 Fcb->ObjectInformation->FileId.Vnode,
3156 Fcb->ObjectInformation->FileId.Unique,
3166 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3167 AFS_TRACE_LEVEL_VERBOSE,
3168 "AFSReleaseExtentsWithFlush Releasing Fcb extents lock %08lX thread %08lX\n",
3169 &pNPFcb->Specific.File.ExtentsResource,
3170 PsGetCurrentThread());
3172 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
3177 AFSExFreePool( pRelease);
3185 AFSReleaseCleanExtents( IN AFSFcb *Fcb,
3188 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3191 AFSReleaseExtentsCB *pRelease = NULL;
3193 ULONG initialDirtyCount = 0;
3194 BOOLEAN bExtentsLocked = FALSE;
3197 NTSTATUS ntStatus = STATUS_SUCCESS;
3198 LARGE_INTEGER liLastFlush;
3199 ULONG ulRemainingExtentLength = 0;
3200 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3201 GUID *pAuthGroup = AuthGroup;
3204 ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
3207 // Save, then reset the flush time
3210 liLastFlush = Fcb->Specific.File.LastServerFlush;
3212 KeQueryTickCount( &Fcb->Specific.File.LastServerFlush);
3217 if( pAuthGroup == NULL ||
3218 RtlCompareMemory( pAuthGroup,
3219 &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
3220 sizeof( GUID)) == sizeof( GUID))
3223 RtlZeroMemory( &stAuthGroup,
3226 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
3231 if( !NT_SUCCESS( ntStatus))
3233 try_return( ntStatus);
3236 pAuthGroup = &stAuthGroup;
3240 // Look for a start in the list to flush entries
3245 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
3247 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
3249 AFS_EXTENT_RELEASE_TAG);
3250 if( NULL == pRelease)
3253 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
3256 while( Fcb->Specific.File.ExtentLength > (LONG)ulRemainingExtentLength)
3259 AFSLockForExtentsTrim( Fcb);
3261 bExtentsLocked = TRUE;
3263 pRelease->Flags = AFS_EXTENT_FLAG_RELEASE;
3266 // Update the metadata for this call
3269 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
3270 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
3271 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
3272 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
3273 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
3277 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3279 while( count < AFS_MAXIMUM_EXTENT_RELEASE_COUNT &&
3280 le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
3283 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3287 if( pExtent->ActiveCount > 0 ||
3288 BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3293 pRelease->FileExtents[count].Flags = AFS_EXTENT_FLAG_RELEASE;
3295 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3296 AFS_TRACE_LEVEL_VERBOSE,
3297 "AFSReleaseCleanExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3299 Fcb->ObjectInformation->FileId.Cell,
3300 Fcb->ObjectInformation->FileId.Volume,
3301 Fcb->ObjectInformation->FileId.Vnode,
3302 Fcb->ObjectInformation->FileId.Unique,
3303 pExtent->FileOffset.QuadPart,
3306 pRelease->FileExtents[count].Length = pExtent->Size;
3307 pRelease->FileExtents[count].DirtyLength = pExtent->Size;
3308 pRelease->FileExtents[count].DirtyOffset = 0;
3309 pRelease->FileExtents[count].CacheOffset = pExtent->CacheOffset;
3310 pRelease->FileExtents[count].FileOffset = pExtent->FileOffset;
3313 RtlCopyMemory( pRelease->FileExtents[count].MD5,
3315 sizeof(pExtent->MD5));
3317 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_MD5_SET;
3321 // Need to pull this extent from the main list as well
3324 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
3326 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
3328 RemoveEntryList( &pExtent->Lists[i] );
3332 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
3334 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
3336 AFSExFreePool( pExtent);
3338 InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
3340 if( InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount) == 0)
3343 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
3352 // If we are done then get out
3358 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3359 AFS_TRACE_LEVEL_VERBOSE,
3360 "AFSReleaseCleanExtents No more dirty extents found\n");
3366 // Fire off the request synchronously
3369 sz = sizeof( AFSReleaseExtentsCB ) + (count * sizeof ( AFSFileExtentCB ));
3371 pRelease->ExtentCount = count;
3374 // Drop the extents lock for the duration of the call to
3375 // the network. We have pinned the extents so, even
3376 // though we might get extents added during this period,
3377 // but none will be removed. Hence we can carry on from
3381 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3382 AFS_TRACE_LEVEL_VERBOSE,
3383 "AFSReleaseCleanExtents Releasing Fcb extents lock %08lX thread %08lX\n",
3384 &pNPFcb->Specific.File.ExtentsResource,
3385 PsGetCurrentThread());
3387 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource);
3388 bExtentsLocked = FALSE;
3390 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
3391 AFS_REQUEST_FLAG_SYNCHRONOUS,
3394 &Fcb->ObjectInformation->FileId,
3400 if( !NT_SUCCESS(ntStatus))
3404 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
3405 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
3408 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3409 AFS_TRACE_LEVEL_ERROR,
3410 "AFSReleaseCleanExtents AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3411 Fcb->ObjectInformation->FileId.Cell,
3412 Fcb->ObjectInformation->FileId.Volume,
3413 Fcb->ObjectInformation->FileId.Vnode,
3414 Fcb->ObjectInformation->FileId.Unique,
3424 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3425 AFS_TRACE_LEVEL_VERBOSE,
3426 "AFSReleaseCleanExtents Releasing Fcb extents lock %08lX thread %08lX\n",
3427 &pNPFcb->Specific.File.ExtentsResource,
3428 PsGetCurrentThread());
3430 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
3435 AFSExFreePool( pRelease);
3443 AFSMarkDirty( IN AFSFcb *Fcb,
3444 IN AFSExtent *StartExtent,
3445 IN ULONG ExtentsCount,
3446 IN LARGE_INTEGER *StartingByte,
3447 IN BOOLEAN DerefExtents)
3450 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3451 AFSExtent *pExtent = StartExtent;
3452 AFSExtent *pNextExtent, *pCurrentExtent = NULL;
3454 BOOLEAN bInsertTail = FALSE, bInsertHead = FALSE;
3456 BOOLEAN bLocked = FALSE;
3458 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3459 AFS_TRACE_LEVEL_VERBOSE,
3460 "AFSMarkDirty Acquiring Fcb extents lock %08lX SHARED %08lX\n",
3461 &Fcb->NPFcb->Specific.File.ExtentsResource,
3462 PsGetCurrentThread());
3464 if( !ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource))
3466 AFSAcquireShared( &Fcb->NPFcb->Specific.File.ExtentsResource, TRUE);
3470 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3476 // Find the insertion point
3479 if( pNPFcb->Specific.File.DirtyListHead == NULL)
3484 else if( StartingByte->QuadPart == 0)
3492 pCurrentExtent = pNPFcb->Specific.File.DirtyListHead;
3494 while( pCurrentExtent != NULL)
3497 if( pCurrentExtent->FileOffset.QuadPart + pCurrentExtent->Size >= StartingByte->QuadPart ||
3498 pCurrentExtent->DirtyList.fLink == NULL)
3504 pCurrentExtent = (AFSExtent *)pCurrentExtent->DirtyList.fLink;
3508 while( ulCount < ExtentsCount)
3511 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
3513 if( !BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3516 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3517 AFS_TRACE_LEVEL_VERBOSE,
3518 "AFSMarkDirty Marking extent offset %I64X Length %08lX DIRTY\n",
3519 pExtent->FileOffset.QuadPart,
3522 pExtent->DirtyList.fLink = NULL;
3523 pExtent->DirtyList.bLink = NULL;
3528 pExtent->DirtyList.fLink = (void *)pNPFcb->Specific.File.DirtyListHead;
3530 pExtent->DirtyList.bLink = NULL;
3532 pNPFcb->Specific.File.DirtyListHead->DirtyList.bLink = (void *)pExtent;
3534 pNPFcb->Specific.File.DirtyListHead = pExtent;
3536 pCurrentExtent = pExtent;
3538 bInsertHead = FALSE;
3540 else if( bInsertTail)
3543 if( pNPFcb->Specific.File.DirtyListHead == NULL)
3546 pNPFcb->Specific.File.DirtyListHead = pExtent;
3551 pNPFcb->Specific.File.DirtyListTail->DirtyList.fLink = (void *)pExtent;
3553 pExtent->DirtyList.bLink = (void *)pNPFcb->Specific.File.DirtyListTail;
3556 pNPFcb->Specific.File.DirtyListTail = pExtent;
3561 pExtent->DirtyList.fLink = pCurrentExtent->DirtyList.fLink;
3563 pExtent->DirtyList.bLink = (void *)pCurrentExtent;
3565 if( pExtent->DirtyList.fLink == NULL)
3568 pNPFcb->Specific.File.DirtyListTail = pExtent;
3573 ((AFSExtent *)pExtent->DirtyList.fLink)->DirtyList.bLink = (void *)pExtent;
3576 pCurrentExtent->DirtyList.fLink = (void *)pExtent;
3578 pCurrentExtent = pExtent;
3581 pExtent->Flags |= AFS_EXTENT_DIRTY;
3584 // Up the dirty count
3587 lCount = InterlockedIncrement( &Fcb->Specific.File.ExtentsDirtyCount);
3592 pCurrentExtent = pExtent;
3595 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_ACTIVE_COUNTING,
3596 AFS_TRACE_LEVEL_VERBOSE,
3597 "AFSMarkDirty Decrement count on extent %08lX Cnt %d\n",
3599 pExtent->ActiveCount);
3603 ASSERT( pExtent->ActiveCount > 0);
3604 lCount = InterlockedDecrement( &pExtent->ActiveCount);
3607 pExtent = pNextExtent;
3612 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
3617 "EXCEPTION - AFSMarkDirty\n");
3619 AFSDumpTraceFilesFnc();
3622 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3624 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3625 AFS_TRACE_LEVEL_VERBOSE,
3626 "AFSMarkDirty Releasing Fcb extents lock %08lX SHARED %08lX\n",
3627 &Fcb->NPFcb->Specific.File.ExtentsResource,
3628 PsGetCurrentThread());
3632 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
3643 ExtentFor(PLIST_ENTRY le, ULONG SkipList)
3646 return CONTAINING_RECORD( le, AFSExtent, Lists[SkipList] );
3650 NextExtent(AFSExtent *Extent, ULONG SkipList)
3653 return ExtentFor(Extent->Lists[SkipList].Flink, SkipList);
3656 static AFSExtent *DirtyExtentFor(PLIST_ENTRY le)
3659 return CONTAINING_RECORD( le, AFSExtent, DirtyList );
3662 static VOID VerifyExtentsLists(AFSFcb *Fcb)
3666 // Check the ordering of the extents lists
3668 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
3670 ASSERT(Fcb->Specific.File.ExtentsLists[0].Flink != &Fcb->Specific.File.ExtentsLists[1]);
3672 for (ULONG listNo = 0; listNo < AFS_NUM_EXTENT_LISTS; listNo ++)
3674 LARGE_INTEGER lastOffset;
3676 lastOffset.QuadPart = 0;
3678 for (PLIST_ENTRY pLe = Fcb->Specific.File.ExtentsLists[listNo].Flink;
3679 pLe != &Fcb->Specific.File.ExtentsLists[listNo];
3684 pExtent = ExtentFor(pLe, listNo);
3687 ASSERT(pLe != &Fcb->Specific.File.ExtentsLists[1] &&
3688 pLe->Flink !=&Fcb->Specific.File.ExtentsLists[1] &&
3689 pLe->Blink !=&Fcb->Specific.File.ExtentsLists[1]);
3692 ASSERT(pLe->Flink->Blink == pLe);
3693 ASSERT(pLe->Blink->Flink == pLe);
3696 // Should follow on from previous
3698 ASSERT(pExtent->FileOffset.QuadPart >= lastOffset.QuadPart);
3699 lastOffset.QuadPart = pExtent->FileOffset.QuadPart + pExtent->Size;
3702 // Should match alignment criteria
3704 ASSERT( 0 == (pExtent->FileOffset.LowPart & ExtentsMasks[listNo]) );
3707 // "lower" lists should be populated
3709 for (LONG subListNo = listNo-1; subListNo > 0; subListNo --)
3711 ASSERT( !IsListEmpty(&pExtent->Lists[subListNo]));
3719 AFSTrimExtents( IN AFSFcb *Fcb,
3720 IN PLARGE_INTEGER FileSize)
3723 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3726 BOOLEAN locked = FALSE;
3727 NTSTATUS ntStatus = STATUS_SUCCESS;
3728 LARGE_INTEGER liAlignedOffset = {0,0};
3729 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
3730 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3737 // Get an aligned offset
3740 if( FileSize != NULL)
3743 liAlignedOffset = *FileSize;
3746 if( liAlignedOffset.QuadPart > 0 &&
3747 liAlignedOffset.QuadPart % pDevExt->Specific.RDR.CacheBlockSize != 0)
3751 // Align UP to the next cache block size
3754 liAlignedOffset.QuadPart = (ULONGLONG)( (ULONGLONG)((liAlignedOffset.QuadPart / pDevExt->Specific.RDR.CacheBlockSize) + 1) * (ULONGLONG)pDevExt->Specific.RDR.CacheBlockSize);
3758 // Ensure that no one is working with the extents and grab the
3762 AFSLockForExtentsTrim( Fcb);
3766 if( 0 == Fcb->Specific.File.ExtentCount)
3770 // Update the request extent status
3773 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
3775 try_return( ntStatus = STATUS_SUCCESS);
3779 // We are truncating from a specific length in the file. If the offset
3780 // is non-zero then go find the first extent to remove
3783 if( 0 == FileSize->QuadPart)
3786 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3791 pExtent = AFSExtentForOffset( Fcb,
3795 if( NULL == pExtent)
3798 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3802 le = &pExtent->Lists[AFS_EXTENTS_LIST];
3806 while( le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
3809 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3812 // Only trim down extents beyond the aligned offset
3817 if( pExtent->FileOffset.QuadPart >= liAlignedOffset.QuadPart)
3820 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3823 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3826 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3830 AFSRemoveEntryDirtyList( Fcb,
3833 dirtyCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
3835 ASSERT(dirtyCount >= 0);
3838 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3841 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
3843 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
3845 RemoveEntryList( &pExtent->Lists[i] );
3849 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3850 AFS_TRACE_LEVEL_VERBOSE,
3851 "AFSTrimExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3853 Fcb->ObjectInformation->FileId.Cell,
3854 Fcb->ObjectInformation->FileId.Volume,
3855 Fcb->ObjectInformation->FileId.Vnode,
3856 Fcb->ObjectInformation->FileId.Unique,
3857 pExtent->FileOffset.QuadPart,
3860 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
3862 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
3864 ASSERT( pExtent->ActiveCount == 0);
3869 AFSExFreePool( pExtent);
3871 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
3873 lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount);
3878 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
3886 // Update the request extent status
3889 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
3896 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3897 AFS_TRACE_LEVEL_VERBOSE,
3898 "AFSTrimExtents Releasing Fcb extents lock %08lX thread %08lX\n",
3899 &Fcb->NPFcb->Specific.File.ExtentsResource,
3900 PsGetCurrentThread());
3902 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
3910 AFSTrimSpecifiedExtents( IN AFSFcb *Fcb,
3912 IN AFSFileExtentCB *Result)
3915 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3918 AFSFileExtentCB *pFileExtents = Result;
3919 NTSTATUS ntStatus = STATUS_SUCCESS;
3920 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
3921 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3927 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3929 while( le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST] &&
3933 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3936 // Only trim down extents beyond the aligned offset
3941 if( pExtent->FileOffset.QuadPart == pFileExtents->FileOffset.QuadPart)
3944 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3947 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3950 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3955 AFSRemoveEntryDirtyList( Fcb,
3958 dirtyCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
3960 ASSERT( dirtyCount >= 0);
3964 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3968 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
3970 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
3972 RemoveEntryList( &pExtent->Lists[i] );
3976 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3977 AFS_TRACE_LEVEL_VERBOSE,
3978 "AFSTrimSpecifiedExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3980 Fcb->ObjectInformation->FileId.Cell,
3981 Fcb->ObjectInformation->FileId.Volume,
3982 Fcb->ObjectInformation->FileId.Vnode,
3983 Fcb->ObjectInformation->FileId.Unique,
3984 pExtent->FileOffset.QuadPart,
3987 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
3989 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
3991 ASSERT( pExtent->ActiveCount == 0);
3996 AFSExFreePool( pExtent);
3998 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
4000 lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount);
4005 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
4011 // Next extent we are looking for
4021 // Update the request extent status
4024 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
4031 AFSReferenceActiveExtents( IN AFSExtent *StartExtent,
4032 IN ULONG ExtentsCount)
4035 AFSExtent *pExtent = StartExtent;
4036 AFSExtent *pNextExtent;
4040 while( ulCount < ExtentsCount)
4043 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
4045 lCount = InterlockedIncrement( &pExtent->ActiveCount);
4047 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_ACTIVE_COUNTING,
4048 AFS_TRACE_LEVEL_VERBOSE,
4049 "AFSReferenceActiveExtents Increment count on extent %08lX Cnt %d\n",
4053 pExtent = pNextExtent;
4062 AFSDereferenceActiveExtents( IN AFSExtent *StartExtent,
4063 IN ULONG ExtentsCount)
4066 AFSExtent *pExtent = StartExtent;
4067 AFSExtent *pNextExtent;
4071 while( ulCount < ExtentsCount)
4074 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
4076 ASSERT( pExtent->ActiveCount > 0);
4078 lCount = InterlockedDecrement( &pExtent->ActiveCount);
4080 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_ACTIVE_COUNTING,
4081 AFS_TRACE_LEVEL_VERBOSE,
4082 "AFSDereferenceActiveExtents Decrement count on extent %08lX Cnt %d\n",
4086 pExtent = pNextExtent;
4095 AFSRemoveEntryDirtyList( IN AFSFcb *Fcb,
4096 IN AFSExtent *Extent)
4099 if( Extent->DirtyList.fLink == NULL)
4102 Fcb->NPFcb->Specific.File.DirtyListTail = (AFSExtent *)Extent->DirtyList.bLink;
4104 if( Fcb->NPFcb->Specific.File.DirtyListTail != NULL)
4107 Fcb->NPFcb->Specific.File.DirtyListTail->DirtyList.fLink = NULL;
4113 ((AFSExtent *)Extent->DirtyList.fLink)->DirtyList.bLink = Extent->DirtyList.bLink;
4116 if( Extent->DirtyList.bLink == NULL)
4119 Fcb->NPFcb->Specific.File.DirtyListHead = (AFSExtent *)Extent->DirtyList.fLink;
4121 if( Fcb->NPFcb->Specific.File.DirtyListHead != NULL)
4124 Fcb->NPFcb->Specific.File.DirtyListHead->DirtyList.bLink = NULL;
4130 ((AFSExtent *)Extent->DirtyList.bLink)->DirtyList.fLink = Extent->DirtyList.fLink;
4138 AFSConstructCleanByteRangeList( AFSFcb * pFcb,
4139 AFSByteRange ** pByteRangeList)
4142 ULONG ulByteRangeMax;
4143 ULONG ulByteRangeCount = 0;
4144 AFSByteRange *ByteRangeList;
4145 AFSExtent *pExtent, *pNextExtent;
4147 AFSAcquireShared( &pFcb->NPFcb->Specific.File.DirtyExtentsListLock, TRUE);
4149 ulByteRangeMax = pFcb->Specific.File.ExtentsDirtyCount + 1;
4151 ByteRangeList = (AFSByteRange *) AFSExAllocatePoolWithTag( PagedPool,
4152 ulByteRangeMax * sizeof( AFSByteRange),
4155 if ( ByteRangeList == NULL)
4158 (*pByteRangeList) = NULL;
4160 try_return( ulByteRangeCount = DWORD_MAX);
4163 RtlZeroMemory( ByteRangeList,
4164 ulByteRangeMax * sizeof( AFSByteRange));
4167 // The for loop populates the ByteRangeList entries with values that are
4168 // the gaps in the DirtyList. In other words, if a range is not present
4169 // in the DirtyList it will be represented in the ByteRangeList array.
4172 for ( ulByteRangeCount = 0,
4173 pExtent = (AFSExtent *)pFcb->NPFcb->Specific.File.DirtyListHead;
4174 ulByteRangeCount < ulByteRangeMax && pExtent != NULL;
4175 pExtent = pNextExtent)
4178 pNextExtent = (AFSExtent *)pExtent->DirtyList.fLink;
4181 // The first time the for() is entered the ulByteRangeCount will be zero and
4182 // ByteRangeList[0] FileOffset and Length will both be zero. If the first
4183 // extent is not for offset zero, the ByteRangeList[0] Length is set to the
4184 // FileOffset of the Extent.
4186 // Future passes through the loop behave in a similar fashion but
4187 // ByteRangeList[ulByteRangeCount] FileOffset will have been set below.
4190 if ( pExtent->FileOffset.QuadPart != ByteRangeList[ulByteRangeCount].FileOffset.QuadPart + ByteRangeList[ulByteRangeCount].Length.QuadPart)
4193 ByteRangeList[ulByteRangeCount].Length.QuadPart =
4194 pExtent->FileOffset.QuadPart - ByteRangeList[ulByteRangeCount].FileOffset.QuadPart;
4200 // Having processed the current dirty extent, the following while loop
4201 // searches for the next clean gap between dirty extents.
4204 while ( pNextExtent && pNextExtent->FileOffset.QuadPart == pExtent->FileOffset.QuadPart + pExtent->Size)
4207 pExtent = pNextExtent;
4209 pNextExtent = (AFSExtent *)pExtent->DirtyList.fLink;
4213 // Having found the next gap, the ByteRangeList[] FileOffset is set to the start of the gap.
4214 // The Length is left at zero and will be assigned either when the for loop continues or
4215 // when the for loop exits.
4218 ByteRangeList[ulByteRangeCount].FileOffset.QuadPart = pExtent->FileOffset.QuadPart + pExtent->Size;
4222 // Assign the Length of the final clean range to match the file length.
4225 ByteRangeList[ulByteRangeCount].Length.QuadPart =
4226 pFcb->ObjectInformation->EndOfFile.QuadPart - ByteRangeList[ulByteRangeCount].FileOffset.QuadPart;
4228 (*pByteRangeList) = ByteRangeList;
4232 AFSReleaseResource( &pFcb->NPFcb->Specific.File.DirtyExtentsListLock);
4234 return ulByteRangeCount;
4239 AFSSetupMD5Hash( IN AFSFcb *Fcb,
4240 IN AFSExtent *StartExtent,
4241 IN ULONG ExtentsCount,
4242 IN void *SystemBuffer,
4243 IN LARGE_INTEGER *ByteOffset,
4247 NTSTATUS ntStatus = STATUS_SUCCESS;
4248 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
4249 AFSExtent *pExtent = StartExtent;
4250 AFSExtent *pNextExtent, *pCurrentExtent = NULL;
4252 char *pCurrentBuffer = (char *)SystemBuffer;
4253 char *pMD5Buffer = NULL;
4254 ULONG ulCurrentLen = 0;
4255 void *pExtentBuffer = NULL;
4256 LARGE_INTEGER liByteOffset;
4257 ULONG ulBytesRead = 0;
4262 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4263 AFS_TRACE_LEVEL_VERBOSE,
4264 "AFSSetupMD5Hash Acquiring Fcb extents lock %08lX SHARED %08lX\n",
4265 &Fcb->NPFcb->Specific.File.ExtentsResource,
4266 PsGetCurrentThread());
4268 AFSAcquireShared( &Fcb->NPFcb->Specific.File.ExtentsResource, TRUE);
4272 liByteOffset.QuadPart = ByteOffset->QuadPart;
4274 while( ulCount < ExtentsCount)
4277 RtlZeroMemory( pExtent->MD5,
4278 sizeof( pExtent->MD5));
4280 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
4282 if( liByteOffset.QuadPart == pExtent->FileOffset.QuadPart &&
4283 ByteCount < pExtent->Size)
4286 if( pExtentBuffer == NULL)
4289 pExtentBuffer = AFSExAllocatePoolWithTag( PagedPool,
4291 AFS_GENERIC_MEMORY_9_TAG);
4293 if( pExtentBuffer == NULL)
4300 RtlZeroMemory( pExtentBuffer,
4303 RtlCopyMemory( pExtentBuffer,
4307 pMD5Buffer = (char *)pExtentBuffer;
4309 ulCurrentLen = ByteCount;
4311 else if( liByteOffset.QuadPart != pExtent->FileOffset.QuadPart)
4314 pExtentBuffer = AFSExAllocatePoolWithTag( PagedPool,
4316 AFS_GENERIC_MEMORY_10_TAG);
4318 if( pExtentBuffer == NULL)
4324 RtlZeroMemory( pExtentBuffer,
4327 if( BooleanFlagOn( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE))
4331 RtlCopyMemory( pExtentBuffer,
4332 ((char *)AFSLibCacheBaseAddress + pExtent->CacheOffset.QuadPart),
4335 ASSERT( pExtent->CacheOffset.HighPart == 0);
4336 RtlCopyMemory( pExtentBuffer,
4337 ((char *)AFSLibCacheBaseAddress + pExtent->CacheOffset.LowPart),
4341 ulBytesRead = pExtent->Size;
4346 ntStatus = AFSReadCacheFile( pExtentBuffer,
4347 &pExtent->CacheOffset,
4351 if( !NT_SUCCESS( ntStatus))
4358 pMD5Buffer = (char *)pExtentBuffer;
4360 ulCurrentLen = min( ByteCount, pExtent->Size - (ULONG)(liByteOffset.QuadPart - pExtent->FileOffset.QuadPart));
4362 RtlCopyMemory( (void *)((char *)pExtentBuffer + (ULONG)(liByteOffset.QuadPart - pExtent->FileOffset.QuadPart)),
4369 ulCurrentLen = pExtent->Size;
4371 pMD5Buffer = pCurrentBuffer;
4374 AFSGenerateMD5( pMD5Buffer,
4378 pExtent = pNextExtent;
4382 ByteCount -= ulCurrentLen;
4384 pCurrentBuffer += ulCurrentLen;
4386 liByteOffset.QuadPart += ulCurrentLen;
4389 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4390 AFS_TRACE_LEVEL_VERBOSE,
4391 "AFSSetupMD5Hash Releasing Fcb extents lock %08lX SHARED %08lX\n",
4392 &Fcb->NPFcb->Specific.File.ExtentsResource,
4393 PsGetCurrentThread());
4396 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
4401 "EXCEPTION - AFSSetupMD5Hash\n");
4403 AFSDumpTraceFilesFnc();
4406 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
4408 if( pExtentBuffer != NULL)
4411 AFSExFreePool( pExtentBuffer);