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 AFSExtent *ExtentFor( PLIST_ENTRY le, ULONG SkipList );
43 static AFSExtent *NextExtent( AFSExtent *Extent, ULONG SkipList );
44 static ULONG ExtentsMasks[AFS_NUM_EXTENT_LISTS] = AFS_EXTENTS_MASKS;
45 static VOID VerifyExtentsLists(AFSFcb *Fcb);
46 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 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
63 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
64 AFS_TRACE_LEVEL_VERBOSE,
65 "AFSLockForExtentsTrim Acuiring Fcb extents lock %08lX EXCL %08lX\n",
66 &pNPFcb->Specific.File.ExtentsResource,
67 PsGetCurrentThread());
69 AFSAcquireExcl( &pNPFcb->Specific.File.ExtentsResource, TRUE );
75 // return FALSE *or* with Extents lock EX and noone using them
78 AFSLockForExtentsTrimNoWait( IN AFSFcb *Fcb)
80 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
82 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
83 AFS_TRACE_LEVEL_VERBOSE,
84 "AFSLockForExtentsTrimNoWait Attempting to acquiring Fcb extent lock %08lX EXCL %08lX\n",
85 &pNPFcb->Specific.File.ExtentsResource,
86 PsGetCurrentThread());
88 if (!AFSAcquireExcl( &pNPFcb->Specific.File.ExtentsResource, FALSE ))
91 // Couldn't lock immediately
94 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
95 AFS_TRACE_LEVEL_VERBOSE,
96 "AFSLockForExtentsTrimNoWait Refused to wait for Fcb extent lock %08lX EXCL %08lX\n",
97 &pNPFcb->Specific.File.ExtentsResource,
98 PsGetCurrentThread());
106 // Pull all the extents away from the FCB.
109 AFSTearDownFcbExtents( IN AFSFcb *Fcb )
111 BOOLEAN bFoundExtents = FALSE;
112 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
115 ULONG ulCount = 0, ulReleaseCount = 0, ulProcessCount = 0;
117 AFSReleaseExtentsCB *pRelease = NULL;
118 BOOLEAN locked = FALSE;
120 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
126 // Ensure that no one is working with the extents and grab the
130 AFSLockForExtentsTrim( Fcb );
134 if (0 == Fcb->Specific.File.ExtentCount)
136 try_return ( ntStatus = STATUS_SUCCESS);
140 // Release a max of 100 extents at a time
143 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
145 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
147 AFS_EXTENT_RELEASE_TAG);
148 if (NULL == pRelease)
151 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
154 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
156 ulCount = Fcb->Specific.File.ExtentCount;
158 while( ulReleaseCount < ulCount)
161 bFoundExtents = TRUE;
163 RtlZeroMemory( pRelease,
164 sizeof( AFSReleaseExtentsCB ) +
165 (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB )));
167 if( ulCount - ulReleaseCount <= AFS_MAXIMUM_EXTENT_RELEASE_COUNT)
169 ulProcessCount = ulCount - ulReleaseCount;
173 ulProcessCount = AFS_MAXIMUM_EXTENT_RELEASE_COUNT;
176 pRelease->Flags = AFS_EXTENT_FLAG_RELEASE;
177 pRelease->ExtentCount = ulProcessCount;
180 // Update the metadata for this call
183 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
184 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
185 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
186 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
187 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
191 while (ulProcessCount < pRelease->ExtentCount)
193 pEntry = ExtentFor( le, AFS_EXTENTS_LIST );
195 pRelease->FileExtents[ulProcessCount].Flags = AFS_EXTENT_FLAG_RELEASE;
198 RtlCopyMemory( pRelease->FileExtents[ulProcessCount].MD5,
200 sizeof(pEntry->MD5));
202 pRelease->FileExtents[ulProcessCount].Flags |= AFS_EXTENT_FLAG_MD5_SET;
205 if( BooleanFlagOn( pEntry->Flags, AFS_EXTENT_DIRTY))
208 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
211 if( BooleanFlagOn( pEntry->Flags, AFS_EXTENT_DIRTY))
216 AFSRemoveEntryDirtyList( Fcb,
219 pRelease->FileExtents[ulProcessCount].Flags |= AFS_EXTENT_FLAG_DIRTY;
221 dirtyCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
223 ASSERT( dirtyCount >= 0);
226 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
229 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
230 AFS_TRACE_LEVEL_VERBOSE,
231 "AFSTearDownFcbExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %08lX-%08lX Len %08lX\n",
233 Fcb->ObjectInformation->FileId.Cell,
234 Fcb->ObjectInformation->FileId.Volume,
235 Fcb->ObjectInformation->FileId.Vnode,
236 Fcb->ObjectInformation->FileId.Unique,
237 pEntry->FileOffset.HighPart,
238 pEntry->FileOffset.LowPart,
241 pRelease->FileExtents[ulProcessCount].Length = pEntry->Size;
242 pRelease->FileExtents[ulProcessCount].DirtyLength = pEntry->Size;
243 pRelease->FileExtents[ulProcessCount].DirtyOffset = 0;
244 pRelease->FileExtents[ulProcessCount].CacheOffset = pEntry->CacheOffset;
245 pRelease->FileExtents[ulProcessCount].FileOffset = pEntry->FileOffset;
247 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pEntry->Size/1024)));
249 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pEntry->Size/1024)));
251 ASSERT( pEntry->ActiveCount == 0);
255 AFSExFreePool( pEntry);
257 InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
259 if( InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount) == 0)
262 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
269 // Send the request down. We cannot send this down
270 // asynchronously - if we did that we could request them
271 // back before the service got this request and then this
272 // request would be a corruption.
275 sz = sizeof( AFSReleaseExtentsCB ) + (ulProcessCount * sizeof ( AFSFileExtentCB ));
277 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
278 AFS_REQUEST_FLAG_SYNCHRONOUS,
281 &Fcb->ObjectInformation->FileId,
287 if( !NT_SUCCESS(ntStatus))
291 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
292 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
295 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
296 AFS_TRACE_LEVEL_ERROR,
297 "AFSTearDownFcbExtents AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
298 Fcb->ObjectInformation->FileId.Cell,
299 Fcb->ObjectInformation->FileId.Volume,
300 Fcb->ObjectInformation->FileId.Vnode,
301 Fcb->ObjectInformation->FileId.Unique,
306 ulReleaseCount += ulProcessCount;
310 // Reinitialize the skip lists
313 ASSERT( Fcb->Specific.File.ExtentCount == 0);
315 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i++)
317 InitializeListHead(&Fcb->Specific.File.ExtentsLists[i]);
321 // Reinitialize the dirty list as well
324 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
327 ASSERT( Fcb->Specific.File.ExtentsDirtyCount == 0);
329 Fcb->NPFcb->Specific.File.DirtyListHead = NULL;
330 Fcb->NPFcb->Specific.File.DirtyListTail = NULL;
332 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
334 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
341 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
342 AFS_TRACE_LEVEL_VERBOSE,
343 "AFSTearDownFcbExtents Releasing Fcb extent lock %08lX thread %08lX\n",
344 &Fcb->NPFcb->Specific.File.ExtentsResource,
345 PsGetCurrentThread());
347 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
353 AFSExFreePool( pRelease);
357 return bFoundExtents;
361 ExtentForOffsetInList( IN AFSFcb *Fcb,
364 IN PLARGE_INTEGER Offset)
367 // Return the extent that maps the offset, that
368 // - Contains the offset
369 // - or is immediately ahead of the offset (in this list)
370 // - otherwise return NULL.
373 PLIST_ENTRY pLe = List;
374 AFSExtent *pPrevious = NULL;
376 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
378 while (pLe != &Fcb->Specific.File.ExtentsLists[ListNumber])
382 entry = ExtentFor( pLe, ListNumber );
389 if (Offset->QuadPart < entry->FileOffset.QuadPart)
392 // Offset is ahead of entry. Return previous
397 if (Offset->QuadPart >= (entry->FileOffset.QuadPart + entry->Size))
400 // We start after this extent - carry on round
408 // Otherwise its a match
415 // Got to the end. Return Previous
421 AFSExtentContains( IN AFSExtent *Extent, IN PLARGE_INTEGER Offset)
427 return (Extent->FileOffset.QuadPart <= Offset->QuadPart &&
428 (Extent->FileOffset.QuadPart + Extent->Size) > Offset->QuadPart);
433 // Return the extent that contains the offset
436 AFSExtentForOffsetHint( IN AFSFcb *Fcb,
437 IN PLARGE_INTEGER Offset,
438 IN BOOLEAN ReturnPrevious,
441 AFSExtent *pPrevious = Hint;
445 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
447 #if AFS_VALIDATE_EXTENTS
448 VerifyExtentsLists(Fcb);
452 // So we will go across the skip lists until we find an
453 // appropriate entry (previous or direct match). If it's a match
454 // we are done, other wise we start on the next layer down
456 for (i = AFS_NUM_EXTENT_LISTS-1; i >= AFS_EXTENTS_LIST; i--)
458 if (NULL == pPrevious)
461 // We haven't found anything in the previous layers
463 pLe = Fcb->Specific.File.ExtentsLists[i].Flink;
465 else if (NULL == pPrevious->Lists[i].Flink)
467 ASSERT(AFS_EXTENTS_LIST != i);
469 // The hint doesn't exist at this level, next one down
476 // take the previous into the next
478 pLe = &pPrevious->Lists[i];
481 pPrevious = ExtentForOffsetInList( Fcb, pLe, i, Offset);
483 if (NULL != pPrevious && AFSExtentContains(pPrevious, Offset))
486 // Found it immediately. Stop here
492 if (NULL == pPrevious || ReturnPrevious )
497 ASSERT( !AFSExtentContains(pPrevious, Offset) );
503 AFSEntryForOffset( IN AFSFcb *Fcb,
504 IN PLARGE_INTEGER Offset)
506 AFSExtent *pPrevious = NULL;
510 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
512 #if AFS_VALIDATE_EXTENTS
513 VerifyExtentsLists(Fcb);
517 // So we will go across the skip lists until we find an
518 // appropriate entry (previous or direct match). If it's a match
519 // we are done, other wise we start on the next layer down
521 for (i = AFS_NUM_EXTENT_LISTS-1; i >= AFS_EXTENTS_LIST; i--)
523 if (NULL == pPrevious)
526 // We haven't found anything in the previous layers
528 pLe = Fcb->Specific.File.ExtentsLists[i].Flink;
530 else if (NULL == pPrevious->Lists[i].Flink)
532 ASSERT(AFS_EXTENTS_LIST != i);
534 // The hint doesn't exist at this level, next one down
541 // take the previous into the next
543 pLe = &pPrevious->Lists[i];
546 pPrevious = ExtentForOffsetInList( Fcb, pLe, i, Offset);
548 if (NULL != pPrevious && AFSExtentContains(pPrevious, Offset))
551 // Found it immediately. Stop here
561 AFSExtentForOffset( IN AFSFcb *Fcb,
562 IN PLARGE_INTEGER Offset,
563 IN BOOLEAN ReturnPrevious)
565 return AFSExtentForOffsetHint(Fcb, Offset, ReturnPrevious, NULL);
569 BOOLEAN AFSDoExtentsMapRegion(IN AFSFcb *Fcb,
570 IN PLARGE_INTEGER Offset,
572 IN OUT AFSExtent **FirstExtent,
573 OUT AFSExtent **LastExtent)
576 // Return TRUE region is completely mapped. FALSE
577 // otherwise. If the region isn't mapped then the last
578 // extent to map part of the region is returned.
580 // *LastExtent as input is where to start looking.
581 // *LastExtent as output is either the extent which
582 // contains the Offset, or the last one which doesn't
586 BOOLEAN retVal = FALSE;
591 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
592 AFS_TRACE_LEVEL_VERBOSE,
593 "AFSDoExtentsMapRegion Acquiring Fcb extent lock %08lX SHARED %08lX\n",
594 &Fcb->NPFcb->Specific.File.ExtentsResource,
595 PsGetCurrentThread());
597 AFSAcquireShared( &Fcb->NPFcb->Specific.File.ExtentsResource, TRUE );
599 entry = AFSExtentForOffsetHint(Fcb, Offset, TRUE, *FirstExtent);
600 *FirstExtent = entry;
602 if (NULL == entry || !AFSExtentContains(entry, Offset))
604 try_return (retVal = FALSE);
607 ASSERT(Offset->QuadPart >= entry->FileOffset.QuadPart);
611 if ((entry->FileOffset.QuadPart + entry->Size) >=
612 (Offset->QuadPart + Size))
615 // The end is inside the extent
617 try_return (retVal = TRUE);
620 if (entry->Lists[AFS_EXTENTS_LIST].Flink == &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
623 // Run out of extents
625 try_return (retVal = FALSE);
628 newEntry = NextExtent( entry, AFS_EXTENTS_LIST );
630 if (newEntry->FileOffset.QuadPart !=
631 (entry->FileOffset.QuadPart + entry->Size))
636 try_return (retVal = FALSE);
644 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
645 AFS_TRACE_LEVEL_VERBOSE,
646 "AFSDoExtentsMapRegion Releasing Fcb extent lock %08lX SHARED %08lX\n",
647 &Fcb->NPFcb->Specific.File.ExtentsResource,
648 PsGetCurrentThread());
650 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
659 // Given an FCB and an Offset we look to see whether there extents to
660 // Map them all. If there are then we return TRUE to fullymapped
661 // and *FirstExtent points to the first extent to map the extent.
662 // If not then we return FALSE, but we request the extents to be mapped.
663 // Further *FirstExtent (if non null) is the last extent which doesn't
666 // Finally on the way *in* if *FirstExtent is non null it is where we start looking
670 AFSRequestExtents( IN AFSFcb *Fcb,
671 IN PLARGE_INTEGER Offset,
673 OUT BOOLEAN *FullyMapped)
676 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
677 NTSTATUS ntStatus = STATUS_SUCCESS;
679 AFSRequestExtentsCB request;
680 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
681 AFSExtent *pFirstExtent;
682 LARGE_INTEGER liAlignedOffset;
683 ULONG ulAlignedLength = 0;
684 LARGE_INTEGER liTimeOut;
685 ULONGLONG ullProcessId = (ULONGLONG)PsGetCurrentProcessId();
688 // Check our extents, then fire off a request if we need to.
689 // We start off knowing nothing about where we will go.
694 *FullyMapped = AFSDoExtentsMapRegion( Fcb, Offset, Size, &pFirstExtent, &pExtent );
699 ASSERT(AFSExtentContains(pFirstExtent, Offset));
700 LARGE_INTEGER end = *Offset;
701 end.QuadPart += (Size-1);
702 ASSERT(AFSExtentContains(pExtent, &end));
704 return STATUS_SUCCESS;
708 // So we need to queue a request. Since we will be clearing the
709 // ExtentsRequestComplete event we need to do with with the lock
713 liTimeOut.QuadPart = -(50000000);
717 if (!NT_SUCCESS( pNPFcb->Specific.File.ExtentsRequestStatus))
721 // If this isn't the same process which caused the failure
722 // then try to request them again
725 if( Fcb->Specific.File.ExtentRequestProcessId == ullProcessId)
727 ntStatus = pNPFcb->Specific.File.ExtentsRequestStatus;
732 pNPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
735 ntStatus = KeWaitForSingleObject( &pNPFcb->Specific.File.ExtentsRequestComplete,
740 if (!NT_SUCCESS(ntStatus))
751 // Lock resource EX and look again
754 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
755 AFS_TRACE_LEVEL_VERBOSE,
756 "AFSRequestExtents Acquiring Fcb extent lock %08lX EXCL %08lX\n",
757 &pNPFcb->Specific.File.ExtentsResource,
758 PsGetCurrentThread());
760 AFSAcquireExcl( &pNPFcb->Specific.File.ExtentsResource, TRUE );
762 if (!NT_SUCCESS( pNPFcb->Specific.File.ExtentsRequestStatus))
766 // If this isn't the same process which caused the failure then try to request them again
769 if( Fcb->Specific.File.ExtentRequestProcessId == ullProcessId)
771 ntStatus = pNPFcb->Specific.File.ExtentsRequestStatus;
773 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
774 AFS_TRACE_LEVEL_VERBOSE,
775 "AFSRequestExtents Releasing Fcb extent lock %08lX EXCL %08lX\n",
776 &pNPFcb->Specific.File.ExtentsResource,
777 PsGetCurrentThread());
779 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
784 pNPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
787 if( KeReadStateEvent( &pNPFcb->Specific.File.ExtentsRequestComplete) ||
788 ntStatus == STATUS_TIMEOUT)
791 ntStatus = pNPFcb->Specific.File.ExtentsRequestStatus;
793 if( !NT_SUCCESS( ntStatus))
797 // If this isn't the same process which caused the failure
798 // then try to request them again
801 if( Fcb->Specific.File.ExtentRequestProcessId == ullProcessId)
803 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
804 AFS_TRACE_LEVEL_VERBOSE,
805 "AFSRequestExtents Releasing Fcb extent lock %08lX EXCL %08lX\n",
806 &pNPFcb->Specific.File.ExtentsResource,
807 PsGetCurrentThread());
809 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
814 pNPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
816 ntStatus = STATUS_SUCCESS;
823 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
824 AFS_TRACE_LEVEL_VERBOSE,
825 "AFSRequestExtents Releasing Fcb extent lock %08lX EXCL %08lX\n",
826 &pNPFcb->Specific.File.ExtentsResource,
827 PsGetCurrentThread());
829 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
832 if (!NT_SUCCESS(ntStatus))
841 // We have the lock Ex and there is no filling going on.
842 // Check again to see whether things have moved since we last
843 // checked. Since we haven't locked against pinning, we will
849 *FullyMapped = AFSDoExtentsMapRegion(Fcb, Offset, Size, &pFirstExtent, &pExtent);
854 ASSERT(AFSExtentContains(pFirstExtent, Offset));
855 LARGE_INTEGER end = *Offset;
856 end.QuadPart += (Size-1);
857 ASSERT(AFSExtentContains(pExtent, &end));
859 try_return (ntStatus = STATUS_SUCCESS);
862 RtlZeroMemory( &request,
863 sizeof( AFSRequestExtentsCB));
869 ulAlignedLength = Size;
871 liAlignedOffset = *Offset;
873 if( liAlignedOffset.QuadPart % pDevExt->Specific.RDR.CacheBlockSize != 0)
876 liAlignedOffset.QuadPart = (ULONGLONG)( (ULONGLONG)(liAlignedOffset.QuadPart / pDevExt->Specific.RDR.CacheBlockSize) * (ULONGLONG)pDevExt->Specific.RDR.CacheBlockSize);
878 ulAlignedLength += (ULONG)(Offset->QuadPart - liAlignedOffset.QuadPart);
881 if( ulAlignedLength % pDevExt->Specific.RDR.CacheBlockSize != 0)
884 ulAlignedLength = (ULONG)(((ulAlignedLength / pDevExt->Specific.RDR.CacheBlockSize) + 1) * pDevExt->Specific.RDR.CacheBlockSize);
887 request.ByteOffset = liAlignedOffset;
888 request.Length = ulAlignedLength;
890 if( !AFSIsExtentRequestQueued( &Fcb->ObjectInformation->FileId,
895 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
896 AFS_TRACE_LEVEL_VERBOSE,
897 "AFSRequestExtents Request extents for fid %08lX-%08lX-%08lX-%08lX Offset %08lX Len %08lX Thread %08lX\n",
898 Fcb->ObjectInformation->FileId.Cell,
899 Fcb->ObjectInformation->FileId.Volume,
900 Fcb->ObjectInformation->FileId.Vnode,
901 Fcb->ObjectInformation->FileId.Unique,
902 request.ByteOffset.LowPart,
904 PsGetCurrentThread());
906 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS,
910 &Fcb->ObjectInformation->FileId,
912 sizeof( AFSRequestExtentsCB ),
916 if( NT_SUCCESS( ntStatus))
918 KeClearEvent( &pNPFcb->Specific.File.ExtentsRequestComplete );
924 KeClearEvent( &pNPFcb->Specific.File.ExtentsRequestComplete );
929 if (NT_SUCCESS( ntStatus ))
931 KeQueryTickCount( &Fcb->Specific.File.LastExtentAccess );
934 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
935 AFS_TRACE_LEVEL_VERBOSE,
936 "AFSRequestExtents Releasing Fcb extent lock %08lX EXCL %08lX\n",
937 &pNPFcb->Specific.File.ExtentsResource,
938 PsGetCurrentThread());
940 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
947 AFSRequestExtentsAsync( IN AFSFcb *Fcb,
948 IN PLARGE_INTEGER Offset,
952 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
953 NTSTATUS ntStatus = STATUS_SUCCESS;
954 AFSExtent *pExtent = NULL;
955 AFSRequestExtentsCB request;
956 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
957 AFSExtent *pFirstExtent = NULL;
958 LARGE_INTEGER liAlignedOffset;
959 ULONG ulAlignedLength = 0;
960 BOOLEAN bRegionMapped = FALSE;
961 ULONGLONG ullProcessId = (ULONGLONG)PsGetCurrentProcessId();
966 ASSERT( !ExIsResourceAcquiredLite( &pNPFcb->Specific.File.ExtentsResource ));
969 // If the service set a failure on the file since the last
970 // CreateFile was issued, return it now.
973 if (!NT_SUCCESS( pNPFcb->Specific.File.ExtentsRequestStatus))
977 // If this isn't the same process which caused the failure then try to request them again
980 if( Fcb->Specific.File.ExtentRequestProcessId == ullProcessId)
982 try_return( ntStatus = pNPFcb->Specific.File.ExtentsRequestStatus);
985 pNPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
989 // Check if we are already mapped
992 bRegionMapped = AFSDoExtentsMapRegion( Fcb, Offset, Size, &pFirstExtent, &pExtent);
997 try_return( ntStatus = STATUS_SUCCESS);
1001 // Align our request on extent size boundary
1004 ulAlignedLength = Size;
1006 liAlignedOffset = *Offset;
1008 if( liAlignedOffset.QuadPart % pDevExt->Specific.RDR.CacheBlockSize != 0)
1011 liAlignedOffset.QuadPart = (ULONGLONG)( (ULONGLONG)(liAlignedOffset.QuadPart / pDevExt->Specific.RDR.CacheBlockSize) * (ULONGLONG)pDevExt->Specific.RDR.CacheBlockSize);
1013 ulAlignedLength += (ULONG)(Offset->QuadPart - liAlignedOffset.QuadPart);
1016 if( ulAlignedLength % pDevExt->Specific.RDR.CacheBlockSize != 0)
1019 ulAlignedLength = (ULONG)(((ulAlignedLength / pDevExt->Specific.RDR.CacheBlockSize) + 1) * pDevExt->Specific.RDR.CacheBlockSize);
1022 RtlZeroMemory( &request,
1023 sizeof( AFSRequestExtentsCB));
1025 request.ByteOffset = liAlignedOffset;
1026 request.Length = ulAlignedLength;
1028 if( !AFSIsExtentRequestQueued( &Fcb->ObjectInformation->FileId,
1029 &request.ByteOffset,
1033 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1034 AFS_TRACE_LEVEL_VERBOSE,
1035 "AFSRequestExtentsAsync Request extents for fid %08lX-%08lX-%08lX-%08lX Offset %08lX Len %08lX Thread %08lX\n",
1036 Fcb->ObjectInformation->FileId.Cell,
1037 Fcb->ObjectInformation->FileId.Volume,
1038 Fcb->ObjectInformation->FileId.Vnode,
1039 Fcb->ObjectInformation->FileId.Unique,
1040 request.ByteOffset.LowPart,
1042 PsGetCurrentThread());
1044 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS,
1048 &Fcb->ObjectInformation->FileId,
1050 sizeof( AFSRequestExtentsCB ),
1054 if( NT_SUCCESS( ntStatus))
1057 KeClearEvent( &pNPFcb->Specific.File.ExtentsRequestComplete );
1063 KeClearEvent( &pNPFcb->Specific.File.ExtentsRequestComplete );
1075 AFSProcessExtentsResult( IN AFSFcb *Fcb,
1077 IN AFSFileExtentCB *Result)
1079 NTSTATUS ntStatus = STATUS_SUCCESS;
1080 AFSFileExtentCB *pFileExtents = Result;
1083 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
1084 ULONG fileExtentsUsed = 0;
1085 BOOLEAN bFoundExtent = FALSE;
1086 LIST_ENTRY *pSkipEntries[AFS_NUM_EXTENT_LISTS] = { 0 };
1087 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1090 // Grab the extents exclusive for the duration
1093 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1094 AFS_TRACE_LEVEL_VERBOSE,
1095 "AFSProcessExtentsResult Acquiring Fcb extent lock %08lX EXCL %08lX\n",
1096 &pNPFcb->Specific.File.ExtentsResource,
1097 PsGetCurrentThread());
1099 AFSAcquireExcl( &pNPFcb->Specific.File.ExtentsResource, TRUE );
1105 // Find where to put the extents
1107 for (ULONG i = AFS_EXTENTS_LIST; i < AFS_NUM_EXTENT_LISTS; i++)
1110 pSkipEntries[i] = Fcb->Specific.File.ExtentsLists[i].Flink;
1113 le = pSkipEntries[AFS_EXTENTS_LIST];
1115 if (le == &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
1118 // No extents. Insert at head of list (which is where the skip lists point!)
1122 else if (0 != pFileExtents->FileOffset.QuadPart)
1125 // We want to find the best extents immediately *behind* this offset
1127 LARGE_INTEGER offset = pFileExtents->FileOffset;
1130 // Ask in the top skip list first, then work down
1132 for (LONG i = AFS_NUM_EXTENT_LISTS-1; i >= AFS_EXTENTS_LIST; i--)
1134 pExtent = ExtentForOffsetInList( Fcb,
1139 if (NULL == pExtent)
1142 // No dice. Header has to become the head of the list
1144 pSkipEntries[i] = &Fcb->Specific.File.ExtentsLists[i];
1146 // And as a loop invariant we should never have found an extent
1148 ASSERT(!bFoundExtent);
1153 // pExtent is where to start to insert at this level
1155 pSkipEntries[i] = &pExtent->Lists[i];
1158 // And also where to start to look at the next level
1161 if (i > AFS_EXTENTS_LIST)
1163 pSkipEntries[i-1] = &pExtent->Lists[i-1];
1165 bFoundExtent = TRUE;
1169 if (NULL == pExtent)
1171 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
1176 le = pExtent->Lists[AFS_EXTENTS_LIST].Blink;
1182 // Looking at offset 0, so we must start at the beginning
1185 pExtent = ExtentFor(le, AFS_EXTENTS_LIST);
1189 // And set up the skip lists
1192 for (ULONG i = AFS_EXTENTS_LIST; i < AFS_NUM_EXTENT_LISTS; i++)
1194 pSkipEntries[i] = &Fcb->Specific.File.ExtentsLists[i];
1198 while (fileExtentsUsed < Count)
1202 // Loop invariant - le points to where to insert after and
1203 // pExtent points to le->fLink
1206 ASSERT (NULL == pExtent ||
1207 le->Flink == &pExtent->Lists[AFS_EXTENTS_LIST]);
1209 if (NULL == pExtent ||
1210 pExtent->FileOffset.QuadPart > pFileExtents->FileOffset.QuadPart)
1213 // We need to insert a new extent at le. Start with
1214 // some sanity check on spanning
1216 if (NULL != pExtent &&
1217 ((pFileExtents->FileOffset.QuadPart + pFileExtents->Length) >
1218 pExtent->FileOffset.QuadPart))
1221 // File Extents overlaps pExtent
1223 ASSERT( (pFileExtents->FileOffset.QuadPart + pFileExtents->Length) <=
1224 pExtent->FileOffset.QuadPart);
1226 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1230 // File offset is entirely in front of this extent. Create
1231 // a new one (remember le is the previous list entry)
1233 pExtent = (AFSExtent *) AFSExAllocatePoolWithTag( NonPagedPool,
1236 if (NULL == pExtent)
1241 try_return (ntStatus = STATUS_INSUFFICIENT_RESOURCES );
1244 RtlZeroMemory( pExtent, sizeof( AFSExtent ));
1246 pExtent->FileOffset = pFileExtents->FileOffset;
1247 pExtent->CacheOffset = pFileExtents->CacheOffset;
1248 pExtent->Size = pFileExtents->Length;
1250 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1251 AFS_TRACE_LEVEL_VERBOSE,
1252 "AFSProcessExtentsResult Received extent for fid %08lX-%08lX-%08lX-%08lX File Offset %I64X Cache Offset %I64X Len %08lX\n",
1253 Fcb->ObjectInformation->FileId.Cell,
1254 Fcb->ObjectInformation->FileId.Volume,
1255 Fcb->ObjectInformation->FileId.Vnode,
1256 Fcb->ObjectInformation->FileId.Unique,
1257 pFileExtents->FileOffset.QuadPart,
1258 pFileExtents->CacheOffset.QuadPart,
1259 pFileExtents->Length);
1261 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, (LONG)(pExtent->Size/1024));
1263 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, (LONG)(pExtent->Size/1024));
1265 InterlockedIncrement( &Fcb->Specific.File.ExtentCount);
1267 if( InterlockedIncrement( &pControlDevExt->Specific.Control.ExtentCount) == 1)
1270 KeClearEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent);
1276 InsertHeadList(le, &pExtent->Lists[AFS_EXTENTS_LIST]);
1277 ASSERT(le->Flink == &pExtent->Lists[AFS_EXTENTS_LIST]);
1278 ASSERT(0 == (pExtent->FileOffset.LowPart & ExtentsMasks[AFS_EXTENTS_LIST]));
1281 // Do not move the cursor - we will do it next time
1285 // And into the (upper) skip lists - Again, do not move the cursor
1287 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1289 if (0 == (pExtent->FileOffset.LowPart & ExtentsMasks[i]))
1291 InsertHeadList(pSkipEntries[i], &pExtent->Lists[i]);
1292 #if AFS_VALIDATE_EXTENTS
1293 VerifyExtentsLists(Fcb);
1298 else if (pExtent->FileOffset.QuadPart == pFileExtents->FileOffset.QuadPart)
1301 if (pExtent->Size != pFileExtents->Length)
1304 ASSERT (pExtent->Size == pFileExtents->Length);
1306 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1310 // Move both cursors forward.
1312 // First the extent pointer
1315 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1318 // Then the skip lists cursors forward if needed
1320 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1322 if (0 == (pExtent->FileOffset.LowPart & ExtentsMasks[i]))
1325 // Check sanity before
1327 #if AFS_VALIDATE_EXTENTS
1328 VerifyExtentsLists(Fcb);
1332 // Skip list should point to us
1334 //ASSERT(pSkipEntries[i] == &pExtent->Lists[i]);
1336 // Move forward cursor
1338 pSkipEntries[i] = pSkipEntries[i]->Flink;
1340 // Check sanity before
1342 #if AFS_VALIDATE_EXTENTS
1343 VerifyExtentsLists(Fcb);
1349 // And then the cursor in the supplied array
1355 // setup pExtent if there is one
1357 if (le->Flink != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
1359 pExtent = NextExtent( pExtent, AFS_EXTENTS_LIST ) ;
1369 ASSERT( pExtent->FileOffset.QuadPart < pFileExtents->FileOffset.QuadPart );
1372 // Sanity check on spanning
1374 if ((pExtent->FileOffset.QuadPart + pExtent->Size) >
1375 pFileExtents->FileOffset.QuadPart)
1378 ASSERT( (pExtent->FileOffset.QuadPart + pExtent->Size) <=
1379 pFileExtents->FileOffset.QuadPart);
1381 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1385 // Move le and pExtent forward
1387 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1391 // Then the check the skip lists cursors
1393 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1395 if (0 == (pFileExtents->FileOffset.LowPart & ExtentsMasks[i]))
1399 // - empty list (pSkipEntries[i]->Flink == pSkipEntries[i]->Flink == fcb->lists[i]
1400 // - We are the last on the list (pSkipEntries[i]->Flink == fcb->lists[i])
1401 // - We are not the last on the list. In that case we have to be strictly less than
1403 if (pSkipEntries[i]->Flink != &Fcb->Specific.File.ExtentsLists[i]) {
1405 AFSExtent *otherExtent = ExtentFor(pSkipEntries[i]->Flink, i);
1406 ASSERT(pFileExtents->FileOffset.QuadPart < otherExtent->FileOffset.QuadPart);
1413 // setup pExtent if there is one
1416 if (le->Flink != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
1418 pExtent = NextExtent( pExtent, AFS_EXTENTS_LIST ) ;
1428 // All done, signal that we are done drop the lock, exit
1433 if( !NT_SUCCESS( ntStatus))
1437 // If we failed the service is going to drop all extents so trim away the
1441 AFSTrimSpecifiedExtents( Fcb,
1446 #if AFS_VALIDATE_EXTENTS
1447 VerifyExtentsLists(Fcb);
1450 KeSetEvent( &pNPFcb->Specific.File.ExtentsRequestComplete,
1454 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1455 AFS_TRACE_LEVEL_VERBOSE,
1456 "AFSProcessExtentsResult Releasing Fcb extent lock %08lX EXCL %08lX\n",
1457 &pNPFcb->Specific.File.ExtentsResource,
1458 PsGetCurrentThread());
1460 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
1467 AFSProcessSetFileExtents( IN AFSSetFileExtentsCB *SetExtents )
1469 AFSFcb *pFcb = NULL;
1470 AFSVolumeCB *pVolumeCB = NULL;
1471 NTSTATUS ntStatus = STATUS_SUCCESS;
1472 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1473 ULONGLONG ullIndex = 0;
1474 AFSObjectInfoCB *pObjectInfo = NULL;
1479 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1480 AFS_TRACE_LEVEL_VERBOSE,
1481 "AFSProcessSetFileExtents Acquiring RDR VolumeTreeLock lock %08lX SHARED %08lX\n",
1482 &pDevExt->Specific.RDR.VolumeTreeLock,
1483 PsGetCurrentThread());
1485 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
1487 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1488 AFS_TRACE_LEVEL_VERBOSE,
1489 "AFSProcessSetFileExtents Set extents for fid %08lX-%08lX-%08lX-%08lX\n",
1490 SetExtents->FileId.Cell,
1491 SetExtents->FileId.Volume,
1492 SetExtents->FileId.Vnode,
1493 SetExtents->FileId.Unique);
1496 // Locate the volume node
1499 ullIndex = AFSCreateHighIndex( &SetExtents->FileId);
1501 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
1503 (AFSBTreeEntry **)&pVolumeCB);
1505 if( pVolumeCB != NULL)
1508 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1509 AFS_TRACE_LEVEL_VERBOSE,
1510 "AFSProcessSetFileExtents Acquiring VolumeRoot FileIDTree.TreeLock lock %08lX SHARED %08lX\n",
1511 pVolumeCB->ObjectInfoTree.TreeLock,
1512 PsGetCurrentThread());
1514 InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1517 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
1519 if( !NT_SUCCESS( ntStatus) ||
1523 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1524 AFS_TRACE_LEVEL_ERROR,
1525 "AFSProcessSetFileExtents Set extents for fid %08lX-%08lX-%08lX-%08lX Failed to locate volume Status %08lX\n",
1526 SetExtents->FileId.Cell,
1527 SetExtents->FileId.Volume,
1528 SetExtents->FileId.Vnode,
1529 SetExtents->FileId.Unique,
1532 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1535 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1538 InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1541 // Now locate the Object in this volume
1544 ullIndex = AFSCreateLowIndex( &SetExtents->FileId);
1546 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
1548 (AFSBTreeEntry **)&pObjectInfo);
1550 if( pObjectInfo != NULL)
1554 // Reference the node so it won't be torn down
1557 InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
1559 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1560 AFS_TRACE_LEVEL_VERBOSE,
1561 "AFSProcessSetFileExtents Increment count on object %08lX Cnt %d\n",
1563 pObjectInfo->ObjectReferenceCount);
1566 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1568 if( !NT_SUCCESS( ntStatus) ||
1569 pObjectInfo == NULL)
1572 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1573 AFS_TRACE_LEVEL_ERROR,
1574 "AFSProcessSetFileExtents Set extents for hash %I64X fid %08lX-%08lX-%08lX-%08lX Failed to locate file in volume %08lX\n",
1576 SetExtents->FileId.Cell,
1577 SetExtents->FileId.Volume,
1578 SetExtents->FileId.Vnode,
1579 SetExtents->FileId.Unique,
1582 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1585 pFcb = pObjectInfo->Fcb;
1588 // If we have a result failure then don't bother trying to set the extents
1591 if( SetExtents->ResultStatus != STATUS_SUCCESS)
1594 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1595 AFS_TRACE_LEVEL_ERROR,
1596 "AFSProcessSetFileExtents Set extents failure fid %08lX-%08lX-%08lX-%08lX ResultStatus %08lX\n",
1597 SetExtents->FileId.Cell,
1598 SetExtents->FileId.Volume,
1599 SetExtents->FileId.Vnode,
1600 SetExtents->FileId.Unique,
1601 SetExtents->ResultStatus);
1603 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1604 AFS_TRACE_LEVEL_VERBOSE,
1605 "AFSProcessSetFileExtents Acquiring Fcb extents lock %08lX EXCL %08lX\n",
1606 &pFcb->NPFcb->Specific.File.ExtentsResource,
1607 PsGetCurrentThread());
1609 AFSAcquireExcl( &pFcb->NPFcb->Specific.File.ExtentsResource,
1612 pFcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_CANCELLED;
1614 KeSetEvent( &pFcb->NPFcb->Specific.File.ExtentsRequestComplete,
1618 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1619 AFS_TRACE_LEVEL_VERBOSE,
1620 "AFSProcessSetFileExtents Releasing Fcb extent lock %08lX EXCL %08lX\n",
1621 &pFcb->NPFcb->Specific.File.ExtentsResource,
1622 PsGetCurrentThread());
1624 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
1626 try_return( ntStatus);
1629 ntStatus = AFSProcessExtentsResult ( pFcb,
1630 SetExtents->ExtentCount,
1631 SetExtents->FileExtents );
1635 if( pObjectInfo != NULL)
1638 InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
1640 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1641 AFS_TRACE_LEVEL_VERBOSE,
1642 "AFSProcessSetFileExtents Decrement count on object %08lX Cnt %d\n",
1644 pObjectInfo->ObjectReferenceCount);
1652 // Helper fuctions for Usermode initiation of release of extents
1655 AFSReleaseSpecifiedExtents( IN AFSReleaseFileExtentsCB *Extents,
1657 OUT AFSFileExtentCB *FileExtents,
1658 IN ULONG BufferSize,
1659 OUT ULONG *ExtentCount,
1660 OUT BOOLEAN *DirtyExtents)
1665 ULONG ulExtentCount = 0;
1666 NTSTATUS ntStatus = STATUS_SUCCESS;
1667 BOOLEAN bReleaseAll = FALSE;
1668 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1672 ASSERT( ExIsResourceAcquiredExclusiveLite( &Fcb->NPFcb->Specific.File.ExtentsResource));
1674 if (BufferSize < (Extents->ExtentCount * sizeof( AFSFileExtentCB)))
1677 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1678 AFS_TRACE_LEVEL_VERBOSE,
1679 "AFSReleaseSpecifiedExtents Buffer too small\n");
1681 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL);
1684 RtlZeroMemory( FileExtents, BufferSize);
1687 *DirtyExtents = FALSE;
1690 // iterate until we have dealt with all we were asked for or
1691 // are at the end of the list. Note that this deals (albeit
1692 // badly) with out of order extents
1695 pExtent = AFSExtentForOffset( Fcb,
1696 &Extents->FileExtents[0].FileOffset,
1699 if (NULL == pExtent)
1701 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1705 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1709 if( BooleanFlagOn( Extents->Flags, AFS_RELEASE_EXTENTS_FLAGS_RELEASE_ALL) ||
1710 ( Extents->FileId.Cell == 0 &&
1711 Extents->FileId.Volume == 0 &&
1712 Extents->FileId.Vnode == 0 &&
1713 Extents->FileId.Unique == 0))
1719 while( le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST] &&
1720 ulExtentCount < Extents->ExtentCount)
1724 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
1729 if( pExtent->FileOffset.QuadPart < Extents->FileExtents[ulExtentCount].FileOffset.QuadPart)
1732 // Skip forward through the extent list until we get
1733 // to the one we want
1739 else if (pExtent->FileOffset.QuadPart > Extents->FileExtents[ulExtentCount].FileOffset.QuadPart)
1742 // We don't have the extent asked for so return UNKNOWN
1745 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1746 AFS_TRACE_LEVEL_VERBOSE,
1747 "AFSReleaseSpecifiedExtents Located UNKNOWN extent Offset %I64X Len %08lX\n",
1748 Extents->FileExtents[ulExtentCount].FileOffset.QuadPart,
1749 Extents->FileExtents[ulExtentCount].Length);
1751 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_UNKNOWN;
1753 FileExtents[*ExtentCount].Length = 0;
1754 FileExtents[*ExtentCount].CacheOffset.QuadPart = 0;
1755 FileExtents[*ExtentCount].FileOffset = Extents->FileExtents[ulExtentCount].FileOffset;
1757 *ExtentCount = (*ExtentCount) + 1;
1762 // Reset where we are looking
1765 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1769 else if( pExtent->ActiveCount > 0)
1772 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1773 AFS_TRACE_LEVEL_VERBOSE,
1774 "AFSReleaseSpecifiedExtents Located IN_USE extent Offset %I64X Len %08lX\n",
1775 Extents->FileExtents[ulExtentCount].FileOffset.QuadPart,
1776 Extents->FileExtents[ulExtentCount].Length);
1778 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_IN_USE;
1780 FileExtents[*ExtentCount].Length = 0;
1781 FileExtents[*ExtentCount].CacheOffset.QuadPart = 0;
1782 FileExtents[*ExtentCount].FileOffset = Extents->FileExtents[ulExtentCount].FileOffset;
1784 *ExtentCount = (*ExtentCount) + 1;
1789 // Reset where we are looking
1792 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1801 // If the extent is currently active then skip it
1804 if( pExtent->ActiveCount > 0)
1813 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_RELEASE;
1815 FileExtents[*ExtentCount].Length = pExtent->Size;
1816 FileExtents[*ExtentCount].DirtyLength = pExtent->Size;
1817 FileExtents[*ExtentCount].DirtyOffset = 0;
1818 FileExtents[*ExtentCount].CacheOffset = pExtent->CacheOffset;
1819 FileExtents[*ExtentCount].FileOffset = pExtent->FileOffset;
1821 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1822 AFS_TRACE_LEVEL_VERBOSE,
1823 "AFSReleaseSpecifiedExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
1825 Fcb->ObjectInformation->FileId.Cell,
1826 Fcb->ObjectInformation->FileId.Volume,
1827 Fcb->ObjectInformation->FileId.Vnode,
1828 Fcb->ObjectInformation->FileId.Unique,
1829 FileExtents[*ExtentCount].FileOffset.QuadPart,
1830 FileExtents[*ExtentCount].Length);
1832 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
1835 AFSAcquireExcl( &Fcb->NPFcb->Specific.File.DirtyExtentsListLock,
1838 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
1841 AFSRemoveEntryDirtyList( Fcb,
1844 FileExtents[*ExtentCount].Flags |= AFS_EXTENT_FLAG_DIRTY;
1846 InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
1848 *DirtyExtents = TRUE;
1851 AFSReleaseResource( &Fcb->NPFcb->Specific.File.DirtyExtentsListLock);
1855 // move forward all three cursors
1859 *ExtentCount = (*ExtentCount) + 1;
1864 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
1866 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
1868 RemoveEntryList( &pExtent->Lists[i] );
1872 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
1874 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
1879 AFSExFreePool( pExtent);
1881 InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
1883 if( InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount) == 0)
1886 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
1901 AFSFindFcbToClean(ULONG IgnoreTime, AFSFcb *LastFcb, BOOLEAN Block)
1904 AFSFcb *pFcb = NULL;
1905 AFSVolumeCB *pVolumeCB = NULL;
1906 AFSDeviceExt *pRDRDeviceExt = NULL;
1907 AFSDeviceExt *pControlDeviceExt = NULL;
1908 BOOLEAN bLocatedEntry = FALSE;
1909 AFSObjectInfoCB *pCurrentObject = NULL;
1910 BOOLEAN bReleaseVolumeListLock = FALSE;
1912 pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1913 pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1915 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1916 AFS_TRACE_LEVEL_VERBOSE,
1917 "AFSFindFcbToClean Acquiring RDR VolumeListLock lock %08lX SHARED %08lX\n",
1918 &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1919 PsGetCurrentThread());
1921 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1924 bReleaseVolumeListLock = TRUE;
1926 pVolumeCB = pRDRDeviceExt->Specific.RDR.VolumeListHead;
1928 while( pVolumeCB != NULL)
1932 // The Volume list may move under our feet. Lock it.
1935 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1936 AFS_TRACE_LEVEL_VERBOSE,
1937 "AFSFindFcbToClean Acquiring VolumeRoot ObjectInfoTree lock %08lX SHARED %08lX\n",
1938 pVolumeCB->ObjectInfoTree.TreeLock,
1939 PsGetCurrentThread());
1941 InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1943 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1945 bReleaseVolumeListLock = FALSE;
1947 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1950 InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1952 if( NULL == LastFcb)
1955 pCurrentObject = pVolumeCB->ObjectInfoListHead;
1960 pCurrentObject = (AFSObjectInfoCB *)LastFcb->ObjectInformation->ListEntry.fLink;
1965 while( pCurrentObject != NULL)
1968 pFcb = (AFSFcb *)pCurrentObject->Fcb;
1971 // If the FCB is a candidate we try to lock it (but without waiting - which
1972 // means we are deadlock free
1976 pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
1982 AFSLockForExtentsTrim( pFcb);
1987 if( !AFSLockForExtentsTrimNoWait( pFcb))
1990 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1999 // Need to be sure there are no current flushes in the queue
2002 if( pFcb->Specific.File.ExtentCount == 0)
2005 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2006 AFS_TRACE_LEVEL_VERBOSE,
2007 "AFSFindFcbToClean Releasing Fcb extent lock %08lX thread %08lX\n",
2008 &pFcb->NPFcb->Specific.File.ExtentsResource,
2009 PsGetCurrentThread());
2011 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
2013 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
2020 if( pFcb->Specific.File.QueuedFlushCount > 0)
2023 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2024 AFS_TRACE_LEVEL_VERBOSE,
2025 "AFSFindFcbToClean Releasing Fcb extent lock %08lX thread %08lX\n",
2026 &pFcb->NPFcb->Specific.File.ExtentsResource,
2027 PsGetCurrentThread());
2029 AFSReleaseResource(&pFcb->NPFcb->Specific.File.ExtentsResource);
2033 AFSWaitOnQueuedFlushes( pFcb);
2038 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
2046 if( pFcb->OpenHandleCount > 0)
2049 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2050 AFS_TRACE_LEVEL_VERBOSE,
2051 "AFSFindFcbToClean Releasing Fcb extent lock %08lX thread %08lX\n",
2052 &pFcb->NPFcb->Specific.File.ExtentsResource,
2053 PsGetCurrentThread());
2055 AFSReleaseResource(&pFcb->NPFcb->Specific.File.ExtentsResource);
2057 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
2065 // A hit a very palpable hit. Pin it
2068 InterlockedIncrement( &pCurrentObject->ObjectReferenceCount);
2070 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2071 AFS_TRACE_LEVEL_VERBOSE,
2072 "AFSFindFcbToClean Increment count on Fcb %08lX Cnt %d\n",
2074 pCurrentObject->ObjectReferenceCount);
2076 bLocatedEntry = TRUE;
2081 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
2086 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2093 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
2096 bReleaseVolumeListLock = TRUE;
2098 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
2101 if( bReleaseVolumeListLock)
2104 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
2111 AFSProcessExtentFailure( PIRP Irp)
2113 AFSExtentFailureCB *pFailureCB = NULL;
2114 NTSTATUS ntStatus = STATUS_SUCCESS;
2115 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2116 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2117 AFSVolumeCB *pVolumeCB = NULL;
2118 ULONGLONG ullIndex = 0;
2119 AFSObjectInfoCB *pObjectInfo = NULL;
2123 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSExtentFailureCB))
2126 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2127 AFS_TRACE_LEVEL_ERROR,
2128 "AFSProcessExtentFailure Input buffer too small\n");
2130 try_return( ntStatus = STATUS_INVALID_PARAMETER);
2133 pFailureCB = (AFSExtentFailureCB *)Irp->AssociatedIrp.SystemBuffer;
2135 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2136 AFS_TRACE_LEVEL_ERROR,
2137 "AFSProcessExtentFailure Service Reports Failure fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2138 pFailureCB->FileId.Cell,
2139 pFailureCB->FileId.Volume,
2140 pFailureCB->FileId.Vnode,
2141 pFailureCB->FileId.Unique,
2142 pFailureCB->FailureStatus);
2144 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
2147 // Locate the volume node
2150 ullIndex = AFSCreateHighIndex( &pFailureCB->FileId);
2152 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
2154 (AFSBTreeEntry **)&pVolumeCB);
2156 if( pVolumeCB != NULL)
2159 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2160 AFS_TRACE_LEVEL_VERBOSE,
2161 "AFSProcessExtentFailure Acquiring VolumeRoot FileIDTree.TreeLock lock %08lX SHARED %08lX\n",
2162 pVolumeCB->ObjectInfoTree.TreeLock,
2163 PsGetCurrentThread());
2165 InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
2168 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
2170 if( !NT_SUCCESS( ntStatus) ||
2174 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2175 AFS_TRACE_LEVEL_ERROR,
2176 "AFSProcessExtentFailure Invalid volume index %I64X status %08X\n",
2177 ullIndex, ntStatus);
2179 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2182 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
2185 InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
2188 // Now locate the Object in this volume
2191 ullIndex = AFSCreateLowIndex( &pFailureCB->FileId);
2193 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
2195 (AFSBTreeEntry **)&pObjectInfo);
2197 if( pObjectInfo != NULL &&
2198 pObjectInfo->Fcb != NULL)
2202 // Reference the node so it won't be torn down
2205 InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
2207 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2208 AFS_TRACE_LEVEL_VERBOSE,
2209 "AFSProcessExtentFailure Increment count on object %08lX Cnt %d\n",
2211 pObjectInfo->ObjectReferenceCount);
2214 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2216 if( !NT_SUCCESS( ntStatus) ||
2217 pObjectInfo == NULL ||
2218 pObjectInfo->Fcb == NULL)
2221 if( pObjectInfo == NULL)
2223 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2224 AFS_TRACE_LEVEL_ERROR,
2225 "AFSProcessExtentFailure Invalid file index %I64X\n",
2230 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2231 AFS_TRACE_LEVEL_ERROR,
2232 "AFSProcessExtentFailure Fcb dealocated for %I64X\n",
2236 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2239 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2240 AFS_TRACE_LEVEL_VERBOSE,
2241 "AFSProcessExtentFailure Acquiring Fcb extent lock %08lX EXCL %08lX\n",
2242 &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2243 PsGetCurrentThread());
2245 AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2248 pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestStatus = pFailureCB->FailureStatus;
2250 KeSetEvent( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
2254 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2255 AFS_TRACE_LEVEL_VERBOSE,
2256 "AFSProcessExtentFailure Releasing Fcb extent lock %08lX EXCL %08lX\n",
2257 &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2258 PsGetCurrentThread());
2260 AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource);
2262 InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
2264 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2265 AFS_TRACE_LEVEL_VERBOSE,
2266 "AFSProcessExtentFailure Decrement count on object %08lX Cnt %d\n",
2268 pObjectInfo->ObjectReferenceCount);
2279 AFSProcessReleaseFileExtents( IN PIRP Irp)
2281 NTSTATUS ntStatus = STATUS_SUCCESS;
2282 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2283 PFILE_OBJECT pFileObject = pIrpSp->FileObject;
2284 AFSFcb *pFcb = NULL;
2285 AFSVolumeCB *pVolumeCB = NULL;
2286 AFSDeviceExt *pDevExt;
2287 AFSReleaseFileExtentsCB *pExtents;
2288 AFSReleaseFileExtentsResultCB *pResult = NULL;
2289 AFSReleaseFileExtentsResultFileCB *pFile = NULL;
2291 ULONGLONG ullIndex = 0;
2292 AFSObjectInfoCB *pObjectInfo = NULL;
2293 BOOLEAN bLocked = FALSE;
2294 BOOLEAN bDirtyExtents = FALSE;
2299 pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2301 pExtents = (AFSReleaseFileExtentsCB*) Irp->AssociatedIrp.SystemBuffer;
2303 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2304 sizeof( AFSReleaseFileExtentsCB))
2307 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2308 AFS_TRACE_LEVEL_ERROR,
2309 "AFSProcessReleaseFileExtents INPUT Buffer too small\n");
2311 try_return( ntStatus = STATUS_INVALID_PARAMETER );
2314 if ( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength <
2315 sizeof(AFSReleaseFileExtentsResultCB))
2318 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2319 AFS_TRACE_LEVEL_ERROR,
2320 "AFSProcessReleaseFileExtents OUTPUT Buffer too small [1]\n");
2323 // Must have space for one extent in one file
2326 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL);
2329 if (pExtents->ExtentCount == 0)
2332 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2333 AFS_TRACE_LEVEL_ERROR,
2334 "AFSProcessReleaseFileExtents Extent count zero\n");
2336 try_return( ntStatus = STATUS_INVALID_PARAMETER);
2339 if (pExtents->FileId.Cell != 0 ||
2340 pExtents->FileId.Volume != 0 ||
2341 pExtents->FileId.Vnode != 0 ||
2342 pExtents->FileId.Unique != 0)
2345 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2346 AFS_TRACE_LEVEL_VERBOSE,
2347 "AFSProcessReleaseFileExtents Processing FID %08lX:%08lX:%08lX:%08lX\n",
2348 pExtents->FileId.Cell,
2349 pExtents->FileId.Volume,
2350 pExtents->FileId.Vnode,
2351 pExtents->FileId.Unique);
2353 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2354 ( FIELD_OFFSET( AFSReleaseFileExtentsCB, ExtentCount) + sizeof(ULONG)) ||
2355 pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2356 ( FIELD_OFFSET( AFSReleaseFileExtentsCB, ExtentCount) + sizeof(ULONG) +
2357 sizeof (AFSFileExtentCB) * pExtents->ExtentCount))
2360 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2361 AFS_TRACE_LEVEL_ERROR,
2362 "AFSProcessReleaseFileExtents Buffer too small for FID %08lX:%08lx:%08lX:%08lX\n",
2363 pExtents->FileId.Cell,
2364 pExtents->FileId.Volume,
2365 pExtents->FileId.Vnode,
2366 pExtents->FileId.Unique);
2368 try_return( ntStatus = STATUS_INVALID_PARAMETER );
2371 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2372 AFS_TRACE_LEVEL_VERBOSE,
2373 "AFSProcessReleaseFileExtents Acquiring RDR VolumeTreeLock lock %08lX SHARED %08lX\n",
2374 &pDevExt->Specific.RDR.VolumeTreeLock,
2375 PsGetCurrentThread());
2377 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
2380 // Locate the volume node
2383 ullIndex = AFSCreateHighIndex( &pExtents->FileId);
2385 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
2387 (AFSBTreeEntry **)&pVolumeCB);
2389 if( pVolumeCB != NULL)
2392 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2393 AFS_TRACE_LEVEL_VERBOSE,
2394 "AFSProcessReleaseFileExtents Acquiring VolumeRoot FileIDTree.TreeLock lock %08lX SHARED %08lX\n",
2395 pVolumeCB->ObjectInfoTree.TreeLock,
2396 PsGetCurrentThread());
2398 InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
2401 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
2403 if( !NT_SUCCESS( ntStatus) ||
2407 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2408 AFS_TRACE_LEVEL_ERROR,
2409 "AFSProcessReleaseFileExtents Invalid volume index %I64X status %08X\n",
2410 ullIndex, ntStatus);
2412 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2415 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
2418 InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
2421 // Now locate the Object in this volume
2424 ullIndex = AFSCreateLowIndex( &pExtents->FileId);
2426 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
2428 (AFSBTreeEntry **)&pObjectInfo);
2430 if( pObjectInfo != NULL)
2434 // Reference the node so it won't be torn down
2437 InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
2439 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2440 AFS_TRACE_LEVEL_VERBOSE,
2441 "AFSProcessReleaseFileExtents Increment count on object %08lX Cnt %d\n",
2443 pObjectInfo->ObjectReferenceCount);
2446 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2448 if( !NT_SUCCESS( ntStatus) ||
2449 pObjectInfo == NULL)
2452 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2453 AFS_TRACE_LEVEL_ERROR,
2454 "AFSProcessReleaseFileExtents Invalid file index %I64X\n",
2457 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2460 pFcb = pObjectInfo->Fcb;
2465 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2466 AFS_TRACE_LEVEL_ERROR,
2467 "AFSProcessReleaseFileExtents Fcb not initialied (NO EXTENTS) for FID %08lX:%08lx:%08lX:%08lX\n",
2468 pExtents->FileId.Cell,
2469 pExtents->FileId.Volume,
2470 pExtents->FileId.Vnode,
2471 pExtents->FileId.Unique);
2473 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2476 AFSLockForExtentsTrim( pFcb );
2484 // Locate an Fcb to trim down
2487 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2488 AFS_TRACE_LEVEL_VERBOSE,
2489 "AFSProcessReleaseFileExtents Searching for a Fcb to Trim Down\n");
2491 pFcb = AFSFindFcbToClean( 0, NULL, FALSE);
2496 pFcb = AFSFindFcbToClean( 0, NULL, TRUE);
2502 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2503 AFS_TRACE_LEVEL_ERROR,
2504 "AFSProcessReleaseFileExtents Failed to locate Fcb for release ...\n");
2506 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2509 pObjectInfo = pFcb->ObjectInformation;
2515 // Allocate a scratch buffer to move in the extent information
2518 ulSz = (pExtents->ExtentCount-1) * sizeof(AFSFileExtentCB);
2519 ulSz += sizeof(AFSReleaseFileExtentsResultCB);
2521 if (ulSz > pIrpSp->Parameters.DeviceIoControl.OutputBufferLength)
2523 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2524 AFS_TRACE_LEVEL_ERROR,
2525 "AFSProcessReleaseFileExtents OUTPUT Buffer too small [2]\n");
2527 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL );
2530 pResult = (AFSReleaseFileExtentsResultCB*) AFSExAllocatePoolWithTag( PagedPool,
2532 AFS_EXTENTS_RESULT_TAG);
2533 if (NULL == pResult)
2536 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2537 AFS_TRACE_LEVEL_ERROR,
2538 "AFSProcessReleaseFileExtents Failed to allocate result block\n");
2540 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2544 // Set up the header (for an array of one)
2546 pResult->FileCount = 1;
2547 pResult->Flags = AFS_EXTENT_FLAG_RELEASE;
2548 ulSz -= FIELD_OFFSET(AFSReleaseFileExtentsResultCB, Files);
2551 // Setup the first (and only) file
2553 pFile = pResult->Files;
2554 pFile->FileId = pObjectInfo->FileId;
2555 pFile->Flags = AFS_EXTENT_FLAG_RELEASE;
2558 // Stash away the auth group
2561 RtlCopyMemory( &pFile->AuthGroup,
2566 // Update the metadata for this call
2569 pFile->AllocationSize = pFcb->ObjectInformation->EndOfFile;
2570 pFile->CreateTime = pFcb->ObjectInformation->CreationTime;
2571 pFile->ChangeTime = pFcb->ObjectInformation->ChangeTime;
2572 pFile->LastAccessTime = pFcb->ObjectInformation->LastAccessTime;
2573 pFile->LastWriteTime = pFcb->ObjectInformation->LastWriteTime;
2575 ulSz -= FIELD_OFFSET(AFSReleaseFileExtentsResultFileCB, FileExtents);
2577 ntStatus = AFSReleaseSpecifiedExtents( pExtents,
2581 &pFile->ExtentCount,
2584 if (!NT_SUCCESS(ntStatus))
2587 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2588 AFS_TRACE_LEVEL_ERROR,
2589 "AFSProcessReleaseFileExtents Failed to release extents Status %08lX\n",
2592 try_return( ntStatus );
2595 if( pExtents->ExtentCount == 0)
2598 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2599 AFS_TRACE_LEVEL_WARNING,
2600 "AFSProcessReleaseFileExtents Failed to release ANY extents\n");
2603 ulSz = sizeof(AFSReleaseFileExtentsResultCB);
2605 if( pExtents->ExtentCount > 0)
2607 ulSz += ((pExtents->ExtentCount-1) * sizeof(AFSFileExtentCB));
2610 RtlCopyMemory( Irp->AssociatedIrp.SystemBuffer,
2619 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2620 AFS_TRACE_LEVEL_VERBOSE,
2621 "AFSProcessReleaseFileExtents Releasing Fcb extent lock %08lX thread %08lX\n",
2622 &pFcb->NPFcb->Specific.File.ExtentsResource,
2623 PsGetCurrentThread());
2625 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
2628 if( NULL != pResult &&
2629 Irp->AssociatedIrp.SystemBuffer != pResult)
2632 AFSExFreePool(pResult);
2635 if (NT_SUCCESS(ntStatus))
2637 Irp->IoStatus.Information = ulSz;
2641 Irp->IoStatus.Information = 0;
2644 Irp->IoStatus.Status = ntStatus;
2646 if( pObjectInfo != NULL)
2649 InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
2651 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2652 AFS_TRACE_LEVEL_VERBOSE,
2653 "AFSProcessReleaseFileExtents Decrement count on object %08lX Cnt %d\n",
2655 pObjectInfo->ObjectReferenceCount);
2663 AFSWaitForExtentMapping( AFSFcb *Fcb )
2665 NTSTATUS ntStatus = STATUS_SUCCESS;
2666 LARGE_INTEGER liTimeOut;
2667 ULONGLONG ullProcessId = (ULONGLONG)PsGetCurrentProcessId();
2672 ASSERT( !ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
2674 if (!NT_SUCCESS( Fcb->NPFcb->Specific.File.ExtentsRequestStatus))
2678 // If this isn't the same process which caused the failure then try to request them again
2681 if( Fcb->Specific.File.ExtentRequestProcessId == ullProcessId)
2683 try_return( ntStatus = Fcb->NPFcb->Specific.File.ExtentsRequestStatus);
2686 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
2689 liTimeOut.QuadPart = -(50000000);
2691 ntStatus = KeWaitForSingleObject( &Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
2697 if (!NT_SUCCESS( Fcb->NPFcb->Specific.File.ExtentsRequestStatus))
2701 // If this isn't the same process which caused the failure
2702 // and this isn't the System process, then try to request them again
2705 if( Fcb->Specific.File.ExtentRequestProcessId == ullProcessId ||
2706 ullProcessId == 0x4)
2708 try_return( ntStatus = Fcb->NPFcb->Specific.File.ExtentsRequestStatus);
2711 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
2714 if( ntStatus == STATUS_TIMEOUT)
2717 ntStatus = STATUS_SUCCESS;
2729 AFSFlushExtents( IN AFSFcb *Fcb)
2731 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
2732 AFSExtent *pExtent, *pNextExtent;
2734 AFSReleaseExtentsCB *pRelease = NULL;
2736 ULONG initialDirtyCount = 0;
2737 BOOLEAN bExtentsLocked = FALSE;
2740 NTSTATUS ntStatus = STATUS_SUCCESS;
2741 LARGE_INTEGER liLastFlush;
2742 AFSExtent *pDirtyListHead = NULL, *pDirtyListTail = NULL;
2743 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2745 ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
2748 // Save, then reset the flush time
2751 liLastFlush = Fcb->Specific.File.LastServerFlush;
2753 KeQueryTickCount( &Fcb->Specific.File.LastServerFlush);
2759 // Lock extents while we count and set up the array to send to
2763 AFSLockForExtentsTrim( Fcb);
2765 bExtentsLocked = TRUE;
2767 InterlockedIncrement( &Fcb->Specific.File.QueuedFlushCount);
2770 // Clear our queued flush event
2773 KeClearEvent( &Fcb->NPFcb->Specific.File.QueuedFlushEvent);
2776 // Look for a start in the list to flush entries
2781 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
2783 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
2785 AFS_EXTENT_RELEASE_TAG);
2786 if( NULL == pRelease)
2789 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2792 initialDirtyCount = Fcb->Specific.File.ExtentsDirtyCount;
2794 while( Fcb->Specific.File.ExtentsDirtyCount > 0)
2797 pRelease->Flags = AFS_EXTENT_FLAG_DIRTY;
2799 if( BooleanFlagOn( Fcb->Flags, AFS_FCB_FILE_CLOSED))
2802 pRelease->Flags |= AFS_EXTENT_FLAG_FLUSH;
2806 // Update the metadata for this call
2809 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
2810 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
2811 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
2812 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
2813 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
2817 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
2820 pExtent = (AFSExtent *)pNPFcb->Specific.File.DirtyListHead;
2822 while( count < AFS_MAXIMUM_EXTENT_RELEASE_COUNT)
2825 if ( pExtent == NULL)
2831 pNextExtent = (AFSExtent *)pExtent->DirtyList.fLink;
2833 if ( pExtent->ActiveCount > 0)
2835 pExtent = pNextExtent;
2839 AFSRemoveEntryDirtyList( Fcb, pExtent);
2841 pExtent->DirtyList.fLink = NULL;
2842 pExtent->DirtyList.bLink = NULL;
2844 InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
2847 // Clear the flag in advance of the write. If we do
2848 // things this was we know that the clear is
2849 // pessimistic (any write which happens from now on
2850 // will set the flag dirty again).
2853 pExtent->Flags &= ~AFS_EXTENT_DIRTY;
2855 pRelease->FileExtents[count].Flags = AFS_EXTENT_FLAG_DIRTY;
2857 pRelease->FileExtents[count].Length = pExtent->Size;
2858 pRelease->FileExtents[count].DirtyLength = pExtent->Size;
2859 pRelease->FileExtents[count].DirtyOffset = 0;
2860 pRelease->FileExtents[count].CacheOffset = pExtent->CacheOffset;
2861 pRelease->FileExtents[count].FileOffset = pExtent->FileOffset;
2864 RtlCopyMemory( pRelease->FileExtents[count].MD5,
2866 sizeof(pExtent->MD5));
2868 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_MD5_SET;
2871 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2872 AFS_TRACE_LEVEL_VERBOSE,
2873 "AFSFlushExtents Releasing DIRTY extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
2875 Fcb->ObjectInformation->FileId.Cell,
2876 Fcb->ObjectInformation->FileId.Volume,
2877 Fcb->ObjectInformation->FileId.Vnode,
2878 Fcb->ObjectInformation->FileId.Unique,
2879 pExtent->FileOffset.QuadPart,
2882 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_RELEASE;
2885 // Need to pull this extent from the main list as well
2888 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
2890 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
2892 RemoveEntryList( &pExtent->Lists[i] );
2896 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
2898 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
2900 AFSExFreePool( pExtent);
2902 InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
2904 if( InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount) == 0)
2907 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
2914 pExtent = pNextExtent;
2917 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
2920 // If we are done then get out
2926 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2927 AFS_TRACE_LEVEL_VERBOSE,
2928 "AFSFlushExtents No more dirty extents found\n");
2934 // Fire off the request synchronously
2937 sz = sizeof( AFSReleaseExtentsCB ) + (count * sizeof ( AFSFileExtentCB ));
2939 pRelease->ExtentCount = count;
2941 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2942 AFS_TRACE_LEVEL_VERBOSE,
2943 "AFSFlushExtents Releasing(1) Fcb extents lock %08lX SHARED %08lX\n",
2944 &pNPFcb->Specific.File.ExtentsResource,
2945 PsGetCurrentThread());
2947 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource);
2948 bExtentsLocked = FALSE;
2950 KeSetEvent( &pNPFcb->Specific.File.FlushEvent,
2954 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
2955 AFS_REQUEST_FLAG_SYNCHRONOUS,
2958 &Fcb->ObjectInformation->FileId,
2964 if( !NT_SUCCESS(ntStatus))
2968 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
2969 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
2972 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2973 AFS_TRACE_LEVEL_ERROR,
2974 "AFSFlushExtents AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2975 Fcb->ObjectInformation->FileId.Cell,
2976 Fcb->ObjectInformation->FileId.Volume,
2977 Fcb->ObjectInformation->FileId.Vnode,
2978 Fcb->ObjectInformation->FileId.Unique,
2982 AFSLockForExtentsTrim( Fcb);
2984 bExtentsLocked = TRUE;
2989 if( InterlockedDecrement( &Fcb->Specific.File.QueuedFlushCount) == 0)
2992 KeSetEvent( &pNPFcb->Specific.File.QueuedFlushEvent,
2997 KeSetEvent( &pNPFcb->Specific.File.FlushEvent,
3004 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3005 AFS_TRACE_LEVEL_VERBOSE,
3006 "AFSFlushExtents Releasing(2) Fcb extents lock %08lX SHARED %08lX\n",
3007 &pNPFcb->Specific.File.ExtentsResource,
3008 PsGetCurrentThread());
3010 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
3015 AFSExFreePool( pRelease);
3023 AFSReleaseExtentsWithFlush( IN AFSFcb *Fcb)
3025 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3028 AFSReleaseExtentsCB *pRelease = NULL;
3030 ULONG initialDirtyCount = 0;
3031 BOOLEAN bExtentsLocked = FALSE;
3034 NTSTATUS ntStatus = STATUS_SUCCESS;
3035 LARGE_INTEGER liLastFlush;
3036 ULONG ulRemainingExtentLength = 0;
3037 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3039 ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
3042 // Save, then reset the flush time
3045 liLastFlush = Fcb->Specific.File.LastServerFlush;
3047 KeQueryTickCount( &Fcb->Specific.File.LastServerFlush);
3053 // Look for a start in the list to flush entries
3058 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
3060 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
3062 AFS_EXTENT_RELEASE_TAG);
3063 if( NULL == pRelease)
3066 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
3069 if( Fcb->OpenHandleCount > 0)
3073 // Don't release everything ...
3077 // For now release everything
3080 //ulRemainingExtentLength = 1500;
3083 while( Fcb->Specific.File.ExtentLength > (LONG)ulRemainingExtentLength)
3086 AFSLockForExtentsTrim( Fcb);
3088 bExtentsLocked = TRUE;
3090 pRelease->Flags = AFS_EXTENT_FLAG_RELEASE;
3093 // Update the metadata for this call
3096 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
3097 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
3098 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
3099 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
3100 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
3104 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3106 while( count < AFS_MAXIMUM_EXTENT_RELEASE_COUNT &&
3107 le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
3110 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3114 if( pExtent->ActiveCount > 0)
3120 pRelease->FileExtents[count].Flags = AFS_EXTENT_FLAG_RELEASE;
3122 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3123 AFS_TRACE_LEVEL_VERBOSE,
3124 "AFSReleaseExtentsWithFlush Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3126 Fcb->ObjectInformation->FileId.Cell,
3127 Fcb->ObjectInformation->FileId.Volume,
3128 Fcb->ObjectInformation->FileId.Vnode,
3129 Fcb->ObjectInformation->FileId.Unique,
3130 pExtent->FileOffset.QuadPart,
3133 pRelease->FileExtents[count].Length = pExtent->Size;
3134 pRelease->FileExtents[count].DirtyLength = pExtent->Size;
3135 pRelease->FileExtents[count].DirtyOffset = 0;
3136 pRelease->FileExtents[count].CacheOffset = pExtent->CacheOffset;
3137 pRelease->FileExtents[count].FileOffset = pExtent->FileOffset;
3140 RtlCopyMemory( pRelease->FileExtents[count].MD5,
3142 sizeof(pExtent->MD5));
3144 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_MD5_SET;
3147 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3150 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3153 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3156 AFSRemoveEntryDirtyList( Fcb,
3159 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_DIRTY;
3161 InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
3164 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3168 // Need to pull this extent from the main list as well
3171 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
3173 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
3175 RemoveEntryList( &pExtent->Lists[i] );
3179 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
3181 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
3183 AFSExFreePool( pExtent);
3185 InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
3187 if( InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount) == 0)
3190 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
3199 // If we are done then get out
3205 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3206 AFS_TRACE_LEVEL_VERBOSE,
3207 "AFSReleaseExtentsWithFlush No more dirty extents found\n");
3213 // Fire off the request synchronously
3216 sz = sizeof( AFSReleaseExtentsCB ) + (count * sizeof ( AFSFileExtentCB ));
3218 pRelease->ExtentCount = count;
3221 // Drop the extents lock for the duration of the call to
3222 // the network. We have pinned the extents so, even
3223 // though we might get extents added during this period,
3224 // but none will be removed. Hence we can carry on from
3228 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3229 AFS_TRACE_LEVEL_VERBOSE,
3230 "AFSReleaseExtentsWithFlush Releasing Fcb extents lock %08lX thread %08lX\n",
3231 &pNPFcb->Specific.File.ExtentsResource,
3232 PsGetCurrentThread());
3234 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource);
3235 bExtentsLocked = FALSE;
3237 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
3238 AFS_REQUEST_FLAG_SYNCHRONOUS,
3241 &Fcb->ObjectInformation->FileId,
3247 if( !NT_SUCCESS(ntStatus))
3251 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
3252 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
3255 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3256 AFS_TRACE_LEVEL_ERROR,
3257 "AFSReleaseExtentsWithFlush AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3258 Fcb->ObjectInformation->FileId.Cell,
3259 Fcb->ObjectInformation->FileId.Volume,
3260 Fcb->ObjectInformation->FileId.Vnode,
3261 Fcb->ObjectInformation->FileId.Unique,
3271 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3272 AFS_TRACE_LEVEL_VERBOSE,
3273 "AFSReleaseExtentsWithFlush Releasing Fcb extents lock %08lX thread %08lX\n",
3274 &pNPFcb->Specific.File.ExtentsResource,
3275 PsGetCurrentThread());
3277 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
3282 AFSExFreePool( pRelease);
3290 AFSMarkDirty( IN AFSFcb *Fcb,
3291 IN AFSExtent *StartExtent,
3292 IN ULONG ExtentsCount,
3293 IN LARGE_INTEGER *StartingByte)
3296 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3297 AFSExtent *pExtent = StartExtent;
3298 AFSExtent *pNextExtent, *pCurrentExtent = NULL;
3300 BOOLEAN bInsertTail = FALSE, bInsertHead = FALSE;
3302 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3303 AFS_TRACE_LEVEL_VERBOSE,
3304 "AFSMarkDirty Acquiring Fcb extents lock %08lX SHARED %08lX\n",
3305 &Fcb->NPFcb->Specific.File.ExtentsResource,
3306 PsGetCurrentThread());
3308 AFSAcquireShared( &Fcb->NPFcb->Specific.File.ExtentsResource, TRUE);
3310 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3314 // Find the insertion point
3317 if( pNPFcb->Specific.File.DirtyListHead == NULL)
3322 else if( StartingByte->QuadPart == 0)
3330 pCurrentExtent = pNPFcb->Specific.File.DirtyListHead;
3332 while( pCurrentExtent != NULL)
3335 if( pCurrentExtent->FileOffset.QuadPart + pCurrentExtent->Size >= StartingByte->QuadPart ||
3336 pCurrentExtent->DirtyList.fLink == NULL)
3342 pCurrentExtent = (AFSExtent *)pCurrentExtent->DirtyList.fLink;
3346 while( ulCount < ExtentsCount)
3349 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
3351 if( !BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3354 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3355 AFS_TRACE_LEVEL_VERBOSE,
3356 "AFSMarkDirty Marking extent offset %I64X Length %08lX DIRTY\n",
3357 pExtent->FileOffset.QuadPart,
3360 pExtent->DirtyList.fLink = NULL;
3361 pExtent->DirtyList.bLink = NULL;
3366 pExtent->DirtyList.fLink = (void *)pNPFcb->Specific.File.DirtyListHead;
3368 pExtent->DirtyList.bLink = NULL;
3370 pNPFcb->Specific.File.DirtyListHead->DirtyList.bLink = (void *)pExtent;
3372 pNPFcb->Specific.File.DirtyListHead = pExtent;
3374 pCurrentExtent = pExtent;
3376 bInsertHead = FALSE;
3378 else if( bInsertTail)
3381 if( pNPFcb->Specific.File.DirtyListHead == NULL)
3384 pNPFcb->Specific.File.DirtyListHead = pExtent;
3389 pNPFcb->Specific.File.DirtyListTail->DirtyList.fLink = (void *)pExtent;
3391 pExtent->DirtyList.bLink = (void *)pNPFcb->Specific.File.DirtyListTail;
3394 pNPFcb->Specific.File.DirtyListTail = pExtent;
3399 pExtent->DirtyList.fLink = pCurrentExtent->DirtyList.fLink;
3400 pExtent->DirtyList.bLink = (void *)pCurrentExtent;
3402 if( pExtent->DirtyList.fLink == NULL)
3405 pNPFcb->Specific.File.DirtyListTail = pExtent;
3410 ((AFSExtent *)pExtent->DirtyList.fLink)->DirtyList.bLink = (void *)pExtent;
3413 pCurrentExtent->DirtyList.fLink = (void *)pExtent;
3415 pCurrentExtent = pExtent;
3418 pExtent->Flags |= AFS_EXTENT_DIRTY;
3421 // Up the dirty count
3424 InterlockedIncrement( &Fcb->Specific.File.ExtentsDirtyCount);
3429 pCurrentExtent = pExtent;
3432 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_ACTIVE_COUNTING,
3433 AFS_TRACE_LEVEL_VERBOSE,
3434 "AFSMarkDirty Decrement count on extent %08lX Cnt %d\n",
3436 pExtent->ActiveCount);
3438 ASSERT( pExtent->ActiveCount > 0);
3440 InterlockedDecrement( &pExtent->ActiveCount);
3442 pExtent = pNextExtent;
3447 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3449 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3450 AFS_TRACE_LEVEL_VERBOSE,
3451 "AFSMarkDirty Releasing Fcb extents lock %08lX SHARED %08lX\n",
3452 &Fcb->NPFcb->Specific.File.ExtentsResource,
3453 PsGetCurrentThread());
3455 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
3464 static AFSExtent *ExtentFor(PLIST_ENTRY le, ULONG SkipList)
3466 return CONTAINING_RECORD( le, AFSExtent, Lists[SkipList] );
3469 static AFSExtent *NextExtent(AFSExtent *Extent, ULONG SkipList)
3471 return ExtentFor(Extent->Lists[SkipList].Flink, SkipList);
3474 static AFSExtent *DirtyExtentFor(PLIST_ENTRY le)
3476 return CONTAINING_RECORD( le, AFSExtent, DirtyList );
3479 static VOID VerifyExtentsLists(AFSFcb *Fcb)
3483 // Check the ordering of the extents lists
3485 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
3487 ASSERT(Fcb->Specific.File.ExtentsLists[0].Flink != &Fcb->Specific.File.ExtentsLists[1]);
3489 for (ULONG listNo = 0; listNo < AFS_NUM_EXTENT_LISTS; listNo ++)
3491 LARGE_INTEGER lastOffset;
3493 lastOffset.QuadPart = 0;
3495 for (PLIST_ENTRY pLe = Fcb->Specific.File.ExtentsLists[listNo].Flink;
3496 pLe != &Fcb->Specific.File.ExtentsLists[listNo];
3501 pExtent = ExtentFor(pLe, listNo);
3504 ASSERT(pLe != &Fcb->Specific.File.ExtentsLists[1] &&
3505 pLe->Flink !=&Fcb->Specific.File.ExtentsLists[1] &&
3506 pLe->Blink !=&Fcb->Specific.File.ExtentsLists[1]);
3509 ASSERT(pLe->Flink->Blink == pLe);
3510 ASSERT(pLe->Blink->Flink == pLe);
3513 // Should follow on from previous
3515 ASSERT(pExtent->FileOffset.QuadPart >= lastOffset.QuadPart);
3516 lastOffset.QuadPart = pExtent->FileOffset.QuadPart + pExtent->Size;
3519 // Should match alignment criteria
3521 ASSERT( 0 == (pExtent->FileOffset.LowPart & ExtentsMasks[listNo]) );
3524 // "lower" lists should be populated
3526 for (LONG subListNo = listNo-1; subListNo > 0; subListNo --)
3528 ASSERT( !IsListEmpty(&pExtent->Lists[subListNo]));
3536 AFSTrimExtents( IN AFSFcb *Fcb,
3537 IN PLARGE_INTEGER FileSize)
3540 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3543 BOOLEAN locked = FALSE;
3544 NTSTATUS ntStatus = STATUS_SUCCESS;
3545 LARGE_INTEGER liAlignedOffset = {0,0};
3546 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
3547 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3553 // Get an aligned offset
3556 if( FileSize != NULL)
3559 liAlignedOffset = *FileSize;
3562 if( liAlignedOffset.QuadPart > 0 &&
3563 liAlignedOffset.QuadPart % pDevExt->Specific.RDR.CacheBlockSize != 0)
3567 // Align UP to the next cache block size
3570 liAlignedOffset.QuadPart = (ULONGLONG)( (ULONGLONG)((liAlignedOffset.QuadPart / pDevExt->Specific.RDR.CacheBlockSize) + 1) * (ULONGLONG)pDevExt->Specific.RDR.CacheBlockSize);
3574 // Ensure that no one is working with the extents and grab the
3578 AFSLockForExtentsTrim( Fcb);
3582 if( 0 == Fcb->Specific.File.ExtentCount)
3586 // Update the request extent status
3589 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
3591 try_return( ntStatus = STATUS_SUCCESS);
3595 // We are truncating from a specific length in the file. If the offset
3596 // is non-zero then go find the first extent to remove
3599 if( 0 == FileSize->QuadPart)
3602 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3607 pExtent = AFSExtentForOffset( Fcb,
3611 if( NULL == pExtent)
3614 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3618 le = &pExtent->Lists[AFS_EXTENTS_LIST];
3622 while( le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
3625 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3628 // Only trim down extents beyond the aligned offset
3633 if( pExtent->FileOffset.QuadPart >= liAlignedOffset.QuadPart)
3636 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3639 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3642 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3646 AFSRemoveEntryDirtyList( Fcb,
3649 dirtyCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
3651 ASSERT(dirtyCount >= 0);
3654 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3657 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
3659 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
3661 RemoveEntryList( &pExtent->Lists[i] );
3665 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3666 AFS_TRACE_LEVEL_VERBOSE,
3667 "AFSTrimExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3669 Fcb->ObjectInformation->FileId.Cell,
3670 Fcb->ObjectInformation->FileId.Volume,
3671 Fcb->ObjectInformation->FileId.Vnode,
3672 Fcb->ObjectInformation->FileId.Unique,
3673 pExtent->FileOffset.QuadPart,
3676 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
3678 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
3680 ASSERT( pExtent->ActiveCount == 0);
3685 AFSExFreePool( pExtent);
3687 InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
3689 if( InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount) == 0)
3692 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
3700 // Update the request extent status
3703 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
3710 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3711 AFS_TRACE_LEVEL_VERBOSE,
3712 "AFSTrimExtents Releasing Fcb extents lock %08lX thread %08lX\n",
3713 &Fcb->NPFcb->Specific.File.ExtentsResource,
3714 PsGetCurrentThread());
3716 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
3724 AFSTrimSpecifiedExtents( IN AFSFcb *Fcb,
3726 IN AFSFileExtentCB *Result)
3729 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3732 AFSFileExtentCB *pFileExtents = Result;
3733 NTSTATUS ntStatus = STATUS_SUCCESS;
3734 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
3735 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3740 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3742 while( le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST] &&
3746 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3749 // Only trim down extents beyond the aligned offset
3754 if( pExtent->FileOffset.QuadPart == pFileExtents->FileOffset.QuadPart)
3757 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3760 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3763 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3768 AFSRemoveEntryDirtyList( Fcb,
3771 dirtyCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
3773 ASSERT( dirtyCount >= 0);
3777 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3781 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
3783 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
3785 RemoveEntryList( &pExtent->Lists[i] );
3789 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3790 AFS_TRACE_LEVEL_VERBOSE,
3791 "AFSTrimSpecifiedExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3793 Fcb->ObjectInformation->FileId.Cell,
3794 Fcb->ObjectInformation->FileId.Volume,
3795 Fcb->ObjectInformation->FileId.Vnode,
3796 Fcb->ObjectInformation->FileId.Unique,
3797 pExtent->FileOffset.QuadPart,
3800 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
3802 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
3804 ASSERT( pExtent->ActiveCount == 0);
3809 AFSExFreePool( pExtent);
3811 InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
3813 if( InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount) == 0)
3816 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
3822 // Next extent we are looking for
3832 // Update the request extent status
3835 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
3842 AFSReferenceActiveExtents( IN AFSExtent *StartExtent,
3843 IN ULONG ExtentsCount)
3846 AFSExtent *pExtent = StartExtent;
3847 AFSExtent *pNextExtent;
3850 while( ulCount < ExtentsCount)
3853 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
3855 InterlockedIncrement( &pExtent->ActiveCount);
3857 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_ACTIVE_COUNTING,
3858 AFS_TRACE_LEVEL_VERBOSE,
3859 "AFSReferenceActiveExtents Increment count on extent %08lX Cnt %d\n",
3861 pExtent->ActiveCount);
3863 pExtent = pNextExtent;
3872 AFSDereferenceActiveExtents( IN AFSExtent *StartExtent,
3873 IN ULONG ExtentsCount)
3876 AFSExtent *pExtent = StartExtent;
3877 AFSExtent *pNextExtent;
3880 while( ulCount < ExtentsCount)
3883 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
3885 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_ACTIVE_COUNTING,
3886 AFS_TRACE_LEVEL_VERBOSE,
3887 "AFSDereferenceActiveExtents Decrement count on extent %08lX Cnt %d\n",
3889 pExtent->ActiveCount);
3891 ASSERT( pExtent->ActiveCount > 0);
3893 InterlockedDecrement( &pExtent->ActiveCount);
3895 pExtent = pNextExtent;
3904 AFSRemoveEntryDirtyList( IN AFSFcb *Fcb,
3905 IN AFSExtent *Extent)
3908 if( Extent->DirtyList.fLink == NULL)
3911 Fcb->NPFcb->Specific.File.DirtyListTail = (AFSExtent *)Extent->DirtyList.bLink;
3913 if( Fcb->NPFcb->Specific.File.DirtyListTail != NULL)
3916 Fcb->NPFcb->Specific.File.DirtyListTail->DirtyList.fLink = NULL;
3922 ((AFSExtent *)Extent->DirtyList.fLink)->DirtyList.bLink = Extent->DirtyList.bLink;
3925 if( Extent->DirtyList.bLink == NULL)
3928 Fcb->NPFcb->Specific.File.DirtyListHead = (AFSExtent *)Extent->DirtyList.fLink;
3930 if( Fcb->NPFcb->Specific.File.DirtyListHead != NULL)
3933 Fcb->NPFcb->Specific.File.DirtyListHead->DirtyList.bLink = NULL;
3939 ((AFSExtent *)Extent->DirtyList.bLink)->DirtyList.fLink = Extent->DirtyList.fLink;
3948 AFSSetupMD5Hash( IN AFSFcb *Fcb,
3949 IN AFSExtent *StartExtent,
3950 IN ULONG ExtentsCount,
3951 IN void *SystemBuffer,
3952 IN LARGE_INTEGER *ByteOffset,
3956 NTSTATUS ntStatus = STATUS_SUCCESS;
3957 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3958 AFSExtent *pExtent = StartExtent;
3959 AFSExtent *pNextExtent, *pCurrentExtent = NULL;
3961 char *pCurrentBuffer = (char *)SystemBuffer;
3962 char *pMD5Buffer = NULL;
3963 ULONG ulCurrentLen = 0;
3964 void *pExtentBuffer = NULL;
3965 LARGE_INTEGER liByteOffset;
3966 ULONG ulBytesRead = 0;
3971 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3972 AFS_TRACE_LEVEL_VERBOSE,
3973 "AFSSetupMD5Hash Acquiring Fcb extents lock %08lX SHARED %08lX\n",
3974 &Fcb->NPFcb->Specific.File.ExtentsResource,
3975 PsGetCurrentThread());
3977 AFSAcquireShared( &Fcb->NPFcb->Specific.File.ExtentsResource, TRUE);
3979 liByteOffset.QuadPart = ByteOffset->QuadPart;
3981 while( ulCount < ExtentsCount)
3984 RtlZeroMemory( pExtent->MD5,
3985 sizeof( pExtent->MD5));
3987 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
3989 if( liByteOffset.QuadPart == pExtent->FileOffset.QuadPart &&
3990 ByteCount < pExtent->Size)
3993 if( pExtentBuffer == NULL)
3996 pExtentBuffer = AFSExAllocatePoolWithTag( PagedPool,
3998 AFS_GENERIC_MEMORY_9_TAG);
4000 if( pExtentBuffer == NULL)
4007 RtlZeroMemory( pExtentBuffer,
4010 RtlCopyMemory( pExtentBuffer,
4014 pMD5Buffer = (char *)pExtentBuffer;
4016 ulCurrentLen = ByteCount;
4018 else if( liByteOffset.QuadPart != pExtent->FileOffset.QuadPart)
4021 pExtentBuffer = AFSExAllocatePoolWithTag( PagedPool,
4023 AFS_GENERIC_MEMORY_10_TAG);
4025 if( pExtentBuffer == NULL)
4031 RtlZeroMemory( pExtentBuffer,
4034 if( BooleanFlagOn( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE))
4038 RtlCopyMemory( pExtentBuffer,
4039 ((char *)AFSLibCacheBaseAddress + pExtent->CacheOffset.QuadPart),
4042 ASSERT( pExtent->CacheOffset.HighPart == 0);
4043 RtlCopyMemory( pExtentBuffer,
4044 ((char *)AFSLibCacheBaseAddress + pExtent->CacheOffset.LowPart),
4048 ulBytesRead = pExtent->Size;
4053 ntStatus = AFSReadCacheFile( pExtentBuffer,
4054 &pExtent->CacheOffset,
4058 if( !NT_SUCCESS( ntStatus))
4064 pMD5Buffer = (char *)pExtentBuffer;
4066 ulCurrentLen = min( ByteCount, pExtent->Size - (ULONG)(liByteOffset.QuadPart - pExtent->FileOffset.QuadPart));
4068 RtlCopyMemory( (void *)((char *)pExtentBuffer + (ULONG)(liByteOffset.QuadPart - pExtent->FileOffset.QuadPart)),
4075 ulCurrentLen = pExtent->Size;
4077 pMD5Buffer = pCurrentBuffer;
4080 AFSGenerateMD5( pMD5Buffer,
4084 pExtent = pNextExtent;
4088 ByteCount -= ulCurrentLen;
4090 pCurrentBuffer += ulCurrentLen;
4092 liByteOffset.QuadPart += ulCurrentLen;
4095 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4096 AFS_TRACE_LEVEL_VERBOSE,
4097 "AFSSetupMD5Hash Releasing Fcb extents lock %08lX SHARED %08lX\n",
4098 &Fcb->NPFcb->Specific.File.ExtentsResource,
4099 PsGetCurrentThread());
4101 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
4103 if( pExtentBuffer != NULL)
4106 AFSExFreePool( pExtentBuffer);