2 * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3 * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * - Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
14 * this list of conditions and the following disclaimer in the
16 * and/or other materials provided with the distribution.
17 * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
18 * nor the names of their contributors may be used to endorse or promote
19 * products derived from this software without specific prior written
20 * permission from Kernel Drivers, LLC and Your File System, Inc.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
26 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 // File: AFSCommSupport.cpp
38 #include "AFSCommon.h"
40 #define AFS_MAX_FCBS_TO_DROP 10
42 static ULONG ExtentsMasks[AFS_NUM_EXTENT_LISTS] = AFS_EXTENTS_MASKS;
43 static VOID VerifyExtentsLists(AFSFcb *Fcb);
44 static AFSExtent *DirtyExtentFor(PLIST_ENTRY le);
47 AFSEntryForOffset( IN AFSFcb *Fcb,
48 IN PLARGE_INTEGER Offset);
52 // Returns with Extents lock EX and no one using them.
56 AFSLockForExtentsTrim( IN AFSFcb *Fcb)
59 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
60 AFS_TRACE_LEVEL_VERBOSE,
61 "AFSLockForExtentsTrim Acquiring Fcb extents lock %08lX EXCL %08lX\n",
62 &Fcb->NPFcb->Specific.File.ExtentsResource,
63 PsGetCurrentThread());
65 AFSAcquireExcl( &Fcb->NPFcb->Specific.File.ExtentsResource, TRUE );
71 // return FALSE *or* with Extents lock EX and noone using them
74 AFSLockForExtentsTrimNoWait( IN AFSFcb *Fcb)
77 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
78 AFS_TRACE_LEVEL_VERBOSE,
79 "AFSLockForExtentsTrimNoWait Attempting to acquire Fcb extent lock %08lX EXCL %08lX\n",
80 &Fcb->NPFcb->Specific.File.ExtentsResource,
81 PsGetCurrentThread());
83 if (!AFSAcquireExcl( &Fcb->NPFcb->Specific.File.ExtentsResource, FALSE ))
86 // Couldn't lock immediately
89 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
90 AFS_TRACE_LEVEL_VERBOSE,
91 "AFSLockForExtentsTrimNoWait Refused to wait for Fcb extent lock %08lX EXCL %08lX\n",
92 &Fcb->NPFcb->Specific.File.ExtentsResource,
93 PsGetCurrentThread());
102 AFSFreeExtent( IN AFSFcb *Fcb,
103 IN AFSExtent *pExtent)
105 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
108 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
110 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
112 RemoveEntryList( &pExtent->Lists[i] );
116 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
118 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
120 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
122 lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount);
127 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
132 AFSExFreePoolWithTag( pExtent, AFS_EXTENT_TAG);
136 // AFSTearDownFcbExtents was originally written to
137 // remove all of the extents from an FCB. For that to happen
138 // it must be an invariant that the extent list cannot change
139 // from the moment the caller decides to execute AFSTearDownFcbExtents
140 // until it returns. This invariant does not hold because the
141 // the decision to call AFSTearDownFcbExtents is made without
142 // holding the ExtentsResource and it is possible that extents
143 // are in active use. Therefore, AFSTearDownFcbExtents now releases
144 // as many non-active extents as it can.
147 AFSTearDownFcbExtents( IN AFSFcb *Fcb,
150 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
151 LIST_ENTRY *le, *leNext;
153 LONG lExtentCount = 0, lProcessCount = 0;
154 LONG lFcbExtentCount;
155 ULONG ulReleaseCount = 0;
157 AFSReleaseExtentsCB *pRelease = NULL;
158 BOOLEAN locked = FALSE;
160 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
161 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 %08lX 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;
414 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
421 // Ensure that no one is working with the extents and grab the
425 AFSLockForExtentsTrim( Fcb );
429 if (0 == Fcb->Specific.File.ExtentCount)
431 try_return ( ntStatus = STATUS_SUCCESS);
434 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
436 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
439 for( le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink,
441 lFcbExtentCount = Fcb->Specific.File.ExtentCount;
442 lExtentCount < lFcbExtentCount;
443 lExtentCount += lProcessCount)
446 for( lProcessCount = 0;
448 lExtentCount + lProcessCount < lFcbExtentCount;
449 lProcessCount++, le = leNext)
454 pEntry = ExtentFor( le, AFS_EXTENTS_LIST );
456 if( BooleanFlagOn( pEntry->Flags, AFS_EXTENT_DIRTY))
461 AFSRemoveEntryDirtyList( Fcb,
464 dirtyCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
466 ASSERT( dirtyCount >= 0);
469 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
470 AFS_TRACE_LEVEL_VERBOSE,
471 "AFSDeleteFcbExtents Deleting extent %p fid %08lX-%08lX-%08lX-%08lX Offset %08lX-%08lX Len %08lX\n",
473 Fcb->ObjectInformation->FileId.Cell,
474 Fcb->ObjectInformation->FileId.Volume,
475 Fcb->ObjectInformation->FileId.Vnode,
476 Fcb->ObjectInformation->FileId.Unique,
477 pEntry->FileOffset.HighPart,
478 pEntry->FileOffset.LowPart,
486 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
489 // if all extents have been released, reinitialize the skip lists
492 ASSERT( Fcb->Specific.File.ExtentCount == 0);
494 if( Fcb->Specific.File.ExtentCount == 0)
497 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i++)
499 InitializeListHead(&Fcb->Specific.File.ExtentsLists[i]);
503 // Reinitialize the dirty list as well
506 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
509 ASSERT( Fcb->Specific.File.ExtentsDirtyCount == 0);
511 Fcb->NPFcb->Specific.File.DirtyListHead = NULL;
512 Fcb->NPFcb->Specific.File.DirtyListTail = NULL;
514 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
517 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
524 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
525 AFS_TRACE_LEVEL_VERBOSE,
526 "AFSDeleteFcbExtents Releasing Fcb extent lock %08lX thread %08lX\n",
527 &Fcb->NPFcb->Specific.File.ExtentsResource,
528 PsGetCurrentThread());
530 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
537 ExtentForOffsetInList( IN AFSFcb *Fcb,
540 IN PLARGE_INTEGER Offset)
543 // Return the extent that maps the offset, that
544 // - Contains the offset
545 // - or is immediately ahead of the offset (in this list)
546 // - otherwise return NULL.
549 PLIST_ENTRY pLe = List;
550 AFSExtent *pPrevious = NULL;
552 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
554 while (pLe != &Fcb->Specific.File.ExtentsLists[ListNumber])
558 entry = ExtentFor( pLe, ListNumber );
565 if (Offset->QuadPart < entry->FileOffset.QuadPart)
568 // Offset is ahead of entry. Return previous
573 if (Offset->QuadPart >= (entry->FileOffset.QuadPart + entry->Size))
576 // We start after this extent - carry on round
584 // Otherwise its a match
591 // Got to the end. Return Previous
597 AFSExtentContains( IN AFSExtent *Extent, IN PLARGE_INTEGER Offset)
603 return (Extent->FileOffset.QuadPart <= Offset->QuadPart &&
604 (Extent->FileOffset.QuadPart + Extent->Size) > Offset->QuadPart);
609 // Return the extent that contains the offset
612 AFSExtentForOffsetHint( IN AFSFcb *Fcb,
613 IN PLARGE_INTEGER Offset,
614 IN BOOLEAN ReturnPrevious,
617 AFSExtent *pPrevious = Hint;
621 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
623 #if AFS_VALIDATE_EXTENTS
624 VerifyExtentsLists(Fcb);
628 // So we will go across the skip lists until we find an
629 // appropriate entry (previous or direct match). If it's a match
630 // we are done, other wise we start on the next layer down
632 for (i = AFS_NUM_EXTENT_LISTS-1; i >= AFS_EXTENTS_LIST; i--)
634 if (NULL == pPrevious)
637 // We haven't found anything in the previous layers
639 pLe = Fcb->Specific.File.ExtentsLists[i].Flink;
641 else if (NULL == pPrevious->Lists[i].Flink)
643 ASSERT(AFS_EXTENTS_LIST != i);
645 // The hint doesn't exist at this level, next one down
652 // take the previous into the next
654 pLe = &pPrevious->Lists[i];
657 pPrevious = ExtentForOffsetInList( Fcb, pLe, i, Offset);
659 if (NULL != pPrevious && AFSExtentContains(pPrevious, Offset))
662 // Found it immediately. Stop here
668 if (NULL == pPrevious || ReturnPrevious )
673 ASSERT( !AFSExtentContains(pPrevious, Offset) );
679 AFSEntryForOffset( IN AFSFcb *Fcb,
680 IN PLARGE_INTEGER Offset)
682 AFSExtent *pPrevious = NULL;
686 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
688 #if AFS_VALIDATE_EXTENTS
689 VerifyExtentsLists(Fcb);
693 // So we will go across the skip lists until we find an
694 // appropriate entry (previous or direct match). If it's a match
695 // we are done, other wise we start on the next layer down
697 for (i = AFS_NUM_EXTENT_LISTS-1; i >= AFS_EXTENTS_LIST; i--)
699 if (NULL == pPrevious)
702 // We haven't found anything in the previous layers
704 pLe = Fcb->Specific.File.ExtentsLists[i].Flink;
706 else if (NULL == pPrevious->Lists[i].Flink)
708 ASSERT(AFS_EXTENTS_LIST != i);
710 // The hint doesn't exist at this level, next one down
717 // take the previous into the next
719 pLe = &pPrevious->Lists[i];
722 pPrevious = ExtentForOffsetInList( Fcb, pLe, i, Offset);
724 if (NULL != pPrevious && AFSExtentContains(pPrevious, Offset))
727 // Found it immediately. Stop here
737 AFSExtentForOffset( IN AFSFcb *Fcb,
738 IN PLARGE_INTEGER Offset,
739 IN BOOLEAN ReturnPrevious)
741 return AFSExtentForOffsetHint(Fcb, Offset, ReturnPrevious, NULL);
745 BOOLEAN AFSDoExtentsMapRegion(IN AFSFcb *Fcb,
746 IN PLARGE_INTEGER Offset,
748 IN OUT AFSExtent **FirstExtent,
749 OUT AFSExtent **LastExtent)
752 // Return TRUE region is completely mapped. FALSE
753 // otherwise. If the region isn't mapped then the last
754 // extent to map part of the region is returned.
756 // *LastExtent as input is where to start looking.
757 // *LastExtent as output is either the extent which
758 // contains the Offset, or the last one which doesn't
762 BOOLEAN retVal = FALSE;
767 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
771 entry = AFSExtentForOffsetHint(Fcb, Offset, TRUE, *FirstExtent);
772 *FirstExtent = entry;
774 if (NULL == entry || !AFSExtentContains(entry, Offset))
776 try_return (retVal = FALSE);
779 ASSERT(Offset->QuadPart >= entry->FileOffset.QuadPart);
783 if ((entry->FileOffset.QuadPart + entry->Size) >=
784 (Offset->QuadPart + Size))
787 // The end is inside the extent
789 try_return (retVal = TRUE);
792 if (entry->Lists[AFS_EXTENTS_LIST].Flink == &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
795 // Run out of extents
797 try_return (retVal = FALSE);
800 newEntry = NextExtent( entry, AFS_EXTENTS_LIST );
802 if (newEntry->FileOffset.QuadPart !=
803 (entry->FileOffset.QuadPart + entry->Size))
808 try_return (retVal = FALSE);
814 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
819 "EXCEPTION - AFSDoExtentsMapRegion\n");
821 AFSDumpTraceFilesFnc();
833 AFSRequestExtentsAsync( IN AFSFcb *Fcb,
835 IN PLARGE_INTEGER Offset,
839 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
840 NTSTATUS ntStatus = STATUS_SUCCESS;
841 AFSExtent *pExtent = NULL;
842 AFSRequestExtentsCB request;
843 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
844 AFSExtent *pFirstExtent = NULL;
845 LARGE_INTEGER liAlignedOffset;
846 ULONG ulAlignedLength = 0;
847 BOOLEAN bRegionMapped = FALSE;
848 ULONGLONG ullProcessId = (ULONGLONG)PsGetCurrentProcessId();
853 ASSERT( !ExIsResourceAcquiredLite( &pNPFcb->Specific.File.ExtentsResource ));
856 // If the service set a failure on the file since the last
857 // CreateFile was issued, return it now.
860 if (!NT_SUCCESS( pNPFcb->Specific.File.ExtentsRequestStatus))
864 // If this isn't the same authgroup which caused the failure
865 // then try to request them again
868 if( RtlCompareMemory( &pNPFcb->Specific.File.ExtentsRequestAuthGroup,
870 sizeof( GUID)) == sizeof( GUID))
873 ntStatus = pNPFcb->Specific.File.ExtentsRequestStatus;
875 pNPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
877 RtlZeroMemory( &pNPFcb->Specific.File.ExtentsRequestAuthGroup,
880 try_return( ntStatus);
885 // Check if we are already mapped
888 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
889 AFS_TRACE_LEVEL_VERBOSE,
890 "AFSRequestExtentsAsync Acquiring Fcb extents lock %08lX SHARED %08lX\n",
891 &pNPFcb->Specific.File.ExtentsResource,
892 PsGetCurrentThread());
894 AFSAcquireShared( &pNPFcb->Specific.File.ExtentsResource, TRUE );
896 bRegionMapped = AFSDoExtentsMapRegion( Fcb, Offset, Size, &pFirstExtent, &pExtent);
901 KeClearEvent( &pNPFcb->Specific.File.ExtentsRequestComplete );
904 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
905 AFS_TRACE_LEVEL_VERBOSE,
906 "AFSRequestExtentsAsync Releasing Fcb extents lock %08lX SHARED %08lX\n",
907 &pNPFcb->Specific.File.ExtentsResource,
908 PsGetCurrentThread());
910 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
915 try_return( ntStatus = STATUS_SUCCESS);
919 // Align our request on extent size boundary
922 ulAlignedLength = Size;
924 liAlignedOffset = *Offset;
926 if( liAlignedOffset.QuadPart % pDevExt->Specific.RDR.CacheBlockSize != 0)
929 liAlignedOffset.QuadPart = (ULONGLONG)( (ULONGLONG)(liAlignedOffset.QuadPart / pDevExt->Specific.RDR.CacheBlockSize) * (ULONGLONG)pDevExt->Specific.RDR.CacheBlockSize);
931 ulAlignedLength += (ULONG)(Offset->QuadPart - liAlignedOffset.QuadPart);
934 if( ulAlignedLength % pDevExt->Specific.RDR.CacheBlockSize != 0)
937 ulAlignedLength = (ULONG)(((ulAlignedLength / pDevExt->Specific.RDR.CacheBlockSize) + 1) * pDevExt->Specific.RDR.CacheBlockSize);
940 RtlZeroMemory( &request,
941 sizeof( AFSRequestExtentsCB));
943 request.ByteOffset = liAlignedOffset;
944 request.Length = ulAlignedLength;
946 if( !AFSIsExtentRequestQueued( &Fcb->ObjectInformation->FileId,
951 KeClearEvent( &pNPFcb->Specific.File.ExtentsRequestComplete );
953 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
954 AFS_TRACE_LEVEL_VERBOSE,
955 "AFSRequestExtentsAsync Request extents for fid %08lX-%08lX-%08lX-%08lX Offset %08lX Len %08lX Thread %08lX\n",
956 Fcb->ObjectInformation->FileId.Cell,
957 Fcb->ObjectInformation->FileId.Volume,
958 Fcb->ObjectInformation->FileId.Vnode,
959 Fcb->ObjectInformation->FileId.Unique,
960 request.ByteOffset.LowPart,
962 PsGetCurrentThread());
964 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS,
968 &Fcb->ObjectInformation->FileId,
970 sizeof( AFSRequestExtentsCB ),
974 if ( ntStatus == STATUS_ACCESS_DENIED)
979 ntStatus2 = AFSRetrieveValidAuthGroup( Fcb,
984 if ( NT_SUCCESS( ntStatus2) &&
985 RtlCompareMemory( &stAuthGroup,
987 sizeof( GUID)) != sizeof( GUID))
990 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS,
994 &Fcb->ObjectInformation->FileId,
996 sizeof( AFSRequestExtentsCB ),
1002 if( !NT_SUCCESS( ntStatus))
1005 KeSetEvent( &pNPFcb->Specific.File.ExtentsRequestComplete,
1020 AFSProcessExtentsResult( IN AFSFcb *Fcb,
1022 IN AFSFileExtentCB *Result)
1024 NTSTATUS ntStatus = STATUS_SUCCESS;
1025 AFSFileExtentCB *pFileExtents = Result;
1028 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
1029 ULONG fileExtentsUsed = 0;
1030 BOOLEAN bFoundExtent = FALSE;
1031 LIST_ENTRY *pSkipEntries[AFS_NUM_EXTENT_LISTS] = { 0 };
1032 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1036 // Grab the extents exclusive for the duration
1039 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1040 AFS_TRACE_LEVEL_VERBOSE,
1041 "AFSProcessExtentsResult Acquiring Fcb extent lock %08lX EXCL %08lX\n",
1042 &pNPFcb->Specific.File.ExtentsResource,
1043 PsGetCurrentThread());
1045 AFSAcquireExcl( &pNPFcb->Specific.File.ExtentsResource, TRUE );
1051 // Find where to put the extents
1053 for (ULONG i = AFS_EXTENTS_LIST; i < AFS_NUM_EXTENT_LISTS; i++)
1056 pSkipEntries[i] = Fcb->Specific.File.ExtentsLists[i].Flink;
1059 le = pSkipEntries[AFS_EXTENTS_LIST];
1061 if (le == &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
1064 // No extents. Insert at head of list (which is where the skip lists point!)
1068 else if (0 != pFileExtents->FileOffset.QuadPart)
1071 // We want to find the best extents immediately *behind* this offset
1073 LARGE_INTEGER offset = pFileExtents->FileOffset;
1076 // Ask in the top skip list first, then work down
1078 for (LONG i = AFS_NUM_EXTENT_LISTS-1; i >= AFS_EXTENTS_LIST; i--)
1080 pExtent = ExtentForOffsetInList( Fcb,
1085 if (NULL == pExtent)
1088 // No dice. Header has to become the head of the list
1090 pSkipEntries[i] = &Fcb->Specific.File.ExtentsLists[i];
1092 // And as a loop invariant we should never have found an extent
1094 ASSERT(!bFoundExtent);
1099 // pExtent is where to start to insert at this level
1101 pSkipEntries[i] = &pExtent->Lists[i];
1104 // And also where to start to look at the next level
1107 if (i > AFS_EXTENTS_LIST)
1109 pSkipEntries[i-1] = &pExtent->Lists[i-1];
1111 bFoundExtent = TRUE;
1115 if (NULL == pExtent)
1117 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
1122 le = pExtent->Lists[AFS_EXTENTS_LIST].Blink;
1128 // Looking at offset 0, so we must start at the beginning
1131 pExtent = ExtentFor(le, AFS_EXTENTS_LIST);
1135 // And set up the skip lists
1138 for (ULONG i = AFS_EXTENTS_LIST; i < AFS_NUM_EXTENT_LISTS; i++)
1140 pSkipEntries[i] = &Fcb->Specific.File.ExtentsLists[i];
1144 while (fileExtentsUsed < Count)
1148 // Loop invariant - le points to where to insert after and
1149 // pExtent points to le->fLink
1152 ASSERT (NULL == pExtent ||
1153 le->Flink == &pExtent->Lists[AFS_EXTENTS_LIST]);
1155 if (NULL == pExtent ||
1156 pExtent->FileOffset.QuadPart > pFileExtents->FileOffset.QuadPart)
1159 // We need to insert a new extent at le. Start with
1160 // some sanity check on spanning
1162 if (NULL != pExtent &&
1163 ((pFileExtents->FileOffset.QuadPart + pFileExtents->Length) >
1164 pExtent->FileOffset.QuadPart))
1167 // File Extents overlaps pExtent
1169 ASSERT( (pFileExtents->FileOffset.QuadPart + pFileExtents->Length) <=
1170 pExtent->FileOffset.QuadPart);
1172 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1176 // File offset is entirely in front of this extent. Create
1177 // a new one (remember le is the previous list entry)
1179 pExtent = (AFSExtent *) AFSExAllocatePoolWithTag( NonPagedPool,
1182 if (NULL == pExtent)
1185 try_return (ntStatus = STATUS_INSUFFICIENT_RESOURCES );
1188 RtlZeroMemory( pExtent, sizeof( AFSExtent ));
1190 pExtent->FileOffset = pFileExtents->FileOffset;
1191 pExtent->CacheOffset = pFileExtents->CacheOffset;
1192 pExtent->Size = pFileExtents->Length;
1194 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1195 AFS_TRACE_LEVEL_VERBOSE,
1196 "AFSProcessExtentsResult Received extent for fid %08lX-%08lX-%08lX-%08lX File Offset %I64X Cache Offset %I64X Len %08lX\n",
1197 Fcb->ObjectInformation->FileId.Cell,
1198 Fcb->ObjectInformation->FileId.Volume,
1199 Fcb->ObjectInformation->FileId.Vnode,
1200 Fcb->ObjectInformation->FileId.Unique,
1201 pFileExtents->FileOffset.QuadPart,
1202 pFileExtents->CacheOffset.QuadPart,
1203 pFileExtents->Length);
1205 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, (LONG)(pExtent->Size/1024));
1207 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, (LONG)(pExtent->Size/1024));
1209 lCount = InterlockedIncrement( &Fcb->Specific.File.ExtentCount);
1211 lCount = InterlockedIncrement( &pControlDevExt->Specific.Control.ExtentCount);
1216 KeClearEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent);
1222 InsertHeadList(le, &pExtent->Lists[AFS_EXTENTS_LIST]);
1223 ASSERT(le->Flink == &pExtent->Lists[AFS_EXTENTS_LIST]);
1224 ASSERT(0 == (pExtent->FileOffset.LowPart & ExtentsMasks[AFS_EXTENTS_LIST]));
1227 // Do not move the cursor - we will do it next time
1231 // And into the (upper) skip lists - Again, do not move the cursor
1233 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1235 if (0 == (pExtent->FileOffset.LowPart & ExtentsMasks[i]))
1237 InsertHeadList(pSkipEntries[i], &pExtent->Lists[i]);
1238 #if AFS_VALIDATE_EXTENTS
1239 VerifyExtentsLists(Fcb);
1244 else if (pExtent->FileOffset.QuadPart == pFileExtents->FileOffset.QuadPart)
1247 if (pExtent->Size != pFileExtents->Length)
1250 ASSERT (pExtent->Size == pFileExtents->Length);
1252 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1256 // Move both cursors forward.
1258 // First the extent pointer
1261 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1264 // Then the skip lists cursors forward if needed
1266 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1268 if (0 == (pExtent->FileOffset.LowPart & ExtentsMasks[i]))
1271 // Check sanity before
1273 #if AFS_VALIDATE_EXTENTS
1274 VerifyExtentsLists(Fcb);
1278 // Skip list should point to us
1280 //ASSERT(pSkipEntries[i] == &pExtent->Lists[i]);
1282 // Move forward cursor
1284 pSkipEntries[i] = pSkipEntries[i]->Flink;
1286 // Check sanity before
1288 #if AFS_VALIDATE_EXTENTS
1289 VerifyExtentsLists(Fcb);
1295 // And then the cursor in the supplied array
1301 // setup pExtent if there is one
1303 if (le->Flink != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
1305 pExtent = NextExtent( pExtent, AFS_EXTENTS_LIST ) ;
1315 ASSERT( pExtent->FileOffset.QuadPart < pFileExtents->FileOffset.QuadPart );
1318 // Sanity check on spanning
1320 if ((pExtent->FileOffset.QuadPart + pExtent->Size) >
1321 pFileExtents->FileOffset.QuadPart)
1324 ASSERT( (pExtent->FileOffset.QuadPart + pExtent->Size) <=
1325 pFileExtents->FileOffset.QuadPart);
1327 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1331 // Move le and pExtent forward
1333 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1336 // setup pExtent if there is one
1339 if (le->Flink != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
1341 pExtent = NextExtent( pExtent, AFS_EXTENTS_LIST ) ;
1351 // All done, signal that we are done drop the lock, exit
1356 if( !NT_SUCCESS( ntStatus))
1360 // If we failed the service is going to drop all extents so trim away the
1364 AFSTrimSpecifiedExtents( Fcb,
1369 #if AFS_VALIDATE_EXTENTS
1370 VerifyExtentsLists(Fcb);
1373 KeSetEvent( &pNPFcb->Specific.File.ExtentsRequestComplete,
1377 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1378 AFS_TRACE_LEVEL_VERBOSE,
1379 "AFSProcessExtentsResult Releasing Fcb extent lock %08lX EXCL %08lX\n",
1380 &pNPFcb->Specific.File.ExtentsResource,
1381 PsGetCurrentThread());
1383 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
1390 AFSProcessSetFileExtents( IN AFSSetFileExtentsCB *SetExtents )
1392 AFSFcb *pFcb = NULL;
1393 AFSVolumeCB *pVolumeCB = NULL;
1394 NTSTATUS ntStatus = STATUS_SUCCESS;
1395 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1396 ULONGLONG ullIndex = 0;
1397 AFSObjectInfoCB *pObjectInfo = NULL;
1403 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1404 AFS_TRACE_LEVEL_VERBOSE,
1405 "AFSProcessSetFileExtents Acquiring RDR VolumeTreeLock lock %08lX SHARED %08lX\n",
1406 &pDevExt->Specific.RDR.VolumeTreeLock,
1407 PsGetCurrentThread());
1409 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
1411 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1412 AFS_TRACE_LEVEL_VERBOSE,
1413 "AFSProcessSetFileExtents Set extents for fid %08lX-%08lX-%08lX-%08lX\n",
1414 SetExtents->FileId.Cell,
1415 SetExtents->FileId.Volume,
1416 SetExtents->FileId.Vnode,
1417 SetExtents->FileId.Unique);
1420 // Locate the volume node
1423 ullIndex = AFSCreateHighIndex( &SetExtents->FileId);
1425 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
1427 (AFSBTreeEntry **)&pVolumeCB);
1429 if( pVolumeCB != NULL)
1432 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1434 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1435 AFS_TRACE_LEVEL_VERBOSE,
1436 "AFSProcessSetFileExtents Increment count on volume %08lX Cnt %d\n",
1441 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
1443 if( !NT_SUCCESS( ntStatus) ||
1447 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1448 AFS_TRACE_LEVEL_ERROR,
1449 "AFSProcessSetFileExtents Set extents for fid %08lX-%08lX-%08lX-%08lX Failed to locate volume Status %08lX\n",
1450 SetExtents->FileId.Cell,
1451 SetExtents->FileId.Volume,
1452 SetExtents->FileId.Vnode,
1453 SetExtents->FileId.Unique,
1456 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1459 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1463 // Now locate the Object in this volume
1466 ullIndex = AFSCreateLowIndex( &SetExtents->FileId);
1468 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
1470 (AFSBTreeEntry **)&pObjectInfo);
1472 if( pObjectInfo != NULL)
1476 // Reference the node so it won't be torn down
1479 lCount = AFSObjectInfoIncrement( pObjectInfo);
1481 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1482 AFS_TRACE_LEVEL_VERBOSE,
1483 "AFSProcessSetFileExtents Increment count on object %08lX Cnt %d\n",
1488 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1490 if( !NT_SUCCESS( ntStatus) ||
1491 pObjectInfo == NULL)
1494 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1495 AFS_TRACE_LEVEL_ERROR,
1496 "AFSProcessSetFileExtents Set extents for hash %I64X fid %08lX-%08lX-%08lX-%08lX Failed to locate file in volume %08lX\n",
1498 SetExtents->FileId.Cell,
1499 SetExtents->FileId.Volume,
1500 SetExtents->FileId.Vnode,
1501 SetExtents->FileId.Unique,
1504 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1507 pFcb = pObjectInfo->Fcb;
1510 // If we have a result failure then don't bother trying to set the extents
1513 if( SetExtents->ResultStatus != STATUS_SUCCESS)
1516 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1517 AFS_TRACE_LEVEL_ERROR,
1518 "AFSProcessSetFileExtents Set extents failure fid %08lX-%08lX-%08lX-%08lX ResultStatus %08lX\n",
1519 SetExtents->FileId.Cell,
1520 SetExtents->FileId.Volume,
1521 SetExtents->FileId.Vnode,
1522 SetExtents->FileId.Unique,
1523 SetExtents->ResultStatus);
1525 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1526 AFS_TRACE_LEVEL_VERBOSE,
1527 "AFSProcessSetFileExtents Acquiring Fcb extents lock %08lX EXCL %08lX\n",
1528 &pFcb->NPFcb->Specific.File.ExtentsResource,
1529 PsGetCurrentThread());
1531 AFSAcquireExcl( &pFcb->NPFcb->Specific.File.ExtentsResource,
1534 pFcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_CANCELLED;
1536 KeSetEvent( &pFcb->NPFcb->Specific.File.ExtentsRequestComplete,
1540 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1541 AFS_TRACE_LEVEL_VERBOSE,
1542 "AFSProcessSetFileExtents Releasing Fcb extent lock %08lX EXCL %08lX\n",
1543 &pFcb->NPFcb->Specific.File.ExtentsResource,
1544 PsGetCurrentThread());
1546 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
1548 try_return( ntStatus);
1551 ntStatus = AFSProcessExtentsResult ( pFcb,
1552 SetExtents->ExtentCount,
1553 SetExtents->FileExtents );
1557 if( pObjectInfo != NULL)
1560 lCount = AFSObjectInfoDecrement( pObjectInfo);
1562 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1563 AFS_TRACE_LEVEL_VERBOSE,
1564 "AFSProcessSetFileExtents Decrement count on object %08lX Cnt %d\n",
1572 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1574 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1575 AFS_TRACE_LEVEL_VERBOSE,
1576 "AFSProcessSetFileExtents Decrement count on volume %08lX Cnt %d\n",
1586 // Helper fuctions for Usermode initiation of release of extents
1589 AFSReleaseSpecifiedExtents( IN AFSReleaseFileExtentsCB *Extents,
1591 OUT AFSFileExtentCB *FileExtents,
1592 IN ULONG BufferSize,
1593 OUT ULONG *ExtentCount,
1594 OUT BOOLEAN *DirtyExtents)
1599 ULONG ulExtentCount = 0;
1600 NTSTATUS ntStatus = STATUS_SUCCESS;
1601 BOOLEAN bReleaseAll = FALSE;
1602 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1607 ASSERT( ExIsResourceAcquiredExclusiveLite( &Fcb->NPFcb->Specific.File.ExtentsResource));
1609 if (BufferSize < (Extents->ExtentCount * sizeof( AFSFileExtentCB)))
1612 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1613 AFS_TRACE_LEVEL_VERBOSE,
1614 "AFSReleaseSpecifiedExtents Buffer too small\n");
1616 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL);
1619 RtlZeroMemory( FileExtents, BufferSize);
1622 *DirtyExtents = FALSE;
1625 // iterate until we have dealt with all we were asked for or
1626 // are at the end of the list. Note that this deals (albeit
1627 // badly) with out of order extents
1630 pExtent = AFSExtentForOffset( Fcb,
1631 &Extents->FileExtents[0].FileOffset,
1634 if (NULL == pExtent)
1636 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1640 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1644 if( BooleanFlagOn( Extents->Flags, AFS_RELEASE_EXTENTS_FLAGS_RELEASE_ALL) ||
1645 ( Extents->FileId.Cell == 0 &&
1646 Extents->FileId.Volume == 0 &&
1647 Extents->FileId.Vnode == 0 &&
1648 Extents->FileId.Unique == 0))
1654 while( le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST] &&
1655 ulExtentCount < Extents->ExtentCount)
1659 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
1664 if( pExtent->FileOffset.QuadPart < Extents->FileExtents[ulExtentCount].FileOffset.QuadPart)
1667 // Skip forward through the extent list until we get
1668 // to the one we want
1674 else if (pExtent->FileOffset.QuadPart > Extents->FileExtents[ulExtentCount].FileOffset.QuadPart)
1677 // We don't have the extent asked for so return UNKNOWN
1680 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1681 AFS_TRACE_LEVEL_VERBOSE,
1682 "AFSReleaseSpecifiedExtents Located UNKNOWN extent Offset %I64X Len %08lX\n",
1683 Extents->FileExtents[ulExtentCount].FileOffset.QuadPart,
1684 Extents->FileExtents[ulExtentCount].Length);
1686 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_UNKNOWN;
1688 FileExtents[*ExtentCount].Length = 0;
1689 FileExtents[*ExtentCount].CacheOffset.QuadPart = 0;
1690 FileExtents[*ExtentCount].FileOffset = Extents->FileExtents[ulExtentCount].FileOffset;
1692 *ExtentCount = (*ExtentCount) + 1;
1697 // Reset where we are looking
1700 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1704 else if( pExtent->ActiveCount > 0)
1707 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1708 AFS_TRACE_LEVEL_VERBOSE,
1709 "AFSReleaseSpecifiedExtents Located IN_USE extent Offset %I64X Len %08lX\n",
1710 Extents->FileExtents[ulExtentCount].FileOffset.QuadPart,
1711 Extents->FileExtents[ulExtentCount].Length);
1713 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_IN_USE;
1715 FileExtents[*ExtentCount].Length = 0;
1716 FileExtents[*ExtentCount].CacheOffset.QuadPart = 0;
1717 FileExtents[*ExtentCount].FileOffset = Extents->FileExtents[ulExtentCount].FileOffset;
1719 *ExtentCount = (*ExtentCount) + 1;
1724 // Reset where we are looking
1727 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1736 // If the extent is currently active then skip it
1739 if( pExtent->ActiveCount > 0)
1748 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_RELEASE;
1750 FileExtents[*ExtentCount].Length = pExtent->Size;
1751 FileExtents[*ExtentCount].DirtyLength = pExtent->Size;
1752 FileExtents[*ExtentCount].DirtyOffset = 0;
1753 FileExtents[*ExtentCount].CacheOffset = pExtent->CacheOffset;
1754 FileExtents[*ExtentCount].FileOffset = pExtent->FileOffset;
1756 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1757 AFS_TRACE_LEVEL_VERBOSE,
1758 "AFSReleaseSpecifiedExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
1760 Fcb->ObjectInformation->FileId.Cell,
1761 Fcb->ObjectInformation->FileId.Volume,
1762 Fcb->ObjectInformation->FileId.Vnode,
1763 Fcb->ObjectInformation->FileId.Unique,
1764 FileExtents[*ExtentCount].FileOffset.QuadPart,
1765 FileExtents[*ExtentCount].Length);
1767 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
1770 AFSAcquireExcl( &Fcb->NPFcb->Specific.File.DirtyExtentsListLock,
1773 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
1776 AFSRemoveEntryDirtyList( Fcb,
1779 FileExtents[*ExtentCount].Flags |= AFS_EXTENT_FLAG_DIRTY;
1781 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
1783 *DirtyExtents = TRUE;
1786 AFSReleaseResource( &Fcb->NPFcb->Specific.File.DirtyExtentsListLock);
1790 // move forward all three cursors
1794 *ExtentCount = (*ExtentCount) + 1;
1809 AFSFindFcbToClean(ULONG IgnoreTime, AFSFcb *LastFcb, BOOLEAN Block)
1812 AFSFcb *pFcb = NULL;
1813 AFSVolumeCB *pVolumeCB = NULL;
1814 AFSDeviceExt *pRDRDeviceExt = NULL;
1815 AFSDeviceExt *pControlDeviceExt = NULL;
1816 BOOLEAN bLocatedEntry = FALSE;
1817 AFSObjectInfoCB *pCurrentObject = NULL;
1818 BOOLEAN bReleaseVolumeListLock = FALSE;
1821 pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1822 pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1824 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1825 AFS_TRACE_LEVEL_VERBOSE,
1826 "AFSFindFcbToClean Acquiring RDR VolumeListLock lock %08lX SHARED %08lX\n",
1827 &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1828 PsGetCurrentThread());
1830 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1833 bReleaseVolumeListLock = TRUE;
1835 pVolumeCB = pRDRDeviceExt->Specific.RDR.VolumeListHead;
1837 while( pVolumeCB != NULL)
1841 // The Volume list may move under our feet. Lock it.
1844 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1846 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1847 AFS_TRACE_LEVEL_VERBOSE,
1848 "AFSFindFcbToClean Increment count on volume %08lX Cnt %d\n",
1852 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1854 bReleaseVolumeListLock = FALSE;
1856 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1857 AFS_TRACE_LEVEL_VERBOSE,
1858 "AFSFindFcbToClean Acquiring VolumeRoot ObjectInfoTree lock %08lX SHARED %08lX\n",
1859 pVolumeCB->ObjectInfoTree.TreeLock,
1860 PsGetCurrentThread());
1862 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1865 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1867 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1868 AFS_TRACE_LEVEL_VERBOSE,
1869 "AFSFindFcbToClean Decrement count on volume %08lX Cnt %d\n",
1873 if( NULL == LastFcb)
1876 pCurrentObject = pVolumeCB->ObjectInfoListHead;
1881 pCurrentObject = (AFSObjectInfoCB *)LastFcb->ObjectInformation->ListEntry.fLink;
1886 while( pCurrentObject != NULL)
1889 pFcb = (AFSFcb *)pCurrentObject->Fcb;
1892 // If the FCB is a candidate we try to lock it (but without waiting - which
1893 // means we are deadlock free
1897 pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
1903 AFSLockForExtentsTrim( pFcb);
1908 if( !AFSLockForExtentsTrimNoWait( pFcb))
1911 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1920 // Need to be sure there are no current flushes in the queue
1923 if( pFcb->Specific.File.ExtentCount == 0)
1926 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1927 AFS_TRACE_LEVEL_VERBOSE,
1928 "AFSFindFcbToClean Releasing Fcb extent lock %08lX thread %08lX\n",
1929 &pFcb->NPFcb->Specific.File.ExtentsResource,
1930 PsGetCurrentThread());
1932 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
1934 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1941 if( pFcb->Specific.File.QueuedFlushCount > 0)
1944 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1945 AFS_TRACE_LEVEL_VERBOSE,
1946 "AFSFindFcbToClean Releasing Fcb extent lock %08lX thread %08lX\n",
1947 &pFcb->NPFcb->Specific.File.ExtentsResource,
1948 PsGetCurrentThread());
1950 AFSReleaseResource(&pFcb->NPFcb->Specific.File.ExtentsResource);
1954 AFSWaitOnQueuedFlushes( pFcb);
1959 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1967 if( pFcb->OpenHandleCount > 0)
1970 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1971 AFS_TRACE_LEVEL_VERBOSE,
1972 "AFSFindFcbToClean Releasing Fcb extent lock %08lX thread %08lX\n",
1973 &pFcb->NPFcb->Specific.File.ExtentsResource,
1974 PsGetCurrentThread());
1976 AFSReleaseResource(&pFcb->NPFcb->Specific.File.ExtentsResource);
1978 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1986 // A hit a very palpable hit. Pin it
1989 lCount = AFSObjectInfoIncrement( pCurrentObject);
1991 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1992 AFS_TRACE_LEVEL_VERBOSE,
1993 "AFSFindFcbToClean Increment count on Fcb %08lX Cnt %d\n",
1997 bLocatedEntry = TRUE;
2002 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
2007 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2014 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
2017 bReleaseVolumeListLock = TRUE;
2019 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
2022 if( bReleaseVolumeListLock)
2025 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
2032 AFSProcessExtentFailure( PIRP Irp)
2034 AFSExtentFailureCB *pFailureCB = NULL;
2035 NTSTATUS ntStatus = STATUS_SUCCESS;
2036 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2037 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2038 AFSVolumeCB *pVolumeCB = NULL;
2039 ULONGLONG ullIndex = 0;
2040 AFSObjectInfoCB *pObjectInfo = NULL;
2045 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSExtentFailureCB))
2048 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2049 AFS_TRACE_LEVEL_ERROR,
2050 "AFSProcessExtentFailure Input buffer too small\n");
2052 try_return( ntStatus = STATUS_INVALID_PARAMETER);
2055 pFailureCB = (AFSExtentFailureCB *)Irp->AssociatedIrp.SystemBuffer;
2057 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2058 AFS_TRACE_LEVEL_ERROR,
2059 "AFSProcessExtentFailure Service Reports Failure fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2060 pFailureCB->FileId.Cell,
2061 pFailureCB->FileId.Volume,
2062 pFailureCB->FileId.Vnode,
2063 pFailureCB->FileId.Unique,
2064 pFailureCB->FailureStatus);
2066 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
2069 // Locate the volume node
2072 ullIndex = AFSCreateHighIndex( &pFailureCB->FileId);
2074 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
2076 (AFSBTreeEntry **)&pVolumeCB);
2078 if( pVolumeCB != NULL)
2081 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
2083 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2084 AFS_TRACE_LEVEL_VERBOSE,
2085 "AFSProcessExtentFailure Increment count on volume %08lX Cnt %d\n",
2090 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
2092 if( !NT_SUCCESS( ntStatus) ||
2096 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2097 AFS_TRACE_LEVEL_ERROR,
2098 "AFSProcessExtentFailure Invalid volume index %I64X status %08X\n",
2099 ullIndex, ntStatus);
2101 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2104 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2105 AFS_TRACE_LEVEL_VERBOSE,
2106 "AFSProcessExtentFailure Acquiring VolumeRoot FileIDTree.TreeLock lock %08lX SHARED %08lX\n",
2107 pVolumeCB->ObjectInfoTree.TreeLock,
2108 PsGetCurrentThread());
2110 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
2114 // Now locate the Object in this volume
2117 ullIndex = AFSCreateLowIndex( &pFailureCB->FileId);
2119 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
2121 (AFSBTreeEntry **)&pObjectInfo);
2123 if( pObjectInfo != NULL &&
2124 pObjectInfo->Fcb != NULL)
2128 // Reference the node so it won't be torn down
2131 lCount = AFSObjectInfoIncrement( pObjectInfo);
2133 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2134 AFS_TRACE_LEVEL_VERBOSE,
2135 "AFSProcessExtentFailure Increment count on object %08lX Cnt %d\n",
2140 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2142 if( !NT_SUCCESS( ntStatus) ||
2143 pObjectInfo == NULL ||
2144 pObjectInfo->Fcb == NULL)
2147 if( pObjectInfo == NULL)
2149 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2150 AFS_TRACE_LEVEL_ERROR,
2151 "AFSProcessExtentFailure Invalid file index %I64X\n",
2156 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2157 AFS_TRACE_LEVEL_ERROR,
2158 "AFSProcessExtentFailure Fcb dealocated for %I64X\n",
2162 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2165 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2166 AFS_TRACE_LEVEL_VERBOSE,
2167 "AFSProcessExtentFailure Acquiring Fcb extent lock %08lX EXCL %08lX\n",
2168 &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2169 PsGetCurrentThread());
2171 AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2174 pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestStatus = pFailureCB->FailureStatus;
2176 RtlCopyMemory( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2177 &pFailureCB->AuthGroup,
2180 KeSetEvent( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
2184 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2185 AFS_TRACE_LEVEL_VERBOSE,
2186 "AFSProcessExtentFailure Releasing Fcb extent lock %08lX EXCL %08lX\n",
2187 &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2188 PsGetCurrentThread());
2190 AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource);
2192 lCount = AFSObjectInfoDecrement( pObjectInfo);
2194 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2195 AFS_TRACE_LEVEL_VERBOSE,
2196 "AFSProcessExtentFailure Decrement count on object %08lX Cnt %d\n",
2205 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
2207 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2208 AFS_TRACE_LEVEL_VERBOSE,
2209 "AFSProcessExtentFailure Decrement count on volume %08lX Cnt %d\n",
2219 AFSProcessReleaseFileExtents( IN PIRP Irp)
2221 NTSTATUS ntStatus = STATUS_SUCCESS;
2222 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2223 PFILE_OBJECT pFileObject = pIrpSp->FileObject;
2224 AFSFcb *pFcb = NULL;
2225 AFSVolumeCB *pVolumeCB = NULL;
2226 AFSDeviceExt *pDevExt;
2227 AFSReleaseFileExtentsCB *pExtents;
2228 AFSReleaseFileExtentsResultCB *pResult = NULL;
2229 AFSReleaseFileExtentsResultFileCB *pFile = NULL;
2231 ULONGLONG ullIndex = 0;
2232 AFSObjectInfoCB *pObjectInfo = NULL;
2233 BOOLEAN bLocked = FALSE;
2234 BOOLEAN bDirtyExtents = FALSE;
2241 pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2243 pExtents = (AFSReleaseFileExtentsCB*) Irp->AssociatedIrp.SystemBuffer;
2245 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2246 sizeof( AFSReleaseFileExtentsCB))
2249 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2250 AFS_TRACE_LEVEL_ERROR,
2251 "AFSProcessReleaseFileExtents INPUT Buffer too small\n");
2253 try_return( ntStatus = STATUS_INVALID_PARAMETER );
2256 if ( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength <
2257 sizeof(AFSReleaseFileExtentsResultCB))
2260 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2261 AFS_TRACE_LEVEL_ERROR,
2262 "AFSProcessReleaseFileExtents OUTPUT Buffer too small [1]\n");
2265 // Must have space for one extent in one file
2268 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL);
2271 if (pExtents->ExtentCount == 0)
2274 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2275 AFS_TRACE_LEVEL_ERROR,
2276 "AFSProcessReleaseFileExtents Extent count zero\n");
2278 try_return( ntStatus = STATUS_INVALID_PARAMETER);
2281 if (pExtents->FileId.Cell != 0 ||
2282 pExtents->FileId.Volume != 0 ||
2283 pExtents->FileId.Vnode != 0 ||
2284 pExtents->FileId.Unique != 0)
2287 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2288 AFS_TRACE_LEVEL_VERBOSE,
2289 "AFSProcessReleaseFileExtents Processing FID %08lX:%08lX:%08lX:%08lX\n",
2290 pExtents->FileId.Cell,
2291 pExtents->FileId.Volume,
2292 pExtents->FileId.Vnode,
2293 pExtents->FileId.Unique);
2295 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2296 ( FIELD_OFFSET( AFSReleaseFileExtentsCB, ExtentCount) + sizeof(ULONG)) ||
2297 pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2298 ( FIELD_OFFSET( AFSReleaseFileExtentsCB, ExtentCount) + sizeof(ULONG) +
2299 sizeof (AFSFileExtentCB) * pExtents->ExtentCount))
2302 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2303 AFS_TRACE_LEVEL_ERROR,
2304 "AFSProcessReleaseFileExtents Buffer too small for FID %08lX:%08lx:%08lX:%08lX\n",
2305 pExtents->FileId.Cell,
2306 pExtents->FileId.Volume,
2307 pExtents->FileId.Vnode,
2308 pExtents->FileId.Unique);
2310 try_return( ntStatus = STATUS_INVALID_PARAMETER );
2313 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2314 AFS_TRACE_LEVEL_VERBOSE,
2315 "AFSProcessReleaseFileExtents Acquiring RDR VolumeTreeLock lock %08lX SHARED %08lX\n",
2316 &pDevExt->Specific.RDR.VolumeTreeLock,
2317 PsGetCurrentThread());
2319 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
2322 // Locate the volume node
2325 ullIndex = AFSCreateHighIndex( &pExtents->FileId);
2327 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
2329 (AFSBTreeEntry **)&pVolumeCB);
2331 if( pVolumeCB != NULL)
2334 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
2336 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2337 AFS_TRACE_LEVEL_VERBOSE,
2338 "AFSProcessReleaseFileExtents Increment count on volume %08lX Cnt %d\n",
2343 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
2345 if( !NT_SUCCESS( ntStatus) ||
2349 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2350 AFS_TRACE_LEVEL_ERROR,
2351 "AFSProcessReleaseFileExtents Invalid volume index %I64X status %08X\n",
2352 ullIndex, ntStatus);
2354 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2357 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2358 AFS_TRACE_LEVEL_VERBOSE,
2359 "AFSProcessReleaseFileExtents Acquiring VolumeRoot FileIDTree.TreeLock lock %08lX SHARED %08lX\n",
2360 pVolumeCB->ObjectInfoTree.TreeLock,
2361 PsGetCurrentThread());
2363 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
2367 // Now locate the Object in this volume
2370 ullIndex = AFSCreateLowIndex( &pExtents->FileId);
2372 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
2374 (AFSBTreeEntry **)&pObjectInfo);
2376 if( pObjectInfo != NULL)
2380 // Reference the node so it won't be torn down
2383 lCount = AFSObjectInfoIncrement( pObjectInfo);
2385 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2386 AFS_TRACE_LEVEL_VERBOSE,
2387 "AFSProcessReleaseFileExtents Increment count on object %08lX Cnt %d\n",
2392 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2394 if( !NT_SUCCESS( ntStatus) ||
2395 pObjectInfo == NULL)
2398 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2399 AFS_TRACE_LEVEL_ERROR,
2400 "AFSProcessReleaseFileExtents Invalid file index %I64X\n",
2403 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2406 pFcb = pObjectInfo->Fcb;
2411 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2412 AFS_TRACE_LEVEL_ERROR,
2413 "AFSProcessReleaseFileExtents Fcb not initialied (NO EXTENTS) for FID %08lX:%08lx:%08lX:%08lX\n",
2414 pExtents->FileId.Cell,
2415 pExtents->FileId.Volume,
2416 pExtents->FileId.Vnode,
2417 pExtents->FileId.Unique);
2419 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2422 AFSLockForExtentsTrim( pFcb );
2430 // Locate an Fcb to trim down
2433 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2434 AFS_TRACE_LEVEL_VERBOSE,
2435 "AFSProcessReleaseFileExtents Searching for a Fcb to Trim Down\n");
2437 pFcb = AFSFindFcbToClean( 0, NULL, FALSE);
2442 pFcb = AFSFindFcbToClean( 0, NULL, TRUE);
2448 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2449 AFS_TRACE_LEVEL_ERROR,
2450 "AFSProcessReleaseFileExtents Failed to locate Fcb for release ...\n");
2452 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2455 pObjectInfo = pFcb->ObjectInformation;
2461 // Allocate a scratch buffer to move in the extent information
2464 ulSz = (pExtents->ExtentCount-1) * sizeof(AFSFileExtentCB);
2465 ulSz += sizeof(AFSReleaseFileExtentsResultCB);
2467 if (ulSz > pIrpSp->Parameters.DeviceIoControl.OutputBufferLength)
2469 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2470 AFS_TRACE_LEVEL_ERROR,
2471 "AFSProcessReleaseFileExtents OUTPUT Buffer too small [2]\n");
2473 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL );
2476 pResult = (AFSReleaseFileExtentsResultCB*) AFSExAllocatePoolWithTag( PagedPool,
2478 AFS_EXTENTS_RESULT_TAG);
2479 if (NULL == pResult)
2482 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2483 AFS_TRACE_LEVEL_ERROR,
2484 "AFSProcessReleaseFileExtents Failed to allocate result block\n");
2486 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2490 // Set up the header (for an array of one)
2492 pResult->FileCount = 1;
2493 pResult->Flags = AFS_EXTENT_FLAG_RELEASE;
2494 ulSz -= FIELD_OFFSET(AFSReleaseFileExtentsResultCB, Files);
2497 // Setup the first (and only) file
2499 pFile = pResult->Files;
2500 pFile->FileId = pObjectInfo->FileId;
2501 pFile->Flags = AFS_EXTENT_FLAG_RELEASE;
2504 // Stash away the auth group
2507 RtlZeroMemory( &stAuthGroup,
2510 ntStatus = AFSRetrieveValidAuthGroup( pFcb,
2515 if( !NT_SUCCESS( ntStatus))
2517 try_return( ntStatus);
2520 RtlCopyMemory( &pFile->AuthGroup,
2525 // Update the metadata for this call
2528 pFile->AllocationSize = pFcb->ObjectInformation->EndOfFile;
2529 pFile->CreateTime = pFcb->ObjectInformation->CreationTime;
2530 pFile->ChangeTime = pFcb->ObjectInformation->ChangeTime;
2531 pFile->LastAccessTime = pFcb->ObjectInformation->LastAccessTime;
2532 pFile->LastWriteTime = pFcb->ObjectInformation->LastWriteTime;
2534 ulSz -= FIELD_OFFSET(AFSReleaseFileExtentsResultFileCB, FileExtents);
2536 ntStatus = AFSReleaseSpecifiedExtents( pExtents,
2540 &pFile->ExtentCount,
2543 if (!NT_SUCCESS(ntStatus))
2546 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2547 AFS_TRACE_LEVEL_ERROR,
2548 "AFSProcessReleaseFileExtents Failed to release extents Status %08lX\n",
2551 try_return( ntStatus );
2554 if( pExtents->ExtentCount == 0)
2557 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2558 AFS_TRACE_LEVEL_WARNING,
2559 "AFSProcessReleaseFileExtents Failed to release ANY extents\n");
2562 ulSz = sizeof(AFSReleaseFileExtentsResultCB);
2564 if( pExtents->ExtentCount > 0)
2566 ulSz += ((pExtents->ExtentCount-1) * sizeof(AFSFileExtentCB));
2569 RtlCopyMemory( Irp->AssociatedIrp.SystemBuffer,
2578 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2579 AFS_TRACE_LEVEL_VERBOSE,
2580 "AFSProcessReleaseFileExtents Releasing Fcb extent lock %08lX thread %08lX\n",
2581 &pFcb->NPFcb->Specific.File.ExtentsResource,
2582 PsGetCurrentThread());
2584 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
2587 if( NULL != pResult &&
2588 Irp->AssociatedIrp.SystemBuffer != pResult)
2591 AFSExFreePoolWithTag(pResult, AFS_EXTENTS_RESULT_TAG);
2594 if (NT_SUCCESS(ntStatus))
2596 Irp->IoStatus.Information = ulSz;
2600 Irp->IoStatus.Information = 0;
2603 Irp->IoStatus.Status = ntStatus;
2605 if( pObjectInfo != NULL)
2608 lCount = AFSObjectInfoDecrement( pObjectInfo);
2610 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2611 AFS_TRACE_LEVEL_VERBOSE,
2612 "AFSProcessReleaseFileExtents Decrement count on object %08lX Cnt %d\n",
2620 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
2622 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2623 AFS_TRACE_LEVEL_VERBOSE,
2624 "AFSProcessReleaseFileExtents Decrement count on volume %08lX Cnt %d\n",
2635 AFSWaitForExtentMapping( AFSFcb *Fcb,
2638 NTSTATUS ntStatus = STATUS_SUCCESS;
2639 LARGE_INTEGER liTimeOut;
2640 ULONGLONG ullProcessId = (ULONGLONG)PsGetCurrentProcessId();
2645 ASSERT( !ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
2647 if (!NT_SUCCESS( Fcb->NPFcb->Specific.File.ExtentsRequestStatus))
2651 // If this isn't the same authgroup which caused the failure
2652 // then try to request them again
2655 if( RtlCompareMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2657 sizeof( GUID)) == sizeof( GUID))
2660 ntStatus = Fcb->NPFcb->Specific.File.ExtentsRequestStatus;
2662 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
2664 RtlZeroMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2667 try_return( ntStatus);
2671 liTimeOut.QuadPart = -(1 * AFS_ONE_SECOND);
2673 ntStatus = KeWaitForSingleObject( &Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
2679 if (!NT_SUCCESS( Fcb->NPFcb->Specific.File.ExtentsRequestStatus))
2683 // If this isn't the same authgroup which caused the failure
2684 // or the System Process,
2685 // then try to request the extents again
2688 if( RtlCompareMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2690 sizeof( GUID)) == sizeof( GUID) ||
2691 ullProcessId == (ULONGLONG)AFSSysProcess)
2694 ntStatus = Fcb->NPFcb->Specific.File.ExtentsRequestStatus;
2696 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
2698 RtlZeroMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2701 try_return( ntStatus);
2705 if( ntStatus == STATUS_TIMEOUT)
2708 ntStatus = STATUS_SUCCESS;
2720 AFSFlushExtents( IN AFSFcb *Fcb,
2723 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
2724 AFSExtent *pExtent, *pNextExtent;
2726 AFSReleaseExtentsCB *pRelease = NULL;
2728 ULONG initialDirtyCount = 0;
2729 BOOLEAN bExtentsLocked = FALSE;
2732 NTSTATUS ntStatus = STATUS_SUCCESS;
2733 LARGE_INTEGER liLastFlush;
2734 AFSExtent *pDirtyListHead = NULL, *pDirtyListTail = NULL;
2735 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2736 GUID *pAuthGroup = AuthGroup;
2740 ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
2743 // Save, then reset the flush time
2746 liLastFlush = Fcb->Specific.File.LastServerFlush;
2748 KeQueryTickCount( &Fcb->Specific.File.LastServerFlush);
2753 lCount = InterlockedIncrement( &Fcb->Specific.File.QueuedFlushCount);
2755 if( pAuthGroup == NULL ||
2756 RtlCompareMemory( pAuthGroup,
2757 &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2758 sizeof( GUID)) == sizeof( GUID))
2761 RtlZeroMemory( &stAuthGroup,
2764 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
2769 if( !NT_SUCCESS( ntStatus))
2771 try_return( ntStatus);
2774 pAuthGroup = &stAuthGroup;
2778 // Lock extents while we count and set up the array to send to
2782 AFSLockForExtentsTrim( Fcb);
2784 bExtentsLocked = TRUE;
2787 // Clear our queued flush event
2790 KeClearEvent( &Fcb->NPFcb->Specific.File.QueuedFlushEvent);
2793 // Look for a start in the list to flush entries
2798 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
2800 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
2802 AFS_EXTENT_RELEASE_TAG);
2803 if( NULL == pRelease)
2806 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2809 initialDirtyCount = Fcb->Specific.File.ExtentsDirtyCount;
2811 while( Fcb->Specific.File.ExtentsDirtyCount > 0)
2814 pRelease->Flags = AFS_EXTENT_FLAG_DIRTY;
2816 if( BooleanFlagOn( Fcb->Flags, AFS_FCB_FILE_CLOSED))
2819 pRelease->Flags |= AFS_EXTENT_FLAG_FLUSH;
2823 // Update the metadata for this call
2826 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
2827 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
2828 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
2829 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
2830 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
2834 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
2837 pExtent = (AFSExtent *)pNPFcb->Specific.File.DirtyListHead;
2839 while( count < AFS_MAXIMUM_EXTENT_RELEASE_COUNT)
2842 if ( pExtent == NULL)
2848 pNextExtent = (AFSExtent *)pExtent->DirtyList.fLink;
2850 if ( pExtent->ActiveCount > 0)
2852 pExtent = pNextExtent;
2856 AFSRemoveEntryDirtyList( Fcb, pExtent);
2858 pExtent->DirtyList.fLink = NULL;
2859 pExtent->DirtyList.bLink = NULL;
2861 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
2864 // Clear the flag in advance of the write. If we do
2865 // things this was we know that the clear is
2866 // pessimistic (any write which happens from now on
2867 // will set the flag dirty again).
2870 pExtent->Flags &= ~AFS_EXTENT_DIRTY;
2872 pRelease->FileExtents[count].Flags = AFS_EXTENT_FLAG_DIRTY;
2874 pRelease->FileExtents[count].Length = pExtent->Size;
2875 pRelease->FileExtents[count].DirtyLength = pExtent->Size;
2876 pRelease->FileExtents[count].DirtyOffset = 0;
2877 pRelease->FileExtents[count].CacheOffset = pExtent->CacheOffset;
2878 pRelease->FileExtents[count].FileOffset = pExtent->FileOffset;
2881 RtlCopyMemory( pRelease->FileExtents[count].MD5,
2883 sizeof(pExtent->MD5));
2885 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_MD5_SET;
2888 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2889 AFS_TRACE_LEVEL_VERBOSE,
2890 "AFSFlushExtents Releasing DIRTY extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
2892 Fcb->ObjectInformation->FileId.Cell,
2893 Fcb->ObjectInformation->FileId.Volume,
2894 Fcb->ObjectInformation->FileId.Vnode,
2895 Fcb->ObjectInformation->FileId.Unique,
2896 pExtent->FileOffset.QuadPart,
2899 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_RELEASE;
2906 pExtent = pNextExtent;
2909 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
2912 // If we are done then get out
2918 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2919 AFS_TRACE_LEVEL_VERBOSE,
2920 "AFSFlushExtents No more dirty extents found\n");
2926 // Fire off the request synchronously
2929 sz = sizeof( AFSReleaseExtentsCB ) + (count * sizeof ( AFSFileExtentCB ));
2931 pRelease->ExtentCount = count;
2933 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2934 AFS_TRACE_LEVEL_VERBOSE,
2935 "AFSFlushExtents Releasing(1) Fcb extents lock %08lX SHARED %08lX\n",
2936 &pNPFcb->Specific.File.ExtentsResource,
2937 PsGetCurrentThread());
2939 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource);
2940 bExtentsLocked = FALSE;
2942 KeSetEvent( &pNPFcb->Specific.File.FlushEvent,
2946 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
2947 AFS_REQUEST_FLAG_SYNCHRONOUS,
2950 &Fcb->ObjectInformation->FileId,
2956 if( !NT_SUCCESS(ntStatus))
2960 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
2961 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
2964 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2965 AFS_TRACE_LEVEL_ERROR,
2966 "AFSFlushExtents AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2967 Fcb->ObjectInformation->FileId.Cell,
2968 Fcb->ObjectInformation->FileId.Volume,
2969 Fcb->ObjectInformation->FileId.Vnode,
2970 Fcb->ObjectInformation->FileId.Unique,
2975 AFSLockForExtentsTrim( Fcb);
2977 bExtentsLocked = TRUE;
2982 lCount = InterlockedDecrement( &Fcb->Specific.File.QueuedFlushCount);
2984 ASSERT( lCount >= 0);
2989 KeSetEvent( &pNPFcb->Specific.File.QueuedFlushEvent,
2994 KeSetEvent( &pNPFcb->Specific.File.FlushEvent,
3001 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3002 AFS_TRACE_LEVEL_VERBOSE,
3003 "AFSFlushExtents Releasing(2) Fcb extents lock %08lX SHARED %08lX\n",
3004 &pNPFcb->Specific.File.ExtentsResource,
3005 PsGetCurrentThread());
3007 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
3012 AFSExFreePoolWithTag( pRelease, AFS_EXTENT_RELEASE_TAG);
3020 AFSReleaseExtentsWithFlush( IN AFSFcb *Fcb,
3022 IN BOOLEAN bReleaseAll)
3024 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3027 AFSReleaseExtentsCB *pRelease = NULL;
3029 ULONG initialDirtyCount = 0;
3030 BOOLEAN bExtentsLocked = FALSE;
3033 NTSTATUS ntStatus = STATUS_SUCCESS;
3034 LARGE_INTEGER liLastFlush;
3035 ULONG ulRemainingExtentLength = 0;
3036 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3037 GUID *pAuthGroup = AuthGroup;
3041 ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
3044 // Save, then reset the flush time
3047 liLastFlush = Fcb->Specific.File.LastServerFlush;
3049 KeQueryTickCount( &Fcb->Specific.File.LastServerFlush);
3054 if( pAuthGroup == NULL ||
3055 RtlCompareMemory( pAuthGroup,
3056 &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
3057 sizeof( GUID)) == sizeof( GUID))
3060 RtlZeroMemory( &stAuthGroup,
3063 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
3068 if( !NT_SUCCESS( ntStatus))
3070 try_return( ntStatus);
3073 pAuthGroup = &stAuthGroup;
3077 // Look for a start in the list to flush entries
3082 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
3084 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
3086 AFS_EXTENT_RELEASE_TAG);
3087 if( NULL == pRelease)
3090 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
3093 if( Fcb->OpenHandleCount > 0 &&
3098 // Don't release everything ...
3101 ulRemainingExtentLength = 1024;
3104 while( Fcb->Specific.File.ExtentLength > (LONG)ulRemainingExtentLength)
3107 AFSLockForExtentsTrim( Fcb);
3109 bExtentsLocked = TRUE;
3111 pRelease->Flags = AFS_EXTENT_FLAG_RELEASE;
3114 // Update the metadata for this call
3117 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
3118 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
3119 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
3120 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
3121 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
3125 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3127 while( count < AFS_MAXIMUM_EXTENT_RELEASE_COUNT &&
3128 le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
3131 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3135 if( pExtent->ActiveCount > 0)
3141 pRelease->FileExtents[count].Flags = AFS_EXTENT_FLAG_RELEASE;
3143 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3144 AFS_TRACE_LEVEL_VERBOSE,
3145 "AFSReleaseExtentsWithFlush Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3147 Fcb->ObjectInformation->FileId.Cell,
3148 Fcb->ObjectInformation->FileId.Volume,
3149 Fcb->ObjectInformation->FileId.Vnode,
3150 Fcb->ObjectInformation->FileId.Unique,
3151 pExtent->FileOffset.QuadPart,
3154 pRelease->FileExtents[count].Length = pExtent->Size;
3155 pRelease->FileExtents[count].DirtyLength = pExtent->Size;
3156 pRelease->FileExtents[count].DirtyOffset = 0;
3157 pRelease->FileExtents[count].CacheOffset = pExtent->CacheOffset;
3158 pRelease->FileExtents[count].FileOffset = pExtent->FileOffset;
3161 RtlCopyMemory( pRelease->FileExtents[count].MD5,
3163 sizeof(pExtent->MD5));
3165 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_MD5_SET;
3168 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3171 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3174 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3177 AFSRemoveEntryDirtyList( Fcb,
3180 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_DIRTY;
3182 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
3185 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3195 // If we are done then get out
3201 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3202 AFS_TRACE_LEVEL_VERBOSE,
3203 "AFSReleaseExtentsWithFlush No more dirty extents found\n");
3209 // Fire off the request synchronously
3212 sz = sizeof( AFSReleaseExtentsCB ) + (count * sizeof ( AFSFileExtentCB ));
3214 pRelease->ExtentCount = count;
3217 // Drop the extents lock for the duration of the call to
3218 // the network. We have pinned the extents so, even
3219 // though we might get extents added during this period,
3220 // but none will be removed. Hence we can carry on from
3224 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3225 AFS_TRACE_LEVEL_VERBOSE,
3226 "AFSReleaseExtentsWithFlush Releasing Fcb extents lock %08lX thread %08lX\n",
3227 &pNPFcb->Specific.File.ExtentsResource,
3228 PsGetCurrentThread());
3230 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource);
3231 bExtentsLocked = FALSE;
3233 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
3234 AFS_REQUEST_FLAG_SYNCHRONOUS,
3237 &Fcb->ObjectInformation->FileId,
3243 if( !NT_SUCCESS(ntStatus))
3247 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
3248 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
3251 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3252 AFS_TRACE_LEVEL_ERROR,
3253 "AFSReleaseExtentsWithFlush AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3254 Fcb->ObjectInformation->FileId.Cell,
3255 Fcb->ObjectInformation->FileId.Volume,
3256 Fcb->ObjectInformation->FileId.Vnode,
3257 Fcb->ObjectInformation->FileId.Unique,
3267 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3268 AFS_TRACE_LEVEL_VERBOSE,
3269 "AFSReleaseExtentsWithFlush Releasing Fcb extents lock %08lX thread %08lX\n",
3270 &pNPFcb->Specific.File.ExtentsResource,
3271 PsGetCurrentThread());
3273 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
3278 AFSExFreePoolWithTag( pRelease, AFS_EXTENT_RELEASE_TAG);
3286 AFSReleaseCleanExtents( IN AFSFcb *Fcb,
3289 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3292 AFSReleaseExtentsCB *pRelease = NULL;
3294 ULONG initialDirtyCount = 0;
3295 BOOLEAN bExtentsLocked = FALSE;
3298 NTSTATUS ntStatus = STATUS_SUCCESS;
3299 LARGE_INTEGER liLastFlush;
3300 ULONG ulRemainingExtentLength = 0;
3301 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3302 GUID *pAuthGroup = AuthGroup;
3305 ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
3308 // Save, then reset the flush time
3311 liLastFlush = Fcb->Specific.File.LastServerFlush;
3313 KeQueryTickCount( &Fcb->Specific.File.LastServerFlush);
3318 if( pAuthGroup == NULL ||
3319 RtlCompareMemory( pAuthGroup,
3320 &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
3321 sizeof( GUID)) == sizeof( GUID))
3324 RtlZeroMemory( &stAuthGroup,
3327 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
3332 if( !NT_SUCCESS( ntStatus))
3334 try_return( ntStatus);
3337 pAuthGroup = &stAuthGroup;
3341 // Look for a start in the list to flush entries
3346 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
3348 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
3350 AFS_EXTENT_RELEASE_TAG);
3351 if( NULL == pRelease)
3354 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
3357 while( Fcb->Specific.File.ExtentLength > (LONG)ulRemainingExtentLength)
3360 AFSLockForExtentsTrim( Fcb);
3362 bExtentsLocked = TRUE;
3364 pRelease->Flags = AFS_EXTENT_FLAG_RELEASE;
3367 // Update the metadata for this call
3370 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
3371 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
3372 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
3373 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
3374 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
3378 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3380 while( count < AFS_MAXIMUM_EXTENT_RELEASE_COUNT &&
3381 le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
3384 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3388 if( pExtent->ActiveCount > 0 ||
3389 BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3394 pRelease->FileExtents[count].Flags = AFS_EXTENT_FLAG_RELEASE;
3396 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3397 AFS_TRACE_LEVEL_VERBOSE,
3398 "AFSReleaseCleanExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3400 Fcb->ObjectInformation->FileId.Cell,
3401 Fcb->ObjectInformation->FileId.Volume,
3402 Fcb->ObjectInformation->FileId.Vnode,
3403 Fcb->ObjectInformation->FileId.Unique,
3404 pExtent->FileOffset.QuadPart,
3407 pRelease->FileExtents[count].Length = pExtent->Size;
3408 pRelease->FileExtents[count].DirtyLength = pExtent->Size;
3409 pRelease->FileExtents[count].DirtyOffset = 0;
3410 pRelease->FileExtents[count].CacheOffset = pExtent->CacheOffset;
3411 pRelease->FileExtents[count].FileOffset = pExtent->FileOffset;
3414 RtlCopyMemory( pRelease->FileExtents[count].MD5,
3416 sizeof(pExtent->MD5));
3418 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_MD5_SET;
3428 // If we are done then get out
3434 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3435 AFS_TRACE_LEVEL_VERBOSE,
3436 "AFSReleaseCleanExtents No more dirty extents found\n");
3442 // Fire off the request synchronously
3445 sz = sizeof( AFSReleaseExtentsCB ) + (count * sizeof ( AFSFileExtentCB ));
3447 pRelease->ExtentCount = count;
3450 // Drop the extents lock for the duration of the call to
3451 // the network. We have pinned the extents so, even
3452 // though we might get extents added during this period,
3453 // but none will be removed. Hence we can carry on from
3457 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3458 AFS_TRACE_LEVEL_VERBOSE,
3459 "AFSReleaseCleanExtents Releasing Fcb extents lock %08lX thread %08lX\n",
3460 &pNPFcb->Specific.File.ExtentsResource,
3461 PsGetCurrentThread());
3463 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource);
3464 bExtentsLocked = FALSE;
3466 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
3467 AFS_REQUEST_FLAG_SYNCHRONOUS,
3470 &Fcb->ObjectInformation->FileId,
3476 if( !NT_SUCCESS(ntStatus))
3480 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
3481 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
3484 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3485 AFS_TRACE_LEVEL_ERROR,
3486 "AFSReleaseCleanExtents AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3487 Fcb->ObjectInformation->FileId.Cell,
3488 Fcb->ObjectInformation->FileId.Volume,
3489 Fcb->ObjectInformation->FileId.Vnode,
3490 Fcb->ObjectInformation->FileId.Unique,
3500 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3501 AFS_TRACE_LEVEL_VERBOSE,
3502 "AFSReleaseCleanExtents Releasing Fcb extents lock %08lX thread %08lX\n",
3503 &pNPFcb->Specific.File.ExtentsResource,
3504 PsGetCurrentThread());
3506 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
3511 AFSExFreePoolWithTag( pRelease, AFS_EXTENT_RELEASE_TAG);
3519 AFSMarkDirty( IN AFSFcb *Fcb,
3520 IN AFSExtent *StartExtent,
3521 IN ULONG ExtentsCount,
3522 IN LARGE_INTEGER *StartingByte,
3523 IN BOOLEAN DerefExtents)
3526 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3527 AFSExtent *pExtent = StartExtent;
3528 AFSExtent *pNextExtent, *pCurrentExtent = NULL;
3530 BOOLEAN bInsertTail = FALSE, bInsertHead = FALSE;
3533 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3534 AFS_TRACE_LEVEL_VERBOSE,
3535 "AFSMarkDirty Acquiring Fcb extents lock %08lX SHARED %08lX\n",
3536 &Fcb->NPFcb->Specific.File.ExtentsResource,
3537 PsGetCurrentThread());
3539 ASSERT( ExIsResourceAcquiredLite( &pNPFcb->Specific.File.ExtentsResource));
3541 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3547 // Find the insertion point
3550 if( pNPFcb->Specific.File.DirtyListHead == NULL)
3555 else if( StartingByte->QuadPart == 0)
3563 pCurrentExtent = pNPFcb->Specific.File.DirtyListHead;
3565 while( pCurrentExtent != NULL)