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,
324 Fcb->ObjectInformation->VolumeCB->VolumeInformation.Cell,
325 Fcb->ObjectInformation->VolumeCB->VolumeInformation.CellLength,
331 if( !NT_SUCCESS(ntStatus))
335 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
336 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
339 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
340 AFS_TRACE_LEVEL_ERROR,
341 "AFSTearDownFcbExtents AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
342 Fcb->ObjectInformation->FileId.Cell,
343 Fcb->ObjectInformation->FileId.Volume,
344 Fcb->ObjectInformation->FileId.Vnode,
345 Fcb->ObjectInformation->FileId.Unique,
352 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
355 // if all extents have been released, reinitialize the skip lists
358 if( Fcb->Specific.File.ExtentCount == 0)
361 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i++)
363 InitializeListHead(&Fcb->Specific.File.ExtentsLists[i]);
367 // Reinitialize the dirty list as well
370 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
373 ASSERT( Fcb->Specific.File.ExtentsDirtyCount == 0);
375 Fcb->NPFcb->Specific.File.DirtyListHead = NULL;
376 Fcb->NPFcb->Specific.File.DirtyListTail = NULL;
378 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
381 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
388 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
389 AFS_TRACE_LEVEL_VERBOSE,
390 "AFSTearDownFcbExtents Releasing Fcb extent lock %p thread %08lX\n",
391 &Fcb->NPFcb->Specific.File.ExtentsResource,
392 PsGetCurrentThread());
394 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
400 AFSExFreePoolWithTag( pRelease, AFS_EXTENT_RELEASE_TAG);
406 AFSDeleteFcbExtents( IN AFSFcb *Fcb)
408 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
409 LIST_ENTRY *le, *leNext;
411 LONG lExtentCount = 0, lProcessCount = 0;
412 LONG lFcbExtentCount;
414 BOOLEAN locked = FALSE;
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 %p 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
760 AFSExtent *entry = NULL;
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;
852 ASSERT( !ExIsResourceAcquiredLite( &pNPFcb->Specific.File.ExtentsResource ));
855 // If the service set a failure on the file since the last
856 // CreateFile was issued, return it now.
859 if (!NT_SUCCESS( pNPFcb->Specific.File.ExtentsRequestStatus))
863 // If this isn't the same authgroup which caused the failure
864 // then try to request them again
867 if( RtlCompareMemory( &pNPFcb->Specific.File.ExtentsRequestAuthGroup,
869 sizeof( GUID)) == sizeof( GUID))
872 ntStatus = pNPFcb->Specific.File.ExtentsRequestStatus;
874 pNPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
876 RtlZeroMemory( &pNPFcb->Specific.File.ExtentsRequestAuthGroup,
879 try_return( ntStatus);
884 // Check if we are already mapped
887 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
888 AFS_TRACE_LEVEL_VERBOSE,
889 "AFSRequestExtentsAsync Acquiring Fcb extents lock %p SHARED %08lX\n",
890 &pNPFcb->Specific.File.ExtentsResource,
891 PsGetCurrentThread());
893 AFSAcquireShared( &pNPFcb->Specific.File.ExtentsResource, TRUE );
895 bRegionMapped = AFSDoExtentsMapRegion( Fcb, Offset, Size, &pFirstExtent, &pExtent);
900 KeClearEvent( &pNPFcb->Specific.File.ExtentsRequestComplete );
903 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
904 AFS_TRACE_LEVEL_VERBOSE,
905 "AFSRequestExtentsAsync Releasing Fcb extents lock %p SHARED %08lX\n",
906 &pNPFcb->Specific.File.ExtentsResource,
907 PsGetCurrentThread());
909 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
914 try_return( ntStatus = STATUS_SUCCESS);
918 // Align our request on extent size boundary
921 ulAlignedLength = Size;
923 liAlignedOffset = *Offset;
925 if( liAlignedOffset.QuadPart % pDevExt->Specific.RDR.CacheBlockSize != 0)
928 liAlignedOffset.QuadPart = (ULONGLONG)( (ULONGLONG)(liAlignedOffset.QuadPart / pDevExt->Specific.RDR.CacheBlockSize) * (ULONGLONG)pDevExt->Specific.RDR.CacheBlockSize);
930 ulAlignedLength += (ULONG)(Offset->QuadPart - liAlignedOffset.QuadPart);
933 if( ulAlignedLength % pDevExt->Specific.RDR.CacheBlockSize != 0)
936 ulAlignedLength = (ULONG)(((ulAlignedLength / pDevExt->Specific.RDR.CacheBlockSize) + 1) * pDevExt->Specific.RDR.CacheBlockSize);
939 RtlZeroMemory( &request,
940 sizeof( AFSRequestExtentsCB));
942 request.ByteOffset = liAlignedOffset;
943 request.Length = ulAlignedLength;
945 if( !AFSIsExtentRequestQueued( &Fcb->ObjectInformation->FileId,
950 KeClearEvent( &pNPFcb->Specific.File.ExtentsRequestComplete );
952 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
953 AFS_TRACE_LEVEL_VERBOSE,
954 "AFSRequestExtentsAsync Request extents for fid %08lX-%08lX-%08lX-%08lX Offset %08lX Len %08lX Thread %08lX\n",
955 Fcb->ObjectInformation->FileId.Cell,
956 Fcb->ObjectInformation->FileId.Volume,
957 Fcb->ObjectInformation->FileId.Vnode,
958 Fcb->ObjectInformation->FileId.Unique,
959 request.ByteOffset.LowPart,
961 PsGetCurrentThread());
963 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS,
967 &Fcb->ObjectInformation->FileId,
968 Fcb->ObjectInformation->VolumeCB->VolumeInformation.Cell,
969 Fcb->ObjectInformation->VolumeCB->VolumeInformation.CellLength,
971 sizeof( AFSRequestExtentsCB ),
975 if ( ntStatus == STATUS_ACCESS_DENIED)
980 ntStatus2 = AFSRetrieveValidAuthGroup( Fcb,
985 if ( NT_SUCCESS( ntStatus2) &&
986 RtlCompareMemory( &stAuthGroup,
988 sizeof( GUID)) != sizeof( GUID))
991 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS,
995 &Fcb->ObjectInformation->FileId,
996 Fcb->ObjectInformation->VolumeCB->VolumeInformation.Cell,
997 Fcb->ObjectInformation->VolumeCB->VolumeInformation.CellLength,
999 sizeof( AFSRequestExtentsCB ),
1005 if( !NT_SUCCESS( ntStatus))
1008 KeSetEvent( &pNPFcb->Specific.File.ExtentsRequestComplete,
1023 AFSProcessExtentsResult( IN AFSFcb *Fcb,
1025 IN AFSFileExtentCB *Result)
1027 NTSTATUS ntStatus = STATUS_SUCCESS;
1028 AFSFileExtentCB *pFileExtents = Result;
1031 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
1032 ULONG fileExtentsUsed = 0;
1033 BOOLEAN bFoundExtent = FALSE;
1034 LIST_ENTRY *pSkipEntries[AFS_NUM_EXTENT_LISTS] = { 0 };
1035 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1039 // Grab the extents exclusive for the duration
1042 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1043 AFS_TRACE_LEVEL_VERBOSE,
1044 "AFSProcessExtentsResult Acquiring Fcb extent lock %p EXCL %08lX\n",
1045 &pNPFcb->Specific.File.ExtentsResource,
1046 PsGetCurrentThread());
1048 AFSAcquireExcl( &pNPFcb->Specific.File.ExtentsResource, TRUE );
1054 // Find where to put the extents
1056 for (ULONG i = AFS_EXTENTS_LIST; i < AFS_NUM_EXTENT_LISTS; i++)
1059 pSkipEntries[i] = Fcb->Specific.File.ExtentsLists[i].Flink;
1062 le = pSkipEntries[AFS_EXTENTS_LIST];
1064 if (le == &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
1067 // No extents. Insert at head of list (which is where the skip lists point!)
1071 else if (0 != pFileExtents->FileOffset.QuadPart)
1074 // We want to find the best extents immediately *behind* this offset
1076 LARGE_INTEGER offset = pFileExtents->FileOffset;
1079 // Ask in the top skip list first, then work down
1081 for (LONG i = AFS_NUM_EXTENT_LISTS-1; i >= AFS_EXTENTS_LIST; i--)
1083 pExtent = ExtentForOffsetInList( Fcb,
1088 if (NULL == pExtent)
1091 // No dice. Header has to become the head of the list
1093 pSkipEntries[i] = &Fcb->Specific.File.ExtentsLists[i];
1095 // And as a loop invariant we should never have found an extent
1097 ASSERT(!bFoundExtent);
1102 // pExtent is where to start to insert at this level
1104 pSkipEntries[i] = &pExtent->Lists[i];
1107 // And also where to start to look at the next level
1110 if (i > AFS_EXTENTS_LIST)
1112 pSkipEntries[i-1] = &pExtent->Lists[i-1];
1114 bFoundExtent = TRUE;
1118 if (NULL == pExtent)
1120 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
1125 le = pExtent->Lists[AFS_EXTENTS_LIST].Blink;
1131 // Looking at offset 0, so we must start at the beginning
1134 pExtent = ExtentFor(le, AFS_EXTENTS_LIST);
1138 // And set up the skip lists
1141 for (ULONG i = AFS_EXTENTS_LIST; i < AFS_NUM_EXTENT_LISTS; i++)
1143 pSkipEntries[i] = &Fcb->Specific.File.ExtentsLists[i];
1147 while (fileExtentsUsed < Count)
1151 // Loop invariant - le points to where to insert after and
1152 // pExtent points to le->fLink
1155 ASSERT (NULL == pExtent ||
1156 le->Flink == &pExtent->Lists[AFS_EXTENTS_LIST]);
1158 if (NULL == pExtent ||
1159 pExtent->FileOffset.QuadPart > pFileExtents->FileOffset.QuadPart)
1162 // We need to insert a new extent at le. Start with
1163 // some sanity check on spanning
1165 if (NULL != pExtent &&
1166 ((pFileExtents->FileOffset.QuadPart + pFileExtents->Length) >
1167 pExtent->FileOffset.QuadPart))
1170 // File Extents overlaps pExtent
1172 ASSERT( (pFileExtents->FileOffset.QuadPart + pFileExtents->Length) <=
1173 pExtent->FileOffset.QuadPart);
1175 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1179 // File offset is entirely in front of this extent. Create
1180 // a new one (remember le is the previous list entry)
1182 pExtent = (AFSExtent *) AFSExAllocatePoolWithTag( NonPagedPool,
1185 if (NULL == pExtent)
1188 try_return (ntStatus = STATUS_INSUFFICIENT_RESOURCES );
1191 RtlZeroMemory( pExtent, sizeof( AFSExtent ));
1193 pExtent->FileOffset = pFileExtents->FileOffset;
1194 pExtent->CacheOffset = pFileExtents->CacheOffset;
1195 pExtent->Size = pFileExtents->Length;
1197 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1198 AFS_TRACE_LEVEL_VERBOSE,
1199 "AFSProcessExtentsResult Received extent for fid %08lX-%08lX-%08lX-%08lX File Offset %I64X Cache Offset %I64X Len %08lX\n",
1200 Fcb->ObjectInformation->FileId.Cell,
1201 Fcb->ObjectInformation->FileId.Volume,
1202 Fcb->ObjectInformation->FileId.Vnode,
1203 Fcb->ObjectInformation->FileId.Unique,
1204 pFileExtents->FileOffset.QuadPart,
1205 pFileExtents->CacheOffset.QuadPart,
1206 pFileExtents->Length);
1208 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, (LONG)(pExtent->Size/1024));
1210 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, (LONG)(pExtent->Size/1024));
1212 lCount = InterlockedIncrement( &Fcb->Specific.File.ExtentCount);
1214 lCount = InterlockedIncrement( &pControlDevExt->Specific.Control.ExtentCount);
1219 KeClearEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent);
1225 InsertHeadList(le, &pExtent->Lists[AFS_EXTENTS_LIST]);
1226 ASSERT(le->Flink == &pExtent->Lists[AFS_EXTENTS_LIST]);
1227 ASSERT(0 == (pExtent->FileOffset.LowPart & ExtentsMasks[AFS_EXTENTS_LIST]));
1230 // Do not move the cursor - we will do it next time
1234 // And into the (upper) skip lists - Again, do not move the cursor
1236 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1238 if (0 == (pExtent->FileOffset.LowPart & ExtentsMasks[i]))
1240 InsertHeadList(pSkipEntries[i], &pExtent->Lists[i]);
1241 #if AFS_VALIDATE_EXTENTS
1242 VerifyExtentsLists(Fcb);
1247 else if (pExtent->FileOffset.QuadPart == pFileExtents->FileOffset.QuadPart)
1250 if (pExtent->Size != pFileExtents->Length)
1253 ASSERT (pExtent->Size == pFileExtents->Length);
1255 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1259 // Move both cursors forward.
1261 // First the extent pointer
1264 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1267 // Then the skip lists cursors forward if needed
1269 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1271 if (0 == (pExtent->FileOffset.LowPart & ExtentsMasks[i]))
1274 // Check sanity before
1276 #if AFS_VALIDATE_EXTENTS
1277 VerifyExtentsLists(Fcb);
1281 // Skip list should point to us
1283 //ASSERT(pSkipEntries[i] == &pExtent->Lists[i]);
1285 // Move forward cursor
1287 pSkipEntries[i] = pSkipEntries[i]->Flink;
1289 // Check sanity before
1291 #if AFS_VALIDATE_EXTENTS
1292 VerifyExtentsLists(Fcb);
1298 // And then the cursor in the supplied array
1304 // setup pExtent if there is one
1306 if (le->Flink != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
1308 pExtent = NextExtent( pExtent, AFS_EXTENTS_LIST ) ;
1318 ASSERT( pExtent->FileOffset.QuadPart < pFileExtents->FileOffset.QuadPart );
1321 // Sanity check on spanning
1323 if ((pExtent->FileOffset.QuadPart + pExtent->Size) >
1324 pFileExtents->FileOffset.QuadPart)
1327 ASSERT( (pExtent->FileOffset.QuadPart + pExtent->Size) <=
1328 pFileExtents->FileOffset.QuadPart);
1330 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1334 // Move le and pExtent forward
1336 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1339 // setup pExtent if there is one
1342 if (le->Flink != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
1344 pExtent = NextExtent( pExtent, AFS_EXTENTS_LIST ) ;
1354 // All done, signal that we are done drop the lock, exit
1359 if( !NT_SUCCESS( ntStatus))
1363 // If we failed the service is going to drop all extents so trim away the
1367 AFSTrimSpecifiedExtents( Fcb,
1372 #if AFS_VALIDATE_EXTENTS
1373 VerifyExtentsLists(Fcb);
1376 KeSetEvent( &pNPFcb->Specific.File.ExtentsRequestComplete,
1380 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1381 AFS_TRACE_LEVEL_VERBOSE,
1382 "AFSProcessExtentsResult Releasing Fcb extent lock %p EXCL %08lX\n",
1383 &pNPFcb->Specific.File.ExtentsResource,
1384 PsGetCurrentThread());
1386 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
1393 AFSProcessSetFileExtents( IN AFSSetFileExtentsCB *SetExtents )
1395 AFSFcb *pFcb = NULL;
1396 AFSVolumeCB *pVolumeCB = NULL;
1397 NTSTATUS ntStatus = STATUS_SUCCESS;
1398 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1399 ULONGLONG ullIndex = 0;
1400 AFSObjectInfoCB *pObjectInfo = NULL;
1406 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1407 AFS_TRACE_LEVEL_VERBOSE,
1408 "AFSProcessSetFileExtents Acquiring RDR VolumeTreeLock lock %p SHARED %08lX\n",
1409 &pDevExt->Specific.RDR.VolumeTreeLock,
1410 PsGetCurrentThread());
1412 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
1414 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1415 AFS_TRACE_LEVEL_VERBOSE,
1416 "AFSProcessSetFileExtents Set extents for fid %08lX-%08lX-%08lX-%08lX\n",
1417 SetExtents->FileId.Cell,
1418 SetExtents->FileId.Volume,
1419 SetExtents->FileId.Vnode,
1420 SetExtents->FileId.Unique);
1423 // Locate the volume node
1426 ullIndex = AFSCreateHighIndex( &SetExtents->FileId);
1428 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
1430 (AFSBTreeEntry **)&pVolumeCB);
1432 if( pVolumeCB != NULL)
1435 lCount = AFSVolumeIncrement( pVolumeCB,
1436 AFS_VOLUME_REFERENCE_EXTENTS);
1438 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1439 AFS_TRACE_LEVEL_VERBOSE,
1440 "AFSProcessSetFileExtents Increment count on volume %p Cnt %d\n",
1445 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
1447 if( !NT_SUCCESS( ntStatus) ||
1451 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1452 AFS_TRACE_LEVEL_ERROR,
1453 "AFSProcessSetFileExtents Set extents for fid %08lX-%08lX-%08lX-%08lX Failed to locate volume Status %08lX\n",
1454 SetExtents->FileId.Cell,
1455 SetExtents->FileId.Volume,
1456 SetExtents->FileId.Vnode,
1457 SetExtents->FileId.Unique,
1460 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1463 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1467 // Now locate the Object in this volume
1470 ullIndex = AFSCreateLowIndex( &SetExtents->FileId);
1472 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
1474 (AFSBTreeEntry **)&pObjectInfo);
1476 if( pObjectInfo != NULL)
1480 // Reference the node so it won't be torn down
1483 lCount = AFSObjectInfoIncrement( pObjectInfo,
1484 AFS_OBJECT_REFERENCE_EXTENTS);
1486 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1487 AFS_TRACE_LEVEL_VERBOSE,
1488 "AFSProcessSetFileExtents Increment count on object %p Cnt %d\n",
1493 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1495 if( !NT_SUCCESS( ntStatus) ||
1496 pObjectInfo == NULL)
1499 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1500 AFS_TRACE_LEVEL_ERROR,
1501 "AFSProcessSetFileExtents Set extents for hash %I64X fid %08lX-%08lX-%08lX-%08lX Failed to locate file in volume %p\n",
1503 SetExtents->FileId.Cell,
1504 SetExtents->FileId.Volume,
1505 SetExtents->FileId.Vnode,
1506 SetExtents->FileId.Unique,
1509 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1512 pFcb = pObjectInfo->Fcb;
1515 // If we have a result failure then don't bother trying to set the extents
1518 if( SetExtents->ResultStatus != STATUS_SUCCESS)
1521 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1522 AFS_TRACE_LEVEL_ERROR,
1523 "AFSProcessSetFileExtents Set extents failure fid %08lX-%08lX-%08lX-%08lX ResultStatus %08lX\n",
1524 SetExtents->FileId.Cell,
1525 SetExtents->FileId.Volume,
1526 SetExtents->FileId.Vnode,
1527 SetExtents->FileId.Unique,
1528 SetExtents->ResultStatus);
1530 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1531 AFS_TRACE_LEVEL_VERBOSE,
1532 "AFSProcessSetFileExtents Acquiring Fcb extents lock %p EXCL %08lX\n",
1533 &pFcb->NPFcb->Specific.File.ExtentsResource,
1534 PsGetCurrentThread());
1536 AFSAcquireExcl( &pFcb->NPFcb->Specific.File.ExtentsResource,
1539 pFcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_CANCELLED;
1541 KeSetEvent( &pFcb->NPFcb->Specific.File.ExtentsRequestComplete,
1545 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1546 AFS_TRACE_LEVEL_VERBOSE,
1547 "AFSProcessSetFileExtents Releasing Fcb extent lock %p EXCL %08lX\n",
1548 &pFcb->NPFcb->Specific.File.ExtentsResource,
1549 PsGetCurrentThread());
1551 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
1553 try_return( ntStatus);
1556 ntStatus = AFSProcessExtentsResult ( pFcb,
1557 SetExtents->ExtentCount,
1558 SetExtents->FileExtents );
1562 if( pObjectInfo != NULL)
1565 lCount = AFSObjectInfoDecrement( pObjectInfo,
1566 AFS_OBJECT_REFERENCE_EXTENTS);
1568 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1569 AFS_TRACE_LEVEL_VERBOSE,
1570 "AFSProcessSetFileExtents Decrement count on object %p Cnt %d\n",
1578 lCount = AFSVolumeDecrement( pVolumeCB,
1579 AFS_VOLUME_REFERENCE_EXTENTS);
1581 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1582 AFS_TRACE_LEVEL_VERBOSE,
1583 "AFSProcessSetFileExtents Decrement count on volume %p Cnt %d\n",
1593 // Helper fuctions for Usermode initiation of release of extents
1596 AFSReleaseSpecifiedExtents( IN AFSReleaseFileExtentsCB *Extents,
1598 OUT AFSFileExtentCB *FileExtents,
1599 IN ULONG BufferSize,
1600 OUT ULONG *ExtentCount,
1601 OUT BOOLEAN *DirtyExtents)
1605 ULONG ulExtentCount = 0;
1606 NTSTATUS ntStatus = STATUS_SUCCESS;
1607 BOOLEAN bReleaseAll = FALSE;
1612 ASSERT( ExIsResourceAcquiredExclusiveLite( &Fcb->NPFcb->Specific.File.ExtentsResource));
1614 if (BufferSize < (Extents->ExtentCount * sizeof( AFSFileExtentCB)))
1617 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1618 AFS_TRACE_LEVEL_VERBOSE,
1619 "AFSReleaseSpecifiedExtents Buffer too small\n");
1621 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL);
1624 RtlZeroMemory( FileExtents, BufferSize);
1627 *DirtyExtents = FALSE;
1630 // iterate until we have dealt with all we were asked for or
1631 // are at the end of the list. Note that this deals (albeit
1632 // badly) with out of order extents
1635 pExtent = AFSExtentForOffset( Fcb,
1636 &Extents->FileExtents[0].FileOffset,
1639 if (NULL == pExtent)
1641 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1645 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1649 if( BooleanFlagOn( Extents->Flags, AFS_RELEASE_EXTENTS_FLAGS_RELEASE_ALL) ||
1650 ( Extents->FileId.Cell == 0 &&
1651 Extents->FileId.Volume == 0 &&
1652 Extents->FileId.Vnode == 0 &&
1653 Extents->FileId.Unique == 0))
1659 while( le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST] &&
1660 ulExtentCount < Extents->ExtentCount)
1664 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
1669 if( pExtent->FileOffset.QuadPart < Extents->FileExtents[ulExtentCount].FileOffset.QuadPart)
1672 // Skip forward through the extent list until we get
1673 // to the one we want
1679 else if (pExtent->FileOffset.QuadPart > Extents->FileExtents[ulExtentCount].FileOffset.QuadPart)
1682 // We don't have the extent asked for so return UNKNOWN
1685 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1686 AFS_TRACE_LEVEL_VERBOSE,
1687 "AFSReleaseSpecifiedExtents Located UNKNOWN extent Offset %I64X Len %08lX\n",
1688 Extents->FileExtents[ulExtentCount].FileOffset.QuadPart,
1689 Extents->FileExtents[ulExtentCount].Length);
1691 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_UNKNOWN;
1693 FileExtents[*ExtentCount].Length = 0;
1694 FileExtents[*ExtentCount].CacheOffset.QuadPart = 0;
1695 FileExtents[*ExtentCount].FileOffset = Extents->FileExtents[ulExtentCount].FileOffset;
1697 *ExtentCount = (*ExtentCount) + 1;
1702 // Reset where we are looking
1705 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1709 else if( pExtent->ActiveCount > 0)
1712 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1713 AFS_TRACE_LEVEL_VERBOSE,
1714 "AFSReleaseSpecifiedExtents Located IN_USE extent Offset %I64X Len %08lX\n",
1715 Extents->FileExtents[ulExtentCount].FileOffset.QuadPart,
1716 Extents->FileExtents[ulExtentCount].Length);
1718 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_IN_USE;
1720 FileExtents[*ExtentCount].Length = 0;
1721 FileExtents[*ExtentCount].CacheOffset.QuadPart = 0;
1722 FileExtents[*ExtentCount].FileOffset = Extents->FileExtents[ulExtentCount].FileOffset;
1724 *ExtentCount = (*ExtentCount) + 1;
1729 // Reset where we are looking
1732 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1741 // If the extent is currently active then skip it
1744 if( pExtent->ActiveCount > 0)
1753 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_RELEASE;
1755 FileExtents[*ExtentCount].Length = pExtent->Size;
1756 FileExtents[*ExtentCount].DirtyLength = pExtent->Size;
1757 FileExtents[*ExtentCount].DirtyOffset = 0;
1758 FileExtents[*ExtentCount].CacheOffset = pExtent->CacheOffset;
1759 FileExtents[*ExtentCount].FileOffset = pExtent->FileOffset;
1761 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1762 AFS_TRACE_LEVEL_VERBOSE,
1763 "AFSReleaseSpecifiedExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
1765 Fcb->ObjectInformation->FileId.Cell,
1766 Fcb->ObjectInformation->FileId.Volume,
1767 Fcb->ObjectInformation->FileId.Vnode,
1768 Fcb->ObjectInformation->FileId.Unique,
1769 FileExtents[*ExtentCount].FileOffset.QuadPart,
1770 FileExtents[*ExtentCount].Length);
1772 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
1775 AFSAcquireExcl( &Fcb->NPFcb->Specific.File.DirtyExtentsListLock,
1778 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
1781 AFSRemoveEntryDirtyList( Fcb,
1784 FileExtents[*ExtentCount].Flags |= AFS_EXTENT_FLAG_DIRTY;
1786 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
1788 *DirtyExtents = TRUE;
1791 AFSReleaseResource( &Fcb->NPFcb->Specific.File.DirtyExtentsListLock);
1795 // move forward all three cursors
1799 *ExtentCount = (*ExtentCount) + 1;
1814 AFSFindFcbToClean(ULONG IgnoreTime, AFSFcb *LastFcb, BOOLEAN Block)
1817 UNREFERENCED_PARAMETER(IgnoreTime);
1818 AFSFcb *pFcb = NULL;
1819 AFSVolumeCB *pVolumeCB = NULL;
1820 AFSDeviceExt *pRDRDeviceExt = NULL;
1821 AFSDeviceExt *pControlDeviceExt = NULL;
1822 BOOLEAN bLocatedEntry = FALSE;
1823 AFSObjectInfoCB *pCurrentObject = NULL;
1824 BOOLEAN bReleaseVolumeListLock = FALSE;
1827 pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1828 pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1830 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1831 AFS_TRACE_LEVEL_VERBOSE,
1832 "AFSFindFcbToClean Acquiring RDR VolumeListLock lock %p SHARED %08lX\n",
1833 &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1834 PsGetCurrentThread());
1836 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1839 bReleaseVolumeListLock = TRUE;
1841 pVolumeCB = pRDRDeviceExt->Specific.RDR.VolumeListHead;
1843 while( pVolumeCB != NULL)
1847 // The Volume list may move under our feet. Lock it.
1850 lCount = AFSVolumeIncrement( pVolumeCB,
1851 AFS_VOLUME_REFERENCE_EXTENTS);
1853 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1854 AFS_TRACE_LEVEL_VERBOSE,
1855 "AFSFindFcbToClean Increment count on volume %p Cnt %d\n",
1859 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1861 bReleaseVolumeListLock = FALSE;
1863 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1864 AFS_TRACE_LEVEL_VERBOSE,
1865 "AFSFindFcbToClean Acquiring VolumeRoot ObjectInfoTree lock %p SHARED %08lX\n",
1866 pVolumeCB->ObjectInfoTree.TreeLock,
1867 PsGetCurrentThread());
1869 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1872 lCount = AFSVolumeDecrement( pVolumeCB,
1873 AFS_VOLUME_REFERENCE_EXTENTS);
1875 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1876 AFS_TRACE_LEVEL_VERBOSE,
1877 "AFSFindFcbToClean Decrement count on volume %p Cnt %d\n",
1881 if( NULL == LastFcb)
1884 pCurrentObject = pVolumeCB->ObjectInfoListHead;
1889 pCurrentObject = (AFSObjectInfoCB *)LastFcb->ObjectInformation->ListEntry.fLink;
1894 while( pCurrentObject != NULL)
1897 pFcb = (AFSFcb *)pCurrentObject->Fcb;
1900 // If the FCB is a candidate we try to lock it (but without waiting - which
1901 // means we are deadlock free
1905 pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
1911 AFSLockForExtentsTrim( pFcb);
1916 if( !AFSLockForExtentsTrimNoWait( pFcb))
1919 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1928 // Need to be sure there are no current flushes in the queue
1931 if( pFcb->Specific.File.ExtentCount == 0)
1934 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1935 AFS_TRACE_LEVEL_VERBOSE,
1936 "AFSFindFcbToClean Releasing Fcb extent lock %p thread %08lX\n",
1937 &pFcb->NPFcb->Specific.File.ExtentsResource,
1938 PsGetCurrentThread());
1940 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
1942 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1949 if( pFcb->Specific.File.QueuedFlushCount > 0)
1952 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1953 AFS_TRACE_LEVEL_VERBOSE,
1954 "AFSFindFcbToClean Releasing Fcb extent lock %p thread %08lX\n",
1955 &pFcb->NPFcb->Specific.File.ExtentsResource,
1956 PsGetCurrentThread());
1958 AFSReleaseResource(&pFcb->NPFcb->Specific.File.ExtentsResource);
1962 AFSWaitOnQueuedFlushes( pFcb);
1967 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1975 if( pFcb->OpenHandleCount > 0)
1978 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1979 AFS_TRACE_LEVEL_VERBOSE,
1980 "AFSFindFcbToClean Releasing Fcb extent lock %p thread %08lX\n",
1981 &pFcb->NPFcb->Specific.File.ExtentsResource,
1982 PsGetCurrentThread());
1984 AFSReleaseResource(&pFcb->NPFcb->Specific.File.ExtentsResource);
1986 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1994 // A hit a very palpable hit. Pin it
1997 lCount = AFSObjectInfoIncrement( pFcb->ObjectInformation,
1998 AFS_OBJECT_REFERENCE_EXTENTS);
2000 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2001 AFS_TRACE_LEVEL_VERBOSE,
2002 "AFSFindFcbToClean Increment count on Fcb %p object %pCnt %d\n",
2004 pFcb->ObjectInformation,
2007 bLocatedEntry = TRUE;
2012 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
2017 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2024 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
2027 bReleaseVolumeListLock = TRUE;
2029 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
2032 if( bReleaseVolumeListLock)
2035 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
2042 AFSProcessExtentFailure( PIRP Irp)
2044 AFSExtentFailureCB *pFailureCB = NULL;
2045 NTSTATUS ntStatus = STATUS_SUCCESS;
2046 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2047 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2048 AFSVolumeCB *pVolumeCB = NULL;
2049 ULONGLONG ullIndex = 0;
2050 AFSObjectInfoCB *pObjectInfo = NULL;
2055 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSExtentFailureCB))
2058 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2059 AFS_TRACE_LEVEL_ERROR,
2060 "AFSProcessExtentFailure Input buffer too small\n");
2062 try_return( ntStatus = STATUS_INVALID_PARAMETER);
2065 pFailureCB = (AFSExtentFailureCB *)Irp->AssociatedIrp.SystemBuffer;
2067 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2068 AFS_TRACE_LEVEL_ERROR,
2069 "AFSProcessExtentFailure Service Reports Failure fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2070 pFailureCB->FileId.Cell,
2071 pFailureCB->FileId.Volume,
2072 pFailureCB->FileId.Vnode,
2073 pFailureCB->FileId.Unique,
2074 pFailureCB->FailureStatus);
2076 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
2079 // Locate the volume node
2082 ullIndex = AFSCreateHighIndex( &pFailureCB->FileId);
2084 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
2086 (AFSBTreeEntry **)&pVolumeCB);
2088 if( pVolumeCB != NULL)
2091 lCount = AFSVolumeIncrement( pVolumeCB,
2092 AFS_VOLUME_REFERENCE_EXTENTS);
2094 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2095 AFS_TRACE_LEVEL_VERBOSE,
2096 "AFSProcessExtentFailure Increment count on volume %p Cnt %d\n",
2101 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
2103 if( !NT_SUCCESS( ntStatus) ||
2107 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2108 AFS_TRACE_LEVEL_ERROR,
2109 "AFSProcessExtentFailure Invalid volume index %I64X status %08X\n",
2110 ullIndex, ntStatus);
2112 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2115 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2116 AFS_TRACE_LEVEL_VERBOSE,
2117 "AFSProcessExtentFailure Acquiring VolumeRoot FileIDTree.TreeLock lock %p SHARED %08lX\n",
2118 pVolumeCB->ObjectInfoTree.TreeLock,
2119 PsGetCurrentThread());
2121 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
2125 // Now locate the Object in this volume
2128 ullIndex = AFSCreateLowIndex( &pFailureCB->FileId);
2130 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
2132 (AFSBTreeEntry **)&pObjectInfo);
2134 if( pObjectInfo != NULL &&
2135 pObjectInfo->Fcb != NULL)
2139 // Reference the node so it won't be torn down
2142 lCount = AFSObjectInfoIncrement( pObjectInfo,
2143 AFS_OBJECT_REFERENCE_EXTENTS);
2145 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2146 AFS_TRACE_LEVEL_VERBOSE,
2147 "AFSProcessExtentFailure Increment count on object %p Cnt %d\n",
2152 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2154 if( !NT_SUCCESS( ntStatus) ||
2155 pObjectInfo == NULL ||
2156 pObjectInfo->Fcb == NULL)
2159 if( pObjectInfo == NULL)
2161 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2162 AFS_TRACE_LEVEL_ERROR,
2163 "AFSProcessExtentFailure Invalid file index %I64X\n",
2168 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2169 AFS_TRACE_LEVEL_ERROR,
2170 "AFSProcessExtentFailure Fcb dealocated for %I64X\n",
2174 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2177 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2178 AFS_TRACE_LEVEL_VERBOSE,
2179 "AFSProcessExtentFailure Acquiring Fcb extent lock %p EXCL %08lX\n",
2180 &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2181 PsGetCurrentThread());
2183 AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2186 pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestStatus = pFailureCB->FailureStatus;
2188 RtlCopyMemory( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2189 &pFailureCB->AuthGroup,
2192 KeSetEvent( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
2196 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2197 AFS_TRACE_LEVEL_VERBOSE,
2198 "AFSProcessExtentFailure Releasing Fcb extent lock %p EXCL %08lX\n",
2199 &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2200 PsGetCurrentThread());
2202 AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource);
2204 lCount = AFSObjectInfoDecrement( pObjectInfo,
2205 AFS_OBJECT_REFERENCE_EXTENTS);
2207 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2208 AFS_TRACE_LEVEL_VERBOSE,
2209 "AFSProcessExtentFailure Decrement count on object %p Cnt %d\n",
2218 lCount = AFSVolumeDecrement( pVolumeCB,
2219 AFS_VOLUME_REFERENCE_EXTENTS);
2221 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2222 AFS_TRACE_LEVEL_VERBOSE,
2223 "AFSProcessExtentFailure Decrement count on volume %p Cnt %d\n",
2233 AFSProcessReleaseFileExtents( IN PIRP Irp)
2235 NTSTATUS ntStatus = STATUS_SUCCESS;
2236 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2237 AFSFcb *pFcb = NULL;
2238 AFSVolumeCB *pVolumeCB = NULL;
2239 AFSDeviceExt *pDevExt;
2240 AFSReleaseFileExtentsCB *pExtents;
2241 AFSReleaseFileExtentsResultCB *pResult = NULL;
2242 AFSReleaseFileExtentsResultFileCB *pFile = NULL;
2244 ULONGLONG ullIndex = 0;
2245 AFSObjectInfoCB *pObjectInfo = NULL;
2246 BOOLEAN bLocked = FALSE;
2247 BOOLEAN bDirtyExtents = FALSE;
2254 pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2256 pExtents = (AFSReleaseFileExtentsCB*) Irp->AssociatedIrp.SystemBuffer;
2258 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2259 sizeof( AFSReleaseFileExtentsCB))
2262 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2263 AFS_TRACE_LEVEL_ERROR,
2264 "AFSProcessReleaseFileExtents INPUT Buffer too small\n");
2266 try_return( ntStatus = STATUS_INVALID_PARAMETER );
2269 if ( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength <
2270 sizeof(AFSReleaseFileExtentsResultCB))
2273 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2274 AFS_TRACE_LEVEL_ERROR,
2275 "AFSProcessReleaseFileExtents OUTPUT Buffer too small [1]\n");
2278 // Must have space for one extent in one file
2281 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL);
2284 if (pExtents->ExtentCount == 0)
2287 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2288 AFS_TRACE_LEVEL_ERROR,
2289 "AFSProcessReleaseFileExtents Extent count zero\n");
2291 try_return( ntStatus = STATUS_INVALID_PARAMETER);
2294 if (pExtents->FileId.Cell != 0 ||
2295 pExtents->FileId.Volume != 0 ||
2296 pExtents->FileId.Vnode != 0 ||
2297 pExtents->FileId.Unique != 0)
2300 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2301 AFS_TRACE_LEVEL_VERBOSE,
2302 "AFSProcessReleaseFileExtents Processing FID %08lX:%08lX:%08lX:%08lX\n",
2303 pExtents->FileId.Cell,
2304 pExtents->FileId.Volume,
2305 pExtents->FileId.Vnode,
2306 pExtents->FileId.Unique);
2308 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2309 ( FIELD_OFFSET( AFSReleaseFileExtentsCB, ExtentCount) + sizeof(ULONG)) ||
2310 pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2311 ( FIELD_OFFSET( AFSReleaseFileExtentsCB, ExtentCount) + sizeof(ULONG) +
2312 sizeof (AFSFileExtentCB) * pExtents->ExtentCount))
2315 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2316 AFS_TRACE_LEVEL_ERROR,
2317 "AFSProcessReleaseFileExtents Buffer too small for FID %08lX:%08lx:%08lX:%08lX\n",
2318 pExtents->FileId.Cell,
2319 pExtents->FileId.Volume,
2320 pExtents->FileId.Vnode,
2321 pExtents->FileId.Unique);
2323 try_return( ntStatus = STATUS_INVALID_PARAMETER );
2326 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2327 AFS_TRACE_LEVEL_VERBOSE,
2328 "AFSProcessReleaseFileExtents Acquiring RDR VolumeTreeLock lock %p SHARED %08lX\n",
2329 &pDevExt->Specific.RDR.VolumeTreeLock,
2330 PsGetCurrentThread());
2332 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
2335 // Locate the volume node
2338 ullIndex = AFSCreateHighIndex( &pExtents->FileId);
2340 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
2342 (AFSBTreeEntry **)&pVolumeCB);
2344 if( pVolumeCB != NULL)
2347 lCount = AFSVolumeIncrement( pVolumeCB,
2348 AFS_VOLUME_REFERENCE_EXTENTS);
2350 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2351 AFS_TRACE_LEVEL_VERBOSE,
2352 "AFSProcessReleaseFileExtents Increment count on volume %p Cnt %d\n",
2357 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
2359 if( !NT_SUCCESS( ntStatus) ||
2363 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2364 AFS_TRACE_LEVEL_ERROR,
2365 "AFSProcessReleaseFileExtents Invalid volume index %I64X status %08X\n",
2366 ullIndex, ntStatus);
2368 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2371 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2372 AFS_TRACE_LEVEL_VERBOSE,
2373 "AFSProcessReleaseFileExtents Acquiring VolumeRoot FileIDTree.TreeLock lock %p SHARED %08lX\n",
2374 pVolumeCB->ObjectInfoTree.TreeLock,
2375 PsGetCurrentThread());
2377 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
2381 // Now locate the Object in this volume
2384 ullIndex = AFSCreateLowIndex( &pExtents->FileId);
2386 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
2388 (AFSBTreeEntry **)&pObjectInfo);
2390 if( pObjectInfo != NULL)
2394 // Reference the node so it won't be torn down
2397 lCount = AFSObjectInfoIncrement( pObjectInfo,
2398 AFS_OBJECT_REFERENCE_EXTENTS);
2400 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2401 AFS_TRACE_LEVEL_VERBOSE,
2402 "AFSProcessReleaseFileExtents Increment count on object %p Cnt %d\n",
2407 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2409 if( !NT_SUCCESS( ntStatus) ||
2410 pObjectInfo == NULL)
2413 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2414 AFS_TRACE_LEVEL_ERROR,
2415 "AFSProcessReleaseFileExtents Invalid file index %I64X\n",
2418 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2421 pFcb = pObjectInfo->Fcb;
2426 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2427 AFS_TRACE_LEVEL_ERROR,
2428 "AFSProcessReleaseFileExtents Fcb not initialied (NO EXTENTS) for FID %08lX:%08lx:%08lX:%08lX\n",
2429 pExtents->FileId.Cell,
2430 pExtents->FileId.Volume,
2431 pExtents->FileId.Vnode,
2432 pExtents->FileId.Unique);
2434 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2437 AFSLockForExtentsTrim( pFcb );
2445 // Locate an Fcb to trim down
2448 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2449 AFS_TRACE_LEVEL_VERBOSE,
2450 "AFSProcessReleaseFileExtents Searching for a Fcb to Trim Down\n");
2452 pFcb = AFSFindFcbToClean( 0, NULL, FALSE);
2457 pFcb = AFSFindFcbToClean( 0, NULL, TRUE);
2463 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2464 AFS_TRACE_LEVEL_ERROR,
2465 "AFSProcessReleaseFileExtents Failed to locate Fcb for release ...\n");
2467 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2470 pObjectInfo = pFcb->ObjectInformation;
2476 // Allocate a scratch buffer to move in the extent information
2479 ulSz = (pExtents->ExtentCount-1) * sizeof(AFSFileExtentCB);
2480 ulSz += sizeof(AFSReleaseFileExtentsResultCB);
2482 if (ulSz > pIrpSp->Parameters.DeviceIoControl.OutputBufferLength)
2484 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2485 AFS_TRACE_LEVEL_ERROR,
2486 "AFSProcessReleaseFileExtents OUTPUT Buffer too small [2]\n");
2488 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL );
2491 pResult = (AFSReleaseFileExtentsResultCB*) AFSExAllocatePoolWithTag( PagedPool,
2493 AFS_EXTENTS_RESULT_TAG);
2494 if (NULL == pResult)
2497 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2498 AFS_TRACE_LEVEL_ERROR,
2499 "AFSProcessReleaseFileExtents Failed to allocate result block\n");
2501 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2505 // Set up the header (for an array of one)
2507 pResult->FileCount = 1;
2508 pResult->Flags = AFS_EXTENT_FLAG_RELEASE;
2509 ulSz -= FIELD_OFFSET(AFSReleaseFileExtentsResultCB, Files);
2512 // Setup the first (and only) file
2514 pFile = pResult->Files;
2515 pFile->FileId = pObjectInfo->FileId;
2516 pFile->Flags = AFS_EXTENT_FLAG_RELEASE;
2519 // Stash away the auth group
2522 RtlZeroMemory( &stAuthGroup,
2525 ntStatus = AFSRetrieveValidAuthGroup( pFcb,
2530 if( !NT_SUCCESS( ntStatus))
2532 try_return( ntStatus);
2535 RtlCopyMemory( &pFile->AuthGroup,
2540 // Update the metadata for this call
2543 pFile->AllocationSize = pFcb->ObjectInformation->EndOfFile;
2544 pFile->CreateTime = pFcb->ObjectInformation->CreationTime;
2545 pFile->ChangeTime = pFcb->ObjectInformation->ChangeTime;
2546 pFile->LastAccessTime = pFcb->ObjectInformation->LastAccessTime;
2547 pFile->LastWriteTime = pFcb->ObjectInformation->LastWriteTime;
2549 ulSz -= FIELD_OFFSET(AFSReleaseFileExtentsResultFileCB, FileExtents);
2551 ntStatus = AFSReleaseSpecifiedExtents( pExtents,
2555 &pFile->ExtentCount,
2558 if (!NT_SUCCESS(ntStatus))
2561 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2562 AFS_TRACE_LEVEL_ERROR,
2563 "AFSProcessReleaseFileExtents Failed to release extents Status %08lX\n",
2566 try_return( ntStatus );
2569 if( pExtents->ExtentCount == 0)
2572 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2573 AFS_TRACE_LEVEL_WARNING,
2574 "AFSProcessReleaseFileExtents Failed to release ANY extents\n");
2577 ulSz = sizeof(AFSReleaseFileExtentsResultCB);
2579 if( pExtents->ExtentCount > 0)
2581 ulSz += ((pExtents->ExtentCount-1) * sizeof(AFSFileExtentCB));
2584 RtlCopyMemory( Irp->AssociatedIrp.SystemBuffer,
2593 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2594 AFS_TRACE_LEVEL_VERBOSE,
2595 "AFSProcessReleaseFileExtents Releasing Fcb extent lock %p thread %08lX\n",
2596 &pFcb->NPFcb->Specific.File.ExtentsResource,
2597 PsGetCurrentThread());
2599 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
2602 if( NULL != pResult &&
2603 Irp->AssociatedIrp.SystemBuffer != pResult)
2606 AFSExFreePoolWithTag(pResult, AFS_EXTENTS_RESULT_TAG);
2609 if (NT_SUCCESS(ntStatus))
2611 Irp->IoStatus.Information = ulSz;
2615 Irp->IoStatus.Information = 0;
2618 Irp->IoStatus.Status = ntStatus;
2620 if( pObjectInfo != NULL)
2623 lCount = AFSObjectInfoDecrement( pObjectInfo,
2624 AFS_OBJECT_REFERENCE_EXTENTS);
2626 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2627 AFS_TRACE_LEVEL_VERBOSE,
2628 "AFSProcessReleaseFileExtents Decrement count on object %p Cnt %d\n",
2636 lCount = AFSVolumeDecrement( pVolumeCB,
2637 AFS_VOLUME_REFERENCE_EXTENTS);
2639 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2640 AFS_TRACE_LEVEL_VERBOSE,
2641 "AFSProcessReleaseFileExtents Decrement count on volume %p Cnt %d\n",
2652 AFSWaitForExtentMapping( AFSFcb *Fcb,
2655 NTSTATUS ntStatus = STATUS_SUCCESS;
2656 LARGE_INTEGER liTimeOut;
2657 ULONGLONG ullProcessId = (ULONGLONG)PsGetCurrentProcessId();
2662 ASSERT( !ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
2664 if (!NT_SUCCESS( Fcb->NPFcb->Specific.File.ExtentsRequestStatus))
2668 // If this isn't the same authgroup which caused the failure
2669 // then try to request them again
2672 if( RtlCompareMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2674 sizeof( GUID)) == sizeof( GUID))
2677 ntStatus = Fcb->NPFcb->Specific.File.ExtentsRequestStatus;
2679 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
2681 RtlZeroMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2684 try_return( ntStatus);
2688 liTimeOut.QuadPart = -(1 * AFS_ONE_SECOND);
2690 ntStatus = KeWaitForSingleObject( &Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
2696 if (!NT_SUCCESS( Fcb->NPFcb->Specific.File.ExtentsRequestStatus))
2700 // If this isn't the same authgroup which caused the failure
2701 // or the System Process,
2702 // then try to request the extents again
2705 if( RtlCompareMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2707 sizeof( GUID)) == sizeof( GUID) ||
2708 ullProcessId == (ULONGLONG)AFSSysProcess)
2711 ntStatus = Fcb->NPFcb->Specific.File.ExtentsRequestStatus;
2713 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
2715 RtlZeroMemory( &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2718 try_return( ntStatus);
2722 if( ntStatus == STATUS_TIMEOUT)
2725 ntStatus = STATUS_SUCCESS;
2737 AFSFlushExtents( IN AFSFcb *Fcb,
2740 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
2741 AFSExtent *pExtent, *pNextExtent;
2742 AFSReleaseExtentsCB *pRelease = NULL;
2744 ULONG initialDirtyCount = 0;
2745 BOOLEAN bExtentsLocked = FALSE;
2748 NTSTATUS ntStatus = STATUS_SUCCESS;
2749 LARGE_INTEGER liLastFlush;
2750 GUID *pAuthGroup = AuthGroup;
2754 ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
2757 // Save, then reset the flush time
2760 liLastFlush = Fcb->Specific.File.LastServerFlush;
2762 KeQueryTickCount( &Fcb->Specific.File.LastServerFlush);
2767 lCount = InterlockedIncrement( &Fcb->Specific.File.QueuedFlushCount);
2769 if( pAuthGroup == NULL ||
2770 RtlCompareMemory( pAuthGroup,
2771 &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
2772 sizeof( GUID)) == sizeof( GUID))
2775 RtlZeroMemory( &stAuthGroup,
2778 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
2783 if( !NT_SUCCESS( ntStatus))
2785 try_return( ntStatus);
2788 pAuthGroup = &stAuthGroup;
2792 // Lock extents while we count and set up the array to send to
2796 AFSLockForExtentsTrim( Fcb);
2798 bExtentsLocked = TRUE;
2801 // Clear our queued flush event
2804 KeClearEvent( &Fcb->NPFcb->Specific.File.QueuedFlushEvent);
2807 // Look for a start in the list to flush entries
2812 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
2814 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
2816 AFS_EXTENT_RELEASE_TAG);
2817 if( NULL == pRelease)
2820 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2823 initialDirtyCount = Fcb->Specific.File.ExtentsDirtyCount;
2825 while( Fcb->Specific.File.ExtentsDirtyCount > 0)
2828 pRelease->Flags = AFS_EXTENT_FLAG_DIRTY;
2830 if( BooleanFlagOn( Fcb->Flags, AFS_FCB_FILE_CLOSED))
2833 pRelease->Flags |= AFS_EXTENT_FLAG_FLUSH;
2837 // Update the metadata for this call
2840 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
2841 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
2842 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
2843 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
2844 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
2848 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
2851 pExtent = (AFSExtent *)pNPFcb->Specific.File.DirtyListHead;
2853 while( count < AFS_MAXIMUM_EXTENT_RELEASE_COUNT)
2856 if ( pExtent == NULL)
2862 pNextExtent = (AFSExtent *)pExtent->DirtyList.fLink;
2864 if ( pExtent->ActiveCount > 0)
2866 pExtent = pNextExtent;
2870 AFSRemoveEntryDirtyList( Fcb, pExtent);
2872 pExtent->DirtyList.fLink = NULL;
2873 pExtent->DirtyList.bLink = NULL;
2875 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
2878 // Clear the flag in advance of the write. If we do
2879 // things this was we know that the clear is
2880 // pessimistic (any write which happens from now on
2881 // will set the flag dirty again).
2884 pExtent->Flags &= ~AFS_EXTENT_DIRTY;
2886 pRelease->FileExtents[count].Flags = AFS_EXTENT_FLAG_DIRTY;
2888 pRelease->FileExtents[count].Length = pExtent->Size;
2889 pRelease->FileExtents[count].DirtyLength = pExtent->Size;
2890 pRelease->FileExtents[count].DirtyOffset = 0;
2891 pRelease->FileExtents[count].CacheOffset = pExtent->CacheOffset;
2892 pRelease->FileExtents[count].FileOffset = pExtent->FileOffset;
2895 RtlCopyMemory( pRelease->FileExtents[count].MD5,
2897 sizeof(pExtent->MD5));
2899 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_MD5_SET;
2902 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2903 AFS_TRACE_LEVEL_VERBOSE,
2904 "AFSFlushExtents Releasing DIRTY extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
2906 Fcb->ObjectInformation->FileId.Cell,
2907 Fcb->ObjectInformation->FileId.Volume,
2908 Fcb->ObjectInformation->FileId.Vnode,
2909 Fcb->ObjectInformation->FileId.Unique,
2910 pExtent->FileOffset.QuadPart,
2913 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_RELEASE;
2920 pExtent = pNextExtent;
2923 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
2926 // If we are done then get out
2932 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2933 AFS_TRACE_LEVEL_VERBOSE,
2934 "AFSFlushExtents No more dirty extents found\n");
2940 // Fire off the request synchronously
2943 sz = sizeof( AFSReleaseExtentsCB ) + (count * sizeof ( AFSFileExtentCB ));
2945 pRelease->ExtentCount = count;
2947 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2948 AFS_TRACE_LEVEL_VERBOSE,
2949 "AFSFlushExtents Releasing(1) Fcb extents lock %p SHARED %08lX\n",
2950 &pNPFcb->Specific.File.ExtentsResource,
2951 PsGetCurrentThread());
2953 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource);
2954 bExtentsLocked = FALSE;
2956 KeSetEvent( &pNPFcb->Specific.File.FlushEvent,
2960 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
2961 AFS_REQUEST_FLAG_SYNCHRONOUS,
2964 &Fcb->ObjectInformation->FileId,
2965 Fcb->ObjectInformation->VolumeCB->VolumeInformation.Cell,
2966 Fcb->ObjectInformation->VolumeCB->VolumeInformation.CellLength,
2972 if( !NT_SUCCESS(ntStatus))
2976 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
2977 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
2980 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2981 AFS_TRACE_LEVEL_ERROR,
2982 "AFSFlushExtents AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2983 Fcb->ObjectInformation->FileId.Cell,
2984 Fcb->ObjectInformation->FileId.Volume,
2985 Fcb->ObjectInformation->FileId.Vnode,
2986 Fcb->ObjectInformation->FileId.Unique,
2991 AFSLockForExtentsTrim( Fcb);
2993 bExtentsLocked = TRUE;
2998 lCount = InterlockedDecrement( &Fcb->Specific.File.QueuedFlushCount);
3000 ASSERT( lCount >= 0);
3005 KeSetEvent( &pNPFcb->Specific.File.QueuedFlushEvent,
3010 KeSetEvent( &pNPFcb->Specific.File.FlushEvent,
3017 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3018 AFS_TRACE_LEVEL_VERBOSE,
3019 "AFSFlushExtents Releasing(2) Fcb extents lock %p SHARED %08lX\n",
3020 &pNPFcb->Specific.File.ExtentsResource,
3021 PsGetCurrentThread());
3023 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
3028 AFSExFreePoolWithTag( pRelease, AFS_EXTENT_RELEASE_TAG);
3036 AFSReleaseExtentsWithFlush( IN AFSFcb *Fcb,
3038 IN BOOLEAN bReleaseAll)
3040 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3043 AFSReleaseExtentsCB *pRelease = NULL;
3045 BOOLEAN bExtentsLocked = FALSE;
3048 NTSTATUS ntStatus = STATUS_SUCCESS;
3049 LARGE_INTEGER liLastFlush;
3050 ULONG ulRemainingExtentLength = 0;
3051 GUID *pAuthGroup = AuthGroup;
3055 ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
3058 // Save, then reset the flush time
3061 liLastFlush = Fcb->Specific.File.LastServerFlush;
3063 KeQueryTickCount( &Fcb->Specific.File.LastServerFlush);
3068 if( pAuthGroup == NULL ||
3069 RtlCompareMemory( pAuthGroup,
3070 &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
3071 sizeof( GUID)) == sizeof( GUID))
3074 RtlZeroMemory( &stAuthGroup,
3077 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
3082 if( !NT_SUCCESS( ntStatus))
3084 try_return( ntStatus);
3087 pAuthGroup = &stAuthGroup;
3091 // Look for a start in the list to flush entries
3096 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
3098 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
3100 AFS_EXTENT_RELEASE_TAG);
3101 if( NULL == pRelease)
3104 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
3107 if( Fcb->OpenHandleCount > 0 &&
3112 // Don't release everything ...
3115 ulRemainingExtentLength = 1024;
3118 while( Fcb->Specific.File.ExtentLength > (LONG)ulRemainingExtentLength)
3121 AFSLockForExtentsTrim( Fcb);
3123 bExtentsLocked = TRUE;
3125 pRelease->Flags = AFS_EXTENT_FLAG_RELEASE;
3128 // Update the metadata for this call
3131 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
3132 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
3133 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
3134 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
3135 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
3139 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3141 while( count < AFS_MAXIMUM_EXTENT_RELEASE_COUNT &&
3142 le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
3145 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3149 if( pExtent->ActiveCount > 0)
3155 pRelease->FileExtents[count].Flags = AFS_EXTENT_FLAG_RELEASE;
3157 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3158 AFS_TRACE_LEVEL_VERBOSE,
3159 "AFSReleaseExtentsWithFlush Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3161 Fcb->ObjectInformation->FileId.Cell,
3162 Fcb->ObjectInformation->FileId.Volume,
3163 Fcb->ObjectInformation->FileId.Vnode,
3164 Fcb->ObjectInformation->FileId.Unique,
3165 pExtent->FileOffset.QuadPart,
3168 pRelease->FileExtents[count].Length = pExtent->Size;
3169 pRelease->FileExtents[count].DirtyLength = pExtent->Size;
3170 pRelease->FileExtents[count].DirtyOffset = 0;
3171 pRelease->FileExtents[count].CacheOffset = pExtent->CacheOffset;
3172 pRelease->FileExtents[count].FileOffset = pExtent->FileOffset;
3175 RtlCopyMemory( pRelease->FileExtents[count].MD5,
3177 sizeof(pExtent->MD5));
3179 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_MD5_SET;
3182 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3185 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3188 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3191 AFSRemoveEntryDirtyList( Fcb,
3194 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_DIRTY;
3196 lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
3199 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3209 // If we are done then get out
3215 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3216 AFS_TRACE_LEVEL_VERBOSE,
3217 "AFSReleaseExtentsWithFlush No more dirty extents found\n");
3223 // Fire off the request synchronously
3226 sz = sizeof( AFSReleaseExtentsCB ) + (count * sizeof ( AFSFileExtentCB ));
3228 pRelease->ExtentCount = count;
3231 // Drop the extents lock for the duration of the call to
3232 // the network. We have pinned the extents so, even
3233 // though we might get extents added during this period,
3234 // but none will be removed. Hence we can carry on from
3238 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3239 AFS_TRACE_LEVEL_VERBOSE,
3240 "AFSReleaseExtentsWithFlush Releasing Fcb extents lock %p thread %08lX\n",
3241 &pNPFcb->Specific.File.ExtentsResource,
3242 PsGetCurrentThread());
3244 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource);
3245 bExtentsLocked = FALSE;
3247 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
3248 AFS_REQUEST_FLAG_SYNCHRONOUS,
3251 &Fcb->ObjectInformation->FileId,
3252 Fcb->ObjectInformation->VolumeCB->VolumeInformation.Cell,
3253 Fcb->ObjectInformation->VolumeCB->VolumeInformation.CellLength,
3259 if( !NT_SUCCESS(ntStatus))
3263 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
3264 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
3267 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3268 AFS_TRACE_LEVEL_ERROR,
3269 "AFSReleaseExtentsWithFlush AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3270 Fcb->ObjectInformation->FileId.Cell,
3271 Fcb->ObjectInformation->FileId.Volume,
3272 Fcb->ObjectInformation->FileId.Vnode,
3273 Fcb->ObjectInformation->FileId.Unique,
3283 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3284 AFS_TRACE_LEVEL_VERBOSE,
3285 "AFSReleaseExtentsWithFlush Releasing Fcb extents lock %p thread %08lX\n",
3286 &pNPFcb->Specific.File.ExtentsResource,
3287 PsGetCurrentThread());
3289 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
3294 AFSExFreePoolWithTag( pRelease, AFS_EXTENT_RELEASE_TAG);
3302 AFSReleaseCleanExtents( IN AFSFcb *Fcb,
3305 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3308 AFSReleaseExtentsCB *pRelease = NULL;
3310 BOOLEAN bExtentsLocked = FALSE;
3313 NTSTATUS ntStatus = STATUS_SUCCESS;
3314 LARGE_INTEGER liLastFlush;
3315 ULONG ulRemainingExtentLength = 0;
3316 GUID *pAuthGroup = AuthGroup;
3319 ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
3322 // Save, then reset the flush time
3325 liLastFlush = Fcb->Specific.File.LastServerFlush;
3327 KeQueryTickCount( &Fcb->Specific.File.LastServerFlush);
3332 if( pAuthGroup == NULL ||
3333 RtlCompareMemory( pAuthGroup,
3334 &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
3335 sizeof( GUID)) == sizeof( GUID))
3338 RtlZeroMemory( &stAuthGroup,
3341 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
3346 if( !NT_SUCCESS( ntStatus))
3348 try_return( ntStatus);
3351 pAuthGroup = &stAuthGroup;
3355 // Look for a start in the list to flush entries
3360 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
3362 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
3364 AFS_EXTENT_RELEASE_TAG);
3365 if( NULL == pRelease)
3368 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
3371 while( Fcb->Specific.File.ExtentLength > (LONG)ulRemainingExtentLength)
3374 AFSLockForExtentsTrim( Fcb);
3376 bExtentsLocked = TRUE;
3378 pRelease->Flags = AFS_EXTENT_FLAG_RELEASE;
3381 // Update the metadata for this call
3384 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
3385 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
3386 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
3387 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
3388 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
3392 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3394 while( count < AFS_MAXIMUM_EXTENT_RELEASE_COUNT &&
3395 le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
3398 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3402 if( pExtent->ActiveCount > 0 ||
3403 BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3408 pRelease->FileExtents[count].Flags = AFS_EXTENT_FLAG_RELEASE;
3410 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3411 AFS_TRACE_LEVEL_VERBOSE,
3412 "AFSReleaseCleanExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3414 Fcb->ObjectInformation->FileId.Cell,
3415 Fcb->ObjectInformation->FileId.Volume,
3416 Fcb->ObjectInformation->FileId.Vnode,
3417 Fcb->ObjectInformation->FileId.Unique,
3418 pExtent->FileOffset.QuadPart,
3421 pRelease->FileExtents[count].Length = pExtent->Size;
3422 pRelease->FileExtents[count].DirtyLength = pExtent->Size;
3423 pRelease->FileExtents[count].DirtyOffset = 0;
3424 pRelease->FileExtents[count].CacheOffset = pExtent->CacheOffset;
3425 pRelease->FileExtents[count].FileOffset = pExtent->FileOffset;
3428 RtlCopyMemory( pRelease->FileExtents[count].MD5,
3430 sizeof(pExtent->MD5));
3432 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_MD5_SET;
3442 // If we are done then get out
3448 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3449 AFS_TRACE_LEVEL_VERBOSE,
3450 "AFSReleaseCleanExtents No more dirty extents found\n");
3456 // Fire off the request synchronously
3459 sz = sizeof( AFSReleaseExtentsCB ) + (count * sizeof ( AFSFileExtentCB ));
3461 pRelease->ExtentCount = count;
3464 // Drop the extents lock for the duration of the call to
3465 // the network. We have pinned the extents so, even
3466 // though we might get extents added during this period,
3467 // but none will be removed. Hence we can carry on from
3471 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3472 AFS_TRACE_LEVEL_VERBOSE,
3473 "AFSReleaseCleanExtents Releasing Fcb extents lock %p thread %08lX\n",
3474 &pNPFcb->Specific.File.ExtentsResource,
3475 PsGetCurrentThread());
3477 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource);
3478 bExtentsLocked = FALSE;
3480 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
3481 AFS_REQUEST_FLAG_SYNCHRONOUS,
3484 &Fcb->ObjectInformation->FileId,
3485 Fcb->ObjectInformation->VolumeCB->VolumeInformation.Cell,
3486 Fcb->ObjectInformation->VolumeCB->VolumeInformation.CellLength,
3492 if( !NT_SUCCESS(ntStatus))
3496 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
3497 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
3500 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3501 AFS_TRACE_LEVEL_ERROR,
3502 "AFSReleaseCleanExtents AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3503 Fcb->ObjectInformation->FileId.Cell,
3504 Fcb->ObjectInformation->FileId.Volume,
3505 Fcb->ObjectInformation->FileId.Vnode,
3506 Fcb->ObjectInformation->FileId.Unique,
3516 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3517 AFS_TRACE_LEVEL_VERBOSE,
3518 "AFSReleaseCleanExtents Releasing Fcb extents lock %p thread %08lX\n",
3519 &pNPFcb->Specific.File.ExtentsResource,
3520 PsGetCurrentThread());
3522 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
3527 AFSExFreePoolWithTag( pRelease, AFS_EXTENT_RELEASE_TAG);
3535 AFSMarkDirty( IN AFSFcb *Fcb,
3536 IN AFSExtent *StartExtent,
3537 IN ULONG ExtentsCount,
3538 IN LARGE_INTEGER *StartingByte,
3539 IN BOOLEAN DerefExtents)
3542 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3543 AFSExtent *pExtent = StartExtent;
3544 AFSExtent *pNextExtent, *pCurrentExtent = NULL;
3546 BOOLEAN bInsertTail = FALSE, bInsertHead = FALSE;
3549 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3550 AFS_TRACE_LEVEL_VERBOSE,
3551 "AFSMarkDirty Acquiring Fcb extents lock %p SHARED %08lX\n",
3552 &Fcb->NPFcb->Specific.File.ExtentsResource,
3553 PsGetCurrentThread());
3555 ASSERT( ExIsResourceAcquiredLite( &pNPFcb->Specific.File.ExtentsResource));
3557 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3563 // Find the insertion point
3566 if( pNPFcb->Specific.File.DirtyListHead == NULL)
3571 else if( StartingByte->QuadPart == 0)
3579 pCurrentExtent = pNPFcb->Specific.File.DirtyListHead;
3581 while( pCurrentExtent != NULL)
3584 if( pCurrentExtent->FileOffset.QuadPart + pCurrentExtent->Size >= StartingByte->QuadPart ||
3585 pCurrentExtent->DirtyList.fLink == NULL)
3591 pCurrentExtent = (AFSExtent *)pCurrentExtent->DirtyList.fLink;
3595 while( ulCount < ExtentsCount)
3598 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
3600 if( !BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3603 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3604 AFS_TRACE_LEVEL_VERBOSE,
3605 "AFSMarkDirty Marking extent offset %I64X Length %08lX DIRTY\n",
3606 pExtent->FileOffset.QuadPart,
3609 pExtent->DirtyList.fLink = NULL;
3610 pExtent->DirtyList.bLink = NULL;
3615 pExtent->DirtyList.fLink = (void *)pNPFcb->Specific.File.DirtyListHead;
3617 pExtent->DirtyList.bLink = NULL;
3619 pNPFcb->Specific.File.DirtyListHead->DirtyList.bLink = (void *)pExtent;
3621 pNPFcb->Specific.File.DirtyListHead = pExtent;
3623 pCurrentExtent = pExtent;
3625 bInsertHead = FALSE;
3627 else if( bInsertTail)
3630 if( pNPFcb->Specific.File.DirtyListHead == NULL)
3633 pNPFcb->Specific.File.DirtyListHead = pExtent;
3638 pNPFcb->Specific.File.DirtyListTail->DirtyList.fLink = (void *)pExtent;
3640 pExtent->DirtyList.bLink = (void *)pNPFcb->Specific.File.DirtyListTail;
3643 pNPFcb->Specific.File.DirtyListTail = pExtent;
3648 pExtent->DirtyList.fLink = pCurrentExtent->DirtyList.fLink;
3650 pExtent->DirtyList.bLink = (void *)pCurrentExtent;
3652 if( pExtent->DirtyList.fLink == NULL)
3655 pNPFcb->Specific.File.DirtyListTail = pExtent;
3660 ((AFSExtent *)pExtent->DirtyList.fLink)->DirtyList.bLink = (void *)pExtent;
3663 pCurrentExtent->DirtyList.fLink = (void *)pExtent;
3665 pCurrentExtent = pExtent;
3668 pExtent->Flags |= AFS_EXTENT_DIRTY;
3671 // Up the dirty count
3674 lCount = InterlockedIncrement( &Fcb->Specific.File.ExtentsDirtyCount);
3679 pCurrentExtent = pExtent;
3682 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_ACTIVE_COUNTING,
3683 AFS_TRACE_LEVEL_VERBOSE,
3684 "AFSMarkDirty Decrement count on extent %08lX Cnt %d\n",
3686 pExtent->ActiveCount);
3690 ASSERT( pExtent->ActiveCount > 0);
3691 lCount = InterlockedDecrement( &pExtent->ActiveCount);
3694 pExtent = pNextExtent;
3699 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
3704 "EXCEPTION - AFSMarkDirty\n");
3706 AFSDumpTraceFilesFnc();
3709 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3711 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3712 AFS_TRACE_LEVEL_VERBOSE,
3713 "AFSMarkDirty Releasing Fcb extents lock %p SHARED %08lX\n",
3714 &Fcb->NPFcb->Specific.File.ExtentsResource,
3715 PsGetCurrentThread());
3725 ExtentFor(PLIST_ENTRY le, ULONG SkipList)
3728 return CONTAINING_RECORD( le, AFSExtent, Lists[SkipList] );
3732 NextExtent(AFSExtent *Extent, ULONG SkipList)
3735 return ExtentFor(Extent->Lists[SkipList].Flink, SkipList);
3738 #if AFS_VALIDATE_EXTENTS
3739 static AFSExtent *DirtyExtentFor(PLIST_ENTRY le)
3742 return CONTAINING_RECORD( le, AFSExtent, DirtyList );
3745 static VOID VerifyExtentsLists(AFSFcb *Fcb)
3749 // Check the ordering of the extents lists
3751 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
3753 ASSERT(Fcb->Specific.File.ExtentsLists[0].Flink != &Fcb->Specific.File.ExtentsLists[1]);
3755 for (ULONG listNo = 0; listNo < AFS_NUM_EXTENT_LISTS; listNo ++)
3757 LARGE_INTEGER lastOffset;
3759 lastOffset.QuadPart = 0;
3761 for (PLIST_ENTRY pLe = Fcb->Specific.File.ExtentsLists[listNo].Flink;
3762 pLe != &Fcb->Specific.File.ExtentsLists[listNo];
3767 pExtent = ExtentFor(pLe, listNo);
3770 ASSERT(pLe != &Fcb->Specific.File.ExtentsLists[1] &&
3771 pLe->Flink !=&Fcb->Specific.File.ExtentsLists[1] &&
3772 pLe->Blink !=&Fcb->Specific.File.ExtentsLists[1]);
3775 ASSERT(pLe->Flink->Blink == pLe);
3776 ASSERT(pLe->Blink->Flink == pLe);
3779 // Should follow on from previous
3781 ASSERT(pExtent->FileOffset.QuadPart >= lastOffset.QuadPart);
3782 lastOffset.QuadPart = pExtent->FileOffset.QuadPart + pExtent->Size;
3785 // Should match alignment criteria
3787 ASSERT( 0 == (pExtent->FileOffset.LowPart & ExtentsMasks[listNo]) );
3790 // "lower" lists should be populated
3792 for (LONG subListNo = listNo-1; subListNo > 0; subListNo --)
3794 ASSERT( !IsListEmpty(&pExtent->Lists[subListNo]));
3803 AFSTrimExtents( IN AFSFcb *Fcb,
3804 IN PLARGE_INTEGER FileSize)
3807 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3810 BOOLEAN locked = FALSE;
3811 NTSTATUS ntStatus = STATUS_SUCCESS;
3812 LARGE_INTEGER liAlignedOffset = {0,0};
3813 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
3819 // Get an aligned offset
3822 if( FileSize != NULL)
3825 liAlignedOffset = *FileSize;
3828 if( liAlignedOffset.QuadPart > 0 &&
3829 liAlignedOffset.QuadPart % pDevExt->Specific.RDR.CacheBlockSize != 0)
3833 // Align UP to the next cache block size
3836 liAlignedOffset.QuadPart = (ULONGLONG)( (ULONGLONG)((liAlignedOffset.QuadPart / pDevExt->Specific.RDR.CacheBlockSize) + 1) * (ULONGLONG)pDevExt->Specific.RDR.CacheBlockSize);
3840 // Ensure that no one is working with the extents and grab the
3844 AFSLockForExtentsTrim( Fcb);
3848 if( 0 == Fcb->Specific.File.ExtentCount)
3852 // Update the request extent status
3855 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
3857 try_return( ntStatus = STATUS_SUCCESS);
3861 // We are truncating from a specific length in the file. If the offset
3862 // is non-zero then go find the first extent to remove
3865 if( 0 == FileSize->QuadPart)
3868 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3873 pExtent = AFSExtentForOffset( Fcb,
3877 if( NULL == pExtent)
3880 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3884 le = &pExtent->Lists[AFS_EXTENTS_LIST];
3888 while( le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
3891 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3894 // Only trim down extents beyond the aligned offset
3899 if( pExtent->FileOffset.QuadPart >= liAlignedOffset.QuadPart)
3902 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3905 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3908 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3912 AFSRemoveEntryDirtyList( Fcb,
3915 dirtyCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
3917 ASSERT(dirtyCount >= 0);
3920 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3923 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3924 AFS_TRACE_LEVEL_VERBOSE,
3925 "AFSTrimExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3927 Fcb->ObjectInformation->FileId.Cell,
3928 Fcb->ObjectInformation->FileId.Volume,
3929 Fcb->ObjectInformation->FileId.Vnode,
3930 Fcb->ObjectInformation->FileId.Unique,
3931 pExtent->FileOffset.QuadPart,
3934 ASSERT( pExtent->ActiveCount == 0);
3942 // Update the request extent status
3945 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
3952 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3953 AFS_TRACE_LEVEL_VERBOSE,
3954 "AFSTrimExtents Releasing Fcb extents lock %p thread %08lX\n",
3955 &Fcb->NPFcb->Specific.File.ExtentsResource,
3956 PsGetCurrentThread());
3958 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
3966 AFSTrimSpecifiedExtents( IN AFSFcb *Fcb,
3968 IN AFSFileExtentCB *Result)
3971 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3974 AFSFileExtentCB *pFileExtents = Result;
3979 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3981 while( le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST] &&
3985 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3988 // Only trim down extents beyond the aligned offset
3993 if( pExtent->FileOffset.QuadPart == pFileExtents->FileOffset.QuadPart)
3996 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3999 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
4002 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
4007 AFSRemoveEntryDirtyList( Fcb,
4010 dirtyCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
4012 ASSERT( dirtyCount >= 0);
4016 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
4020 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
4021 AFS_TRACE_LEVEL_VERBOSE,
4022 "AFSTrimSpecifiedExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
4024 Fcb->ObjectInformation->FileId.Cell,
4025 Fcb->ObjectInformation->FileId.Volume,
4026 Fcb->ObjectInformation->FileId.Vnode,
4027 Fcb->ObjectInformation->FileId.Unique,
4028 pExtent->FileOffset.QuadPart,
4031 ASSERT( pExtent->ActiveCount == 0);
4037 // Next extent we are looking for
4047 // Update the request extent status
4050 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
4057 AFSReferenceActiveExtents( IN AFSExtent *StartExtent,
4058 IN ULONG ExtentsCount)
4061 AFSExtent *pExtent = StartExtent;
4062 AFSExtent *pNextExtent;
4066 while( ulCount < ExtentsCount)
4069 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
4071 lCount = InterlockedIncrement( &pExtent->ActiveCount);
4073 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_ACTIVE_COUNTING,
4074 AFS_TRACE_LEVEL_VERBOSE,
4075 "AFSReferenceActiveExtents Increment count on extent %08lX Cnt %d\n",
4079 pExtent = pNextExtent;
4088 AFSDereferenceActiveExtents( IN AFSExtent *StartExtent,
4089 IN ULONG ExtentsCount)
4092 AFSExtent *pExtent = StartExtent;
4093 AFSExtent *pNextExtent;
4097 while( ulCount < ExtentsCount)
4100 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
4102 ASSERT( pExtent->ActiveCount > 0);
4104 lCount = InterlockedDecrement( &pExtent->ActiveCount);
4106 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_ACTIVE_COUNTING,
4107 AFS_TRACE_LEVEL_VERBOSE,
4108 "AFSDereferenceActiveExtents Decrement count on extent %08lX Cnt %d\n",
4112 pExtent = pNextExtent;
4121 AFSRemoveEntryDirtyList( IN AFSFcb *Fcb,
4122 IN AFSExtent *Extent)
4125 if( Extent->DirtyList.fLink == NULL)
4128 Fcb->NPFcb->Specific.File.DirtyListTail = (AFSExtent *)Extent->DirtyList.bLink;
4130 if( Fcb->NPFcb->Specific.File.DirtyListTail != NULL)
4133 Fcb->NPFcb->Specific.File.DirtyListTail->DirtyList.fLink = NULL;
4139 ((AFSExtent *)Extent->DirtyList.fLink)->DirtyList.bLink = Extent->DirtyList.bLink;
4142 if( Extent->DirtyList.bLink == NULL)
4145 Fcb->NPFcb->Specific.File.DirtyListHead = (AFSExtent *)Extent->DirtyList.fLink;
4147 if( Fcb->NPFcb->Specific.File.DirtyListHead != NULL)
4150 Fcb->NPFcb->Specific.File.DirtyListHead->DirtyList.bLink = NULL;
4156 ((AFSExtent *)Extent->DirtyList.bLink)->DirtyList.fLink = Extent->DirtyList.fLink;
4164 AFSConstructCleanByteRangeList( AFSFcb * pFcb,
4165 AFSByteRange ** pByteRangeList)
4168 ULONG ulByteRangeMax;
4169 ULONG ulByteRangeCount = 0;
4170 AFSByteRange *ByteRangeList;
4171 AFSExtent *pExtent, *pNextExtent;
4173 AFSAcquireShared( &pFcb->NPFcb->Specific.File.DirtyExtentsListLock, TRUE);
4175 ulByteRangeMax = pFcb->Specific.File.ExtentsDirtyCount + 1;
4177 ByteRangeList = (AFSByteRange *) AFSExAllocatePoolWithTag( PagedPool,
4178 ulByteRangeMax * sizeof( AFSByteRange),
4181 if ( ByteRangeList == NULL)
4184 (*pByteRangeList) = NULL;
4186 try_return( ulByteRangeCount = DWORD_MAX);
4189 RtlZeroMemory( ByteRangeList,
4190 ulByteRangeMax * sizeof( AFSByteRange));
4193 // The for loop populates the ByteRangeList entries with values that are
4194 // the gaps in the DirtyList. In other words, if a range is not present
4195 // in the DirtyList it will be represented in the ByteRangeList array.
4198 for ( ulByteRangeCount = 0,
4199 pExtent = (AFSExtent *)pFcb->NPFcb->Specific.File.DirtyListHead;
4200 ulByteRangeCount < ulByteRangeMax && pExtent != NULL;
4201 pExtent = pNextExtent)
4204 pNextExtent = (AFSExtent *)pExtent->DirtyList.fLink;
4207 // The first time the for() is entered the ulByteRangeCount will be zero and
4208 // ByteRangeList[0] FileOffset and Length will both be zero. If the first
4209 // extent is not for offset zero, the ByteRangeList[0] Length is set to the
4210 // FileOffset of the Extent.
4212 // Future passes through the loop behave in a similar fashion but
4213 // ByteRangeList[ulByteRangeCount] FileOffset will have been set below.
4216 if ( pExtent->FileOffset.QuadPart != ByteRangeList[ulByteRangeCount].FileOffset.QuadPart + ByteRangeList[ulByteRangeCount].Length.QuadPart)
4219 ByteRangeList[ulByteRangeCount].Length.QuadPart =
4220 pExtent->FileOffset.QuadPart - ByteRangeList[ulByteRangeCount].FileOffset.QuadPart;
4226 // Having processed the current dirty extent, the following while loop
4227 // searches for the next clean gap between dirty extents.
4230 while ( pNextExtent && pNextExtent->FileOffset.QuadPart == pExtent->FileOffset.QuadPart + pExtent->Size)
4233 pExtent = pNextExtent;
4235 pNextExtent = (AFSExtent *)pExtent->DirtyList.fLink;
4239 // Having found the next gap, the ByteRangeList[] FileOffset is set to the start of the gap.
4240 // The Length is left at zero and will be assigned either when the for loop continues or
4241 // when the for loop exits.
4244 ByteRangeList[ulByteRangeCount].FileOffset.QuadPart = pExtent->FileOffset.QuadPart + pExtent->Size;
4248 // Assign the Length of the final clean range to match the file length.
4251 ByteRangeList[ulByteRangeCount].Length.QuadPart =
4252 pFcb->ObjectInformation->EndOfFile.QuadPart - ByteRangeList[ulByteRangeCount].FileOffset.QuadPart;
4254 (*pByteRangeList) = ByteRangeList;
4258 AFSReleaseResource( &pFcb->NPFcb->Specific.File.DirtyExtentsListLock);
4260 return ulByteRangeCount;
4265 AFSSetupMD5Hash( IN AFSFcb *Fcb,
4266 IN AFSExtent *StartExtent,
4267 IN ULONG ExtentsCount,
4268 IN void *SystemBuffer,
4269 IN LARGE_INTEGER *ByteOffset,
4273 NTSTATUS ntStatus = STATUS_SUCCESS;
4274 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
4275 AFSExtent *pExtent = StartExtent;
4276 AFSExtent *pNextExtent, *pCurrentExtent = NULL;
4278 char *pCurrentBuffer = (char *)SystemBuffer;
4279 char *pMD5Buffer = NULL;
4280 ULONG ulCurrentLen = 0;
4281 void *pExtentBuffer = NULL;
4282 LARGE_INTEGER liByteOffset;
4283 ULONG ulBytesRead = 0;
4288 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4289 AFS_TRACE_LEVEL_VERBOSE,
4290 "AFSSetupMD5Hash Acquiring Fcb extents lock %p SHARED %08lX\n",
4291 &Fcb->NPFcb->Specific.File.ExtentsResource,
4292 PsGetCurrentThread());
4294 AFSAcquireShared( &Fcb->NPFcb->Specific.File.ExtentsResource, TRUE);
4298 liByteOffset.QuadPart = ByteOffset->QuadPart;
4300 while( ulCount < ExtentsCount)
4303 RtlZeroMemory( pExtent->MD5,
4304 sizeof( pExtent->MD5));
4306 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
4308 if( liByteOffset.QuadPart == pExtent->FileOffset.QuadPart &&
4309 ByteCount < pExtent->Size)
4312 if( pExtentBuffer == NULL)
4315 pExtentBuffer = AFSExAllocatePoolWithTag( PagedPool,
4317 AFS_GENERIC_MEMORY_9_TAG);
4319 if( pExtentBuffer == NULL)
4326 RtlZeroMemory( pExtentBuffer,
4329 RtlCopyMemory( pExtentBuffer,
4333 pMD5Buffer = (char *)pExtentBuffer;
4335 ulCurrentLen = ByteCount;
4337 else if( liByteOffset.QuadPart != pExtent->FileOffset.QuadPart)
4340 pExtentBuffer = AFSExAllocatePoolWithTag( PagedPool,
4342 AFS_GENERIC_MEMORY_10_TAG);
4344 if( pExtentBuffer == NULL)
4350 RtlZeroMemory( pExtentBuffer,
4353 if( BooleanFlagOn( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE))
4357 RtlCopyMemory( pExtentBuffer,
4358 ((char *)AFSLibCacheBaseAddress + pExtent->CacheOffset.QuadPart),
4361 ASSERT( pExtent->CacheOffset.HighPart == 0);
4362 RtlCopyMemory( pExtentBuffer,
4363 ((char *)AFSLibCacheBaseAddress + pExtent->CacheOffset.LowPart),
4367 ulBytesRead = pExtent->Size;
4372 ntStatus = AFSReadCacheFile( pExtentBuffer,
4373 &pExtent->CacheOffset,
4377 if( !NT_SUCCESS( ntStatus))
4384 pMD5Buffer = (char *)pExtentBuffer;
4386 ulCurrentLen = min( ByteCount, pExtent->Size - (ULONG)(liByteOffset.QuadPart - pExtent->FileOffset.QuadPart));
4388 RtlCopyMemory( (void *)((char *)pExtentBuffer + (ULONG)(liByteOffset.QuadPart - pExtent->FileOffset.QuadPart)),
4395 ulCurrentLen = pExtent->Size;
4397 pMD5Buffer = pCurrentBuffer;
4400 AFSGenerateMD5( pMD5Buffer,
4404 pExtent = pNextExtent;
4408 ByteCount -= ulCurrentLen;
4410 pCurrentBuffer += ulCurrentLen;
4412 liByteOffset.QuadPart += ulCurrentLen;
4415 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4416 AFS_TRACE_LEVEL_VERBOSE,
4417 "AFSSetupMD5Hash Releasing Fcb extents lock %p SHARED %08lX\n",
4418 &Fcb->NPFcb->Specific.File.ExtentsResource,
4419 PsGetCurrentThread());
4422 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
4427 "EXCEPTION - AFSSetupMD5Hash\n");
4429 AFSDumpTraceFilesFnc();
4432 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
4434 if( pExtentBuffer != NULL)
4437 AFSExFreePoolWithTag( pExtentBuffer, AFS_GENERIC_MEMORY_9_TAG);