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,
112 BOOLEAN bFoundExtents = FALSE;
113 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
116 ULONG ulCount = 0, ulReleaseCount = 0, ulProcessCount = 0;
118 AFSReleaseExtentsCB *pRelease = NULL;
119 BOOLEAN locked = FALSE;
121 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
122 GUID *pAuthGroup = AuthGroup;
128 if( pAuthGroup == NULL)
131 RtlZeroMemory( &stAuthGroup,
134 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
139 if( !NT_SUCCESS( ntStatus))
141 try_return( ntStatus);
144 pAuthGroup = &stAuthGroup;
148 // Ensure that no one is working with the extents and grab the
152 AFSLockForExtentsTrim( Fcb );
156 if (0 == Fcb->Specific.File.ExtentCount)
158 try_return ( ntStatus = STATUS_SUCCESS);
162 // Release a max of 100 extents at a time
165 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
167 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
169 AFS_EXTENT_RELEASE_TAG);
170 if (NULL == pRelease)
173 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
176 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
178 ulCount = Fcb->Specific.File.ExtentCount;
180 while( ulReleaseCount < ulCount)
183 bFoundExtents = TRUE;
185 RtlZeroMemory( pRelease,
186 sizeof( AFSReleaseExtentsCB ) +
187 (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB )));
189 if( ulCount - ulReleaseCount <= AFS_MAXIMUM_EXTENT_RELEASE_COUNT)
191 ulProcessCount = ulCount - ulReleaseCount;
195 ulProcessCount = AFS_MAXIMUM_EXTENT_RELEASE_COUNT;
198 pRelease->Flags = AFS_EXTENT_FLAG_RELEASE;
199 pRelease->ExtentCount = ulProcessCount;
202 // Update the metadata for this call
205 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
206 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
207 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
208 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
209 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
213 while (ulProcessCount < pRelease->ExtentCount)
215 pEntry = ExtentFor( le, AFS_EXTENTS_LIST );
217 pRelease->FileExtents[ulProcessCount].Flags = AFS_EXTENT_FLAG_RELEASE;
220 RtlCopyMemory( pRelease->FileExtents[ulProcessCount].MD5,
222 sizeof(pEntry->MD5));
224 pRelease->FileExtents[ulProcessCount].Flags |= AFS_EXTENT_FLAG_MD5_SET;
227 if( BooleanFlagOn( pEntry->Flags, AFS_EXTENT_DIRTY))
230 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
233 if( BooleanFlagOn( pEntry->Flags, AFS_EXTENT_DIRTY))
238 AFSRemoveEntryDirtyList( Fcb,
241 pRelease->FileExtents[ulProcessCount].Flags |= AFS_EXTENT_FLAG_DIRTY;
243 dirtyCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
245 ASSERT( dirtyCount >= 0);
248 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
251 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
252 AFS_TRACE_LEVEL_VERBOSE,
253 "AFSTearDownFcbExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %08lX-%08lX Len %08lX\n",
255 Fcb->ObjectInformation->FileId.Cell,
256 Fcb->ObjectInformation->FileId.Volume,
257 Fcb->ObjectInformation->FileId.Vnode,
258 Fcb->ObjectInformation->FileId.Unique,
259 pEntry->FileOffset.HighPart,
260 pEntry->FileOffset.LowPart,
263 pRelease->FileExtents[ulProcessCount].Length = pEntry->Size;
264 pRelease->FileExtents[ulProcessCount].DirtyLength = pEntry->Size;
265 pRelease->FileExtents[ulProcessCount].DirtyOffset = 0;
266 pRelease->FileExtents[ulProcessCount].CacheOffset = pEntry->CacheOffset;
267 pRelease->FileExtents[ulProcessCount].FileOffset = pEntry->FileOffset;
269 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pEntry->Size/1024)));
271 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pEntry->Size/1024)));
273 ASSERT( pEntry->ActiveCount == 0);
277 AFSExFreePool( pEntry);
279 InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
281 if( InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount) == 0)
284 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
291 // Send the request down. We cannot send this down
292 // asynchronously - if we did that we could request them
293 // back before the service got this request and then this
294 // request would be a corruption.
297 sz = sizeof( AFSReleaseExtentsCB ) + (ulProcessCount * sizeof ( AFSFileExtentCB ));
299 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
300 AFS_REQUEST_FLAG_SYNCHRONOUS,
303 &Fcb->ObjectInformation->FileId,
309 if( !NT_SUCCESS(ntStatus))
313 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
314 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
317 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
318 AFS_TRACE_LEVEL_ERROR,
319 "AFSTearDownFcbExtents AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
320 Fcb->ObjectInformation->FileId.Cell,
321 Fcb->ObjectInformation->FileId.Volume,
322 Fcb->ObjectInformation->FileId.Vnode,
323 Fcb->ObjectInformation->FileId.Unique,
328 ulReleaseCount += ulProcessCount;
332 // Reinitialize the skip lists
335 ASSERT( Fcb->Specific.File.ExtentCount == 0);
337 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i++)
339 InitializeListHead(&Fcb->Specific.File.ExtentsLists[i]);
343 // Reinitialize the dirty list as well
346 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
349 ASSERT( Fcb->Specific.File.ExtentsDirtyCount == 0);
351 Fcb->NPFcb->Specific.File.DirtyListHead = NULL;
352 Fcb->NPFcb->Specific.File.DirtyListTail = NULL;
354 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
356 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
363 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
364 AFS_TRACE_LEVEL_VERBOSE,
365 "AFSTearDownFcbExtents Releasing Fcb extent lock %08lX thread %08lX\n",
366 &Fcb->NPFcb->Specific.File.ExtentsResource,
367 PsGetCurrentThread());
369 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
375 AFSExFreePool( pRelease);
379 return bFoundExtents;
383 ExtentForOffsetInList( IN AFSFcb *Fcb,
386 IN PLARGE_INTEGER Offset)
389 // Return the extent that maps the offset, that
390 // - Contains the offset
391 // - or is immediately ahead of the offset (in this list)
392 // - otherwise return NULL.
395 PLIST_ENTRY pLe = List;
396 AFSExtent *pPrevious = NULL;
398 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
400 while (pLe != &Fcb->Specific.File.ExtentsLists[ListNumber])
404 entry = ExtentFor( pLe, ListNumber );
411 if (Offset->QuadPart < entry->FileOffset.QuadPart)
414 // Offset is ahead of entry. Return previous
419 if (Offset->QuadPart >= (entry->FileOffset.QuadPart + entry->Size))
422 // We start after this extent - carry on round
430 // Otherwise its a match
437 // Got to the end. Return Previous
443 AFSExtentContains( IN AFSExtent *Extent, IN PLARGE_INTEGER Offset)
449 return (Extent->FileOffset.QuadPart <= Offset->QuadPart &&
450 (Extent->FileOffset.QuadPart + Extent->Size) > Offset->QuadPart);
455 // Return the extent that contains the offset
458 AFSExtentForOffsetHint( IN AFSFcb *Fcb,
459 IN PLARGE_INTEGER Offset,
460 IN BOOLEAN ReturnPrevious,
463 AFSExtent *pPrevious = Hint;
467 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
469 #if AFS_VALIDATE_EXTENTS
470 VerifyExtentsLists(Fcb);
474 // So we will go across the skip lists until we find an
475 // appropriate entry (previous or direct match). If it's a match
476 // we are done, other wise we start on the next layer down
478 for (i = AFS_NUM_EXTENT_LISTS-1; i >= AFS_EXTENTS_LIST; i--)
480 if (NULL == pPrevious)
483 // We haven't found anything in the previous layers
485 pLe = Fcb->Specific.File.ExtentsLists[i].Flink;
487 else if (NULL == pPrevious->Lists[i].Flink)
489 ASSERT(AFS_EXTENTS_LIST != i);
491 // The hint doesn't exist at this level, next one down
498 // take the previous into the next
500 pLe = &pPrevious->Lists[i];
503 pPrevious = ExtentForOffsetInList( Fcb, pLe, i, Offset);
505 if (NULL != pPrevious && AFSExtentContains(pPrevious, Offset))
508 // Found it immediately. Stop here
514 if (NULL == pPrevious || ReturnPrevious )
519 ASSERT( !AFSExtentContains(pPrevious, Offset) );
525 AFSEntryForOffset( IN AFSFcb *Fcb,
526 IN PLARGE_INTEGER Offset)
528 AFSExtent *pPrevious = NULL;
532 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
534 #if AFS_VALIDATE_EXTENTS
535 VerifyExtentsLists(Fcb);
539 // So we will go across the skip lists until we find an
540 // appropriate entry (previous or direct match). If it's a match
541 // we are done, other wise we start on the next layer down
543 for (i = AFS_NUM_EXTENT_LISTS-1; i >= AFS_EXTENTS_LIST; i--)
545 if (NULL == pPrevious)
548 // We haven't found anything in the previous layers
550 pLe = Fcb->Specific.File.ExtentsLists[i].Flink;
552 else if (NULL == pPrevious->Lists[i].Flink)
554 ASSERT(AFS_EXTENTS_LIST != i);
556 // The hint doesn't exist at this level, next one down
563 // take the previous into the next
565 pLe = &pPrevious->Lists[i];
568 pPrevious = ExtentForOffsetInList( Fcb, pLe, i, Offset);
570 if (NULL != pPrevious && AFSExtentContains(pPrevious, Offset))
573 // Found it immediately. Stop here
583 AFSExtentForOffset( IN AFSFcb *Fcb,
584 IN PLARGE_INTEGER Offset,
585 IN BOOLEAN ReturnPrevious)
587 return AFSExtentForOffsetHint(Fcb, Offset, ReturnPrevious, NULL);
591 BOOLEAN AFSDoExtentsMapRegion(IN AFSFcb *Fcb,
592 IN PLARGE_INTEGER Offset,
594 IN OUT AFSExtent **FirstExtent,
595 OUT AFSExtent **LastExtent)
598 // Return TRUE region is completely mapped. FALSE
599 // otherwise. If the region isn't mapped then the last
600 // extent to map part of the region is returned.
602 // *LastExtent as input is where to start looking.
603 // *LastExtent as output is either the extent which
604 // contains the Offset, or the last one which doesn't
608 BOOLEAN retVal = FALSE;
613 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
614 AFS_TRACE_LEVEL_VERBOSE,
615 "AFSDoExtentsMapRegion Acquiring Fcb extent lock %08lX SHARED %08lX\n",
616 &Fcb->NPFcb->Specific.File.ExtentsResource,
617 PsGetCurrentThread());
619 AFSAcquireShared( &Fcb->NPFcb->Specific.File.ExtentsResource, TRUE );
621 entry = AFSExtentForOffsetHint(Fcb, Offset, TRUE, *FirstExtent);
622 *FirstExtent = entry;
624 if (NULL == entry || !AFSExtentContains(entry, Offset))
626 try_return (retVal = FALSE);
629 ASSERT(Offset->QuadPart >= entry->FileOffset.QuadPart);
633 if ((entry->FileOffset.QuadPart + entry->Size) >=
634 (Offset->QuadPart + Size))
637 // The end is inside the extent
639 try_return (retVal = TRUE);
642 if (entry->Lists[AFS_EXTENTS_LIST].Flink == &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
645 // Run out of extents
647 try_return (retVal = FALSE);
650 newEntry = NextExtent( entry, AFS_EXTENTS_LIST );
652 if (newEntry->FileOffset.QuadPart !=
653 (entry->FileOffset.QuadPart + entry->Size))
658 try_return (retVal = FALSE);
666 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
667 AFS_TRACE_LEVEL_VERBOSE,
668 "AFSDoExtentsMapRegion Releasing Fcb extent lock %08lX SHARED %08lX\n",
669 &Fcb->NPFcb->Specific.File.ExtentsResource,
670 PsGetCurrentThread());
672 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
681 // Given an FCB and an Offset we look to see whether there extents to
682 // Map them all. If there are then we return TRUE to fullymapped
683 // and *FirstExtent points to the first extent to map the extent.
684 // If not then we return FALSE, but we request the extents to be mapped.
685 // Further *FirstExtent (if non null) is the last extent which doesn't
688 // Finally on the way *in* if *FirstExtent is non null it is where we start looking
692 AFSRequestExtents( IN AFSFcb *Fcb,
694 IN PLARGE_INTEGER Offset,
696 OUT BOOLEAN *FullyMapped)
699 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
700 NTSTATUS ntStatus = STATUS_SUCCESS;
702 AFSRequestExtentsCB request;
703 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
704 AFSExtent *pFirstExtent;
705 LARGE_INTEGER liAlignedOffset;
706 ULONG ulAlignedLength = 0;
707 LARGE_INTEGER liTimeOut;
708 ULONGLONG ullProcessId = (ULONGLONG)PsGetCurrentProcessId();
711 // Check our extents, then fire off a request if we need to.
712 // We start off knowing nothing about where we will go.
717 *FullyMapped = AFSDoExtentsMapRegion( Fcb, Offset, Size, &pFirstExtent, &pExtent );
722 ASSERT(AFSExtentContains(pFirstExtent, Offset));
723 LARGE_INTEGER end = *Offset;
724 end.QuadPart += (Size-1);
725 ASSERT(AFSExtentContains(pExtent, &end));
727 return STATUS_SUCCESS;
731 // So we need to queue a request. Since we will be clearing the
732 // ExtentsRequestComplete event we need to do with with the lock
736 liTimeOut.QuadPart = -(50000000);
740 if (!NT_SUCCESS( pNPFcb->Specific.File.ExtentsRequestStatus))
744 // If this isn't the same process which caused the failure
745 // then try to request them again
748 if( Fcb->Specific.File.ExtentRequestProcessId == ullProcessId)
750 ntStatus = pNPFcb->Specific.File.ExtentsRequestStatus;
755 pNPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
758 ntStatus = KeWaitForSingleObject( &pNPFcb->Specific.File.ExtentsRequestComplete,
763 if (!NT_SUCCESS(ntStatus))
774 // Lock resource EX and look again
777 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
778 AFS_TRACE_LEVEL_VERBOSE,
779 "AFSRequestExtents Acquiring Fcb extent lock %08lX EXCL %08lX\n",
780 &pNPFcb->Specific.File.ExtentsResource,
781 PsGetCurrentThread());
783 AFSAcquireExcl( &pNPFcb->Specific.File.ExtentsResource, TRUE );
785 if (!NT_SUCCESS( pNPFcb->Specific.File.ExtentsRequestStatus))
789 // If this isn't the same process which caused the failure then try to request them again
792 if( Fcb->Specific.File.ExtentRequestProcessId == ullProcessId)
794 ntStatus = pNPFcb->Specific.File.ExtentsRequestStatus;
796 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
797 AFS_TRACE_LEVEL_VERBOSE,
798 "AFSRequestExtents Releasing Fcb extent lock %08lX EXCL %08lX\n",
799 &pNPFcb->Specific.File.ExtentsResource,
800 PsGetCurrentThread());
802 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
807 pNPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
810 if( KeReadStateEvent( &pNPFcb->Specific.File.ExtentsRequestComplete) ||
811 ntStatus == STATUS_TIMEOUT)
814 ntStatus = pNPFcb->Specific.File.ExtentsRequestStatus;
816 if( !NT_SUCCESS( ntStatus))
820 // If this isn't the same process which caused the failure
821 // then try to request them again
824 if( Fcb->Specific.File.ExtentRequestProcessId == ullProcessId)
826 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
827 AFS_TRACE_LEVEL_VERBOSE,
828 "AFSRequestExtents Releasing Fcb extent lock %08lX EXCL %08lX\n",
829 &pNPFcb->Specific.File.ExtentsResource,
830 PsGetCurrentThread());
832 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
837 pNPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
839 ntStatus = STATUS_SUCCESS;
846 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
847 AFS_TRACE_LEVEL_VERBOSE,
848 "AFSRequestExtents Releasing Fcb extent lock %08lX EXCL %08lX\n",
849 &pNPFcb->Specific.File.ExtentsResource,
850 PsGetCurrentThread());
852 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
855 if (!NT_SUCCESS(ntStatus))
864 // We have the lock Ex and there is no filling going on.
865 // Check again to see whether things have moved since we last
866 // checked. Since we haven't locked against pinning, we will
872 *FullyMapped = AFSDoExtentsMapRegion(Fcb, Offset, Size, &pFirstExtent, &pExtent);
877 ASSERT(AFSExtentContains(pFirstExtent, Offset));
878 LARGE_INTEGER end = *Offset;
879 end.QuadPart += (Size-1);
880 ASSERT(AFSExtentContains(pExtent, &end));
882 try_return (ntStatus = STATUS_SUCCESS);
885 RtlZeroMemory( &request,
886 sizeof( AFSRequestExtentsCB));
892 ulAlignedLength = Size;
894 liAlignedOffset = *Offset;
896 if( liAlignedOffset.QuadPart % pDevExt->Specific.RDR.CacheBlockSize != 0)
899 liAlignedOffset.QuadPart = (ULONGLONG)( (ULONGLONG)(liAlignedOffset.QuadPart / pDevExt->Specific.RDR.CacheBlockSize) * (ULONGLONG)pDevExt->Specific.RDR.CacheBlockSize);
901 ulAlignedLength += (ULONG)(Offset->QuadPart - liAlignedOffset.QuadPart);
904 if( ulAlignedLength % pDevExt->Specific.RDR.CacheBlockSize != 0)
907 ulAlignedLength = (ULONG)(((ulAlignedLength / pDevExt->Specific.RDR.CacheBlockSize) + 1) * pDevExt->Specific.RDR.CacheBlockSize);
910 request.ByteOffset = liAlignedOffset;
911 request.Length = ulAlignedLength;
913 if( !AFSIsExtentRequestQueued( &Fcb->ObjectInformation->FileId,
918 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
919 AFS_TRACE_LEVEL_VERBOSE,
920 "AFSRequestExtents Request extents for fid %08lX-%08lX-%08lX-%08lX Offset %08lX Len %08lX Thread %08lX\n",
921 Fcb->ObjectInformation->FileId.Cell,
922 Fcb->ObjectInformation->FileId.Volume,
923 Fcb->ObjectInformation->FileId.Vnode,
924 Fcb->ObjectInformation->FileId.Unique,
925 request.ByteOffset.LowPart,
927 PsGetCurrentThread());
929 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS,
933 &Fcb->ObjectInformation->FileId,
935 sizeof( AFSRequestExtentsCB ),
939 if( NT_SUCCESS( ntStatus))
941 KeClearEvent( &pNPFcb->Specific.File.ExtentsRequestComplete );
947 KeClearEvent( &pNPFcb->Specific.File.ExtentsRequestComplete );
952 if (NT_SUCCESS( ntStatus ))
954 KeQueryTickCount( &Fcb->Specific.File.LastExtentAccess );
957 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
958 AFS_TRACE_LEVEL_VERBOSE,
959 "AFSRequestExtents Releasing Fcb extent lock %08lX EXCL %08lX\n",
960 &pNPFcb->Specific.File.ExtentsResource,
961 PsGetCurrentThread());
963 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
970 AFSRequestExtentsAsync( IN AFSFcb *Fcb,
972 IN PLARGE_INTEGER Offset,
976 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
977 NTSTATUS ntStatus = STATUS_SUCCESS;
978 AFSExtent *pExtent = NULL;
979 AFSRequestExtentsCB request;
980 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
981 AFSExtent *pFirstExtent = NULL;
982 LARGE_INTEGER liAlignedOffset;
983 ULONG ulAlignedLength = 0;
984 BOOLEAN bRegionMapped = FALSE;
985 ULONGLONG ullProcessId = (ULONGLONG)PsGetCurrentProcessId();
990 ASSERT( !ExIsResourceAcquiredLite( &pNPFcb->Specific.File.ExtentsResource ));
993 // If the service set a failure on the file since the last
994 // CreateFile was issued, return it now.
997 if (!NT_SUCCESS( pNPFcb->Specific.File.ExtentsRequestStatus))
1001 // If this isn't the same process which caused the failure then try to request them again
1004 if( Fcb->Specific.File.ExtentRequestProcessId == ullProcessId)
1006 try_return( ntStatus = pNPFcb->Specific.File.ExtentsRequestStatus);
1009 pNPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
1013 // Check if we are already mapped
1016 bRegionMapped = AFSDoExtentsMapRegion( Fcb, Offset, Size, &pFirstExtent, &pExtent);
1021 try_return( ntStatus = STATUS_SUCCESS);
1025 // Align our request on extent size boundary
1028 ulAlignedLength = Size;
1030 liAlignedOffset = *Offset;
1032 if( liAlignedOffset.QuadPart % pDevExt->Specific.RDR.CacheBlockSize != 0)
1035 liAlignedOffset.QuadPart = (ULONGLONG)( (ULONGLONG)(liAlignedOffset.QuadPart / pDevExt->Specific.RDR.CacheBlockSize) * (ULONGLONG)pDevExt->Specific.RDR.CacheBlockSize);
1037 ulAlignedLength += (ULONG)(Offset->QuadPart - liAlignedOffset.QuadPart);
1040 if( ulAlignedLength % pDevExt->Specific.RDR.CacheBlockSize != 0)
1043 ulAlignedLength = (ULONG)(((ulAlignedLength / pDevExt->Specific.RDR.CacheBlockSize) + 1) * pDevExt->Specific.RDR.CacheBlockSize);
1046 RtlZeroMemory( &request,
1047 sizeof( AFSRequestExtentsCB));
1049 request.ByteOffset = liAlignedOffset;
1050 request.Length = ulAlignedLength;
1052 if( !AFSIsExtentRequestQueued( &Fcb->ObjectInformation->FileId,
1053 &request.ByteOffset,
1057 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1058 AFS_TRACE_LEVEL_VERBOSE,
1059 "AFSRequestExtentsAsync Request extents for fid %08lX-%08lX-%08lX-%08lX Offset %08lX Len %08lX Thread %08lX\n",
1060 Fcb->ObjectInformation->FileId.Cell,
1061 Fcb->ObjectInformation->FileId.Volume,
1062 Fcb->ObjectInformation->FileId.Vnode,
1063 Fcb->ObjectInformation->FileId.Unique,
1064 request.ByteOffset.LowPart,
1066 PsGetCurrentThread());
1068 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS,
1072 &Fcb->ObjectInformation->FileId,
1074 sizeof( AFSRequestExtentsCB ),
1078 if( NT_SUCCESS( ntStatus))
1081 KeClearEvent( &pNPFcb->Specific.File.ExtentsRequestComplete );
1087 KeClearEvent( &pNPFcb->Specific.File.ExtentsRequestComplete );
1099 AFSProcessExtentsResult( IN AFSFcb *Fcb,
1101 IN AFSFileExtentCB *Result)
1103 NTSTATUS ntStatus = STATUS_SUCCESS;
1104 AFSFileExtentCB *pFileExtents = Result;
1107 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
1108 ULONG fileExtentsUsed = 0;
1109 BOOLEAN bFoundExtent = FALSE;
1110 LIST_ENTRY *pSkipEntries[AFS_NUM_EXTENT_LISTS] = { 0 };
1111 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1114 // Grab the extents exclusive for the duration
1117 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1118 AFS_TRACE_LEVEL_VERBOSE,
1119 "AFSProcessExtentsResult Acquiring Fcb extent lock %08lX EXCL %08lX\n",
1120 &pNPFcb->Specific.File.ExtentsResource,
1121 PsGetCurrentThread());
1123 AFSAcquireExcl( &pNPFcb->Specific.File.ExtentsResource, TRUE );
1129 // Find where to put the extents
1131 for (ULONG i = AFS_EXTENTS_LIST; i < AFS_NUM_EXTENT_LISTS; i++)
1134 pSkipEntries[i] = Fcb->Specific.File.ExtentsLists[i].Flink;
1137 le = pSkipEntries[AFS_EXTENTS_LIST];
1139 if (le == &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
1142 // No extents. Insert at head of list (which is where the skip lists point!)
1146 else if (0 != pFileExtents->FileOffset.QuadPart)
1149 // We want to find the best extents immediately *behind* this offset
1151 LARGE_INTEGER offset = pFileExtents->FileOffset;
1154 // Ask in the top skip list first, then work down
1156 for (LONG i = AFS_NUM_EXTENT_LISTS-1; i >= AFS_EXTENTS_LIST; i--)
1158 pExtent = ExtentForOffsetInList( Fcb,
1163 if (NULL == pExtent)
1166 // No dice. Header has to become the head of the list
1168 pSkipEntries[i] = &Fcb->Specific.File.ExtentsLists[i];
1170 // And as a loop invariant we should never have found an extent
1172 ASSERT(!bFoundExtent);
1177 // pExtent is where to start to insert at this level
1179 pSkipEntries[i] = &pExtent->Lists[i];
1182 // And also where to start to look at the next level
1185 if (i > AFS_EXTENTS_LIST)
1187 pSkipEntries[i-1] = &pExtent->Lists[i-1];
1189 bFoundExtent = TRUE;
1193 if (NULL == pExtent)
1195 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
1200 le = pExtent->Lists[AFS_EXTENTS_LIST].Blink;
1206 // Looking at offset 0, so we must start at the beginning
1209 pExtent = ExtentFor(le, AFS_EXTENTS_LIST);
1213 // And set up the skip lists
1216 for (ULONG i = AFS_EXTENTS_LIST; i < AFS_NUM_EXTENT_LISTS; i++)
1218 pSkipEntries[i] = &Fcb->Specific.File.ExtentsLists[i];
1222 while (fileExtentsUsed < Count)
1226 // Loop invariant - le points to where to insert after and
1227 // pExtent points to le->fLink
1230 ASSERT (NULL == pExtent ||
1231 le->Flink == &pExtent->Lists[AFS_EXTENTS_LIST]);
1233 if (NULL == pExtent ||
1234 pExtent->FileOffset.QuadPart > pFileExtents->FileOffset.QuadPart)
1237 // We need to insert a new extent at le. Start with
1238 // some sanity check on spanning
1240 if (NULL != pExtent &&
1241 ((pFileExtents->FileOffset.QuadPart + pFileExtents->Length) >
1242 pExtent->FileOffset.QuadPart))
1245 // File Extents overlaps pExtent
1247 ASSERT( (pFileExtents->FileOffset.QuadPart + pFileExtents->Length) <=
1248 pExtent->FileOffset.QuadPart);
1250 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1254 // File offset is entirely in front of this extent. Create
1255 // a new one (remember le is the previous list entry)
1257 pExtent = (AFSExtent *) AFSExAllocatePoolWithTag( NonPagedPool,
1260 if (NULL == pExtent)
1265 try_return (ntStatus = STATUS_INSUFFICIENT_RESOURCES );
1268 RtlZeroMemory( pExtent, sizeof( AFSExtent ));
1270 pExtent->FileOffset = pFileExtents->FileOffset;
1271 pExtent->CacheOffset = pFileExtents->CacheOffset;
1272 pExtent->Size = pFileExtents->Length;
1274 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1275 AFS_TRACE_LEVEL_VERBOSE,
1276 "AFSProcessExtentsResult Received extent for fid %08lX-%08lX-%08lX-%08lX File Offset %I64X Cache Offset %I64X Len %08lX\n",
1277 Fcb->ObjectInformation->FileId.Cell,
1278 Fcb->ObjectInformation->FileId.Volume,
1279 Fcb->ObjectInformation->FileId.Vnode,
1280 Fcb->ObjectInformation->FileId.Unique,
1281 pFileExtents->FileOffset.QuadPart,
1282 pFileExtents->CacheOffset.QuadPart,
1283 pFileExtents->Length);
1285 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, (LONG)(pExtent->Size/1024));
1287 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, (LONG)(pExtent->Size/1024));
1289 InterlockedIncrement( &Fcb->Specific.File.ExtentCount);
1291 if( InterlockedIncrement( &pControlDevExt->Specific.Control.ExtentCount) == 1)
1294 KeClearEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent);
1300 InsertHeadList(le, &pExtent->Lists[AFS_EXTENTS_LIST]);
1301 ASSERT(le->Flink == &pExtent->Lists[AFS_EXTENTS_LIST]);
1302 ASSERT(0 == (pExtent->FileOffset.LowPart & ExtentsMasks[AFS_EXTENTS_LIST]));
1305 // Do not move the cursor - we will do it next time
1309 // And into the (upper) skip lists - Again, do not move the cursor
1311 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1313 if (0 == (pExtent->FileOffset.LowPart & ExtentsMasks[i]))
1315 InsertHeadList(pSkipEntries[i], &pExtent->Lists[i]);
1316 #if AFS_VALIDATE_EXTENTS
1317 VerifyExtentsLists(Fcb);
1322 else if (pExtent->FileOffset.QuadPart == pFileExtents->FileOffset.QuadPart)
1325 if (pExtent->Size != pFileExtents->Length)
1328 ASSERT (pExtent->Size == pFileExtents->Length);
1330 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1334 // Move both cursors forward.
1336 // First the extent pointer
1339 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1342 // Then the skip lists cursors forward if needed
1344 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1346 if (0 == (pExtent->FileOffset.LowPart & ExtentsMasks[i]))
1349 // Check sanity before
1351 #if AFS_VALIDATE_EXTENTS
1352 VerifyExtentsLists(Fcb);
1356 // Skip list should point to us
1358 //ASSERT(pSkipEntries[i] == &pExtent->Lists[i]);
1360 // Move forward cursor
1362 pSkipEntries[i] = pSkipEntries[i]->Flink;
1364 // Check sanity before
1366 #if AFS_VALIDATE_EXTENTS
1367 VerifyExtentsLists(Fcb);
1373 // And then the cursor in the supplied array
1379 // setup pExtent if there is one
1381 if (le->Flink != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
1383 pExtent = NextExtent( pExtent, AFS_EXTENTS_LIST ) ;
1393 ASSERT( pExtent->FileOffset.QuadPart < pFileExtents->FileOffset.QuadPart );
1396 // Sanity check on spanning
1398 if ((pExtent->FileOffset.QuadPart + pExtent->Size) >
1399 pFileExtents->FileOffset.QuadPart)
1402 ASSERT( (pExtent->FileOffset.QuadPart + pExtent->Size) <=
1403 pFileExtents->FileOffset.QuadPart);
1405 try_return (ntStatus = STATUS_INVALID_PARAMETER);
1409 // Move le and pExtent forward
1411 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1415 // Then the check the skip lists cursors
1417 for (ULONG i = AFS_NUM_EXTENT_LISTS-1; i > AFS_EXTENTS_LIST; i--)
1419 if (0 == (pFileExtents->FileOffset.LowPart & ExtentsMasks[i]))
1423 // - empty list (pSkipEntries[i]->Flink == pSkipEntries[i]->Flink == fcb->lists[i]
1424 // - We are the last on the list (pSkipEntries[i]->Flink == fcb->lists[i])
1425 // - We are not the last on the list. In that case we have to be strictly less than
1427 if (pSkipEntries[i]->Flink != &Fcb->Specific.File.ExtentsLists[i]) {
1429 AFSExtent *otherExtent = ExtentFor(pSkipEntries[i]->Flink, i);
1430 ASSERT(pFileExtents->FileOffset.QuadPart < otherExtent->FileOffset.QuadPart);
1437 // setup pExtent if there is one
1440 if (le->Flink != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
1442 pExtent = NextExtent( pExtent, AFS_EXTENTS_LIST ) ;
1452 // All done, signal that we are done drop the lock, exit
1457 if( !NT_SUCCESS( ntStatus))
1461 // If we failed the service is going to drop all extents so trim away the
1465 AFSTrimSpecifiedExtents( Fcb,
1470 #if AFS_VALIDATE_EXTENTS
1471 VerifyExtentsLists(Fcb);
1474 KeSetEvent( &pNPFcb->Specific.File.ExtentsRequestComplete,
1478 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1479 AFS_TRACE_LEVEL_VERBOSE,
1480 "AFSProcessExtentsResult Releasing Fcb extent lock %08lX EXCL %08lX\n",
1481 &pNPFcb->Specific.File.ExtentsResource,
1482 PsGetCurrentThread());
1484 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
1491 AFSProcessSetFileExtents( IN AFSSetFileExtentsCB *SetExtents )
1493 AFSFcb *pFcb = NULL;
1494 AFSVolumeCB *pVolumeCB = NULL;
1495 NTSTATUS ntStatus = STATUS_SUCCESS;
1496 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1497 ULONGLONG ullIndex = 0;
1498 AFSObjectInfoCB *pObjectInfo = NULL;
1503 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1504 AFS_TRACE_LEVEL_VERBOSE,
1505 "AFSProcessSetFileExtents Acquiring RDR VolumeTreeLock lock %08lX SHARED %08lX\n",
1506 &pDevExt->Specific.RDR.VolumeTreeLock,
1507 PsGetCurrentThread());
1509 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
1511 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1512 AFS_TRACE_LEVEL_VERBOSE,
1513 "AFSProcessSetFileExtents Set extents for fid %08lX-%08lX-%08lX-%08lX\n",
1514 SetExtents->FileId.Cell,
1515 SetExtents->FileId.Volume,
1516 SetExtents->FileId.Vnode,
1517 SetExtents->FileId.Unique);
1520 // Locate the volume node
1523 ullIndex = AFSCreateHighIndex( &SetExtents->FileId);
1525 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
1527 (AFSBTreeEntry **)&pVolumeCB);
1529 if( pVolumeCB != NULL)
1532 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1533 AFS_TRACE_LEVEL_VERBOSE,
1534 "AFSProcessSetFileExtents Acquiring VolumeRoot FileIDTree.TreeLock lock %08lX SHARED %08lX\n",
1535 pVolumeCB->ObjectInfoTree.TreeLock,
1536 PsGetCurrentThread());
1538 InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1541 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
1543 if( !NT_SUCCESS( ntStatus) ||
1547 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1548 AFS_TRACE_LEVEL_ERROR,
1549 "AFSProcessSetFileExtents Set extents for fid %08lX-%08lX-%08lX-%08lX Failed to locate volume Status %08lX\n",
1550 SetExtents->FileId.Cell,
1551 SetExtents->FileId.Volume,
1552 SetExtents->FileId.Vnode,
1553 SetExtents->FileId.Unique,
1556 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1559 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1562 InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1565 // Now locate the Object in this volume
1568 ullIndex = AFSCreateLowIndex( &SetExtents->FileId);
1570 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
1572 (AFSBTreeEntry **)&pObjectInfo);
1574 if( pObjectInfo != NULL)
1578 // Reference the node so it won't be torn down
1581 InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
1583 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1584 AFS_TRACE_LEVEL_VERBOSE,
1585 "AFSProcessSetFileExtents Increment count on object %08lX Cnt %d\n",
1587 pObjectInfo->ObjectReferenceCount);
1590 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1592 if( !NT_SUCCESS( ntStatus) ||
1593 pObjectInfo == NULL)
1596 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1597 AFS_TRACE_LEVEL_ERROR,
1598 "AFSProcessSetFileExtents Set extents for hash %I64X fid %08lX-%08lX-%08lX-%08lX Failed to locate file in volume %08lX\n",
1600 SetExtents->FileId.Cell,
1601 SetExtents->FileId.Volume,
1602 SetExtents->FileId.Vnode,
1603 SetExtents->FileId.Unique,
1606 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1609 pFcb = pObjectInfo->Fcb;
1612 // If we have a result failure then don't bother trying to set the extents
1615 if( SetExtents->ResultStatus != STATUS_SUCCESS)
1618 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1619 AFS_TRACE_LEVEL_ERROR,
1620 "AFSProcessSetFileExtents Set extents failure fid %08lX-%08lX-%08lX-%08lX ResultStatus %08lX\n",
1621 SetExtents->FileId.Cell,
1622 SetExtents->FileId.Volume,
1623 SetExtents->FileId.Vnode,
1624 SetExtents->FileId.Unique,
1625 SetExtents->ResultStatus);
1627 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1628 AFS_TRACE_LEVEL_VERBOSE,
1629 "AFSProcessSetFileExtents Acquiring Fcb extents lock %08lX EXCL %08lX\n",
1630 &pFcb->NPFcb->Specific.File.ExtentsResource,
1631 PsGetCurrentThread());
1633 AFSAcquireExcl( &pFcb->NPFcb->Specific.File.ExtentsResource,
1636 pFcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_CANCELLED;
1638 KeSetEvent( &pFcb->NPFcb->Specific.File.ExtentsRequestComplete,
1642 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1643 AFS_TRACE_LEVEL_VERBOSE,
1644 "AFSProcessSetFileExtents Releasing Fcb extent lock %08lX EXCL %08lX\n",
1645 &pFcb->NPFcb->Specific.File.ExtentsResource,
1646 PsGetCurrentThread());
1648 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
1650 try_return( ntStatus);
1653 ntStatus = AFSProcessExtentsResult ( pFcb,
1654 SetExtents->ExtentCount,
1655 SetExtents->FileExtents );
1659 if( pObjectInfo != NULL)
1662 InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
1664 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1665 AFS_TRACE_LEVEL_VERBOSE,
1666 "AFSProcessSetFileExtents Decrement count on object %08lX Cnt %d\n",
1668 pObjectInfo->ObjectReferenceCount);
1676 // Helper fuctions for Usermode initiation of release of extents
1679 AFSReleaseSpecifiedExtents( IN AFSReleaseFileExtentsCB *Extents,
1681 OUT AFSFileExtentCB *FileExtents,
1682 IN ULONG BufferSize,
1683 OUT ULONG *ExtentCount,
1684 OUT BOOLEAN *DirtyExtents)
1689 ULONG ulExtentCount = 0;
1690 NTSTATUS ntStatus = STATUS_SUCCESS;
1691 BOOLEAN bReleaseAll = FALSE;
1692 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1696 ASSERT( ExIsResourceAcquiredExclusiveLite( &Fcb->NPFcb->Specific.File.ExtentsResource));
1698 if (BufferSize < (Extents->ExtentCount * sizeof( AFSFileExtentCB)))
1701 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1702 AFS_TRACE_LEVEL_VERBOSE,
1703 "AFSReleaseSpecifiedExtents Buffer too small\n");
1705 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL);
1708 RtlZeroMemory( FileExtents, BufferSize);
1711 *DirtyExtents = FALSE;
1714 // iterate until we have dealt with all we were asked for or
1715 // are at the end of the list. Note that this deals (albeit
1716 // badly) with out of order extents
1719 pExtent = AFSExtentForOffset( Fcb,
1720 &Extents->FileExtents[0].FileOffset,
1723 if (NULL == pExtent)
1725 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1729 le = &pExtent->Lists[AFS_EXTENTS_LIST];
1733 if( BooleanFlagOn( Extents->Flags, AFS_RELEASE_EXTENTS_FLAGS_RELEASE_ALL) ||
1734 ( Extents->FileId.Cell == 0 &&
1735 Extents->FileId.Volume == 0 &&
1736 Extents->FileId.Vnode == 0 &&
1737 Extents->FileId.Unique == 0))
1743 while( le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST] &&
1744 ulExtentCount < Extents->ExtentCount)
1748 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
1753 if( pExtent->FileOffset.QuadPart < Extents->FileExtents[ulExtentCount].FileOffset.QuadPart)
1756 // Skip forward through the extent list until we get
1757 // to the one we want
1763 else if (pExtent->FileOffset.QuadPart > Extents->FileExtents[ulExtentCount].FileOffset.QuadPart)
1766 // We don't have the extent asked for so return UNKNOWN
1769 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1770 AFS_TRACE_LEVEL_VERBOSE,
1771 "AFSReleaseSpecifiedExtents Located UNKNOWN extent Offset %I64X Len %08lX\n",
1772 Extents->FileExtents[ulExtentCount].FileOffset.QuadPart,
1773 Extents->FileExtents[ulExtentCount].Length);
1775 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_UNKNOWN;
1777 FileExtents[*ExtentCount].Length = 0;
1778 FileExtents[*ExtentCount].CacheOffset.QuadPart = 0;
1779 FileExtents[*ExtentCount].FileOffset = Extents->FileExtents[ulExtentCount].FileOffset;
1781 *ExtentCount = (*ExtentCount) + 1;
1786 // Reset where we are looking
1789 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1793 else if( pExtent->ActiveCount > 0)
1796 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1797 AFS_TRACE_LEVEL_VERBOSE,
1798 "AFSReleaseSpecifiedExtents Located IN_USE extent Offset %I64X Len %08lX\n",
1799 Extents->FileExtents[ulExtentCount].FileOffset.QuadPart,
1800 Extents->FileExtents[ulExtentCount].Length);
1802 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_IN_USE;
1804 FileExtents[*ExtentCount].Length = 0;
1805 FileExtents[*ExtentCount].CacheOffset.QuadPart = 0;
1806 FileExtents[*ExtentCount].FileOffset = Extents->FileExtents[ulExtentCount].FileOffset;
1808 *ExtentCount = (*ExtentCount) + 1;
1813 // Reset where we are looking
1816 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
1825 // If the extent is currently active then skip it
1828 if( pExtent->ActiveCount > 0)
1837 FileExtents[*ExtentCount].Flags = AFS_EXTENT_FLAG_RELEASE;
1839 FileExtents[*ExtentCount].Length = pExtent->Size;
1840 FileExtents[*ExtentCount].DirtyLength = pExtent->Size;
1841 FileExtents[*ExtentCount].DirtyOffset = 0;
1842 FileExtents[*ExtentCount].CacheOffset = pExtent->CacheOffset;
1843 FileExtents[*ExtentCount].FileOffset = pExtent->FileOffset;
1845 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
1846 AFS_TRACE_LEVEL_VERBOSE,
1847 "AFSReleaseSpecifiedExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
1849 Fcb->ObjectInformation->FileId.Cell,
1850 Fcb->ObjectInformation->FileId.Volume,
1851 Fcb->ObjectInformation->FileId.Vnode,
1852 Fcb->ObjectInformation->FileId.Unique,
1853 FileExtents[*ExtentCount].FileOffset.QuadPart,
1854 FileExtents[*ExtentCount].Length);
1856 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
1859 AFSAcquireExcl( &Fcb->NPFcb->Specific.File.DirtyExtentsListLock,
1862 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
1865 AFSRemoveEntryDirtyList( Fcb,
1868 FileExtents[*ExtentCount].Flags |= AFS_EXTENT_FLAG_DIRTY;
1870 InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
1872 *DirtyExtents = TRUE;
1875 AFSReleaseResource( &Fcb->NPFcb->Specific.File.DirtyExtentsListLock);
1879 // move forward all three cursors
1883 *ExtentCount = (*ExtentCount) + 1;
1888 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
1890 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
1892 RemoveEntryList( &pExtent->Lists[i] );
1896 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
1898 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
1903 AFSExFreePool( pExtent);
1905 InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
1907 if( InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount) == 0)
1910 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
1925 AFSFindFcbToClean(ULONG IgnoreTime, AFSFcb *LastFcb, BOOLEAN Block)
1928 AFSFcb *pFcb = NULL;
1929 AFSVolumeCB *pVolumeCB = NULL;
1930 AFSDeviceExt *pRDRDeviceExt = NULL;
1931 AFSDeviceExt *pControlDeviceExt = NULL;
1932 BOOLEAN bLocatedEntry = FALSE;
1933 AFSObjectInfoCB *pCurrentObject = NULL;
1934 BOOLEAN bReleaseVolumeListLock = FALSE;
1936 pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1937 pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1939 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1940 AFS_TRACE_LEVEL_VERBOSE,
1941 "AFSFindFcbToClean Acquiring RDR VolumeListLock lock %08lX SHARED %08lX\n",
1942 &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1943 PsGetCurrentThread());
1945 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1948 bReleaseVolumeListLock = TRUE;
1950 pVolumeCB = pRDRDeviceExt->Specific.RDR.VolumeListHead;
1952 while( pVolumeCB != NULL)
1956 // The Volume list may move under our feet. Lock it.
1959 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1960 AFS_TRACE_LEVEL_VERBOSE,
1961 "AFSFindFcbToClean Acquiring VolumeRoot ObjectInfoTree lock %08lX SHARED %08lX\n",
1962 pVolumeCB->ObjectInfoTree.TreeLock,
1963 PsGetCurrentThread());
1965 InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1967 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1969 bReleaseVolumeListLock = FALSE;
1971 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1974 InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1976 if( NULL == LastFcb)
1979 pCurrentObject = pVolumeCB->ObjectInfoListHead;
1984 pCurrentObject = (AFSObjectInfoCB *)LastFcb->ObjectInformation->ListEntry.fLink;
1989 while( pCurrentObject != NULL)
1992 pFcb = (AFSFcb *)pCurrentObject->Fcb;
1995 // If the FCB is a candidate we try to lock it (but without waiting - which
1996 // means we are deadlock free
2000 pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
2006 AFSLockForExtentsTrim( pFcb);
2011 if( !AFSLockForExtentsTrimNoWait( pFcb))
2014 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
2023 // Need to be sure there are no current flushes in the queue
2026 if( pFcb->Specific.File.ExtentCount == 0)
2029 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2030 AFS_TRACE_LEVEL_VERBOSE,
2031 "AFSFindFcbToClean Releasing Fcb extent lock %08lX thread %08lX\n",
2032 &pFcb->NPFcb->Specific.File.ExtentsResource,
2033 PsGetCurrentThread());
2035 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
2037 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
2044 if( pFcb->Specific.File.QueuedFlushCount > 0)
2047 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2048 AFS_TRACE_LEVEL_VERBOSE,
2049 "AFSFindFcbToClean Releasing Fcb extent lock %08lX thread %08lX\n",
2050 &pFcb->NPFcb->Specific.File.ExtentsResource,
2051 PsGetCurrentThread());
2053 AFSReleaseResource(&pFcb->NPFcb->Specific.File.ExtentsResource);
2057 AFSWaitOnQueuedFlushes( pFcb);
2062 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
2070 if( pFcb->OpenHandleCount > 0)
2073 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2074 AFS_TRACE_LEVEL_VERBOSE,
2075 "AFSFindFcbToClean Releasing Fcb extent lock %08lX thread %08lX\n",
2076 &pFcb->NPFcb->Specific.File.ExtentsResource,
2077 PsGetCurrentThread());
2079 AFSReleaseResource(&pFcb->NPFcb->Specific.File.ExtentsResource);
2081 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
2089 // A hit a very palpable hit. Pin it
2092 InterlockedIncrement( &pCurrentObject->ObjectReferenceCount);
2094 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2095 AFS_TRACE_LEVEL_VERBOSE,
2096 "AFSFindFcbToClean Increment count on Fcb %08lX Cnt %d\n",
2098 pCurrentObject->ObjectReferenceCount);
2100 bLocatedEntry = TRUE;
2105 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
2110 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2117 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
2120 bReleaseVolumeListLock = TRUE;
2122 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
2125 if( bReleaseVolumeListLock)
2128 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
2135 AFSProcessExtentFailure( PIRP Irp)
2137 AFSExtentFailureCB *pFailureCB = NULL;
2138 NTSTATUS ntStatus = STATUS_SUCCESS;
2139 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2140 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2141 AFSVolumeCB *pVolumeCB = NULL;
2142 ULONGLONG ullIndex = 0;
2143 AFSObjectInfoCB *pObjectInfo = NULL;
2147 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSExtentFailureCB))
2150 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2151 AFS_TRACE_LEVEL_ERROR,
2152 "AFSProcessExtentFailure Input buffer too small\n");
2154 try_return( ntStatus = STATUS_INVALID_PARAMETER);
2157 pFailureCB = (AFSExtentFailureCB *)Irp->AssociatedIrp.SystemBuffer;
2159 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2160 AFS_TRACE_LEVEL_ERROR,
2161 "AFSProcessExtentFailure Service Reports Failure fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2162 pFailureCB->FileId.Cell,
2163 pFailureCB->FileId.Volume,
2164 pFailureCB->FileId.Vnode,
2165 pFailureCB->FileId.Unique,
2166 pFailureCB->FailureStatus);
2168 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
2171 // Locate the volume node
2174 ullIndex = AFSCreateHighIndex( &pFailureCB->FileId);
2176 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
2178 (AFSBTreeEntry **)&pVolumeCB);
2180 if( pVolumeCB != NULL)
2183 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2184 AFS_TRACE_LEVEL_VERBOSE,
2185 "AFSProcessExtentFailure Acquiring VolumeRoot FileIDTree.TreeLock lock %08lX SHARED %08lX\n",
2186 pVolumeCB->ObjectInfoTree.TreeLock,
2187 PsGetCurrentThread());
2189 InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
2192 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
2194 if( !NT_SUCCESS( ntStatus) ||
2198 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2199 AFS_TRACE_LEVEL_ERROR,
2200 "AFSProcessExtentFailure Invalid volume index %I64X status %08X\n",
2201 ullIndex, ntStatus);
2203 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2206 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
2209 InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
2212 // Now locate the Object in this volume
2215 ullIndex = AFSCreateLowIndex( &pFailureCB->FileId);
2217 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
2219 (AFSBTreeEntry **)&pObjectInfo);
2221 if( pObjectInfo != NULL &&
2222 pObjectInfo->Fcb != NULL)
2226 // Reference the node so it won't be torn down
2229 InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
2231 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2232 AFS_TRACE_LEVEL_VERBOSE,
2233 "AFSProcessExtentFailure Increment count on object %08lX Cnt %d\n",
2235 pObjectInfo->ObjectReferenceCount);
2238 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2240 if( !NT_SUCCESS( ntStatus) ||
2241 pObjectInfo == NULL ||
2242 pObjectInfo->Fcb == NULL)
2245 if( pObjectInfo == NULL)
2247 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2248 AFS_TRACE_LEVEL_ERROR,
2249 "AFSProcessExtentFailure Invalid file index %I64X\n",
2254 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2255 AFS_TRACE_LEVEL_ERROR,
2256 "AFSProcessExtentFailure Fcb dealocated for %I64X\n",
2260 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2263 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2264 AFS_TRACE_LEVEL_VERBOSE,
2265 "AFSProcessExtentFailure Acquiring Fcb extent lock %08lX EXCL %08lX\n",
2266 &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2267 PsGetCurrentThread());
2269 AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2272 pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestStatus = pFailureCB->FailureStatus;
2274 KeSetEvent( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
2278 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2279 AFS_TRACE_LEVEL_VERBOSE,
2280 "AFSProcessExtentFailure Releasing Fcb extent lock %08lX EXCL %08lX\n",
2281 &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
2282 PsGetCurrentThread());
2284 AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource);
2286 InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
2288 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2289 AFS_TRACE_LEVEL_VERBOSE,
2290 "AFSProcessExtentFailure Decrement count on object %08lX Cnt %d\n",
2292 pObjectInfo->ObjectReferenceCount);
2303 AFSProcessReleaseFileExtents( IN PIRP Irp)
2305 NTSTATUS ntStatus = STATUS_SUCCESS;
2306 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2307 PFILE_OBJECT pFileObject = pIrpSp->FileObject;
2308 AFSFcb *pFcb = NULL;
2309 AFSVolumeCB *pVolumeCB = NULL;
2310 AFSDeviceExt *pDevExt;
2311 AFSReleaseFileExtentsCB *pExtents;
2312 AFSReleaseFileExtentsResultCB *pResult = NULL;
2313 AFSReleaseFileExtentsResultFileCB *pFile = NULL;
2315 ULONGLONG ullIndex = 0;
2316 AFSObjectInfoCB *pObjectInfo = NULL;
2317 BOOLEAN bLocked = FALSE;
2318 BOOLEAN bDirtyExtents = FALSE;
2324 pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2326 pExtents = (AFSReleaseFileExtentsCB*) Irp->AssociatedIrp.SystemBuffer;
2328 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2329 sizeof( AFSReleaseFileExtentsCB))
2332 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2333 AFS_TRACE_LEVEL_ERROR,
2334 "AFSProcessReleaseFileExtents INPUT Buffer too small\n");
2336 try_return( ntStatus = STATUS_INVALID_PARAMETER );
2339 if ( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength <
2340 sizeof(AFSReleaseFileExtentsResultCB))
2343 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2344 AFS_TRACE_LEVEL_ERROR,
2345 "AFSProcessReleaseFileExtents OUTPUT Buffer too small [1]\n");
2348 // Must have space for one extent in one file
2351 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL);
2354 if (pExtents->ExtentCount == 0)
2357 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2358 AFS_TRACE_LEVEL_ERROR,
2359 "AFSProcessReleaseFileExtents Extent count zero\n");
2361 try_return( ntStatus = STATUS_INVALID_PARAMETER);
2364 if (pExtents->FileId.Cell != 0 ||
2365 pExtents->FileId.Volume != 0 ||
2366 pExtents->FileId.Vnode != 0 ||
2367 pExtents->FileId.Unique != 0)
2370 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2371 AFS_TRACE_LEVEL_VERBOSE,
2372 "AFSProcessReleaseFileExtents Processing FID %08lX:%08lX:%08lX:%08lX\n",
2373 pExtents->FileId.Cell,
2374 pExtents->FileId.Volume,
2375 pExtents->FileId.Vnode,
2376 pExtents->FileId.Unique);
2378 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2379 ( FIELD_OFFSET( AFSReleaseFileExtentsCB, ExtentCount) + sizeof(ULONG)) ||
2380 pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
2381 ( FIELD_OFFSET( AFSReleaseFileExtentsCB, ExtentCount) + sizeof(ULONG) +
2382 sizeof (AFSFileExtentCB) * pExtents->ExtentCount))
2385 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2386 AFS_TRACE_LEVEL_ERROR,
2387 "AFSProcessReleaseFileExtents Buffer too small for FID %08lX:%08lx:%08lX:%08lX\n",
2388 pExtents->FileId.Cell,
2389 pExtents->FileId.Volume,
2390 pExtents->FileId.Vnode,
2391 pExtents->FileId.Unique);
2393 try_return( ntStatus = STATUS_INVALID_PARAMETER );
2396 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2397 AFS_TRACE_LEVEL_VERBOSE,
2398 "AFSProcessReleaseFileExtents Acquiring RDR VolumeTreeLock lock %08lX SHARED %08lX\n",
2399 &pDevExt->Specific.RDR.VolumeTreeLock,
2400 PsGetCurrentThread());
2402 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
2405 // Locate the volume node
2408 ullIndex = AFSCreateHighIndex( &pExtents->FileId);
2410 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
2412 (AFSBTreeEntry **)&pVolumeCB);
2414 if( pVolumeCB != NULL)
2417 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2418 AFS_TRACE_LEVEL_VERBOSE,
2419 "AFSProcessReleaseFileExtents Acquiring VolumeRoot FileIDTree.TreeLock lock %08lX SHARED %08lX\n",
2420 pVolumeCB->ObjectInfoTree.TreeLock,
2421 PsGetCurrentThread());
2423 InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
2426 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
2428 if( !NT_SUCCESS( ntStatus) ||
2432 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2433 AFS_TRACE_LEVEL_ERROR,
2434 "AFSProcessReleaseFileExtents Invalid volume index %I64X status %08X\n",
2435 ullIndex, ntStatus);
2437 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2440 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
2443 InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
2446 // Now locate the Object in this volume
2449 ullIndex = AFSCreateLowIndex( &pExtents->FileId);
2451 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
2453 (AFSBTreeEntry **)&pObjectInfo);
2455 if( pObjectInfo != NULL)
2459 // Reference the node so it won't be torn down
2462 InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
2464 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2465 AFS_TRACE_LEVEL_VERBOSE,
2466 "AFSProcessReleaseFileExtents Increment count on object %08lX Cnt %d\n",
2468 pObjectInfo->ObjectReferenceCount);
2471 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2473 if( !NT_SUCCESS( ntStatus) ||
2474 pObjectInfo == NULL)
2477 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2478 AFS_TRACE_LEVEL_ERROR,
2479 "AFSProcessReleaseFileExtents Invalid file index %I64X\n",
2482 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2485 pFcb = pObjectInfo->Fcb;
2490 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2491 AFS_TRACE_LEVEL_ERROR,
2492 "AFSProcessReleaseFileExtents Fcb not initialied (NO EXTENTS) for FID %08lX:%08lx:%08lX:%08lX\n",
2493 pExtents->FileId.Cell,
2494 pExtents->FileId.Volume,
2495 pExtents->FileId.Vnode,
2496 pExtents->FileId.Unique);
2498 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2501 AFSLockForExtentsTrim( pFcb );
2509 // Locate an Fcb to trim down
2512 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2513 AFS_TRACE_LEVEL_VERBOSE,
2514 "AFSProcessReleaseFileExtents Searching for a Fcb to Trim Down\n");
2516 pFcb = AFSFindFcbToClean( 0, NULL, FALSE);
2521 pFcb = AFSFindFcbToClean( 0, NULL, TRUE);
2527 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2528 AFS_TRACE_LEVEL_ERROR,
2529 "AFSProcessReleaseFileExtents Failed to locate Fcb for release ...\n");
2531 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2534 pObjectInfo = pFcb->ObjectInformation;
2540 // Allocate a scratch buffer to move in the extent information
2543 ulSz = (pExtents->ExtentCount-1) * sizeof(AFSFileExtentCB);
2544 ulSz += sizeof(AFSReleaseFileExtentsResultCB);
2546 if (ulSz > pIrpSp->Parameters.DeviceIoControl.OutputBufferLength)
2548 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2549 AFS_TRACE_LEVEL_ERROR,
2550 "AFSProcessReleaseFileExtents OUTPUT Buffer too small [2]\n");
2552 try_return( ntStatus = STATUS_BUFFER_TOO_SMALL );
2555 pResult = (AFSReleaseFileExtentsResultCB*) AFSExAllocatePoolWithTag( PagedPool,
2557 AFS_EXTENTS_RESULT_TAG);
2558 if (NULL == pResult)
2561 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2562 AFS_TRACE_LEVEL_ERROR,
2563 "AFSProcessReleaseFileExtents Failed to allocate result block\n");
2565 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2569 // Set up the header (for an array of one)
2571 pResult->FileCount = 1;
2572 pResult->Flags = AFS_EXTENT_FLAG_RELEASE;
2573 ulSz -= FIELD_OFFSET(AFSReleaseFileExtentsResultCB, Files);
2576 // Setup the first (and only) file
2578 pFile = pResult->Files;
2579 pFile->FileId = pObjectInfo->FileId;
2580 pFile->Flags = AFS_EXTENT_FLAG_RELEASE;
2583 // Stash away the auth group
2586 RtlZeroMemory( &stAuthGroup,
2589 ntStatus = AFSRetrieveValidAuthGroup( pFcb,
2594 if( !NT_SUCCESS( ntStatus))
2596 try_return( ntStatus);
2599 RtlCopyMemory( &pFile->AuthGroup,
2604 // Update the metadata for this call
2607 pFile->AllocationSize = pFcb->ObjectInformation->EndOfFile;
2608 pFile->CreateTime = pFcb->ObjectInformation->CreationTime;
2609 pFile->ChangeTime = pFcb->ObjectInformation->ChangeTime;
2610 pFile->LastAccessTime = pFcb->ObjectInformation->LastAccessTime;
2611 pFile->LastWriteTime = pFcb->ObjectInformation->LastWriteTime;
2613 ulSz -= FIELD_OFFSET(AFSReleaseFileExtentsResultFileCB, FileExtents);
2615 ntStatus = AFSReleaseSpecifiedExtents( pExtents,
2619 &pFile->ExtentCount,
2622 if (!NT_SUCCESS(ntStatus))
2625 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2626 AFS_TRACE_LEVEL_ERROR,
2627 "AFSProcessReleaseFileExtents Failed to release extents Status %08lX\n",
2630 try_return( ntStatus );
2633 if( pExtents->ExtentCount == 0)
2636 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2637 AFS_TRACE_LEVEL_WARNING,
2638 "AFSProcessReleaseFileExtents Failed to release ANY extents\n");
2641 ulSz = sizeof(AFSReleaseFileExtentsResultCB);
2643 if( pExtents->ExtentCount > 0)
2645 ulSz += ((pExtents->ExtentCount-1) * sizeof(AFSFileExtentCB));
2648 RtlCopyMemory( Irp->AssociatedIrp.SystemBuffer,
2657 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2658 AFS_TRACE_LEVEL_VERBOSE,
2659 "AFSProcessReleaseFileExtents Releasing Fcb extent lock %08lX thread %08lX\n",
2660 &pFcb->NPFcb->Specific.File.ExtentsResource,
2661 PsGetCurrentThread());
2663 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource );
2666 if( NULL != pResult &&
2667 Irp->AssociatedIrp.SystemBuffer != pResult)
2670 AFSExFreePool(pResult);
2673 if (NT_SUCCESS(ntStatus))
2675 Irp->IoStatus.Information = ulSz;
2679 Irp->IoStatus.Information = 0;
2682 Irp->IoStatus.Status = ntStatus;
2684 if( pObjectInfo != NULL)
2687 InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
2689 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2690 AFS_TRACE_LEVEL_VERBOSE,
2691 "AFSProcessReleaseFileExtents Decrement count on object %08lX Cnt %d\n",
2693 pObjectInfo->ObjectReferenceCount);
2701 AFSWaitForExtentMapping( AFSFcb *Fcb )
2703 NTSTATUS ntStatus = STATUS_SUCCESS;
2704 LARGE_INTEGER liTimeOut;
2705 ULONGLONG ullProcessId = (ULONGLONG)PsGetCurrentProcessId();
2710 ASSERT( !ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
2712 if (!NT_SUCCESS( Fcb->NPFcb->Specific.File.ExtentsRequestStatus))
2716 // If this isn't the same process which caused the failure then try to request them again
2719 if( Fcb->Specific.File.ExtentRequestProcessId == ullProcessId)
2721 try_return( ntStatus = Fcb->NPFcb->Specific.File.ExtentsRequestStatus);
2724 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
2727 liTimeOut.QuadPart = -(50000000);
2729 ntStatus = KeWaitForSingleObject( &Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
2735 if (!NT_SUCCESS( Fcb->NPFcb->Specific.File.ExtentsRequestStatus))
2739 // If this isn't the same process which caused the failure
2740 // and this isn't the System process, then try to request them again
2743 if( Fcb->Specific.File.ExtentRequestProcessId == ullProcessId ||
2744 ullProcessId == 0x4)
2746 try_return( ntStatus = Fcb->NPFcb->Specific.File.ExtentsRequestStatus);
2749 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
2752 if( ntStatus == STATUS_TIMEOUT)
2755 ntStatus = STATUS_SUCCESS;
2767 AFSFlushExtents( IN AFSFcb *Fcb,
2770 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
2771 AFSExtent *pExtent, *pNextExtent;
2773 AFSReleaseExtentsCB *pRelease = NULL;
2775 ULONG initialDirtyCount = 0;
2776 BOOLEAN bExtentsLocked = FALSE;
2779 NTSTATUS ntStatus = STATUS_SUCCESS;
2780 LARGE_INTEGER liLastFlush;
2781 AFSExtent *pDirtyListHead = NULL, *pDirtyListTail = NULL;
2782 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2783 GUID *pAuthGroup = AuthGroup;
2786 ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
2789 // Save, then reset the flush time
2792 liLastFlush = Fcb->Specific.File.LastServerFlush;
2794 KeQueryTickCount( &Fcb->Specific.File.LastServerFlush);
2799 if( pAuthGroup == NULL)
2802 RtlZeroMemory( &stAuthGroup,
2805 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
2810 if( !NT_SUCCESS( ntStatus))
2812 try_return( ntStatus);
2815 pAuthGroup = &stAuthGroup;
2819 // Lock extents while we count and set up the array to send to
2823 AFSLockForExtentsTrim( Fcb);
2825 bExtentsLocked = TRUE;
2827 InterlockedIncrement( &Fcb->Specific.File.QueuedFlushCount);
2830 // Clear our queued flush event
2833 KeClearEvent( &Fcb->NPFcb->Specific.File.QueuedFlushEvent);
2836 // Look for a start in the list to flush entries
2841 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
2843 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
2845 AFS_EXTENT_RELEASE_TAG);
2846 if( NULL == pRelease)
2849 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2852 initialDirtyCount = Fcb->Specific.File.ExtentsDirtyCount;
2854 while( Fcb->Specific.File.ExtentsDirtyCount > 0)
2857 pRelease->Flags = AFS_EXTENT_FLAG_DIRTY;
2859 if( BooleanFlagOn( Fcb->Flags, AFS_FCB_FILE_CLOSED))
2862 pRelease->Flags |= AFS_EXTENT_FLAG_FLUSH;
2866 // Update the metadata for this call
2869 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
2870 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
2871 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
2872 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
2873 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
2877 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
2880 pExtent = (AFSExtent *)pNPFcb->Specific.File.DirtyListHead;
2882 while( count < AFS_MAXIMUM_EXTENT_RELEASE_COUNT)
2885 if ( pExtent == NULL)
2891 pNextExtent = (AFSExtent *)pExtent->DirtyList.fLink;
2893 if ( pExtent->ActiveCount > 0)
2895 pExtent = pNextExtent;
2899 AFSRemoveEntryDirtyList( Fcb, pExtent);
2901 pExtent->DirtyList.fLink = NULL;
2902 pExtent->DirtyList.bLink = NULL;
2904 InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
2907 // Clear the flag in advance of the write. If we do
2908 // things this was we know that the clear is
2909 // pessimistic (any write which happens from now on
2910 // will set the flag dirty again).
2913 pExtent->Flags &= ~AFS_EXTENT_DIRTY;
2915 pRelease->FileExtents[count].Flags = AFS_EXTENT_FLAG_DIRTY;
2917 pRelease->FileExtents[count].Length = pExtent->Size;
2918 pRelease->FileExtents[count].DirtyLength = pExtent->Size;
2919 pRelease->FileExtents[count].DirtyOffset = 0;
2920 pRelease->FileExtents[count].CacheOffset = pExtent->CacheOffset;
2921 pRelease->FileExtents[count].FileOffset = pExtent->FileOffset;
2924 RtlCopyMemory( pRelease->FileExtents[count].MD5,
2926 sizeof(pExtent->MD5));
2928 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_MD5_SET;
2931 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2932 AFS_TRACE_LEVEL_VERBOSE,
2933 "AFSFlushExtents Releasing DIRTY extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
2935 Fcb->ObjectInformation->FileId.Cell,
2936 Fcb->ObjectInformation->FileId.Volume,
2937 Fcb->ObjectInformation->FileId.Vnode,
2938 Fcb->ObjectInformation->FileId.Unique,
2939 pExtent->FileOffset.QuadPart,
2942 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_RELEASE;
2945 // Need to pull this extent from the main list as well
2948 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
2950 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
2952 RemoveEntryList( &pExtent->Lists[i] );
2956 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
2958 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
2960 AFSExFreePool( pExtent);
2962 InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
2964 if( InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount) == 0)
2967 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
2974 pExtent = pNextExtent;
2977 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
2980 // If we are done then get out
2986 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
2987 AFS_TRACE_LEVEL_VERBOSE,
2988 "AFSFlushExtents No more dirty extents found\n");
2994 // Fire off the request synchronously
2997 sz = sizeof( AFSReleaseExtentsCB ) + (count * sizeof ( AFSFileExtentCB ));
2999 pRelease->ExtentCount = count;
3001 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3002 AFS_TRACE_LEVEL_VERBOSE,
3003 "AFSFlushExtents Releasing(1) Fcb extents lock %08lX SHARED %08lX\n",
3004 &pNPFcb->Specific.File.ExtentsResource,
3005 PsGetCurrentThread());
3007 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource);
3008 bExtentsLocked = FALSE;
3010 KeSetEvent( &pNPFcb->Specific.File.FlushEvent,
3014 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
3015 AFS_REQUEST_FLAG_SYNCHRONOUS,
3018 &Fcb->ObjectInformation->FileId,
3024 if( !NT_SUCCESS(ntStatus))
3028 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
3029 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
3032 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3033 AFS_TRACE_LEVEL_ERROR,
3034 "AFSFlushExtents AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3035 Fcb->ObjectInformation->FileId.Cell,
3036 Fcb->ObjectInformation->FileId.Volume,
3037 Fcb->ObjectInformation->FileId.Vnode,
3038 Fcb->ObjectInformation->FileId.Unique,
3042 AFSLockForExtentsTrim( Fcb);
3044 bExtentsLocked = TRUE;
3049 if( InterlockedDecrement( &Fcb->Specific.File.QueuedFlushCount) == 0)
3052 KeSetEvent( &pNPFcb->Specific.File.QueuedFlushEvent,
3057 KeSetEvent( &pNPFcb->Specific.File.FlushEvent,
3064 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3065 AFS_TRACE_LEVEL_VERBOSE,
3066 "AFSFlushExtents Releasing(2) Fcb extents lock %08lX SHARED %08lX\n",
3067 &pNPFcb->Specific.File.ExtentsResource,
3068 PsGetCurrentThread());
3070 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
3075 AFSExFreePool( pRelease);
3083 AFSReleaseExtentsWithFlush( IN AFSFcb *Fcb,
3086 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3089 AFSReleaseExtentsCB *pRelease = NULL;
3091 ULONG initialDirtyCount = 0;
3092 BOOLEAN bExtentsLocked = FALSE;
3095 NTSTATUS ntStatus = STATUS_SUCCESS;
3096 LARGE_INTEGER liLastFlush;
3097 ULONG ulRemainingExtentLength = 0;
3098 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3099 GUID *pAuthGroup = AuthGroup;
3102 ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
3105 // Save, then reset the flush time
3108 liLastFlush = Fcb->Specific.File.LastServerFlush;
3110 KeQueryTickCount( &Fcb->Specific.File.LastServerFlush);
3115 if( pAuthGroup == NULL)
3118 RtlZeroMemory( &stAuthGroup,
3121 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
3126 if( !NT_SUCCESS( ntStatus))
3128 try_return( ntStatus);
3131 pAuthGroup = &stAuthGroup;
3135 // Look for a start in the list to flush entries
3140 sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
3142 pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
3144 AFS_EXTENT_RELEASE_TAG);
3145 if( NULL == pRelease)
3148 try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
3151 if( Fcb->OpenHandleCount > 0)
3155 // Don't release everything ...
3159 // For now release everything
3162 //ulRemainingExtentLength = 1500;
3165 while( Fcb->Specific.File.ExtentLength > (LONG)ulRemainingExtentLength)
3168 AFSLockForExtentsTrim( Fcb);
3170 bExtentsLocked = TRUE;
3172 pRelease->Flags = AFS_EXTENT_FLAG_RELEASE;
3175 // Update the metadata for this call
3178 pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
3179 pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
3180 pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
3181 pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
3182 pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
3186 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3188 while( count < AFS_MAXIMUM_EXTENT_RELEASE_COUNT &&
3189 le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
3192 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3196 if( pExtent->ActiveCount > 0)
3202 pRelease->FileExtents[count].Flags = AFS_EXTENT_FLAG_RELEASE;
3204 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3205 AFS_TRACE_LEVEL_VERBOSE,
3206 "AFSReleaseExtentsWithFlush Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3208 Fcb->ObjectInformation->FileId.Cell,
3209 Fcb->ObjectInformation->FileId.Volume,
3210 Fcb->ObjectInformation->FileId.Vnode,
3211 Fcb->ObjectInformation->FileId.Unique,
3212 pExtent->FileOffset.QuadPart,
3215 pRelease->FileExtents[count].Length = pExtent->Size;
3216 pRelease->FileExtents[count].DirtyLength = pExtent->Size;
3217 pRelease->FileExtents[count].DirtyOffset = 0;
3218 pRelease->FileExtents[count].CacheOffset = pExtent->CacheOffset;
3219 pRelease->FileExtents[count].FileOffset = pExtent->FileOffset;
3222 RtlCopyMemory( pRelease->FileExtents[count].MD5,
3224 sizeof(pExtent->MD5));
3226 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_MD5_SET;
3229 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3232 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3235 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3238 AFSRemoveEntryDirtyList( Fcb,
3241 pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_DIRTY;
3243 InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
3246 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3250 // Need to pull this extent from the main list as well
3253 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
3255 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
3257 RemoveEntryList( &pExtent->Lists[i] );
3261 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
3263 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
3265 AFSExFreePool( pExtent);
3267 InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
3269 if( InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount) == 0)
3272 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
3281 // If we are done then get out
3287 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3288 AFS_TRACE_LEVEL_VERBOSE,
3289 "AFSReleaseExtentsWithFlush No more dirty extents found\n");
3295 // Fire off the request synchronously
3298 sz = sizeof( AFSReleaseExtentsCB ) + (count * sizeof ( AFSFileExtentCB ));
3300 pRelease->ExtentCount = count;
3303 // Drop the extents lock for the duration of the call to
3304 // the network. We have pinned the extents so, even
3305 // though we might get extents added during this period,
3306 // but none will be removed. Hence we can carry on from
3310 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3311 AFS_TRACE_LEVEL_VERBOSE,
3312 "AFSReleaseExtentsWithFlush Releasing Fcb extents lock %08lX thread %08lX\n",
3313 &pNPFcb->Specific.File.ExtentsResource,
3314 PsGetCurrentThread());
3316 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource);
3317 bExtentsLocked = FALSE;
3319 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
3320 AFS_REQUEST_FLAG_SYNCHRONOUS,
3323 &Fcb->ObjectInformation->FileId,
3329 if( !NT_SUCCESS(ntStatus))
3333 // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
3334 // were released (if AFS_EXTENT_FLAG_RELEASE was set). Log the error so it is known.
3337 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3338 AFS_TRACE_LEVEL_ERROR,
3339 "AFSReleaseExtentsWithFlush AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3340 Fcb->ObjectInformation->FileId.Cell,
3341 Fcb->ObjectInformation->FileId.Volume,
3342 Fcb->ObjectInformation->FileId.Vnode,
3343 Fcb->ObjectInformation->FileId.Unique,
3353 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3354 AFS_TRACE_LEVEL_VERBOSE,
3355 "AFSReleaseExtentsWithFlush Releasing Fcb extents lock %08lX thread %08lX\n",
3356 &pNPFcb->Specific.File.ExtentsResource,
3357 PsGetCurrentThread());
3359 AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
3364 AFSExFreePool( pRelease);
3372 AFSMarkDirty( IN AFSFcb *Fcb,
3373 IN AFSExtent *StartExtent,
3374 IN ULONG ExtentsCount,
3375 IN LARGE_INTEGER *StartingByte)
3378 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3379 AFSExtent *pExtent = StartExtent;
3380 AFSExtent *pNextExtent, *pCurrentExtent = NULL;
3382 BOOLEAN bInsertTail = FALSE, bInsertHead = FALSE;
3384 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3385 AFS_TRACE_LEVEL_VERBOSE,
3386 "AFSMarkDirty Acquiring Fcb extents lock %08lX SHARED %08lX\n",
3387 &Fcb->NPFcb->Specific.File.ExtentsResource,
3388 PsGetCurrentThread());
3390 AFSAcquireShared( &Fcb->NPFcb->Specific.File.ExtentsResource, TRUE);
3392 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3396 // Find the insertion point
3399 if( pNPFcb->Specific.File.DirtyListHead == NULL)
3404 else if( StartingByte->QuadPart == 0)
3412 pCurrentExtent = pNPFcb->Specific.File.DirtyListHead;
3414 while( pCurrentExtent != NULL)
3417 if( pCurrentExtent->FileOffset.QuadPart + pCurrentExtent->Size >= StartingByte->QuadPart ||
3418 pCurrentExtent->DirtyList.fLink == NULL)
3424 pCurrentExtent = (AFSExtent *)pCurrentExtent->DirtyList.fLink;
3428 while( ulCount < ExtentsCount)
3431 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
3433 if( !BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3436 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3437 AFS_TRACE_LEVEL_VERBOSE,
3438 "AFSMarkDirty Marking extent offset %I64X Length %08lX DIRTY\n",
3439 pExtent->FileOffset.QuadPart,
3442 pExtent->DirtyList.fLink = NULL;
3443 pExtent->DirtyList.bLink = NULL;
3448 pExtent->DirtyList.fLink = (void *)pNPFcb->Specific.File.DirtyListHead;
3450 pExtent->DirtyList.bLink = NULL;
3452 pNPFcb->Specific.File.DirtyListHead->DirtyList.bLink = (void *)pExtent;
3454 pNPFcb->Specific.File.DirtyListHead = pExtent;
3456 pCurrentExtent = pExtent;
3458 bInsertHead = FALSE;
3460 else if( bInsertTail)
3463 if( pNPFcb->Specific.File.DirtyListHead == NULL)
3466 pNPFcb->Specific.File.DirtyListHead = pExtent;
3471 pNPFcb->Specific.File.DirtyListTail->DirtyList.fLink = (void *)pExtent;
3473 pExtent->DirtyList.bLink = (void *)pNPFcb->Specific.File.DirtyListTail;
3476 pNPFcb->Specific.File.DirtyListTail = pExtent;
3481 pExtent->DirtyList.fLink = pCurrentExtent->DirtyList.fLink;
3482 pExtent->DirtyList.bLink = (void *)pCurrentExtent;
3484 if( pExtent->DirtyList.fLink == NULL)
3487 pNPFcb->Specific.File.DirtyListTail = pExtent;
3492 ((AFSExtent *)pExtent->DirtyList.fLink)->DirtyList.bLink = (void *)pExtent;
3495 pCurrentExtent->DirtyList.fLink = (void *)pExtent;
3497 pCurrentExtent = pExtent;
3500 pExtent->Flags |= AFS_EXTENT_DIRTY;
3503 // Up the dirty count
3506 InterlockedIncrement( &Fcb->Specific.File.ExtentsDirtyCount);
3511 pCurrentExtent = pExtent;
3514 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_ACTIVE_COUNTING,
3515 AFS_TRACE_LEVEL_VERBOSE,
3516 "AFSMarkDirty Decrement count on extent %08lX Cnt %d\n",
3518 pExtent->ActiveCount);
3520 ASSERT( pExtent->ActiveCount > 0);
3522 InterlockedDecrement( &pExtent->ActiveCount);
3524 pExtent = pNextExtent;
3529 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3531 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3532 AFS_TRACE_LEVEL_VERBOSE,
3533 "AFSMarkDirty Releasing Fcb extents lock %08lX SHARED %08lX\n",
3534 &Fcb->NPFcb->Specific.File.ExtentsResource,
3535 PsGetCurrentThread());
3537 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
3546 static AFSExtent *ExtentFor(PLIST_ENTRY le, ULONG SkipList)
3548 return CONTAINING_RECORD( le, AFSExtent, Lists[SkipList] );
3551 static AFSExtent *NextExtent(AFSExtent *Extent, ULONG SkipList)
3553 return ExtentFor(Extent->Lists[SkipList].Flink, SkipList);
3556 static AFSExtent *DirtyExtentFor(PLIST_ENTRY le)
3558 return CONTAINING_RECORD( le, AFSExtent, DirtyList );
3561 static VOID VerifyExtentsLists(AFSFcb *Fcb)
3565 // Check the ordering of the extents lists
3567 ASSERT( ExIsResourceAcquiredLite( &Fcb->NPFcb->Specific.File.ExtentsResource ));
3569 ASSERT(Fcb->Specific.File.ExtentsLists[0].Flink != &Fcb->Specific.File.ExtentsLists[1]);
3571 for (ULONG listNo = 0; listNo < AFS_NUM_EXTENT_LISTS; listNo ++)
3573 LARGE_INTEGER lastOffset;
3575 lastOffset.QuadPart = 0;
3577 for (PLIST_ENTRY pLe = Fcb->Specific.File.ExtentsLists[listNo].Flink;
3578 pLe != &Fcb->Specific.File.ExtentsLists[listNo];
3583 pExtent = ExtentFor(pLe, listNo);
3586 ASSERT(pLe != &Fcb->Specific.File.ExtentsLists[1] &&
3587 pLe->Flink !=&Fcb->Specific.File.ExtentsLists[1] &&
3588 pLe->Blink !=&Fcb->Specific.File.ExtentsLists[1]);
3591 ASSERT(pLe->Flink->Blink == pLe);
3592 ASSERT(pLe->Blink->Flink == pLe);
3595 // Should follow on from previous
3597 ASSERT(pExtent->FileOffset.QuadPart >= lastOffset.QuadPart);
3598 lastOffset.QuadPart = pExtent->FileOffset.QuadPart + pExtent->Size;
3601 // Should match alignment criteria
3603 ASSERT( 0 == (pExtent->FileOffset.LowPart & ExtentsMasks[listNo]) );
3606 // "lower" lists should be populated
3608 for (LONG subListNo = listNo-1; subListNo > 0; subListNo --)
3610 ASSERT( !IsListEmpty(&pExtent->Lists[subListNo]));
3618 AFSTrimExtents( IN AFSFcb *Fcb,
3619 IN PLARGE_INTEGER FileSize)
3622 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3625 BOOLEAN locked = FALSE;
3626 NTSTATUS ntStatus = STATUS_SUCCESS;
3627 LARGE_INTEGER liAlignedOffset = {0,0};
3628 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
3629 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3635 // Get an aligned offset
3638 if( FileSize != NULL)
3641 liAlignedOffset = *FileSize;
3644 if( liAlignedOffset.QuadPart > 0 &&
3645 liAlignedOffset.QuadPart % pDevExt->Specific.RDR.CacheBlockSize != 0)
3649 // Align UP to the next cache block size
3652 liAlignedOffset.QuadPart = (ULONGLONG)( (ULONGLONG)((liAlignedOffset.QuadPart / pDevExt->Specific.RDR.CacheBlockSize) + 1) * (ULONGLONG)pDevExt->Specific.RDR.CacheBlockSize);
3656 // Ensure that no one is working with the extents and grab the
3660 AFSLockForExtentsTrim( Fcb);
3664 if( 0 == Fcb->Specific.File.ExtentCount)
3668 // Update the request extent status
3671 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
3673 try_return( ntStatus = STATUS_SUCCESS);
3677 // We are truncating from a specific length in the file. If the offset
3678 // is non-zero then go find the first extent to remove
3681 if( 0 == FileSize->QuadPart)
3684 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3689 pExtent = AFSExtentForOffset( Fcb,
3693 if( NULL == pExtent)
3696 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3700 le = &pExtent->Lists[AFS_EXTENTS_LIST];
3704 while( le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
3707 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3710 // Only trim down extents beyond the aligned offset
3715 if( pExtent->FileOffset.QuadPart >= liAlignedOffset.QuadPart)
3718 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3721 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3724 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3728 AFSRemoveEntryDirtyList( Fcb,
3731 dirtyCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
3733 ASSERT(dirtyCount >= 0);
3736 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3739 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
3741 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
3743 RemoveEntryList( &pExtent->Lists[i] );
3747 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3748 AFS_TRACE_LEVEL_VERBOSE,
3749 "AFSTrimExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3751 Fcb->ObjectInformation->FileId.Cell,
3752 Fcb->ObjectInformation->FileId.Volume,
3753 Fcb->ObjectInformation->FileId.Vnode,
3754 Fcb->ObjectInformation->FileId.Unique,
3755 pExtent->FileOffset.QuadPart,
3758 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
3760 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
3762 ASSERT( pExtent->ActiveCount == 0);
3767 AFSExFreePool( pExtent);
3769 InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
3771 if( InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount) == 0)
3774 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
3782 // Update the request extent status
3785 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
3792 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3793 AFS_TRACE_LEVEL_VERBOSE,
3794 "AFSTrimExtents Releasing Fcb extents lock %08lX thread %08lX\n",
3795 &Fcb->NPFcb->Specific.File.ExtentsResource,
3796 PsGetCurrentThread());
3798 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
3806 AFSTrimSpecifiedExtents( IN AFSFcb *Fcb,
3808 IN AFSFileExtentCB *Result)
3811 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
3814 AFSFileExtentCB *pFileExtents = Result;
3815 NTSTATUS ntStatus = STATUS_SUCCESS;
3816 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
3817 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3822 le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
3824 while( le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST] &&
3828 pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
3831 // Only trim down extents beyond the aligned offset
3836 if( pExtent->FileOffset.QuadPart == pFileExtents->FileOffset.QuadPart)
3839 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3842 AFSAcquireExcl( &pNPFcb->Specific.File.DirtyExtentsListLock,
3845 if( BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
3850 AFSRemoveEntryDirtyList( Fcb,
3853 dirtyCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
3855 ASSERT( dirtyCount >= 0);
3859 AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
3863 for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
3865 if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
3867 RemoveEntryList( &pExtent->Lists[i] );
3871 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3872 AFS_TRACE_LEVEL_VERBOSE,
3873 "AFSTrimSpecifiedExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
3875 Fcb->ObjectInformation->FileId.Cell,
3876 Fcb->ObjectInformation->FileId.Volume,
3877 Fcb->ObjectInformation->FileId.Vnode,
3878 Fcb->ObjectInformation->FileId.Unique,
3879 pExtent->FileOffset.QuadPart,
3882 InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
3884 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
3886 ASSERT( pExtent->ActiveCount == 0);
3891 AFSExFreePool( pExtent);
3893 InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
3895 if( InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount) == 0)
3898 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
3904 // Next extent we are looking for
3914 // Update the request extent status
3917 Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
3924 AFSReferenceActiveExtents( IN AFSExtent *StartExtent,
3925 IN ULONG ExtentsCount)
3928 AFSExtent *pExtent = StartExtent;
3929 AFSExtent *pNextExtent;
3932 while( ulCount < ExtentsCount)
3935 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
3937 InterlockedIncrement( &pExtent->ActiveCount);
3939 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_ACTIVE_COUNTING,
3940 AFS_TRACE_LEVEL_VERBOSE,
3941 "AFSReferenceActiveExtents Increment count on extent %08lX Cnt %d\n",
3943 pExtent->ActiveCount);
3945 pExtent = pNextExtent;
3954 AFSDereferenceActiveExtents( IN AFSExtent *StartExtent,
3955 IN ULONG ExtentsCount)
3958 AFSExtent *pExtent = StartExtent;
3959 AFSExtent *pNextExtent;
3962 while( ulCount < ExtentsCount)
3965 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
3967 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_ACTIVE_COUNTING,
3968 AFS_TRACE_LEVEL_VERBOSE,
3969 "AFSDereferenceActiveExtents Decrement count on extent %08lX Cnt %d\n",
3971 pExtent->ActiveCount);
3973 ASSERT( pExtent->ActiveCount > 0);
3975 InterlockedDecrement( &pExtent->ActiveCount);
3977 pExtent = pNextExtent;
3986 AFSRemoveEntryDirtyList( IN AFSFcb *Fcb,
3987 IN AFSExtent *Extent)
3990 if( Extent->DirtyList.fLink == NULL)
3993 Fcb->NPFcb->Specific.File.DirtyListTail = (AFSExtent *)Extent->DirtyList.bLink;
3995 if( Fcb->NPFcb->Specific.File.DirtyListTail != NULL)
3998 Fcb->NPFcb->Specific.File.DirtyListTail->DirtyList.fLink = NULL;
4004 ((AFSExtent *)Extent->DirtyList.fLink)->DirtyList.bLink = Extent->DirtyList.bLink;
4007 if( Extent->DirtyList.bLink == NULL)
4010 Fcb->NPFcb->Specific.File.DirtyListHead = (AFSExtent *)Extent->DirtyList.fLink;
4012 if( Fcb->NPFcb->Specific.File.DirtyListHead != NULL)
4015 Fcb->NPFcb->Specific.File.DirtyListHead->DirtyList.bLink = NULL;
4021 ((AFSExtent *)Extent->DirtyList.bLink)->DirtyList.fLink = Extent->DirtyList.fLink;
4030 AFSSetupMD5Hash( IN AFSFcb *Fcb,
4031 IN AFSExtent *StartExtent,
4032 IN ULONG ExtentsCount,
4033 IN void *SystemBuffer,
4034 IN LARGE_INTEGER *ByteOffset,
4038 NTSTATUS ntStatus = STATUS_SUCCESS;
4039 AFSNonPagedFcb *pNPFcb = Fcb->NPFcb;
4040 AFSExtent *pExtent = StartExtent;
4041 AFSExtent *pNextExtent, *pCurrentExtent = NULL;
4043 char *pCurrentBuffer = (char *)SystemBuffer;
4044 char *pMD5Buffer = NULL;
4045 ULONG ulCurrentLen = 0;
4046 void *pExtentBuffer = NULL;
4047 LARGE_INTEGER liByteOffset;
4048 ULONG ulBytesRead = 0;
4053 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4054 AFS_TRACE_LEVEL_VERBOSE,
4055 "AFSSetupMD5Hash Acquiring Fcb extents lock %08lX SHARED %08lX\n",
4056 &Fcb->NPFcb->Specific.File.ExtentsResource,
4057 PsGetCurrentThread());
4059 AFSAcquireShared( &Fcb->NPFcb->Specific.File.ExtentsResource, TRUE);
4061 liByteOffset.QuadPart = ByteOffset->QuadPart;
4063 while( ulCount < ExtentsCount)
4066 RtlZeroMemory( pExtent->MD5,
4067 sizeof( pExtent->MD5));
4069 pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
4071 if( liByteOffset.QuadPart == pExtent->FileOffset.QuadPart &&
4072 ByteCount < pExtent->Size)
4075 if( pExtentBuffer == NULL)
4078 pExtentBuffer = AFSExAllocatePoolWithTag( PagedPool,
4080 AFS_GENERIC_MEMORY_9_TAG);
4082 if( pExtentBuffer == NULL)
4089 RtlZeroMemory( pExtentBuffer,
4092 RtlCopyMemory( pExtentBuffer,
4096 pMD5Buffer = (char *)pExtentBuffer;
4098 ulCurrentLen = ByteCount;
4100 else if( liByteOffset.QuadPart != pExtent->FileOffset.QuadPart)
4103 pExtentBuffer = AFSExAllocatePoolWithTag( PagedPool,
4105 AFS_GENERIC_MEMORY_10_TAG);
4107 if( pExtentBuffer == NULL)
4113 RtlZeroMemory( pExtentBuffer,
4116 if( BooleanFlagOn( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE))
4120 RtlCopyMemory( pExtentBuffer,
4121 ((char *)AFSLibCacheBaseAddress + pExtent->CacheOffset.QuadPart),
4124 ASSERT( pExtent->CacheOffset.HighPart == 0);
4125 RtlCopyMemory( pExtentBuffer,
4126 ((char *)AFSLibCacheBaseAddress + pExtent->CacheOffset.LowPart),
4130 ulBytesRead = pExtent->Size;
4135 ntStatus = AFSReadCacheFile( pExtentBuffer,
4136 &pExtent->CacheOffset,
4140 if( !NT_SUCCESS( ntStatus))
4146 pMD5Buffer = (char *)pExtentBuffer;
4148 ulCurrentLen = min( ByteCount, pExtent->Size - (ULONG)(liByteOffset.QuadPart - pExtent->FileOffset.QuadPart));
4150 RtlCopyMemory( (void *)((char *)pExtentBuffer + (ULONG)(liByteOffset.QuadPart - pExtent->FileOffset.QuadPart)),
4157 ulCurrentLen = pExtent->Size;
4159 pMD5Buffer = pCurrentBuffer;
4162 AFSGenerateMD5( pMD5Buffer,
4166 pExtent = pNextExtent;
4170 ByteCount -= ulCurrentLen;
4172 pCurrentBuffer += ulCurrentLen;
4174 liByteOffset.QuadPart += ulCurrentLen;
4177 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4178 AFS_TRACE_LEVEL_VERBOSE,
4179 "AFSSetupMD5Hash Releasing Fcb extents lock %08lX SHARED %08lX\n",
4180 &Fcb->NPFcb->Specific.File.ExtentsResource,
4181 PsGetCurrentThread());
4183 AFSReleaseResource( &Fcb->NPFcb->Specific.File.ExtentsResource );
4185 if( pExtentBuffer != NULL)
4188 AFSExFreePool( pExtentBuffer);