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 #if AFS_VALIDATE_EXTENTS
44 static VOID VerifyExtentsLists(AFSFcb *Fcb);
45 static AFSExtent *DirtyExtentFor(PLIST_ENTRY le);
49 AFSEntryForOffset( IN AFSFcb *Fcb,
50 IN PLARGE_INTEGER Offset);
54 // Returns with Extents lock EX and no one using them.
58 AFSLockForExtentsTrim( IN AFSFcb *Fcb)
61 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
62 AFS_TRACE_LEVEL_VERBOSE,
63 "AFSLockForExtentsTrim Acquiring Fcb extents lock %p EXCL %08lX\n",
64 &Fcb->NPFcb->Specific.File.ExtentsResource,
65 PsGetCurrentThread());
67 AFSAcquireExcl( &Fcb->NPFcb->Specific.File.ExtentsResource, TRUE );
73 // return FALSE *or* with Extents lock EX and noone using them
76 AFSLockForExtentsTrimNoWait( IN AFSFcb *Fcb)
79 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
80 AFS_TRACE_LEVEL_VERBOSE,
81 "AFSLockForExtentsTrimNoWait Attempting to acquire Fcb extent lock %p EXCL %08lX\n",
82 &Fcb->NPFcb->Specific.File.ExtentsResource,
83 PsGetCurrentThread());
85 if (!AFSAcquireExcl( &Fcb->NPFcb->Specific.File.ExtentsResource, FALSE ))
88 // Couldn't lock immediately
91 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
92 AFS_TRACE_LEVEL_VERBOSE,
93 "AFSLockForExtentsTrimNoWait Refused to wait for Fcb extent lock %p EXCL %08lX\n",
94 &Fcb->NPFcb->Specific.File.ExtentsResource,
95 PsGetCurrentThread());
104 AFSFreeExtent( IN AFSFcb *Fcb,
105 IN AFSExtent *pExtent)
107 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
110 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
112 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
114 RemoveEntryList( &pExtent->Lists[i] );
118 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
120 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
122 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
124 lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount);
129 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
134 AFSExFreePoolWithTag( pExtent, AFS_EXTENT_TAG);
138 // AFSTearDownFcbExtents was originally written to
139 // remove all of the extents from an FCB. For that to happen
140 // it must be an invariant that the extent list cannot change
141 // from the moment the caller decides to execute AFSTearDownFcbExtents
142 // until it returns. This invariant does not hold because the
143 // the decision to call AFSTearDownFcbExtents is made without
144 // holding the ExtentsResource and it is possible that extents
145 // are in active use. Therefore, AFSTearDownFcbExtents now releases
146 // as many non-active extents as it can.
149 AFSTearDownFcbExtents( IN AFSFcb *Fcb,
152 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
153 LIST_ENTRY *le, *leNext;
155 LONG lExtentCount = 0, lProcessCount = 0;
156 LONG lFcbExtentCount;
157 ULONG ulReleaseCount = 0;
159 AFSReleaseExtentsCB *pRelease = NULL;
160 BOOLEAN locked = FALSE;
162 GUID *pAuthGroup = AuthGroup;
168 if( pAuthGroup == NULL ||
169 RtlCompareMemory( pAuthGroup,
170 &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
171 sizeof( GUID)) == sizeof( GUID))
174 RtlZeroMemory( &stAuthGroup,
177 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
182 if( !NT_SUCCESS( ntStatus))
184 try_return( ntStatus);
187 pAuthGroup = &stAuthGroup;
191 // Ensure that no one is working with the extents and grab the
195 AFSLockForExtentsTrim( Fcb );
199 if (0 == Fcb->Specific.File.ExtentCount)
201 try_return ( ntStatus = STATUS_SUCCESS);
204 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
206 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
208 AFS_EXTENT_RELEASE_TAG);
209 if (NULL == pRelease)
212 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
215 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
218 for( le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink,
220 lFcbExtentCount = Fcb->Specific.File.ExtentCount;
221 lExtentCount < lFcbExtentCount;
222 lExtentCount += lProcessCount)
225 RtlZeroMemory( pRelease,
226 sizeof( AFSReleaseExtentsCB ) +
227 (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB )));
229 for( lProcessCount = 0, ulReleaseCount = 0;
231 ulReleaseCount < AFS_MAXIMUM_EXTENT_RELEASE_COUNT &&
232 lExtentCount + lProcessCount < lFcbExtentCount;
233 lProcessCount++, le = leNext)
238 pEntry = ExtentFor( le, AFS_EXTENTS_LIST );
240 if( pEntry->ActiveCount == 0)
243 pRelease->FileExtents[ulReleaseCount].Flags = AFS_EXTENT_FLAG_RELEASE;
246 RtlCopyMemory( pRelease->FileExtents[ulReleaseCount].MD5,
248 sizeof(pEntry->MD5));
250 pRelease->FileExtents[ulReleaseCount].Flags |= AFS_EXTENT_FLAG_MD5_SET;
253 if( BooleanFlagOn( pEntry->Flags, AFS_EXTENT_DIRTY))
258 AFSRemoveEntryDirtyList( Fcb,
261 pRelease->FileExtents[ulReleaseCount].Flags |= AFS_EXTENT_FLAG_DIRTY;
263 dirtyCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
265 ASSERT( dirtyCount >= 0);
268 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
269 AFS_TRACE_LEVEL_VERBOSE,
270 "AFSTearDownFcbExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %08lX-%08lX Len %08lX\n",
272 Fcb->ObjectInformation->FileId.Cell,
273 Fcb->ObjectInformation->FileId.Volume,
274 Fcb->ObjectInformation->FileId.Vnode,
275 Fcb->ObjectInformation->FileId.Unique,
276 pEntry->FileOffset.HighPart,
277 pEntry->FileOffset.LowPart,
280 pRelease->FileExtents[ulReleaseCount].Length = pEntry->Size;
281 pRelease->FileExtents[ulReleaseCount].DirtyLength = pEntry->Size;
282 pRelease->FileExtents[ulReleaseCount].DirtyOffset = 0;
283 pRelease->FileExtents[ulReleaseCount].CacheOffset = pEntry->CacheOffset;
284 pRelease->FileExtents[ulReleaseCount].FileOffset = pEntry->FileOffset;
293 if ( ulReleaseCount > 0)
296 pRelease->ExtentCount = ulReleaseCount;
298 pRelease->Flags = AFS_EXTENT_FLAG_RELEASE;
301 // Update the metadata for this call
304 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
305 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
306 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
307 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
308 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
311 // Send the request down. We cannot send this down
312 // asynchronously - if we did that we could request them
313 // back before the service got this request and then this
314 // request would be a corruption.
317 sz = sizeof( AFSReleaseExtentsCB ) + (lProcessCount * sizeof ( AFSFileExtentCB ));
319 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
320 AFS_REQUEST_FLAG_SYNCHRONOUS,
323 &Fcb->ObjectInformation->FileId,
329 if( !NT_SUCCESS(ntStatus))
333 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
334 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
337 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
338 AFS_TRACE_LEVEL_ERROR,
339 "AFSTearDownFcbExtents AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
340 Fcb->ObjectInformation->FileId.Cell,
341 Fcb->ObjectInformation->FileId.Volume,
342 Fcb->ObjectInformation->FileId.Vnode,
343 Fcb->ObjectInformation->FileId.Unique,
350 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
353 // if all extents have been released, reinitialize the skip lists
356 if( Fcb->Specific.File.ExtentCount == 0)
359 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i++)
361 InitializeListHead(&Fcb->Specific.File.ExtentsLists[i]);
365 // Reinitialize the dirty list as well
368 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
371 ASSERT( Fcb->Specific.File.ExtentsDirtyCount == 0);
373 Fcb->NPFcb->Specific.File.DirtyListHead = NULL;
374 Fcb->NPFcb->Specific.File.DirtyListTail = NULL;
376 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
379 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
386 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
387 AFS_TRACE_LEVEL_VERBOSE,
388 "AFSTearDownFcbExtents Releasing Fcb extent lock %p thread %08lX\n",
389 &Fcb->NPFcb->Specific.File.ExtentsResource,
390 PsGetCurrentThread());
392 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
398 AFSExFreePoolWithTag( pRelease, AFS_EXTENT_RELEASE_TAG);
404 AFSDeleteFcbExtents( IN AFSFcb *Fcb)
406 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
407 LIST_ENTRY *le, *leNext;
409 LONG lExtentCount = 0, lProcessCount = 0;
410 LONG lFcbExtentCount;
412 BOOLEAN locked = FALSE;
419 // Ensure that no one is working with the extents and grab the
423 AFSLockForExtentsTrim( Fcb );
427 if (0 == Fcb->Specific.File.ExtentCount)
429 try_return ( ntStatus = STATUS_SUCCESS);
432 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
434 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
437 for( le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink,
439 lFcbExtentCount = Fcb->Specific.File.ExtentCount;
440 lExtentCount < lFcbExtentCount;
441 lExtentCount += lProcessCount)
444 for( lProcessCount = 0;
446 lExtentCount + lProcessCount < lFcbExtentCount;
447 lProcessCount++, le = leNext)
452 pEntry = ExtentFor( le, AFS_EXTENTS_LIST );
454 if( BooleanFlagOn( pEntry->Flags, AFS_EXTENT_DIRTY))
459 AFSRemoveEntryDirtyList( Fcb,
462 dirtyCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
464 ASSERT( dirtyCount >= 0);
467 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
468 AFS_TRACE_LEVEL_VERBOSE,
469 "AFSDeleteFcbExtents Deleting extent %p fid %08lX-%08lX-%08lX-%08lX Offset %08lX-%08lX Len %08lX\n",
471 Fcb->ObjectInformation->FileId.Cell,
472 Fcb->ObjectInformation->FileId.Volume,
473 Fcb->ObjectInformation->FileId.Vnode,
474 Fcb->ObjectInformation->FileId.Unique,
475 pEntry->FileOffset.HighPart,
476 pEntry->FileOffset.LowPart,
484 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
487 // if all extents have been released, reinitialize the skip lists
490 ASSERT( Fcb->Specific.File.ExtentCount == 0);
492 if( Fcb->Specific.File.ExtentCount == 0)
495 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i++)
497 InitializeListHead(&Fcb->Specific.File.ExtentsLists[i]);
501 // Reinitialize the dirty list as well
504 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
507 ASSERT( Fcb->Specific.File.ExtentsDirtyCount == 0);
509 Fcb->NPFcb->Specific.File.DirtyListHead = NULL;
510 Fcb->NPFcb->Specific.File.DirtyListTail = NULL;
512 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
515 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
522 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
523 AFS_TRACE_LEVEL_VERBOSE,
524 "AFSDeleteFcbExtents Releasing Fcb extent lock %p thread %08lX\n",
525 &Fcb->NPFcb->Specific.File.ExtentsResource,
526 PsGetCurrentThread());
528 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
535 ExtentForOffsetInList( IN AFSFcb *Fcb,
538 IN PLARGE_INTEGER Offset)
541 // Return the extent that maps the offset, that
542 // - Contains the offset
543 // - or is immediately ahead of the offset (in this list)
544 // - otherwise return NULL.
547 PLIST_ENTRY pLe = List;
548 AFSExtent *pPrevious = NULL;
550 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
552 while (pLe != &Fcb->Specific.File.ExtentsLists[ListNumber])
556 entry = ExtentFor( pLe, ListNumber );
563 if (Offset->QuadPart < entry->FileOffset.QuadPart)
566 // Offset is ahead of entry. Return previous
571 if (Offset->QuadPart >= (entry->FileOffset.QuadPart + entry->Size))
574 // We start after this extent - carry on round
582 // Otherwise its a match
589 // Got to the end. Return Previous
595 AFSExtentContains( IN AFSExtent *Extent, IN PLARGE_INTEGER Offset)
601 return (Extent->FileOffset.QuadPart <= Offset->QuadPart &&
602 (Extent->FileOffset.QuadPart + Extent->Size) > Offset->QuadPart);
607 // Return the extent that contains the offset
610 AFSExtentForOffsetHint( IN AFSFcb *Fcb,
611 IN PLARGE_INTEGER Offset,
612 IN BOOLEAN ReturnPrevious,
615 AFSExtent *pPrevious = Hint;
619 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
621 #if AFS_VALIDATE_EXTENTS
622 VerifyExtentsLists(Fcb);
626 // So we will go across the skip lists until we find an
627 // appropriate entry (previous or direct match). If it's a match
628 // we are done, other wise we start on the next layer down
630 for (i = AFS_NUM_EXTENT_LISTS-1; i >= AFS_EXTENTS_LIST; i--)
632 if (NULL == pPrevious)
635 // We haven't found anything in the previous layers
637 pLe = Fcb->Specific.File.ExtentsLists[i].Flink;
639 else if (NULL == pPrevious->Lists[i].Flink)
641 ASSERT(AFS_EXTENTS_LIST != i);
643 // The hint doesn't exist at this level, next one down
650 // take the previous into the next
652 pLe = &pPrevious->Lists[i];
655 pPrevious = ExtentForOffsetInList( Fcb, pLe, i, Offset);
657 if (NULL != pPrevious && AFSExtentContains(pPrevious, Offset))
660 // Found it immediately. Stop here
666 if (NULL == pPrevious || ReturnPrevious )
671 ASSERT( !AFSExtentContains(pPrevious, Offset) );
677 AFSEntryForOffset( IN AFSFcb *Fcb,
678 IN PLARGE_INTEGER Offset)
680 AFSExtent *pPrevious = NULL;
684 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
686 #if AFS_VALIDATE_EXTENTS
687 VerifyExtentsLists(Fcb);
691 // So we will go across the skip lists until we find an
692 // appropriate entry (previous or direct match). If it's a match
693 // we are done, other wise we start on the next layer down
695 for (i = AFS_NUM_EXTENT_LISTS-1; i >= AFS_EXTENTS_LIST; i--)
697 if (NULL == pPrevious)
700 // We haven't found anything in the previous layers
702 pLe = Fcb->Specific.File.ExtentsLists[i].Flink;
704 else if (NULL == pPrevious->Lists[i].Flink)
706 ASSERT(AFS_EXTENTS_LIST != i);
708 // The hint doesn't exist at this level, next one down
715 // take the previous into the next
717 pLe = &pPrevious->Lists[i];
720 pPrevious = ExtentForOffsetInList( Fcb, pLe, i, Offset);
722 if (NULL != pPrevious && AFSExtentContains(pPrevious, Offset))
725 // Found it immediately. Stop here
735 AFSExtentForOffset( IN AFSFcb *Fcb,
736 IN PLARGE_INTEGER Offset,
737 IN BOOLEAN ReturnPrevious)
739 return AFSExtentForOffsetHint(Fcb, Offset, ReturnPrevious, NULL);
743 BOOLEAN AFSDoExtentsMapRegion(IN AFSFcb *Fcb,
744 IN PLARGE_INTEGER Offset,
746 IN OUT AFSExtent **FirstExtent,
747 OUT AFSExtent **LastExtent)
750 // Return TRUE region is completely mapped. FALSE
751 // otherwise. If the region isn't mapped then the last
752 // extent to map part of the region is returned.
754 // *LastExtent as input is where to start looking.
755 // *LastExtent as output is either the extent which
756 // contains the Offset, or the last one which doesn't
758 AFSExtent *entry = NULL;
760 BOOLEAN retVal = FALSE;
765 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
769 entry = AFSExtentForOffsetHint(Fcb, Offset, TRUE, *FirstExtent);
770 *FirstExtent = entry;
772 if (NULL == entry || !AFSExtentContains(entry, Offset))
774 try_return (retVal = FALSE);
777 ASSERT(Offset->QuadPart >= entry->FileOffset.QuadPart);
781 if ((entry->FileOffset.QuadPart + entry->Size) >=
782 (Offset->QuadPart + Size))
785 // The end is inside the extent
787 try_return (retVal = TRUE);
790 if (entry->Lists[AFS_EXTENTS_LIST].Flink == &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
793 // Run out of extents
795 try_return (retVal = FALSE);
798 newEntry = NextExtent( entry, AFS_EXTENTS_LIST );
800 if (newEntry->FileOffset.QuadPart !=
801 (entry->FileOffset.QuadPart + entry->Size))
806 try_return (retVal = FALSE);
812 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
817 "EXCEPTION - AFSDoExtentsMapRegion\n");
819 AFSDumpTraceFilesFnc();
831 AFSRequestExtentsAsync( IN AFSFcb *Fcb,
833 IN PLARGE_INTEGER Offset,
837 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
838 NTSTATUS ntStatus = STATUS_SUCCESS;
839 AFSExtent *pExtent = NULL;
840 AFSRequestExtentsCB request;
841 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
842 AFSExtent *pFirstExtent = NULL;
843 LARGE_INTEGER liAlignedOffset;
844 ULONG ulAlignedLength = 0;
845 BOOLEAN bRegionMapped = FALSE;
850 ASSERT( !ExIsResourceAcquiredLite( &pNPFcb->Specific.File.ExtentsResource ));
853 // If the service set a failure on the file since the last
854 // CreateFile was issued, return it now.
857 if (!NT_SUCCESS( pNPFcb->Specific.File.ExtentsRequestStatus))
861 // If this isn't the same authgroup which caused the failure
862 // then try to request them again
865 if( RtlCompareMemory( &pNPFcb->Specific.File.ExtentsRequestAuthGroup,
867 sizeof( GUID)) == sizeof( GUID))
870 ntStatus = pNPFcb->Specific.File.ExtentsRequestStatus;
872 pNPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
874 RtlZeroMemory( &pNPFcb->Specific.File.ExtentsRequestAuthGroup,
877 try_return( ntStatus);
882 // Check if we are already mapped
885 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
886 AFS_TRACE_LEVEL_VERBOSE,
887 "AFSRequestExtentsAsync Acquiring Fcb extents lock %p SHARED %08lX\n",
888 &pNPFcb->Specific.File.ExtentsResource,
889 PsGetCurrentThread());
891 AFSAcquireShared( &pNPFcb->Specific.File.ExtentsResource, TRUE );
893 bRegionMapped = AFSDoExtentsMapRegion( Fcb, Offset, Size, &pFirstExtent, &pExtent);
898 KeClearEvent( &pNPFcb->Specific.File.ExtentsRequestComplete );
901 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
902 AFS_TRACE_LEVEL_VERBOSE,
903 "AFSRequestExtentsAsync Releasing Fcb extents lock %p SHARED %08lX\n",
904 &pNPFcb->Specific.File.ExtentsResource,
905 PsGetCurrentThread());
907 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
912 try_return( ntStatus = STATUS_SUCCESS);
916 // Align our request on extent size boundary
919 ulAlignedLength = Size;
921 liAlignedOffset = *Offset;
923 if( liAlignedOffset.QuadPart % pDevExt->Specific.RDR.CacheBlockSize != 0)
926 liAlignedOffset.QuadPart = (ULONGLONG)( (ULONGLONG)(liAlignedOffset.QuadPart / pDevExt->Specific.RDR.CacheBlockSize) * (ULONGLONG)pDevExt->Specific.RDR.CacheBlockSize);
928 ulAlignedLength += (ULONG)(Offset->QuadPart - liAlignedOffset.QuadPart);
931 if( ulAlignedLength % pDevExt->Specific.RDR.CacheBlockSize != 0)
934 ulAlignedLength = (ULONG)(((ulAlignedLength / pDevExt->Specific.RDR.CacheBlockSize) + 1) * pDevExt->Specific.RDR.CacheBlockSize);
937 RtlZeroMemory( &request,
938 sizeof( AFSRequestExtentsCB));
940 request.ByteOffset = liAlignedOffset;
941 request.Length = ulAlignedLength;
943 if( !AFSIsExtentRequestQueued( &Fcb->ObjectInformation->FileId,
948 KeClearEvent( &pNPFcb->Specific.File.ExtentsRequestComplete );
950 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
951 AFS_TRACE_LEVEL_VERBOSE,
952 "AFSRequestExtentsAsync Request extents for fid %08lX-%08lX-%08lX-%08lX Offset %08lX Len %08lX Thread %08lX\n",
953 Fcb->ObjectInformation->FileId.Cell,
954 Fcb->ObjectInformation->FileId.Volume,
955 Fcb->ObjectInformation->FileId.Vnode,
956 Fcb->ObjectInformation->FileId.Unique,
957 request.ByteOffset.LowPart,
959 PsGetCurrentThread());
961 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS,
965 &Fcb->ObjectInformation->FileId,
967 sizeof( AFSRequestExtentsCB ),
971 if ( ntStatus == STATUS_ACCESS_DENIED)
976 ntStatus2 = AFSRetrieveValidAuthGroup( Fcb,
981 if ( NT_SUCCESS( ntStatus2) &&
982 RtlCompareMemory( &stAuthGroup,
984 sizeof( GUID)) != sizeof( GUID))
987 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS,
991 &Fcb->ObjectInformation->FileId,
993 sizeof( AFSRequestExtentsCB ),
999 if( !NT_SUCCESS( ntStatus))
1002 KeSetEvent( &pNPFcb->Specific.File.ExtentsRequestComplete,
1017 AFSProcessExtentsResult( IN AFSFcb *Fcb,
1019 IN AFSFileExtentCB *Result)
1021 NTSTATUS ntStatus = STATUS_SUCCESS;
1022 AFSFileExtentCB *pFileExtents = Result;
1025 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
1026 ULONG fileExtentsUsed = 0;
1027 BOOLEAN bFoundExtent = FALSE;
1028 LIST_ENTRY *pSkipEntries[AFS_NUM_EXTENT_LISTS] = { 0 };
1029 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1033 // Grab the extents exclusive for the duration
1036 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1037 AFS_TRACE_LEVEL_VERBOSE,
1038 "AFSProcessExtentsResult Acquiring Fcb extent lock %p EXCL %08lX\n",
1039 &pNPFcb->Specific.File.ExtentsResource,
1040 PsGetCurrentThread());
1042 AFSAcquireExcl( &pNPFcb->Specific.File.ExtentsResource, TRUE );
1048 // Find where to put the extents
1050 for (ULONG i = AFS_EXTENTS_LIST; i < AFS_NUM_EXTENT_LISTS; i++)
1053 pSkipEntries[i] = Fcb->Specific.File.ExtentsLists[i].Flink;
1056 le = pSkipEntries[AFS_EXTENTS_LIST];
1058 if (le == &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
1061 // No extents. Insert at head of list (which is where the skip lists point!)
1065 else if (0 != pFileExtents->FileOffset.QuadPart)
1068 // We want to find the best extents immediately *behind* this offset
1070 LARGE_INTEGER offset = pFileExtents->FileOffset;
1073 // Ask in the top skip list first, then work down
1075 for (LONG i = AFS_NUM_EXTENT_LISTS-1; i >= AFS_EXTENTS_LIST; i--)
1077 pExtent = ExtentForOffsetInList( Fcb,
1082 if (NULL == pExtent)
1085 // No dice. Header has to become the head of the list
1087 pSkipEntries[i] = &Fcb->Specific.File.ExtentsLists[i];
1089 // And as a loop invariant we should never have found an extent
1091 ASSERT(!bFoundExtent);
1096 // pExtent is where to start to insert at this level
1098 pSkipEntries[i] = &pExtent->Lists[i];
1101 // And also where to start to look at the next level
1104 if (i > AFS_EXTENTS_LIST)
1106 pSkipEntries[i-1] = &pExtent->Lists[i-1];
1108 bFoundExtent = TRUE;
1112 if (NULL == pExtent)
1114 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
1119 le = pExtent->Lists[AFS_EXTENTS_LIST].Blink;
1125 // Looking at offset 0, so we must start at the beginning
1128 pExtent = ExtentFor(le, AFS_EXTENTS_LIST);
1132 // And set up the skip lists
1135 for (ULONG i = AFS_EXTENTS_LIST; i < AFS_NUM_EXTENT_LISTS; i++)
1137 pSkipEntries[i] = &Fcb->Specific.File.ExtentsLists[i];
1141 while (fileExtentsUsed < Count)
1145 // Loop invariant - le points to where to insert after and
1146 // pExtent points to le->fLink
1149 ASSERT (NULL == pExtent ||
1150 le->Flink == &pExtent->Lists[AFS_EXTENTS_LIST]);
1152 if (NULL == pExtent ||
1153 pExtent->FileOffset.QuadPart > pFileExtents->FileOffset.QuadPart)
1156 // We need to insert a new extent at le. Start with
1157 // some sanity check on spanning
1159 if (NULL != pExtent &&
1160 ((pFileExtents->FileOffset.QuadPart + pFileExtents->Length) >
1161 pExtent->FileOffset.QuadPart))
1164 // File Extents overlaps pExtent
1166 ASSERT( (pFileExtents->FileOffset.QuadPart + pFileExtents->Length) <=
1167 pExtent->FileOffset.QuadPart);
1169 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1173 // File offset is entirely in front of this extent. Create
1174 // a new one (remember le is the previous list entry)
1176 pExtent = (AFSExtent *) AFSExAllocatePoolWithTag( NonPagedPool,
1179 if (NULL == pExtent)
1182 try_return (ntStatus = STATUS_INSUFFICIENT_RESOURCES );
1185 RtlZeroMemory( pExtent, sizeof( AFSExtent ));
1187 pExtent->FileOffset = pFileExtents->FileOffset;
1188 pExtent->CacheOffset = pFileExtents->CacheOffset;
1189 pExtent->Size = pFileExtents->Length;
1191 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1192 AFS_TRACE_LEVEL_VERBOSE,
1193 "AFSProcessExtentsResult Received extent for fid %08lX-%08lX-%08lX-%08lX File Offset %I64X Cache Offset %I64X Len %08lX\n",
1194 Fcb->ObjectInformation->FileId.Cell,
1195 Fcb->ObjectInformation->FileId.Volume,
1196 Fcb->ObjectInformation->FileId.Vnode,
1197 Fcb->ObjectInformation->FileId.Unique,
1198 pFileExtents->FileOffset.QuadPart,
1199 pFileExtents->CacheOffset.QuadPart,
1200 pFileExtents->Length);
1202 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, (LONG)(pExtent->Size/1024));
1204 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, (LONG)(pExtent->Size/1024));
1206 lCount = InterlockedIncrement( &Fcb->Specific.File.ExtentCount);
1208 lCount = InterlockedIncrement( &pControlDevExt->Specific.Control.ExtentCount);
1213 KeClearEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent);
1219 InsertHeadList(le, &pExtent->Lists[AFS_EXTENTS_LIST]);
1220 ASSERT(le->Flink == &pExtent->Lists[AFS_EXTENTS_LIST]);
1221 ASSERT(0 == (pExtent->FileOffset.LowPart & ExtentsMasks[AFS_EXTENTS_LIST]));
1224 // Do not move the cursor - we will do it next time
1228 // And into the (upper) skip lists - Again, do not move the cursor
1230 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1232 if (0 == (pExtent->FileOffset.LowPart & ExtentsMasks[i]))
1234 InsertHeadList(pSkipEntries[i], &pExtent->Lists[i]);
1235 #if AFS_VALIDATE_EXTENTS
1236 VerifyExtentsLists(Fcb);
1241 else if (pExtent->FileOffset.QuadPart == pFileExtents->FileOffset.QuadPart)
1244 if (pExtent->Size != pFileExtents->Length)
1247 ASSERT (pExtent->Size == pFileExtents->Length);
1249 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1253 // Move both cursors forward.
1255 // First the extent pointer
1258 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1261 // Then the skip lists cursors forward if needed
1263 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1265 if (0 == (pExtent->FileOffset.LowPart & ExtentsMasks[i]))
1268 // Check sanity before
1270 #if AFS_VALIDATE_EXTENTS
1271 VerifyExtentsLists(Fcb);
1275 // Skip list should point to us
1277 //ASSERT(pSkipEntries[i] == &pExtent->Lists[i]);
1279 // Move forward cursor
1281 pSkipEntries[i] = pSkipEntries[i]->Flink;
1283 // Check sanity before
1285 #if AFS_VALIDATE_EXTENTS
1286 VerifyExtentsLists(Fcb);
1292 // And then the cursor in the supplied array
1298 // setup pExtent if there is one
1300 if (le->Flink != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
1302 pExtent = NextExtent( pExtent, AFS_EXTENTS_LIST ) ;
1312 ASSERT( pExtent->FileOffset.QuadPart < pFileExtents->FileOffset.QuadPart );
1315 // Sanity check on spanning
1317 if ((pExtent->FileOffset.QuadPart + pExtent->Size) >
1318 pFileExtents->FileOffset.QuadPart)
1321 ASSERT( (pExtent->FileOffset.QuadPart + pExtent->Size) <=
1322 pFileExtents->FileOffset.QuadPart);
1324 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1328 // Move le and pExtent forward
1330 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1333 // setup pExtent if there is one
1336 if (le->Flink != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
1338 pExtent = NextExtent( pExtent, AFS_EXTENTS_LIST ) ;
1348 // All done, signal that we are done drop the lock, exit
1353 if( !NT_SUCCESS( ntStatus))
1357 // If we failed the service is going to drop all extents so trim away the
1361 AFSTrimSpecifiedExtents( Fcb,
1366 #if AFS_VALIDATE_EXTENTS
1367 VerifyExtentsLists(Fcb);
1370 KeSetEvent( &pNPFcb->Specific.File.ExtentsRequestComplete,
1374 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1375 AFS_TRACE_LEVEL_VERBOSE,
1376 "AFSProcessExtentsResult Releasing Fcb extent lock %p EXCL %08lX\n",
1377 &pNPFcb->Specific.File.ExtentsResource,
1378 PsGetCurrentThread());
1380 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
1387 AFSProcessSetFileExtents( IN AFSSetFileExtentsCB *SetExtents )
1389 AFSFcb *pFcb = NULL;
1390 AFSVolumeCB *pVolumeCB = NULL;
1391 NTSTATUS ntStatus = STATUS_SUCCESS;
1392 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1393 ULONGLONG ullIndex = 0;
1394 AFSObjectInfoCB *pObjectInfo = NULL;
1400 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1401 AFS_TRACE_LEVEL_VERBOSE,
1402 "AFSProcessSetFileExtents Acquiring RDR VolumeTreeLock lock %p SHARED %08lX\n",
1403 &pDevExt->Specific.RDR.VolumeTreeLock,
1404 PsGetCurrentThread());
1406 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
1408 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1409 AFS_TRACE_LEVEL_VERBOSE,
1410 "AFSProcessSetFileExtents Set extents for fid %08lX-%08lX-%08lX-%08lX\n",
1411 SetExtents->FileId.Cell,
1412 SetExtents->FileId.Volume,
1413 SetExtents->FileId.Vnode,
1414 SetExtents->FileId.Unique);
1417 // Locate the volume node
1420 ullIndex = AFSCreateHighIndex( &SetExtents->FileId);
1422 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
1424 (AFSBTreeEntry **)&pVolumeCB);
1426 if( pVolumeCB != NULL)
1429 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1431 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1432 AFS_TRACE_LEVEL_VERBOSE,
1433 "AFSProcessSetFileExtents Increment count on volume %p Cnt %d\n",
1438 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
1440 if( !NT_SUCCESS( ntStatus) ||
1444 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1445 AFS_TRACE_LEVEL_ERROR,
1446 "AFSProcessSetFileExtents Set extents for fid %08lX-%08lX-%08lX-%08lX Failed to locate volume Status %08lX\n",
1447 SetExtents->FileId.Cell,
1448 SetExtents->FileId.Volume,
1449 SetExtents->FileId.Vnode,
1450 SetExtents->FileId.Unique,
1453 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1456 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1460 // Now locate the Object in this volume
1463 ullIndex = AFSCreateLowIndex( &SetExtents->FileId);
1465 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
1467 (AFSBTreeEntry **)&pObjectInfo);
1469 if( pObjectInfo != NULL)
1473 // Reference the node so it won't be torn down
1476 lCount = AFSObjectInfoIncrement( pObjectInfo);
1478 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1479 AFS_TRACE_LEVEL_VERBOSE,
1480 "AFSProcessSetFileExtents Increment count on object %p Cnt %d\n",
1485 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1487 if( !NT_SUCCESS( ntStatus) ||
1488 pObjectInfo == NULL)
1491 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1492 AFS_TRACE_LEVEL_ERROR,
1493 "AFSProcessSetFileExtents Set extents for hash %I64X fid %08lX-%08lX-%08lX-%08lX Failed to locate file in volume %p\n",
1495 SetExtents->FileId.Cell,
1496 SetExtents->FileId.Volume,
1497 SetExtents->FileId.Vnode,
1498 SetExtents->FileId.Unique,
1501 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1504 pFcb = pObjectInfo->Fcb;
1507 // If we have a result failure then don't bother trying to set the extents
1510 if( SetExtents->ResultStatus != STATUS_SUCCESS)
1513 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1514 AFS_TRACE_LEVEL_ERROR,
1515 "AFSProcessSetFileExtents Set extents failure fid %08lX-%08lX-%08lX-%08lX ResultStatus %08lX\n",
1516 SetExtents->FileId.Cell,
1517 SetExtents->FileId.Volume,
1518 SetExtents->FileId.Vnode,
1519 SetExtents->FileId.Unique,
1520 SetExtents->ResultStatus);
1522 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1523 AFS_TRACE_LEVEL_VERBOSE,
1524 "AFSProcessSetFileExtents Acquiring Fcb extents lock %p EXCL %08lX\n",
1525 &pFcb->NPFcb->Specific.File.ExtentsResource,
1526 PsGetCurrentThread());
1528 AFSAcquireExcl( &pFcb->NPFcb->Specific.File.ExtentsResource,
1531 pFcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_CANCELLED;
1533 KeSetEvent( &pFcb->NPFcb->Specific.File.ExtentsRequestComplete,
1537 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1538 AFS_TRACE_LEVEL_VERBOSE,
1539 "AFSProcessSetFileExtents Releasing Fcb extent lock %p EXCL %08lX\n",
1540 &pFcb->NPFcb->Specific.File.ExtentsResource,
1541 PsGetCurrentThread());
1543 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
1545 try_return( ntStatus);
1548 ntStatus = AFSProcessExtentsResult ( pFcb,
1549 SetExtents->ExtentCount,
1550 SetExtents->FileExtents );
1554 if( pObjectInfo != NULL)
1557 lCount = AFSObjectInfoDecrement( pObjectInfo);
1559 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1560 AFS_TRACE_LEVEL_VERBOSE,
1561 "AFSProcessSetFileExtents Decrement count on object %p Cnt %d\n",
1569 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1571 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1572 AFS_TRACE_LEVEL_VERBOSE,
1573 "AFSProcessSetFileExtents Decrement count on volume %p Cnt %d\n",
1583 // Helper fuctions for Usermode initiation of release of extents
1586 AFSReleaseSpecifiedExtents( IN AFSReleaseFileExtentsCB *Extents,
1588 OUT AFSFileExtentCB *FileExtents,
1589 IN ULONG BufferSize,
1590 OUT ULONG *ExtentCount,
1591 OUT BOOLEAN *DirtyExtents)
1595 ULONG ulExtentCount = 0;
1596 NTSTATUS ntStatus = STATUS_SUCCESS;
1597 BOOLEAN bReleaseAll = FALSE;
1602 ASSERT( ExIsResourceAcquiredExclusiveLite( &Fcb->NPFcb->Specific.File.ExtentsResource));
1604 if (BufferSize < (Extents->ExtentCount * sizeof( AFSFileExtentCB)))
1607 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1608 AFS_TRACE_LEVEL_VERBOSE,
1609 "AFSReleaseSpecifiedExtents Buffer too small\n");
1611 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL);
1614 RtlZeroMemory( FileExtents, BufferSize);
1617 *DirtyExtents = FALSE;
1620 // iterate until we have dealt with all we were asked for or
1621 // are at the end of the list. Note that this deals (albeit
1622 // badly) with out of order extents
1625 pExtent = AFSExtentForOffset( Fcb,
1626 &Extents->FileExtents[0].FileOffset,
1629 if (NULL == pExtent)
1631 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1635 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1639 if( BooleanFlagOn( Extents->Flags, AFS_RELEASE_EXTENTS_FLAGS_RELEASE_ALL) ||
1640 ( Extents->FileId.Cell == 0 &&
1641 Extents->FileId.Volume == 0 &&
1642 Extents->FileId.Vnode == 0 &&
1643 Extents->FileId.Unique == 0))
1649 while( le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST] &&
1650 ulExtentCount < Extents->ExtentCount)
1654 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
1659 if( pExtent->FileOffset.QuadPart < Extents->FileExtents[ulExtentCount].FileOffset.QuadPart)
1662 // Skip forward through the extent list until we get
1663 // to the one we want
1669 else if (pExtent->FileOffset.QuadPart > Extents->FileExtents[ulExtentCount].FileOffset.QuadPart)
1672 // We don't have the extent asked for so return UNKNOWN
1675 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1676 AFS_TRACE_LEVEL_VERBOSE,
1677 "AFSReleaseSpecifiedExtents Located UNKNOWN extent Offset %I64X Len %08lX\n",
1678 Extents->FileExtents[ulExtentCount].FileOffset.QuadPart,
1679 Extents->FileExtents[ulExtentCount].Length);
1681 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_UNKNOWN;
1683 FileExtents[*ExtentCount].Length = 0;
1684 FileExtents[*ExtentCount].CacheOffset.QuadPart = 0;
1685 FileExtents[*ExtentCount].FileOffset = Extents->FileExtents[ulExtentCount].FileOffset;
1687 *ExtentCount = (*ExtentCount) + 1;
1692 // Reset where we are looking
1695 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1699 else if( pExtent->ActiveCount > 0)
1702 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1703 AFS_TRACE_LEVEL_VERBOSE,
1704 "AFSReleaseSpecifiedExtents Located IN_USE extent Offset %I64X Len %08lX\n",
1705 Extents->FileExtents[ulExtentCount].FileOffset.QuadPart,
1706 Extents->FileExtents[ulExtentCount].Length);
1708 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_IN_USE;
1710 FileExtents[*ExtentCount].Length = 0;
1711 FileExtents[*ExtentCount].CacheOffset.QuadPart = 0;
1712 FileExtents[*ExtentCount].FileOffset = Extents->FileExtents[ulExtentCount].FileOffset;
1714 *ExtentCount = (*ExtentCount) + 1;
1719 // Reset where we are looking
1722 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1731 // If the extent is currently active then skip it
1734 if( pExtent->ActiveCount > 0)
1743 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_RELEASE;
1745 FileExtents[*ExtentCount].Length = pExtent->Size;
1746 FileExtents[*ExtentCount].DirtyLength = pExtent->Size;
1747 FileExtents[*ExtentCount].DirtyOffset = 0;
1748 FileExtents[*ExtentCount].CacheOffset = pExtent->CacheOffset;
1749 FileExtents[*ExtentCount].FileOffset = pExtent->FileOffset;
1751 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1752 AFS_TRACE_LEVEL_VERBOSE,
1753 "AFSReleaseSpecifiedExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
1755 Fcb->ObjectInformation->FileId.Cell,
1756 Fcb->ObjectInformation->FileId.Volume,
1757 Fcb->ObjectInformation->FileId.Vnode,
1758 Fcb->ObjectInformation->FileId.Unique,
1759 FileExtents[*ExtentCount].FileOffset.QuadPart,
1760 FileExtents[*ExtentCount].Length);
1762 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
1765 AFSAcquireExcl( &Fcb->NPFcb->Specific.File.DirtyExtentsListLock,
1768 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
1771 AFSRemoveEntryDirtyList( Fcb,
1774 FileExtents[*ExtentCount].Flags |= AFS_EXTENT_FLAG_DIRTY;
1776 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
1778 *DirtyExtents = TRUE;
1781 AFSReleaseResource( &Fcb->NPFcb->Specific.File.DirtyExtentsListLock);
1785 // move forward all three cursors
1789 *ExtentCount = (*ExtentCount) + 1;
1804 AFSFindFcbToClean(ULONG IgnoreTime, AFSFcb *LastFcb, BOOLEAN Block)
1807 UNREFERENCED_PARAMETER(IgnoreTime);
1808 AFSFcb *pFcb = NULL;
1809 AFSVolumeCB *pVolumeCB = NULL;
1810 AFSDeviceExt *pRDRDeviceExt = NULL;
1811 AFSDeviceExt *pControlDeviceExt = NULL;
1812 BOOLEAN bLocatedEntry = FALSE;
1813 AFSObjectInfoCB *pCurrentObject = NULL;
1814 BOOLEAN bReleaseVolumeListLock = FALSE;
1817 pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1818 pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1820 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1821 AFS_TRACE_LEVEL_VERBOSE,
1822 "AFSFindFcbToClean Acquiring RDR VolumeListLock lock %p SHARED %08lX\n",
1823 &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1824 PsGetCurrentThread());
1826 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1829 bReleaseVolumeListLock = TRUE;
1831 pVolumeCB = pRDRDeviceExt->Specific.RDR.VolumeListHead;
1833 while( pVolumeCB != NULL)
1837 // The Volume list may move under our feet. Lock it.
1840 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1842 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1843 AFS_TRACE_LEVEL_VERBOSE,
1844 "AFSFindFcbToClean Increment count on volume %p Cnt %d\n",
1848 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1850 bReleaseVolumeListLock = FALSE;
1852 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1853 AFS_TRACE_LEVEL_VERBOSE,
1854 "AFSFindFcbToClean Acquiring VolumeRoot ObjectInfoTree lock %p SHARED %08lX\n",
1855 pVolumeCB->ObjectInfoTree.TreeLock,
1856 PsGetCurrentThread());
1858 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1861 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1863 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1864 AFS_TRACE_LEVEL_VERBOSE,
1865 "AFSFindFcbToClean Decrement count on volume %p Cnt %d\n",
1869 if( NULL == LastFcb)
1872 pCurrentObject = pVolumeCB->ObjectInfoListHead;
1877 pCurrentObject = (AFSObjectInfoCB *)LastFcb->ObjectInformation->ListEntry.fLink;
1882 while( pCurrentObject != NULL)
1885 pFcb = (AFSFcb *)pCurrentObject->Fcb;
1888 // If the FCB is a candidate we try to lock it (but without waiting - which
1889 // means we are deadlock free
1893 pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
1899 AFSLockForExtentsTrim( pFcb);
1904 if( !AFSLockForExtentsTrimNoWait( pFcb))
1907 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1916 // Need to be sure there are no current flushes in the queue
1919 if( pFcb->Specific.File.ExtentCount == 0)
1922 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1923 AFS_TRACE_LEVEL_VERBOSE,
1924 "AFSFindFcbToClean Releasing Fcb extent lock %p thread %08lX\n",
1925 &pFcb->NPFcb->Specific.File.ExtentsResource,
1926 PsGetCurrentThread());
1928 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
1930 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1937 if( pFcb->Specific.File.QueuedFlushCount > 0)
1940 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1941 AFS_TRACE_LEVEL_VERBOSE,
1942 "AFSFindFcbToClean Releasing Fcb extent lock %p thread %08lX\n",
1943 &pFcb->NPFcb->Specific.File.ExtentsResource,
1944 PsGetCurrentThread());
1946 AFSReleaseResource(&pFcb->NPFcb->Specific.File.ExtentsResource);
1950 AFSWaitOnQueuedFlushes( pFcb);
1955 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1963 if( pFcb->OpenHandleCount > 0)
1966 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1967 AFS_TRACE_LEVEL_VERBOSE,
1968 "AFSFindFcbToClean Releasing Fcb extent lock %p thread %08lX\n",
1969 &pFcb->NPFcb->Specific.File.ExtentsResource,
1970 PsGetCurrentThread());
1972 AFSReleaseResource(&pFcb->NPFcb->Specific.File.ExtentsResource);
1974 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1982 // A hit a very palpable hit. Pin it
1985 lCount = AFSObjectInfoIncrement( pCurrentObject);
1987 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1988 AFS_TRACE_LEVEL_VERBOSE,
1989 "AFSFindFcbToClean Increment count on Fcb %p Cnt %d\n",
1993 bLocatedEntry = TRUE;
1998 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
2003 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2010 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
2013 bReleaseVolumeListLock = TRUE;
2015 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
2018 if( bReleaseVolumeListLock)
2021 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
2028 AFSProcessExtentFailure( PIRP Irp)
2030 AFSExtentFailureCB *pFailureCB = NULL;
2031 NTSTATUS ntStatus = STATUS_SUCCESS;
2032 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2033 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2034 AFSVolumeCB *pVolumeCB = NULL;
2035 ULONGLONG ullIndex = 0;
2036 AFSObjectInfoCB *pObjectInfo = NULL;
2041 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSExtentFailureCB))
2044 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2045 AFS_TRACE_LEVEL_ERROR,
2046 "AFSProcessExtentFailure Input buffer too small\n");
2048 try_return( ntStatus = STATUS_INVALID_PARAMETER);
2051 pFailureCB = (AFSExtentFailureCB *)Irp->AssociatedIrp.SystemBuffer;
2053 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2054 AFS_TRACE_LEVEL_ERROR,
2055 "AFSProcessExtentFailure Service Reports Failure fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2056 pFailureCB->FileId.Cell,
2057 pFailureCB->FileId.Volume,
2058 pFailureCB->FileId.Vnode,
2059 pFailureCB->FileId.Unique,
2060 pFailureCB->FailureStatus);
2062 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
2065 // Locate the volume node
2068 ullIndex = AFSCreateHighIndex( &pFailureCB->FileId);
2070 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
2072 (AFSBTreeEntry **)&pVolumeCB);
2074 if( pVolumeCB != NULL)
2077 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
2079 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2080 AFS_TRACE_LEVEL_VERBOSE,
2081 "AFSProcessExtentFailure Increment count on volume %p Cnt %d\n",
2086 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
2088 if( !NT_SUCCESS( ntStatus) ||
2092 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2093 AFS_TRACE_LEVEL_ERROR,
2094 "AFSProcessExtentFailure Invalid volume index %I64X status %08X\n",
2095 ullIndex, ntStatus);
2097 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2100 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2101 AFS_TRACE_LEVEL_VERBOSE,
2102 "AFSProcessExtentFailure Acquiring VolumeRoot FileIDTree.TreeLock lock %p SHARED %08lX\n",
2103 pVolumeCB->ObjectInfoTree.TreeLock,
2104 PsGetCurrentThread());
2106 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
2110 // Now locate the Object in this volume
2113 ullIndex = AFSCreateLowIndex( &pFailureCB->FileId);
2115 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
2117 (AFSBTreeEntry **)&pObjectInfo);
2119 if( pObjectInfo != NULL &&
2120 pObjectInfo->Fcb != NULL)
2124 // Reference the node so it won't be torn down
2127 lCount = AFSObjectInfoIncrement( pObjectInfo);
2129 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2130 AFS_TRACE_LEVEL_VERBOSE,
2131 "AFSProcessExtentFailure Increment count on object %p Cnt %d\n",
2136 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2138 if( !NT_SUCCESS( ntStatus) ||
2139 pObjectInfo == NULL ||
2140 pObjectInfo->Fcb == NULL)
2143 if( pObjectInfo == NULL)
2145 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2146 AFS_TRACE_LEVEL_ERROR,
2147 "AFSProcessExtentFailure Invalid file index %I64X\n",
2152 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2153 AFS_TRACE_LEVEL_ERROR,
2154 "AFSProcessExtentFailure Fcb dealocated for %I64X\n",
2158 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2161 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2162 AFS_TRACE_LEVEL_VERBOSE,
2163 "AFSProcessExtentFailure Acquiring Fcb extent lock %p EXCL %08lX\n",
2164 &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2165 PsGetCurrentThread());
2167 AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2170 pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestStatus = pFailureCB->FailureStatus;
2172 RtlCopyMemory( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2173 &pFailureCB->AuthGroup,
2176 KeSetEvent( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
2180 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2181 AFS_TRACE_LEVEL_VERBOSE,
2182 "AFSProcessExtentFailure Releasing Fcb extent lock %p EXCL %08lX\n",
2183 &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2184 PsGetCurrentThread());
2186 AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource);
2188 lCount = AFSObjectInfoDecrement( pObjectInfo);
2190 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2191 AFS_TRACE_LEVEL_VERBOSE,
2192 "AFSProcessExtentFailure Decrement count on object %p Cnt %d\n",
2201 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
2203 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2204 AFS_TRACE_LEVEL_VERBOSE,
2205 "AFSProcessExtentFailure Decrement count on volume %p Cnt %d\n",
2215 AFSProcessReleaseFileExtents( IN PIRP Irp)
2217 NTSTATUS ntStatus = STATUS_SUCCESS;
2218 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2219 AFSFcb *pFcb = NULL;
2220 AFSVolumeCB *pVolumeCB = NULL;
2221 AFSDeviceExt *pDevExt;
2222 AFSReleaseFileExtentsCB *pExtents;
2223 AFSReleaseFileExtentsResultCB *pResult = NULL;
2224 AFSReleaseFileExtentsResultFileCB *pFile = NULL;
2226 ULONGLONG ullIndex = 0;
2227 AFSObjectInfoCB *pObjectInfo = NULL;
2228 BOOLEAN bLocked = FALSE;
2229 BOOLEAN bDirtyExtents = FALSE;
2236 pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2238 pExtents = (AFSReleaseFileExtentsCB*) Irp->AssociatedIrp.SystemBuffer;
2240 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2241 sizeof( AFSReleaseFileExtentsCB))
2244 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2245 AFS_TRACE_LEVEL_ERROR,
2246 "AFSProcessReleaseFileExtents INPUT Buffer too small\n");
2248 try_return( ntStatus = STATUS_INVALID_PARAMETER );
2251 if ( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength <
2252 sizeof(AFSReleaseFileExtentsResultCB))
2255 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2256 AFS_TRACE_LEVEL_ERROR,
2257 "AFSProcessReleaseFileExtents OUTPUT Buffer too small [1]\n");
2260 // Must have space for one extent in one file
2263 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL);
2266 if (pExtents->ExtentCount == 0)
2269 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2270 AFS_TRACE_LEVEL_ERROR,
2271 "AFSProcessReleaseFileExtents Extent count zero\n");
2273 try_return( ntStatus = STATUS_INVALID_PARAMETER);
2276 if (pExtents->FileId.Cell != 0 ||
2277 pExtents->FileId.Volume != 0 ||
2278 pExtents->FileId.Vnode != 0 ||
2279 pExtents->FileId.Unique != 0)
2282 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2283 AFS_TRACE_LEVEL_VERBOSE,
2284 "AFSProcessReleaseFileExtents Processing FID %08lX:%08lX:%08lX:%08lX\n",
2285 pExtents->FileId.Cell,
2286 pExtents->FileId.Volume,
2287 pExtents->FileId.Vnode,
2288 pExtents->FileId.Unique);
2290 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2291 ( FIELD_OFFSET( AFSReleaseFileExtentsCB, ExtentCount) + sizeof(ULONG)) ||
2292 pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2293 ( FIELD_OFFSET( AFSReleaseFileExtentsCB, ExtentCount) + sizeof(ULONG) +
2294 sizeof (AFSFileExtentCB) * pExtents->ExtentCount))
2297 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2298 AFS_TRACE_LEVEL_ERROR,
2299 "AFSProcessReleaseFileExtents Buffer too small for FID %08lX:%08lx:%08lX:%08lX\n",
2300 pExtents->FileId.Cell,
2301 pExtents->FileId.Volume,
2302 pExtents->FileId.Vnode,
2303 pExtents->FileId.Unique);
2305 try_return( ntStatus = STATUS_INVALID_PARAMETER );
2308 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2309 AFS_TRACE_LEVEL_VERBOSE,
2310 "AFSProcessReleaseFileExtents Acquiring RDR VolumeTreeLock lock %p SHARED %08lX\n",
2311 &pDevExt->Specific.RDR.VolumeTreeLock,
2312 PsGetCurrentThread());
2314 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
2317 // Locate the volume node
2320 ullIndex = AFSCreateHighIndex( &pExtents->FileId);
2322 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
2324 (AFSBTreeEntry **)&pVolumeCB);
2326 if( pVolumeCB != NULL)
2329 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
2331 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2332 AFS_TRACE_LEVEL_VERBOSE,
2333 "AFSProcessReleaseFileExtents Increment count on volume %p Cnt %d\n",
2338 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
2340 if( !NT_SUCCESS( ntStatus) ||
2344 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2345 AFS_TRACE_LEVEL_ERROR,
2346 "AFSProcessReleaseFileExtents Invalid volume index %I64X status %08X\n",
2347 ullIndex, ntStatus);
2349 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2352 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2353 AFS_TRACE_LEVEL_VERBOSE,
2354 "AFSProcessReleaseFileExtents Acquiring VolumeRoot FileIDTree.TreeLock lock %p SHARED %08lX\n",
2355 pVolumeCB->ObjectInfoTree.TreeLock,
2356 PsGetCurrentThread());
2358 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
2362 // Now locate the Object in this volume
2365 ullIndex = AFSCreateLowIndex( &pExtents->FileId);
2367 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
2369 (AFSBTreeEntry **)&pObjectInfo);
2371 if( pObjectInfo != NULL)
2375 // Reference the node so it won't be torn down
2378 lCount = AFSObjectInfoIncrement( pObjectInfo);
2380 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2381 AFS_TRACE_LEVEL_VERBOSE,
2382 "AFSProcessReleaseFileExtents Increment count on object %p Cnt %d\n",
2387 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2389 if( !NT_SUCCESS( ntStatus) ||
2390 pObjectInfo == NULL)
2393 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2394 AFS_TRACE_LEVEL_ERROR,
2395 "AFSProcessReleaseFileExtents Invalid file index %I64X\n",
2398 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2401 pFcb = pObjectInfo->Fcb;
2406 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2407 AFS_TRACE_LEVEL_ERROR,
2408 "AFSProcessReleaseFileExtents Fcb not initialied (NO EXTENTS) for FID %08lX:%08lx:%08lX:%08lX\n",
2409 pExtents->FileId.Cell,
2410 pExtents->FileId.Volume,
2411 pExtents->FileId.Vnode,
2412 pExtents->FileId.Unique);
2414 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2417 AFSLockForExtentsTrim( pFcb );
2425 // Locate an Fcb to trim down
2428 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2429 AFS_TRACE_LEVEL_VERBOSE,
2430 "AFSProcessReleaseFileExtents Searching for a Fcb to Trim Down\n");
2432 pFcb = AFSFindFcbToClean( 0, NULL, FALSE);
2437 pFcb = AFSFindFcbToClean( 0, NULL, TRUE);
2443 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2444 AFS_TRACE_LEVEL_ERROR,
2445 "AFSProcessReleaseFileExtents Failed to locate Fcb for release ...\n");
2447 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2450 pObjectInfo = pFcb->ObjectInformation;
2456 // Allocate a scratch buffer to move in the extent information
2459 ulSz = (pExtents->ExtentCount-1) * sizeof(AFSFileExtentCB);
2460 ulSz += sizeof(AFSReleaseFileExtentsResultCB);
2462 if (ulSz > pIrpSp->Parameters.DeviceIoControl.OutputBufferLength)
2464 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2465 AFS_TRACE_LEVEL_ERROR,
2466 "AFSProcessReleaseFileExtents OUTPUT Buffer too small [2]\n");
2468 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL );
2471 pResult = (AFSReleaseFileExtentsResultCB*) AFSExAllocatePoolWithTag( PagedPool,
2473 AFS_EXTENTS_RESULT_TAG);
2474 if (NULL == pResult)
2477 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2478 AFS_TRACE_LEVEL_ERROR,
2479 "AFSProcessReleaseFileExtents Failed to allocate result block\n");
2481 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2485 // Set up the header (for an array of one)
2487 pResult->FileCount = 1;
2488 pResult->Flags = AFS_EXTENT_FLAG_RELEASE;
2489 ulSz -= FIELD_OFFSET(AFSReleaseFileExtentsResultCB, Files);
2492 // Setup the first (and only) file
2494 pFile = pResult->Files;
2495 pFile->FileId = pObjectInfo->FileId;
2496 pFile->Flags = AFS_EXTENT_FLAG_RELEASE;
2499 // Stash away the auth group
2502 RtlZeroMemory( &stAuthGroup,
2505 ntStatus = AFSRetrieveValidAuthGroup( pFcb,
2510 if( !NT_SUCCESS( ntStatus))
2512 try_return( ntStatus);
2515 RtlCopyMemory( &pFile->AuthGroup,
2520 // Update the metadata for this call
2523 pFile->AllocationSize = pFcb->ObjectInformation->EndOfFile;
2524 pFile->CreateTime = pFcb->ObjectInformation->CreationTime;
2525 pFile->ChangeTime = pFcb->ObjectInformation->ChangeTime;
2526 pFile->LastAccessTime = pFcb->ObjectInformation->LastAccessTime;
2527 pFile->LastWriteTime = pFcb->ObjectInformation->LastWriteTime;
2529 ulSz -= FIELD_OFFSET(AFSReleaseFileExtentsResultFileCB, FileExtents);
2531 ntStatus = AFSReleaseSpecifiedExtents( pExtents,
2535 &pFile->ExtentCount,
2538 if (!NT_SUCCESS(ntStatus))
2541 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2542 AFS_TRACE_LEVEL_ERROR,
2543 "AFSProcessReleaseFileExtents Failed to release extents Status %08lX\n",
2546 try_return( ntStatus );
2549 if( pExtents->ExtentCount == 0)
2552 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2553 AFS_TRACE_LEVEL_WARNING,
2554 "AFSProcessReleaseFileExtents Failed to release ANY extents\n");
2557 ulSz = sizeof(AFSReleaseFileExtentsResultCB);
2559 if( pExtents->ExtentCount > 0)
2561 ulSz += ((pExtents->ExtentCount-1) * sizeof(AFSFileExtentCB));
2564 RtlCopyMemory( Irp->AssociatedIrp.SystemBuffer,
2573 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2574 AFS_TRACE_LEVEL_VERBOSE,
2575 "AFSProcessReleaseFileExtents Releasing Fcb extent lock %p thread %08lX\n",
2576 &pFcb->NPFcb->Specific.File.ExtentsResource,
2577 PsGetCurrentThread());
2579 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
2582 if( NULL != pResult &&
2583 Irp->AssociatedIrp.SystemBuffer != pResult)
2586 AFSExFreePoolWithTag(pResult, AFS_EXTENTS_RESULT_TAG);
2589 if (NT_SUCCESS(ntStatus))
2591 Irp->IoStatus.Information = ulSz;
2595 Irp->IoStatus.Information = 0;
2598 Irp->IoStatus.Status = ntStatus;
2600 if( pObjectInfo != NULL)
2603 lCount = AFSObjectInfoDecrement( pObjectInfo);
2605 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2606 AFS_TRACE_LEVEL_VERBOSE,
2607 "AFSProcessReleaseFileExtents Decrement count on object %p Cnt %d\n",
2615 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
2617 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2618 AFS_TRACE_LEVEL_VERBOSE,
2619 "AFSProcessReleaseFileExtents Decrement count on volume %p Cnt %d\n",
2630 AFSWaitForExtentMapping( AFSFcb *Fcb,
2633 NTSTATUS ntStatus = STATUS_SUCCESS;
2634 LARGE_INTEGER liTimeOut;
2635 ULONGLONG ullProcessId = (ULONGLONG)PsGetCurrentProcessId();
2640 ASSERT( !ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
2642 if (!NT_SUCCESS( Fcb->NPFcb->Specific.File.ExtentsRequestStatus))
2646 // If this isn't the same authgroup which caused the failure
2647 // then try to request them again
2650 if( RtlCompareMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2652 sizeof( GUID)) == sizeof( GUID))
2655 ntStatus = Fcb->NPFcb->Specific.File.ExtentsRequestStatus;
2657 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
2659 RtlZeroMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2662 try_return( ntStatus);
2666 liTimeOut.QuadPart = -(1 * AFS_ONE_SECOND);
2668 ntStatus = KeWaitForSingleObject( &Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
2674 if (!NT_SUCCESS( Fcb->NPFcb->Specific.File.ExtentsRequestStatus))
2678 // If this isn't the same authgroup which caused the failure
2679 // or the System Process,
2680 // then try to request the extents again
2683 if( RtlCompareMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2685 sizeof( GUID)) == sizeof( GUID) ||
2686 ullProcessId == (ULONGLONG)AFSSysProcess)
2689 ntStatus = Fcb->NPFcb->Specific.File.ExtentsRequestStatus;
2691 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
2693 RtlZeroMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2696 try_return( ntStatus);
2700 if( ntStatus == STATUS_TIMEOUT)
2703 ntStatus = STATUS_SUCCESS;
2715 AFSFlushExtents( IN AFSFcb *Fcb,
2718 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
2719 AFSExtent *pExtent, *pNextExtent;
2720 AFSReleaseExtentsCB *pRelease = NULL;
2722 ULONG initialDirtyCount = 0;
2723 BOOLEAN bExtentsLocked = FALSE;
2726 NTSTATUS ntStatus = STATUS_SUCCESS;
2727 LARGE_INTEGER liLastFlush;
2728 GUID *pAuthGroup = AuthGroup;
2732 ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
2735 // Save, then reset the flush time
2738 liLastFlush = Fcb->Specific.File.LastServerFlush;
2740 KeQueryTickCount( &Fcb->Specific.File.LastServerFlush);
2745 lCount = InterlockedIncrement( &Fcb->Specific.File.QueuedFlushCount);
2747 if( pAuthGroup == NULL ||
2748 RtlCompareMemory( pAuthGroup,
2749 &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2750 sizeof( GUID)) == sizeof( GUID))
2753 RtlZeroMemory( &stAuthGroup,
2756 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
2761 if( !NT_SUCCESS( ntStatus))
2763 try_return( ntStatus);
2766 pAuthGroup = &stAuthGroup;
2770 // Lock extents while we count and set up the array to send to
2774 AFSLockForExtentsTrim( Fcb);
2776 bExtentsLocked = TRUE;
2779 // Clear our queued flush event
2782 KeClearEvent( &Fcb->NPFcb->Specific.File.QueuedFlushEvent);
2785 // Look for a start in the list to flush entries
2790 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
2792 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
2794 AFS_EXTENT_RELEASE_TAG);
2795 if( NULL == pRelease)
2798 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2801 initialDirtyCount = Fcb->Specific.File.ExtentsDirtyCount;
2803 while( Fcb->Specific.File.ExtentsDirtyCount > 0)
2806 pRelease->Flags = AFS_EXTENT_FLAG_DIRTY;
2808 if( BooleanFlagOn( Fcb->Flags, AFS_FCB_FILE_CLOSED))
2811 pRelease->Flags |= AFS_EXTENT_FLAG_FLUSH;
2815 // Update the metadata for this call
2818 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
2819 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
2820 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
2821 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
2822 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
2826 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
2829 pExtent = (AFSExtent *)pNPFcb->Specific.File.DirtyListHead;
2831 while( count < AFS_MAXIMUM_EXTENT_RELEASE_COUNT)
2834 if ( pExtent == NULL)
2840 pNextExtent = (AFSExtent *)pExtent->DirtyList.fLink;
2842 if ( pExtent->ActiveCount > 0)
2844 pExtent = pNextExtent;
2848 AFSRemoveEntryDirtyList( Fcb, pExtent);
2850 pExtent->DirtyList.fLink = NULL;
2851 pExtent->DirtyList.bLink = NULL;
2853 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
2856 // Clear the flag in advance of the write. If we do
2857 // things this was we know that the clear is
2858 // pessimistic (any write which happens from now on
2859 // will set the flag dirty again).
2862 pExtent->Flags &= ~AFS_EXTENT_DIRTY;
2864 pRelease->FileExtents[count].Flags = AFS_EXTENT_FLAG_DIRTY;
2866 pRelease->FileExtents[count].Length = pExtent->Size;
2867 pRelease->FileExtents[count].DirtyLength = pExtent->Size;
2868 pRelease->FileExtents[count].DirtyOffset = 0;
2869 pRelease->FileExtents[count].CacheOffset = pExtent->CacheOffset;
2870 pRelease->FileExtents[count].FileOffset = pExtent->FileOffset;
2873 RtlCopyMemory( pRelease->FileExtents[count].MD5,
2875 sizeof(pExtent->MD5));
2877 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_MD5_SET;
2880 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2881 AFS_TRACE_LEVEL_VERBOSE,
2882 "AFSFlushExtents Releasing DIRTY extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
2884 Fcb->ObjectInformation->FileId.Cell,
2885 Fcb->ObjectInformation->FileId.Volume,
2886 Fcb->ObjectInformation->FileId.Vnode,
2887 Fcb->ObjectInformation->FileId.Unique,
2888 pExtent->FileOffset.QuadPart,
2891 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_RELEASE;
2898 pExtent = pNextExtent;
2901 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
2904 // If we are done then get out
2910 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2911 AFS_TRACE_LEVEL_VERBOSE,
2912 "AFSFlushExtents No more dirty extents found\n");
2918 // Fire off the request synchronously
2921 sz = sizeof( AFSReleaseExtentsCB ) + (count * sizeof ( AFSFileExtentCB ));
2923 pRelease->ExtentCount = count;
2925 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2926 AFS_TRACE_LEVEL_VERBOSE,
2927 "AFSFlushExtents Releasing(1) Fcb extents lock %p SHARED %08lX\n",
2928 &pNPFcb->Specific.File.ExtentsResource,
2929 PsGetCurrentThread());
2931 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource);
2932 bExtentsLocked = FALSE;
2934 KeSetEvent( &pNPFcb->Specific.File.FlushEvent,
2938 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
2939 AFS_REQUEST_FLAG_SYNCHRONOUS,
2942 &Fcb->ObjectInformation->FileId,
2948 if( !NT_SUCCESS(ntStatus))
2952 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
2953 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
2956 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2957 AFS_TRACE_LEVEL_ERROR,
2958 "AFSFlushExtents AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2959 Fcb->ObjectInformation->FileId.Cell,
2960 Fcb->ObjectInformation->FileId.Volume,
2961 Fcb->ObjectInformation->FileId.Vnode,
2962 Fcb->ObjectInformation->FileId.Unique,
2967 AFSLockForExtentsTrim( Fcb);
2969 bExtentsLocked = TRUE;
2974 lCount = InterlockedDecrement( &Fcb->Specific.File.QueuedFlushCount);
2976 ASSERT( lCount >= 0);
2981 KeSetEvent( &pNPFcb->Specific.File.QueuedFlushEvent,
2986 KeSetEvent( &pNPFcb->Specific.File.FlushEvent,
2993 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2994 AFS_TRACE_LEVEL_VERBOSE,
2995 "AFSFlushExtents Releasing(2) Fcb extents lock %p SHARED %08lX\n",
2996 &pNPFcb->Specific.File.ExtentsResource,
2997 PsGetCurrentThread());
2999 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
3004 AFSExFreePoolWithTag( pRelease, AFS_EXTENT_RELEASE_TAG);
3012 AFSReleaseExtentsWithFlush( IN AFSFcb *Fcb,
3014 IN BOOLEAN bReleaseAll)
3016 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3019 AFSReleaseExtentsCB *pRelease = NULL;
3021 BOOLEAN bExtentsLocked = FALSE;
3024 NTSTATUS ntStatus = STATUS_SUCCESS;
3025 LARGE_INTEGER liLastFlush;
3026 ULONG ulRemainingExtentLength = 0;
3027 GUID *pAuthGroup = AuthGroup;
3031 ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
3034 // Save, then reset the flush time
3037 liLastFlush = Fcb->Specific.File.LastServerFlush;
3039 KeQueryTickCount( &Fcb->Specific.File.LastServerFlush);
3044 if( pAuthGroup == NULL ||
3045 RtlCompareMemory( pAuthGroup,
3046 &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
3047 sizeof( GUID)) == sizeof( GUID))
3050 RtlZeroMemory( &stAuthGroup,
3053 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
3058 if( !NT_SUCCESS( ntStatus))
3060 try_return( ntStatus);
3063 pAuthGroup = &stAuthGroup;
3067 // Look for a start in the list to flush entries
3072 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
3074 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
3076 AFS_EXTENT_RELEASE_TAG);
3077 if( NULL == pRelease)
3080 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
3083 if( Fcb->OpenHandleCount > 0 &&
3088 // Don't release everything ...
3091 ulRemainingExtentLength = 1024;
3094 while( Fcb->Specific.File.ExtentLength > (LONG)ulRemainingExtentLength)
3097 AFSLockForExtentsTrim( Fcb);
3099 bExtentsLocked = TRUE;
3101 pRelease->Flags = AFS_EXTENT_FLAG_RELEASE;
3104 // Update the metadata for this call
3107 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
3108 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
3109 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
3110 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
3111 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
3115 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3117 while( count < AFS_MAXIMUM_EXTENT_RELEASE_COUNT &&
3118 le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
3121 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3125 if( pExtent->ActiveCount > 0)
3131 pRelease->FileExtents[count].Flags = AFS_EXTENT_FLAG_RELEASE;
3133 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3134 AFS_TRACE_LEVEL_VERBOSE,
3135 "AFSReleaseExtentsWithFlush Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3137 Fcb->ObjectInformation->FileId.Cell,
3138 Fcb->ObjectInformation->FileId.Volume,
3139 Fcb->ObjectInformation->FileId.Vnode,
3140 Fcb->ObjectInformation->FileId.Unique,
3141 pExtent->FileOffset.QuadPart,
3144 pRelease->FileExtents[count].Length = pExtent->Size;
3145 pRelease->FileExtents[count].DirtyLength = pExtent->Size;
3146 pRelease->FileExtents[count].DirtyOffset = 0;
3147 pRelease->FileExtents[count].CacheOffset = pExtent->CacheOffset;
3148 pRelease->FileExtents[count].FileOffset = pExtent->FileOffset;
3151 RtlCopyMemory( pRelease->FileExtents[count].MD5,
3153 sizeof(pExtent->MD5));
3155 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_MD5_SET;
3158 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3161 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3164 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3167 AFSRemoveEntryDirtyList( Fcb,
3170 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_DIRTY;
3172 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
3175 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3185 // If we are done then get out
3191 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3192 AFS_TRACE_LEVEL_VERBOSE,
3193 "AFSReleaseExtentsWithFlush No more dirty extents found\n");
3199 // Fire off the request synchronously
3202 sz = sizeof( AFSReleaseExtentsCB ) + (count * sizeof ( AFSFileExtentCB ));
3204 pRelease->ExtentCount = count;
3207 // Drop the extents lock for the duration of the call to
3208 // the network. We have pinned the extents so, even
3209 // though we might get extents added during this period,
3210 // but none will be removed. Hence we can carry on from
3214 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3215 AFS_TRACE_LEVEL_VERBOSE,
3216 "AFSReleaseExtentsWithFlush Releasing Fcb extents lock %p thread %08lX\n",
3217 &pNPFcb->Specific.File.ExtentsResource,
3218 PsGetCurrentThread());
3220 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource);
3221 bExtentsLocked = FALSE;
3223 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
3224 AFS_REQUEST_FLAG_SYNCHRONOUS,
3227 &Fcb->ObjectInformation->FileId,
3233 if( !NT_SUCCESS(ntStatus))
3237 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
3238 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
3241 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3242 AFS_TRACE_LEVEL_ERROR,
3243 "AFSReleaseExtentsWithFlush AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3244 Fcb->ObjectInformation->FileId.Cell,
3245 Fcb->ObjectInformation->FileId.Volume,
3246 Fcb->ObjectInformation->FileId.Vnode,
3247 Fcb->ObjectInformation->FileId.Unique,
3257 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3258 AFS_TRACE_LEVEL_VERBOSE,
3259 "AFSReleaseExtentsWithFlush Releasing Fcb extents lock %p thread %08lX\n",
3260 &pNPFcb->Specific.File.ExtentsResource,
3261 PsGetCurrentThread());
3263 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
3268 AFSExFreePoolWithTag( pRelease, AFS_EXTENT_RELEASE_TAG);
3276 AFSReleaseCleanExtents( IN AFSFcb *Fcb,
3279 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3282 AFSReleaseExtentsCB *pRelease = NULL;
3284 BOOLEAN bExtentsLocked = FALSE;
3287 NTSTATUS ntStatus = STATUS_SUCCESS;
3288 LARGE_INTEGER liLastFlush;
3289 ULONG ulRemainingExtentLength = 0;
3290 GUID *pAuthGroup = AuthGroup;
3293 ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
3296 // Save, then reset the flush time
3299 liLastFlush = Fcb->Specific.File.LastServerFlush;
3301 KeQueryTickCount( &Fcb->Specific.File.LastServerFlush);
3306 if( pAuthGroup == NULL ||
3307 RtlCompareMemory( pAuthGroup,
3308 &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
3309 sizeof( GUID)) == sizeof( GUID))
3312 RtlZeroMemory( &stAuthGroup,
3315 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
3320 if( !NT_SUCCESS( ntStatus))
3322 try_return( ntStatus);
3325 pAuthGroup = &stAuthGroup;
3329 // Look for a start in the list to flush entries
3334 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
3336 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
3338 AFS_EXTENT_RELEASE_TAG);
3339 if( NULL == pRelease)
3342 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
3345 while( Fcb->Specific.File.ExtentLength > (LONG)ulRemainingExtentLength)
3348 AFSLockForExtentsTrim( Fcb);
3350 bExtentsLocked = TRUE;
3352 pRelease->Flags = AFS_EXTENT_FLAG_RELEASE;
3355 // Update the metadata for this call
3358 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
3359 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
3360 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
3361 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
3362 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
3366 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3368 while( count < AFS_MAXIMUM_EXTENT_RELEASE_COUNT &&
3369 le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
3372 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3376 if( pExtent->ActiveCount > 0 ||
3377 BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3382 pRelease->FileExtents[count].Flags = AFS_EXTENT_FLAG_RELEASE;
3384 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3385 AFS_TRACE_LEVEL_VERBOSE,
3386 "AFSReleaseCleanExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3388 Fcb->ObjectInformation->FileId.Cell,
3389 Fcb->ObjectInformation->FileId.Volume,
3390 Fcb->ObjectInformation->FileId.Vnode,
3391 Fcb->ObjectInformation->FileId.Unique,
3392 pExtent->FileOffset.QuadPart,
3395 pRelease->FileExtents[count].Length = pExtent->Size;
3396 pRelease->FileExtents[count].DirtyLength = pExtent->Size;
3397 pRelease->FileExtents[count].DirtyOffset = 0;
3398 pRelease->FileExtents[count].CacheOffset = pExtent->CacheOffset;
3399 pRelease->FileExtents[count].FileOffset = pExtent->FileOffset;
3402 RtlCopyMemory( pRelease->FileExtents[count].MD5,
3404 sizeof(pExtent->MD5));
3406 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_MD5_SET;
3416 // If we are done then get out
3422 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3423 AFS_TRACE_LEVEL_VERBOSE,
3424 "AFSReleaseCleanExtents No more dirty extents found\n");
3430 // Fire off the request synchronously
3433 sz = sizeof( AFSReleaseExtentsCB ) + (count * sizeof ( AFSFileExtentCB ));
3435 pRelease->ExtentCount = count;
3438 // Drop the extents lock for the duration of the call to
3439 // the network. We have pinned the extents so, even
3440 // though we might get extents added during this period,
3441 // but none will be removed. Hence we can carry on from
3445 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3446 AFS_TRACE_LEVEL_VERBOSE,
3447 "AFSReleaseCleanExtents Releasing Fcb extents lock %p thread %08lX\n",
3448 &pNPFcb->Specific.File.ExtentsResource,
3449 PsGetCurrentThread());
3451 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource);
3452 bExtentsLocked = FALSE;
3454 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
3455 AFS_REQUEST_FLAG_SYNCHRONOUS,
3458 &Fcb->ObjectInformation->FileId,
3464 if( !NT_SUCCESS(ntStatus))
3468 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
3469 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
3472 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3473 AFS_TRACE_LEVEL_ERROR,
3474 "AFSReleaseCleanExtents AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3475 Fcb->ObjectInformation->FileId.Cell,
3476 Fcb->ObjectInformation->FileId.Volume,
3477 Fcb->ObjectInformation->FileId.Vnode,
3478 Fcb->ObjectInformation->FileId.Unique,
3488 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3489 AFS_TRACE_LEVEL_VERBOSE,
3490 "AFSReleaseCleanExtents Releasing Fcb extents lock %p thread %08lX\n",
3491 &pNPFcb->Specific.File.ExtentsResource,
3492 PsGetCurrentThread());
3494 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
3499 AFSExFreePoolWithTag( pRelease, AFS_EXTENT_RELEASE_TAG);
3507 AFSMarkDirty( IN AFSFcb *Fcb,
3508 IN AFSExtent *StartExtent,
3509 IN ULONG ExtentsCount,
3510 IN LARGE_INTEGER *StartingByte,
3511 IN BOOLEAN DerefExtents)
3514 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3515 AFSExtent *pExtent = StartExtent;
3516 AFSExtent *pNextExtent, *pCurrentExtent = NULL;
3518 BOOLEAN bInsertTail = FALSE, bInsertHead = FALSE;
3521 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3522 AFS_TRACE_LEVEL_VERBOSE,
3523 "AFSMarkDirty Acquiring Fcb extents lock %p SHARED %08lX\n",
3524 &Fcb->NPFcb->Specific.File.ExtentsResource,
3525 PsGetCurrentThread());
3527 ASSERT( ExIsResourceAcquiredLite( &pNPFcb->Specific.File.ExtentsResource));
3529 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3535 // Find the insertion point
3538 if( pNPFcb->Specific.File.DirtyListHead == NULL)
3543 else if( StartingByte->QuadPart == 0)
3551 pCurrentExtent = pNPFcb->Specific.File.DirtyListHead;
3553 while( pCurrentExtent != NULL)
3556 if( pCurrentExtent->FileOffset.QuadPart + pCurrentExtent->Size >= StartingByte->QuadPart ||
3557 pCurrentExtent->DirtyList.fLink == NULL)
3563 pCurrentExtent = (AFSExtent *)pCurrentExtent->DirtyList.fLink;
3567 while( ulCount < ExtentsCount)
3570 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
3572 if( !BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3575 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3576 AFS_TRACE_LEVEL_VERBOSE,
3577 "AFSMarkDirty Marking extent offset %I64X Length %08lX DIRTY\n",
3578 pExtent->FileOffset.QuadPart,
3581 pExtent->DirtyList.fLink = NULL;
3582 pExtent->DirtyList.bLink = NULL;
3587 pExtent->DirtyList.fLink = (void *)pNPFcb->Specific.File.DirtyListHead;
3589 pExtent->DirtyList.bLink = NULL;
3591 pNPFcb->Specific.File.DirtyListHead->DirtyList.bLink = (void *)pExtent;
3593 pNPFcb->Specific.File.DirtyListHead = pExtent;
3595 pCurrentExtent = pExtent;
3597 bInsertHead = FALSE;
3599 else if( bInsertTail)
3602 if( pNPFcb->Specific.File.DirtyListHead == NULL)
3605 pNPFcb->Specific.File.DirtyListHead = pExtent;
3610 pNPFcb->Specific.File.DirtyListTail->DirtyList.fLink = (void *)pExtent;
3612 pExtent->DirtyList.bLink = (void *)pNPFcb->Specific.File.DirtyListTail;
3615 pNPFcb->Specific.File.DirtyListTail = pExtent;
3620 pExtent->DirtyList.fLink = pCurrentExtent->DirtyList.fLink;
3622 pExtent->DirtyList.bLink = (void *)pCurrentExtent;
3624 if( pExtent->DirtyList.fLink == NULL)
3627 pNPFcb->Specific.File.DirtyListTail = pExtent;
3632 ((AFSExtent *)pExtent->DirtyList.fLink)->DirtyList.bLink = (void *)pExtent;
3635 pCurrentExtent->DirtyList.fLink = (void *)pExtent;
3637 pCurrentExtent = pExtent;
3640 pExtent->Flags |= AFS_EXTENT_DIRTY;
3643 // Up the dirty count
3646 lCount = InterlockedIncrement( &Fcb->Specific.File.ExtentsDirtyCount);
3651 pCurrentExtent = pExtent;
3654 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_ACTIVE_COUNTING,
3655 AFS_TRACE_LEVEL_VERBOSE,
3656 "AFSMarkDirty Decrement count on extent %08lX Cnt %d\n",
3658 pExtent->ActiveCount);
3662 ASSERT( pExtent->ActiveCount > 0);
3663 lCount = InterlockedDecrement( &pExtent->ActiveCount);
3666 pExtent = pNextExtent;
3671 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
3676 "EXCEPTION - AFSMarkDirty\n");
3678 AFSDumpTraceFilesFnc();
3681 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3683 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3684 AFS_TRACE_LEVEL_VERBOSE,
3685 "AFSMarkDirty Releasing Fcb extents lock %p SHARED %08lX\n",
3686 &Fcb->NPFcb->Specific.File.ExtentsResource,
3687 PsGetCurrentThread());
3697 ExtentFor(PLIST_ENTRY le, ULONG SkipList)
3700 return CONTAINING_RECORD( le, AFSExtent, Lists[SkipList] );
3704 NextExtent(AFSExtent *Extent, ULONG SkipList)
3707 return ExtentFor(Extent->Lists[SkipList].Flink, SkipList);
3710 #if AFS_VALIDATE_EXTENTS
3711 static AFSExtent *DirtyExtentFor(PLIST_ENTRY le)
3714 return CONTAINING_RECORD( le, AFSExtent, DirtyList );
3717 static VOID VerifyExtentsLists(AFSFcb *Fcb)
3721 // Check the ordering of the extents lists
3723 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
3725 ASSERT(Fcb->Specific.File.ExtentsLists[0].Flink != &Fcb->Specific.File.ExtentsLists[1]);
3727 for (ULONG listNo = 0; listNo < AFS_NUM_EXTENT_LISTS; listNo ++)
3729 LARGE_INTEGER lastOffset;
3731 lastOffset.QuadPart = 0;
3733 for (PLIST_ENTRY pLe = Fcb->Specific.File.ExtentsLists[listNo].Flink;
3734 pLe != &Fcb->Specific.File.ExtentsLists[listNo];
3739 pExtent = ExtentFor(pLe, listNo);
3742 ASSERT(pLe != &Fcb->Specific.File.ExtentsLists[1] &&
3743 pLe->Flink !=&Fcb->Specific.File.ExtentsLists[1] &&
3744 pLe->Blink !=&Fcb->Specific.File.ExtentsLists[1]);
3747 ASSERT(pLe->Flink->Blink == pLe);
3748 ASSERT(pLe->Blink->Flink == pLe);
3751 // Should follow on from previous
3753 ASSERT(pExtent->FileOffset.QuadPart >= lastOffset.QuadPart);
3754 lastOffset.QuadPart = pExtent->FileOffset.QuadPart + pExtent->Size;
3757 // Should match alignment criteria
3759 ASSERT( 0 == (pExtent->FileOffset.LowPart & ExtentsMasks[listNo]) );
3762 // "lower" lists should be populated
3764 for (LONG subListNo = listNo-1; subListNo > 0; subListNo --)
3766 ASSERT( !IsListEmpty(&pExtent->Lists[subListNo]));
3775 AFSTrimExtents( IN AFSFcb *Fcb,
3776 IN PLARGE_INTEGER FileSize)
3779 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3782 BOOLEAN locked = FALSE;
3783 NTSTATUS ntStatus = STATUS_SUCCESS;
3784 LARGE_INTEGER liAlignedOffset = {0,0};
3785 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
3791 // Get an aligned offset
3794 if( FileSize != NULL)
3797 liAlignedOffset = *FileSize;
3800 if( liAlignedOffset.QuadPart > 0 &&
3801 liAlignedOffset.QuadPart % pDevExt->Specific.RDR.CacheBlockSize != 0)
3805 // Align UP to the next cache block size
3808 liAlignedOffset.QuadPart = (ULONGLONG)( (ULONGLONG)((liAlignedOffset.QuadPart / pDevExt->Specific.RDR.CacheBlockSize) + 1) * (ULONGLONG)pDevExt->Specific.RDR.CacheBlockSize);
3812 // Ensure that no one is working with the extents and grab the
3816 AFSLockForExtentsTrim( Fcb);
3820 if( 0 == Fcb->Specific.File.ExtentCount)
3824 // Update the request extent status
3827 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
3829 try_return( ntStatus = STATUS_SUCCESS);
3833 // We are truncating from a specific length in the file. If the offset
3834 // is non-zero then go find the first extent to remove
3837 if( 0 == FileSize->QuadPart)
3840 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3845 pExtent = AFSExtentForOffset( Fcb,
3849 if( NULL == pExtent)
3852 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3856 le = &pExtent->Lists[AFS_EXTENTS_LIST];
3860 while( le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
3863 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3866 // Only trim down extents beyond the aligned offset
3871 if( pExtent->FileOffset.QuadPart >= liAlignedOffset.QuadPart)
3874 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3877 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3880 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3884 AFSRemoveEntryDirtyList( Fcb,
3887 dirtyCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
3889 ASSERT(dirtyCount >= 0);
3892 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3895 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3896 AFS_TRACE_LEVEL_VERBOSE,
3897 "AFSTrimExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3899 Fcb->ObjectInformation->FileId.Cell,
3900 Fcb->ObjectInformation->FileId.Volume,
3901 Fcb->ObjectInformation->FileId.Vnode,
3902 Fcb->ObjectInformation->FileId.Unique,
3903 pExtent->FileOffset.QuadPart,
3906 ASSERT( pExtent->ActiveCount == 0);
3914 // Update the request extent status
3917 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
3924 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3925 AFS_TRACE_LEVEL_VERBOSE,
3926 "AFSTrimExtents Releasing Fcb extents lock %p thread %08lX\n",
3927 &Fcb->NPFcb->Specific.File.ExtentsResource,
3928 PsGetCurrentThread());
3930 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
3938 AFSTrimSpecifiedExtents( IN AFSFcb *Fcb,
3940 IN AFSFileExtentCB *Result)
3943 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3946 AFSFileExtentCB *pFileExtents = Result;
3951 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3953 while( le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST] &&
3957 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3960 // Only trim down extents beyond the aligned offset
3965 if( pExtent->FileOffset.QuadPart == pFileExtents->FileOffset.QuadPart)
3968 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3971 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3974 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3979 AFSRemoveEntryDirtyList( Fcb,
3982 dirtyCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
3984 ASSERT( dirtyCount >= 0);
3988 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3992 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3993 AFS_TRACE_LEVEL_VERBOSE,
3994 "AFSTrimSpecifiedExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3996 Fcb->ObjectInformation->FileId.Cell,
3997 Fcb->ObjectInformation->FileId.Volume,
3998 Fcb->ObjectInformation->FileId.Vnode,
3999 Fcb->ObjectInformation->FileId.Unique,
4000 pExtent->FileOffset.QuadPart,
4003 ASSERT( pExtent->ActiveCount == 0);
4009 // Next extent we are looking for
4019 // Update the request extent status
4022 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
4029 AFSReferenceActiveExtents( IN AFSExtent *StartExtent,
4030 IN ULONG ExtentsCount)
4033 AFSExtent *pExtent = StartExtent;
4034 AFSExtent *pNextExtent;
4038 while( ulCount < ExtentsCount)
4041 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
4043 lCount = InterlockedIncrement( &pExtent->ActiveCount);
4045 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_ACTIVE_COUNTING,
4046 AFS_TRACE_LEVEL_VERBOSE,
4047 "AFSReferenceActiveExtents Increment count on extent %08lX Cnt %d\n",
4051 pExtent = pNextExtent;
4060 AFSDereferenceActiveExtents( IN AFSExtent *StartExtent,
4061 IN ULONG ExtentsCount)
4064 AFSExtent *pExtent = StartExtent;
4065 AFSExtent *pNextExtent;
4069 while( ulCount < ExtentsCount)
4072 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
4074 ASSERT( pExtent->ActiveCount > 0);
4076 lCount = InterlockedDecrement( &pExtent->ActiveCount);
4078 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_ACTIVE_COUNTING,
4079 AFS_TRACE_LEVEL_VERBOSE,
4080 "AFSDereferenceActiveExtents Decrement count on extent %08lX Cnt %d\n",
4084 pExtent = pNextExtent;
4093 AFSRemoveEntryDirtyList( IN AFSFcb *Fcb,
4094 IN AFSExtent *Extent)
4097 if( Extent->DirtyList.fLink == NULL)
4100 Fcb->NPFcb->Specific.File.DirtyListTail = (AFSExtent *)Extent->DirtyList.bLink;
4102 if( Fcb->NPFcb->Specific.File.DirtyListTail != NULL)
4105 Fcb->NPFcb->Specific.File.DirtyListTail->DirtyList.fLink = NULL;
4111 ((AFSExtent *)Extent->DirtyList.fLink)->DirtyList.bLink = Extent->DirtyList.bLink;
4114 if( Extent->DirtyList.bLink == NULL)
4117 Fcb->NPFcb->Specific.File.DirtyListHead = (AFSExtent *)Extent->DirtyList.fLink;
4119 if( Fcb->NPFcb->Specific.File.DirtyListHead != NULL)
4122 Fcb->NPFcb->Specific.File.DirtyListHead->DirtyList.bLink = NULL;
4128 ((AFSExtent *)Extent->DirtyList.bLink)->DirtyList.fLink = Extent->DirtyList.fLink;
4136 AFSConstructCleanByteRangeList( AFSFcb * pFcb,
4137 AFSByteRange ** pByteRangeList)
4140 ULONG ulByteRangeMax;
4141 ULONG ulByteRangeCount = 0;
4142 AFSByteRange *ByteRangeList;
4143 AFSExtent *pExtent, *pNextExtent;
4145 AFSAcquireShared( &pFcb->NPFcb->Specific.File.DirtyExtentsListLock, TRUE);
4147 ulByteRangeMax = pFcb->Specific.File.ExtentsDirtyCount + 1;
4149 ByteRangeList = (AFSByteRange *) AFSExAllocatePoolWithTag( PagedPool,
4150 ulByteRangeMax * sizeof( AFSByteRange),
4153 if ( ByteRangeList == NULL)
4156 (*pByteRangeList) = NULL;
4158 try_return( ulByteRangeCount = DWORD_MAX);
4161 RtlZeroMemory( ByteRangeList,
4162 ulByteRangeMax * sizeof( AFSByteRange));
4165 // The for loop populates the ByteRangeList entries with values that are
4166 // the gaps in the DirtyList. In other words, if a range is not present
4167 // in the DirtyList it will be represented in the ByteRangeList array.
4170 for ( ulByteRangeCount = 0,
4171 pExtent = (AFSExtent *)pFcb->NPFcb->Specific.File.DirtyListHead;
4172 ulByteRangeCount < ulByteRangeMax && pExtent != NULL;
4173 pExtent = pNextExtent)
4176 pNextExtent = (AFSExtent *)pExtent->DirtyList.fLink;
4179 // The first time the for() is entered the ulByteRangeCount will be zero and
4180 // ByteRangeList[0] FileOffset and Length will both be zero. If the first
4181 // extent is not for offset zero, the ByteRangeList[0] Length is set to the
4182 // FileOffset of the Extent.
4184 // Future passes through the loop behave in a similar fashion but
4185 // ByteRangeList[ulByteRangeCount] FileOffset will have been set below.
4188 if ( pExtent->FileOffset.QuadPart != ByteRangeList[ulByteRangeCount].FileOffset.QuadPart + ByteRangeList[ulByteRangeCount].Length.QuadPart)
4191 ByteRangeList[ulByteRangeCount].Length.QuadPart =
4192 pExtent->FileOffset.QuadPart - ByteRangeList[ulByteRangeCount].FileOffset.QuadPart;
4198 // Having processed the current dirty extent, the following while loop
4199 // searches for the next clean gap between dirty extents.
4202 while ( pNextExtent && pNextExtent->FileOffset.QuadPart == pExtent->FileOffset.QuadPart + pExtent->Size)
4205 pExtent = pNextExtent;
4207 pNextExtent = (AFSExtent *)pExtent->DirtyList.fLink;
4211 // Having found the next gap, the ByteRangeList[] FileOffset is set to the start of the gap.
4212 // The Length is left at zero and will be assigned either when the for loop continues or
4213 // when the for loop exits.
4216 ByteRangeList[ulByteRangeCount].FileOffset.QuadPart = pExtent->FileOffset.QuadPart + pExtent->Size;
4220 // Assign the Length of the final clean range to match the file length.
4223 ByteRangeList[ulByteRangeCount].Length.QuadPart =
4224 pFcb->ObjectInformation->EndOfFile.QuadPart - ByteRangeList[ulByteRangeCount].FileOffset.QuadPart;
4226 (*pByteRangeList) = ByteRangeList;
4230 AFSReleaseResource( &pFcb->NPFcb->Specific.File.DirtyExtentsListLock);
4232 return ulByteRangeCount;
4237 AFSSetupMD5Hash( IN AFSFcb *Fcb,
4238 IN AFSExtent *StartExtent,
4239 IN ULONG ExtentsCount,
4240 IN void *SystemBuffer,
4241 IN LARGE_INTEGER *ByteOffset,
4245 NTSTATUS ntStatus = STATUS_SUCCESS;
4246 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
4247 AFSExtent *pExtent = StartExtent;
4248 AFSExtent *pNextExtent, *pCurrentExtent = NULL;
4250 char *pCurrentBuffer = (char *)SystemBuffer;
4251 char *pMD5Buffer = NULL;
4252 ULONG ulCurrentLen = 0;
4253 void *pExtentBuffer = NULL;
4254 LARGE_INTEGER liByteOffset;
4255 ULONG ulBytesRead = 0;
4260 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4261 AFS_TRACE_LEVEL_VERBOSE,
4262 "AFSSetupMD5Hash Acquiring Fcb extents lock %p SHARED %08lX\n",
4263 &Fcb->NPFcb->Specific.File.ExtentsResource,
4264 PsGetCurrentThread());
4266 AFSAcquireShared( &Fcb->NPFcb->Specific.File.ExtentsResource, TRUE);
4270 liByteOffset.QuadPart = ByteOffset->QuadPart;
4272 while( ulCount < ExtentsCount)
4275 RtlZeroMemory( pExtent->MD5,
4276 sizeof( pExtent->MD5));
4278 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
4280 if( liByteOffset.QuadPart == pExtent->FileOffset.QuadPart &&
4281 ByteCount < pExtent->Size)
4284 if( pExtentBuffer == NULL)
4287 pExtentBuffer = AFSExAllocatePoolWithTag( PagedPool,
4289 AFS_GENERIC_MEMORY_9_TAG);
4291 if( pExtentBuffer == NULL)
4298 RtlZeroMemory( pExtentBuffer,
4301 RtlCopyMemory( pExtentBuffer,
4305 pMD5Buffer = (char *)pExtentBuffer;
4307 ulCurrentLen = ByteCount;
4309 else if( liByteOffset.QuadPart != pExtent->FileOffset.QuadPart)
4312 pExtentBuffer = AFSExAllocatePoolWithTag( PagedPool,
4314 AFS_GENERIC_MEMORY_10_TAG);
4316 if( pExtentBuffer == NULL)
4322 RtlZeroMemory( pExtentBuffer,
4325 if( BooleanFlagOn( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE))
4329 RtlCopyMemory( pExtentBuffer,
4330 ((char *)AFSLibCacheBaseAddress + pExtent->CacheOffset.QuadPart),
4333 ASSERT( pExtent->CacheOffset.HighPart == 0);
4334 RtlCopyMemory( pExtentBuffer,
4335 ((char *)AFSLibCacheBaseAddress + pExtent->CacheOffset.LowPart),
4339 ulBytesRead = pExtent->Size;
4344 ntStatus = AFSReadCacheFile( pExtentBuffer,
4345 &pExtent->CacheOffset,
4349 if( !NT_SUCCESS( ntStatus))
4356 pMD5Buffer = (char *)pExtentBuffer;
4358 ulCurrentLen = min( ByteCount, pExtent->Size - (ULONG)(liByteOffset.QuadPart - pExtent->FileOffset.QuadPart));
4360 RtlCopyMemory( (void *)((char *)pExtentBuffer + (ULONG)(liByteOffset.QuadPart - pExtent->FileOffset.QuadPart)),
4367 ulCurrentLen = pExtent->Size;
4369 pMD5Buffer = pCurrentBuffer;
4372 AFSGenerateMD5( pMD5Buffer,
4376 pExtent = pNextExtent;
4380 ByteCount -= ulCurrentLen;
4382 pCurrentBuffer += ulCurrentLen;
4384 liByteOffset.QuadPart += ulCurrentLen;
4387 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4388 AFS_TRACE_LEVEL_VERBOSE,
4389 "AFSSetupMD5Hash Releasing Fcb extents lock %p SHARED %08lX\n",
4390 &Fcb->NPFcb->Specific.File.ExtentsResource,
4391 PsGetCurrentThread());
4394 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
4399 "EXCEPTION - AFSSetupMD5Hash\n");
4401 AFSDumpTraceFilesFnc();
4404 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
4406 if( pExtentBuffer != NULL)
4409 AFSExFreePoolWithTag( pExtentBuffer, AFS_GENERIC_MEMORY_9_TAG);