[NTFS] Correctly find attributes stored in another file record in MFT (and referenced...
[reactos.git] / drivers / filesystems / ntfs / mft.c
index 4896d6d..e1411f0 100644 (file)
@@ -42,9 +42,7 @@ PrepareAttributeContext(PNTFS_ATTR_RECORD AttrRecord)
 {
     PNTFS_ATTR_CONTEXT Context;
 
-    Context = ExAllocatePoolWithTag(NonPagedPool,
-                                    sizeof(NTFS_ATTR_CONTEXT),
-                                    TAG_NTFS);
+    Context = ExAllocateFromNPagedLookasideList(&NtfsGlobalData->AttrCtxtLookasideList);
     if(!Context)
     {
         DPRINT1("Error: Unable to allocate memory for context!\n");
@@ -56,7 +54,7 @@ PrepareAttributeContext(PNTFS_ATTR_RECORD AttrRecord)
     if(!Context->pRecord)
     {
         DPRINT1("Error: Unable to allocate memory for attribute record!\n");
-        ExFreePoolWithTag(Context, TAG_NTFS);
+        ExFreeToNPagedLookasideList(&NtfsGlobalData->AttrCtxtLookasideList, Context);
         return NULL;
     }
 
@@ -93,7 +91,7 @@ PrepareAttributeContext(PNTFS_ATTR_RECORD AttrRecord)
         {
             DPRINT1("Unable to convert data runs to MCB!\n");
             ExFreePoolWithTag(Context->pRecord, TAG_NTFS);
-            ExFreePoolWithTag(Context, TAG_NTFS);
+            ExFreeToNPagedLookasideList(&NtfsGlobalData->AttrCtxtLookasideList, Context);
             return NULL;
         }
     }
@@ -105,15 +103,17 @@ PrepareAttributeContext(PNTFS_ATTR_RECORD AttrRecord)
 VOID
 ReleaseAttributeContext(PNTFS_ATTR_CONTEXT Context)
 {
-    if (Context->pRecord->IsNonResident)
+    if (Context->pRecord)
     {
-        FsRtlUninitializeLargeMcb(&Context->DataRunsMCB);
-    }
+        if (Context->pRecord->IsNonResident)
+        {
+            FsRtlUninitializeLargeMcb(&Context->DataRunsMCB);
+        }
 
-    if(Context->pRecord)
         ExFreePoolWithTag(Context->pRecord, TAG_NTFS);
+    }
 
-    ExFreePoolWithTag(Context, TAG_NTFS);
+    ExFreeToNPagedLookasideList(&NtfsGlobalData->AttrCtxtLookasideList, Context);
 }
 
 
@@ -140,6 +140,7 @@ FindAttribute(PDEVICE_EXTENSION Vcb,
     NTSTATUS Status;
     FIND_ATTR_CONTXT Context;
     PNTFS_ATTR_RECORD Attribute;
+    PNTFS_ATTRIBUTE_LIST_ITEM AttrListItem;
 
     DPRINT("FindAttribute(%p, %p, 0x%x, %S, %lu, %p, %p)\n", Vcb, MftRecord, Type, Name, NameLength, AttrCtx, Offset);
 
@@ -184,6 +185,61 @@ FindAttribute(PDEVICE_EXTENSION Vcb,
         Status = FindNextAttribute(&Context, &Attribute);
     }
 
+    /* No attribute found, check if it is referenced in another file record */
+    Status = FindFirstAttributeListItem(&Context, &AttrListItem);
+    while (NT_SUCCESS(Status))
+    {
+        if (AttrListItem->Type == Type && AttrListItem->NameLength == NameLength)
+        {
+            if (NameLength != 0)
+            {
+                PWCHAR AttrName;
+
+                AttrName = (PWCHAR)((PCHAR)AttrListItem + AttrListItem->NameOffset);
+                DPRINT("%.*S, %.*S\n", AttrListItem->NameLength, AttrName, NameLength, Name);
+                if (RtlCompareMemory(AttrName, Name, NameLength * sizeof(WCHAR)) == (NameLength  * sizeof(WCHAR)))
+                {
+                    Found = TRUE;
+                }
+            }
+            else
+            {
+                Found = TRUE;
+            }
+
+            if (Found == TRUE)
+            {
+                /* Get the MFT Index of attribute */
+                ULONGLONG MftIndex;
+                PFILE_RECORD_HEADER RemoteHdr;
+
+                MftIndex = AttrListItem->MFTIndex & NTFS_MFT_MASK;
+                RemoteHdr = ExAllocateFromNPagedLookasideList(&Vcb->FileRecLookasideList);
+
+                if (RemoteHdr == NULL)
+                {
+                    FindCloseAttribute(&Context);
+                    return STATUS_INSUFFICIENT_RESOURCES;
+                }
+
+                /* Check we are not reading ourselves */
+                if (MftRecord->MFTRecordNumber == MftIndex)
+                {
+                    DPRINT1("Attribute list references missing attribute to this file entry !");
+                    ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, RemoteHdr);
+                    FindCloseAttribute(&Context);
+                    return STATUS_OBJECT_NAME_NOT_FOUND;
+                }
+                /* Read the new file record */
+                ReadFileRecord(Vcb, MftIndex, RemoteHdr);
+                Status = FindAttribute(Vcb, RemoteHdr, Type, Name, NameLength, AttrCtx, Offset);
+                ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, RemoteHdr);
+                FindCloseAttribute(&Context);
+                return Status;
+            }
+        }
+        Status = FindNextAttributeListItem(&Context, &AttrListItem);
+    }
     FindCloseAttribute(&Context);
     return STATUS_OBJECT_NAME_NOT_FOUND;
 }
@@ -277,7 +333,7 @@ IncreaseMftSize(PDEVICE_EXTENSION Vcb, BOOLEAN CanWait)
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("ERROR: Couldn't find $BITMAP attribute of Mft!\n");
-        ExFreePoolWithTag(BlankFileRecord, TAG_NTFS);
+        ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, BlankFileRecord);
         ExReleaseResourceLite(&(Vcb->DirResource));
         return Status;
     }
@@ -308,7 +364,7 @@ IncreaseMftSize(PDEVICE_EXTENSION Vcb, BOOLEAN CanWait)
     if (!BitmapBuffer)
     {
         DPRINT1("ERROR: Unable to allocate memory for bitmap attribute!\n");
-        ExFreePoolWithTag(BlankFileRecord, TAG_NTFS);
+        ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, BlankFileRecord);
         ExReleaseResourceLite(&(Vcb->DirResource));
         ReleaseAttributeContext(BitmapContext);
         return STATUS_INSUFFICIENT_RESOURCES;
@@ -326,7 +382,7 @@ IncreaseMftSize(PDEVICE_EXTENSION Vcb, BOOLEAN CanWait)
     if (BytesRead != BitmapSize.LowPart)
     {
         DPRINT1("ERROR: Bytes read != Bitmap size!\n");
-        ExFreePoolWithTag(BlankFileRecord, TAG_NTFS);
+        ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, BlankFileRecord);
         ExReleaseResourceLite(&(Vcb->DirResource));
         ExFreePoolWithTag(BitmapBuffer, TAG_NTFS);
         ReleaseAttributeContext(BitmapContext);
@@ -338,7 +394,7 @@ IncreaseMftSize(PDEVICE_EXTENSION Vcb, BOOLEAN CanWait)
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("ERROR: Failed to set size of $MFT data attribute!\n");
-        ExFreePoolWithTag(BlankFileRecord, TAG_NTFS);
+        ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, BlankFileRecord);
         ExReleaseResourceLite(&(Vcb->DirResource));
         ExFreePoolWithTag(BitmapBuffer, TAG_NTFS);
         ReleaseAttributeContext(BitmapContext);
@@ -351,7 +407,7 @@ IncreaseMftSize(PDEVICE_EXTENSION Vcb, BOOLEAN CanWait)
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("ERROR: Couldn't find $BITMAP attribute of Mft!\n");
-        ExFreePoolWithTag(BlankFileRecord, TAG_NTFS);
+        ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, BlankFileRecord);
         ExReleaseResourceLite(&(Vcb->DirResource));
         return Status;
     }
@@ -369,7 +425,7 @@ IncreaseMftSize(PDEVICE_EXTENSION Vcb, BOOLEAN CanWait)
         if (!NT_SUCCESS(Status))
         {
             DPRINT1("ERROR: Failed to set size of bitmap attribute!\n");
-            ExFreePoolWithTag(BlankFileRecord, TAG_NTFS);
+            ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, BlankFileRecord);
             ExReleaseResourceLite(&(Vcb->DirResource));
             ExFreePoolWithTag(BitmapBuffer, TAG_NTFS);
             ReleaseAttributeContext(BitmapContext);
@@ -384,7 +440,7 @@ IncreaseMftSize(PDEVICE_EXTENSION Vcb, BOOLEAN CanWait)
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("ERROR: Failed to update $MFT file record!\n");
-        ExFreePoolWithTag(BlankFileRecord, TAG_NTFS);
+        ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, BlankFileRecord);
         ExReleaseResourceLite(&(Vcb->DirResource));
         ExFreePoolWithTag(BitmapBuffer, TAG_NTFS);
         ReleaseAttributeContext(BitmapContext);
@@ -395,7 +451,7 @@ IncreaseMftSize(PDEVICE_EXTENSION Vcb, BOOLEAN CanWait)
     Status = WriteAttribute(Vcb, BitmapContext, 0, BitmapBuffer, NewBitmapSize, &LengthWritten, Vcb->MasterFileTable);
     if (!NT_SUCCESS(Status))
     {
-        ExFreePoolWithTag(BlankFileRecord, TAG_NTFS);
+        ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, BlankFileRecord);
         ExReleaseResourceLite(&(Vcb->DirResource));
         ExFreePoolWithTag(BitmapBuffer, TAG_NTFS);
         ReleaseAttributeContext(BitmapContext);
@@ -410,7 +466,7 @@ IncreaseMftSize(PDEVICE_EXTENSION Vcb, BOOLEAN CanWait)
         if (!NT_SUCCESS(Status))
         {
             DPRINT1("ERROR: Failed to write blank file record!\n");
-            ExFreePoolWithTag(BlankFileRecord, TAG_NTFS);
+            ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, BlankFileRecord);
             ExReleaseResourceLite(&(Vcb->DirResource));
             ExFreePoolWithTag(BitmapBuffer, TAG_NTFS);
             ReleaseAttributeContext(BitmapContext);
@@ -422,7 +478,7 @@ IncreaseMftSize(PDEVICE_EXTENSION Vcb, BOOLEAN CanWait)
     Status = UpdateMftMirror(Vcb);
 
     // Cleanup
-    ExFreePoolWithTag(BlankFileRecord, TAG_NTFS);
+    ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, BlankFileRecord);
     ExReleaseResourceLite(&(Vcb->DirResource));
     ExFreePoolWithTag(BitmapBuffer, TAG_NTFS);
     ReleaseAttributeContext(BitmapContext);
@@ -948,6 +1004,7 @@ SetResidentAttributeDataLength(PDEVICE_EXTENSION Vcb,
                     DPRINT1("Unable to create LargeMcb!\n");
                     if (AttribDataSize.QuadPart > 0)
                         ExFreePoolWithTag(AttribData, TAG_NTFS);
+                    ExFreePoolWithTag(NewRecord, TAG_NTFS);
                     _SEH2_YIELD(return _SEH2_GetExceptionCode());
                 } _SEH2_END;
 
@@ -961,6 +1018,7 @@ SetResidentAttributeDataLength(PDEVICE_EXTENSION Vcb,
                     DPRINT1("ERROR: Couldn't update file record to continue migration!\n");
                     if (AttribDataSize.QuadPart > 0)
                         ExFreePoolWithTag(AttribData, TAG_NTFS);
+                    ExFreePoolWithTag(NewRecord, TAG_NTFS);
                     return Status;
                 }
 
@@ -1064,6 +1122,10 @@ ReadAttribute(PDEVICE_EXTENSION Vcb,
         //TEMPTEMP
         ULONG UsedBufferSize;
         TempBuffer = ExAllocatePoolWithTag(NonPagedPool, Vcb->NtfsInfo.BytesPerFileRecord, TAG_NTFS);
+        if (TempBuffer == NULL)
+        {
+            return STATUS_INSUFFICIENT_RESOURCES;
+        }
 
         LastLCN = 0;
         CurrentOffset = 0;
@@ -1099,6 +1161,7 @@ ReadAttribute(PDEVICE_EXTENSION Vcb,
 
             if (*DataRun == 0)
             {
+                ExFreePoolWithTag(TempBuffer, TAG_NTFS);
                 return AlreadyRead;
             }
 
@@ -1296,7 +1359,7 @@ WriteAttribute(PDEVICE_EXTENSION Vcb,
         // Do we need to read the file record?
         if (FileRecord == NULL)
         {
-            FileRecord = ExAllocatePoolWithTag(NonPagedPool, Vcb->NtfsInfo.BytesPerFileRecord, TAG_NTFS);
+            FileRecord = ExAllocateFromNPagedLookasideList(&Vcb->FileRecLookasideList);
             if (!FileRecord)
             {
                 DPRINT1("Error: Couldn't allocate file record!\n");
@@ -1321,7 +1384,7 @@ WriteAttribute(PDEVICE_EXTENSION Vcb,
         {
             DPRINT1("ERROR: Couldn't find matching attribute!\n");
             if(FileRecordAllocated)
-                ExFreePoolWithTag(FileRecord, TAG_NTFS);
+                ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, FileRecord);
             return Status;
         }
 
@@ -1335,7 +1398,7 @@ WriteAttribute(PDEVICE_EXTENSION Vcb,
             DPRINT1("DRIVER ERROR: Data being written extends past end of file record!\n");
             ReleaseAttributeContext(FoundContext);
             if (FileRecordAllocated)
-                ExFreePoolWithTag(FileRecord, TAG_NTFS);
+                ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, FileRecord);
             return STATUS_INVALID_PARAMETER;
         }
 
@@ -1350,7 +1413,7 @@ WriteAttribute(PDEVICE_EXTENSION Vcb,
 
         ReleaseAttributeContext(FoundContext);
         if (FileRecordAllocated)
-            ExFreePoolWithTag(FileRecord, TAG_NTFS);
+            ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, FileRecord);
 
         if (NT_SUCCESS(Status))
             *RealLengthWritten = Length;
@@ -1379,7 +1442,11 @@ WriteAttribute(PDEVICE_EXTENSION Vcb,
         CurrentOffset = 0;  
 
         // This will be rewritten in the next iteration to just use the DataRuns MCB directly
-        TempBuffer = ExAllocatePoolWithTag(NonPagedPool, Vcb->NtfsInfo.BytesPerFileRecord, TAG_NTFS);        
+        TempBuffer = ExAllocatePoolWithTag(NonPagedPool, Vcb->NtfsInfo.BytesPerFileRecord, TAG_NTFS);
+        if (TempBuffer == NULL)
+        {
+            return STATUS_INSUFFICIENT_RESOURCES;
+        }
 
         ConvertLargeMCBToDataRuns(&Context->DataRunsMCB,
                                   TempBuffer,
@@ -1404,7 +1471,8 @@ WriteAttribute(PDEVICE_EXTENSION Vcb,
                 // (it may require increasing the allocation size).
                 DataRunStartLCN = -1;
                 DPRINT1("FIXME: Writing to sparse files is not supported yet!\n");
-                return STATUS_NOT_IMPLEMENTED;
+                Status = STATUS_NOT_IMPLEMENTED;
+                goto Cleanup;
             }
 
             // Have we reached the data run we're trying to write to?
@@ -1421,7 +1489,8 @@ WriteAttribute(PDEVICE_EXTENSION Vcb,
                 // (Presently, this code will rarely be reached, the write will usually have already failed by now)
                 // [We can reach here by creating a new file record when the MFT isn't large enough]
                 DPRINT1("FIXME: Master File Table needs to be enlarged.\n");
-                return STATUS_END_OF_FILE;
+                Status = STATUS_END_OF_FILE;
+                goto Cleanup;
             }
 
             CurrentOffset += DataRunLength * Vcb->NtfsInfo.BytesPerCluster;
@@ -1455,7 +1524,7 @@ WriteAttribute(PDEVICE_EXTENSION Vcb,
         Context->CacheRunLastLCN = LastLCN;
         Context->CacheRunCurrentOffset = CurrentOffset;
 
-        return Status;
+        goto Cleanup;
     }
 
     Length -= WriteLength;
@@ -1488,7 +1557,8 @@ WriteAttribute(PDEVICE_EXTENSION Vcb,
         if (DataRunStartLCN == -1)
         {
             DPRINT1("FIXME: Don't know how to write to sparse files yet! (DataRunStartLCN == -1)\n");
-            return STATUS_NOT_IMPLEMENTED;
+            Status = STATUS_NOT_IMPLEMENTED;
+            goto Cleanup;
         }
         else
         {
@@ -1519,7 +1589,8 @@ WriteAttribute(PDEVICE_EXTENSION Vcb,
             {
                 // Failed sanity check.
                 DPRINT1("Encountered EOF before expected!\n");
-                return STATUS_END_OF_FILE;
+                Status = STATUS_END_OF_FILE;
+                goto Cleanup;
             }
 
             break;
@@ -1541,10 +1612,6 @@ WriteAttribute(PDEVICE_EXTENSION Vcb,
         }
     } // end while (Length > 0) [more data to write]
 
-    // TEMPTEMP
-    if (Context->pRecord->IsNonResident)
-        ExFreePoolWithTag(TempBuffer, TAG_NTFS);
-
     Context->CacheRun = DataRun;
     Context->CacheRunOffset = Offset + *RealLengthWritten;
     Context->CacheRunStartLCN = DataRunStartLCN;
@@ -1552,6 +1619,11 @@ WriteAttribute(PDEVICE_EXTENSION Vcb,
     Context->CacheRunLastLCN = LastLCN;
     Context->CacheRunCurrentOffset = CurrentOffset;
 
+Cleanup:
+    // TEMPTEMP
+    if (Context->pRecord->IsNonResident)
+        ExFreePoolWithTag(TempBuffer, TAG_NTFS);
+
     return Status;
 }
 
@@ -1610,9 +1682,7 @@ UpdateFileNameRecord(PDEVICE_EXTENSION Vcb,
            NewAllocationSize,
            CaseSensitive ? "TRUE" : "FALSE");
 
-    MftRecord = ExAllocatePoolWithTag(NonPagedPool,
-                                      Vcb->NtfsInfo.BytesPerFileRecord,
-                                      TAG_NTFS);
+    MftRecord = ExAllocateFromNPagedLookasideList(&Vcb->FileRecLookasideList);
     if (MftRecord == NULL)
     {
         return STATUS_INSUFFICIENT_RESOURCES;
@@ -1621,7 +1691,7 @@ UpdateFileNameRecord(PDEVICE_EXTENSION Vcb,
     Status = ReadFileRecord(Vcb, ParentMFTIndex, MftRecord);
     if (!NT_SUCCESS(Status))
     {
-        ExFreePoolWithTag(MftRecord, TAG_NTFS);
+        ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, MftRecord);
         return Status;
     }
 
@@ -1629,7 +1699,7 @@ UpdateFileNameRecord(PDEVICE_EXTENSION Vcb,
     Status = FindAttribute(Vcb, MftRecord, AttributeIndexRoot, L"$I30", 4, &IndexRootCtx, NULL);
     if (!NT_SUCCESS(Status))
     {
-        ExFreePoolWithTag(MftRecord, TAG_NTFS);
+        ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, MftRecord);
         return Status;
     }
 
@@ -1637,7 +1707,7 @@ UpdateFileNameRecord(PDEVICE_EXTENSION Vcb,
     if (IndexRecord == NULL)
     {
         ReleaseAttributeContext(IndexRootCtx);
-        ExFreePoolWithTag(MftRecord, TAG_NTFS);
+        ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, MftRecord);
         return STATUS_INSUFFICIENT_RESOURCES;
     }
 
@@ -1647,7 +1717,8 @@ UpdateFileNameRecord(PDEVICE_EXTENSION Vcb,
         DPRINT1("ERROR: Failed to read Index Root!\n");
         ExFreePoolWithTag(IndexRecord, TAG_NTFS);
         ReleaseAttributeContext(IndexRootCtx);
-        ExFreePoolWithTag(MftRecord, TAG_NTFS);
+        ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, MftRecord);
+        return Status;
     }
 
     IndexRoot = (PINDEX_ROOT_ATTRIBUTE)IndexRecord;
@@ -1685,7 +1756,7 @@ UpdateFileNameRecord(PDEVICE_EXTENSION Vcb,
 
     ReleaseAttributeContext(IndexRootCtx);
     ExFreePoolWithTag(IndexRecord, TAG_NTFS);
-    ExFreePoolWithTag(MftRecord, TAG_NTFS);
+    ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, MftRecord);
 
     return Status;
 }
@@ -2144,9 +2215,7 @@ NtfsAddFilenameToDirectory(PDEVICE_EXTENSION DeviceExt,
     ULONG NodeSize;
 
     // Allocate memory for the parent directory
-    ParentFileRecord = ExAllocatePoolWithTag(NonPagedPool,
-                                             DeviceExt->NtfsInfo.BytesPerFileRecord,
-                                             TAG_NTFS);
+    ParentFileRecord = ExAllocateFromNPagedLookasideList(&DeviceExt->FileRecLookasideList);
     if (!ParentFileRecord)
     {
         DPRINT1("ERROR: Couldn't allocate memory for file record!\n");
@@ -2157,7 +2226,7 @@ NtfsAddFilenameToDirectory(PDEVICE_EXTENSION DeviceExt,
     Status = ReadFileRecord(DeviceExt, DirectoryMftIndex, ParentFileRecord);
     if (!NT_SUCCESS(Status))
     {
-        ExFreePoolWithTag(ParentFileRecord, TAG_NTFS);
+        ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, ParentFileRecord);
         DPRINT1("ERROR: Couldn't read parent directory with index %I64u\n",
                 DirectoryMftIndex);
         return Status;
@@ -2180,7 +2249,7 @@ NtfsAddFilenameToDirectory(PDEVICE_EXTENSION DeviceExt,
     {
         DPRINT1("ERROR: Couldn't find $I30 $INDEX_ROOT attribute for parent directory with MFT #: %I64u!\n",
                 DirectoryMftIndex);
-        ExFreePoolWithTag(ParentFileRecord, TAG_NTFS);
+        ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, ParentFileRecord);
         return Status;
     }
 
@@ -2216,7 +2285,7 @@ NtfsAddFilenameToDirectory(PDEVICE_EXTENSION DeviceExt,
     {
         DPRINT1("ERROR: Couldn't allocate memory for index root attribute!\n");
         ReleaseAttributeContext(IndexRootContext);
-        ExFreePoolWithTag(ParentFileRecord, TAG_NTFS);
+        ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, ParentFileRecord);
         return STATUS_INSUFFICIENT_RESOURCES;
     }
 
@@ -2227,7 +2296,7 @@ NtfsAddFilenameToDirectory(PDEVICE_EXTENSION DeviceExt,
         DPRINT1("ERROR: Couln't read index root attribute for Mft index #%I64u\n", DirectoryMftIndex);
         ReleaseAttributeContext(IndexRootContext);
         ExFreePoolWithTag(I30IndexRoot, TAG_NTFS);
-        ExFreePoolWithTag(ParentFileRecord, TAG_NTFS);
+        ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, ParentFileRecord);
         return Status;
     }
 
@@ -2242,7 +2311,7 @@ NtfsAddFilenameToDirectory(PDEVICE_EXTENSION DeviceExt,
         DPRINT1("ERROR: Failed to create B-Tree from Index!\n");
         ReleaseAttributeContext(IndexRootContext);
         ExFreePoolWithTag(I30IndexRoot, TAG_NTFS);
-        ExFreePoolWithTag(ParentFileRecord, TAG_NTFS);
+        ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, ParentFileRecord);
         return Status;
     }
 
@@ -2266,7 +2335,7 @@ NtfsAddFilenameToDirectory(PDEVICE_EXTENSION DeviceExt,
         DestroyBTree(NewTree);
         ReleaseAttributeContext(IndexRootContext);
         ExFreePoolWithTag(I30IndexRoot, TAG_NTFS);
-        ExFreePoolWithTag(ParentFileRecord, TAG_NTFS);
+        ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, ParentFileRecord);
         return Status;
     }
 
@@ -2315,7 +2384,7 @@ NtfsAddFilenameToDirectory(PDEVICE_EXTENSION DeviceExt,
         DestroyBTree(NewTree);
         ReleaseAttributeContext(IndexRootContext);
         ExFreePoolWithTag(I30IndexRoot, TAG_NTFS);
-        ExFreePoolWithTag(ParentFileRecord, TAG_NTFS);
+        ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, ParentFileRecord);
         return Status;
     }
 
@@ -2327,7 +2396,7 @@ NtfsAddFilenameToDirectory(PDEVICE_EXTENSION DeviceExt,
         DestroyBTree(NewTree);
         ReleaseAttributeContext(IndexRootContext);
         ExFreePoolWithTag(I30IndexRoot, TAG_NTFS);
-        ExFreePoolWithTag(ParentFileRecord, TAG_NTFS);
+        ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, ParentFileRecord);
         return Status;
     }
 
@@ -2376,7 +2445,7 @@ NtfsAddFilenameToDirectory(PDEVICE_EXTENSION DeviceExt,
             DestroyBTree(NewTree);
             ReleaseAttributeContext(IndexRootContext);
             ExFreePoolWithTag(I30IndexRoot, TAG_NTFS);
-            ExFreePoolWithTag(ParentFileRecord, TAG_NTFS);
+            ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, ParentFileRecord);
             return Status;
         }
 
@@ -2388,7 +2457,7 @@ NtfsAddFilenameToDirectory(PDEVICE_EXTENSION DeviceExt,
             DestroyBTree(NewTree);
             ReleaseAttributeContext(IndexRootContext);
             ExFreePoolWithTag(I30IndexRoot, TAG_NTFS);
-            ExFreePoolWithTag(ParentFileRecord, TAG_NTFS);
+            ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, ParentFileRecord);
             return Status;
         }
 
@@ -2430,7 +2499,7 @@ NtfsAddFilenameToDirectory(PDEVICE_EXTENSION DeviceExt,
         DestroyBTree(NewTree);
         ReleaseAttributeContext(IndexRootContext);
         ExFreePoolWithTag(I30IndexRoot, TAG_NTFS);
-        ExFreePoolWithTag(ParentFileRecord, TAG_NTFS);
+        ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, ParentFileRecord);
         return Status;
     }
 
@@ -2457,7 +2526,7 @@ NtfsAddFilenameToDirectory(PDEVICE_EXTENSION DeviceExt,
             ExFreePoolWithTag(NewIndexRoot, TAG_NTFS);
             ReleaseAttributeContext(IndexRootContext);
             ExFreePoolWithTag(I30IndexRoot, TAG_NTFS);
-            ExFreePoolWithTag(ParentFileRecord, TAG_NTFS);
+            ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, ParentFileRecord);
             DPRINT1("ERROR: Unable to set resident attribute length!\n");
             return Status;
         }
@@ -2470,7 +2539,7 @@ NtfsAddFilenameToDirectory(PDEVICE_EXTENSION DeviceExt,
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("ERROR: Failed to update file record of directory with index: %llx\n", DirectoryMftIndex);
-        ExFreePoolWithTag(ParentFileRecord, TAG_NTFS);
+        ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, ParentFileRecord);
         ExFreePoolWithTag(NewIndexRoot, TAG_NTFS);
         ReleaseAttributeContext(IndexRootContext);
         ExFreePoolWithTag(I30IndexRoot, TAG_NTFS);
@@ -2491,7 +2560,7 @@ NtfsAddFilenameToDirectory(PDEVICE_EXTENSION DeviceExt,
         ExFreePoolWithTag(NewIndexRoot, TAG_NTFS);
         ReleaseAttributeContext(IndexRootContext);
         ExFreePoolWithTag(I30IndexRoot, TAG_NTFS);
-        ExFreePoolWithTag(ParentFileRecord, TAG_NTFS);
+        ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, ParentFileRecord);
         return Status;
     }
 
@@ -2525,7 +2594,7 @@ NtfsAddFilenameToDirectory(PDEVICE_EXTENSION DeviceExt,
     ExFreePoolWithTag(NewIndexRoot, TAG_NTFS);
     ReleaseAttributeContext(IndexRootContext);
     ExFreePoolWithTag(I30IndexRoot, TAG_NTFS);
-    ExFreePoolWithTag(ParentFileRecord, TAG_NTFS);
+    ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, ParentFileRecord);
 
     return Status;
 }
@@ -2654,7 +2723,7 @@ UpdateMftMirror(PNTFS_VCB Vcb)
     ULONG LengthWritten;
 
     // Allocate memory for the Mft mirror file record
-    MirrorFileRecord = ExAllocatePoolWithTag(NonPagedPool, Vcb->NtfsInfo.BytesPerFileRecord, TAG_NTFS);
+    MirrorFileRecord = ExAllocateFromNPagedLookasideList(&Vcb->FileRecLookasideList);
     if (!MirrorFileRecord)
     {
         DPRINT1("Error: Failed to allocate memory for $MFTMirr!\n");
@@ -2666,7 +2735,7 @@ UpdateMftMirror(PNTFS_VCB Vcb)
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("ERROR: Failed to read $MFTMirr!\n");
-        ExFreePoolWithTag(MirrorFileRecord, TAG_NTFS);
+        ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, MirrorFileRecord);
         return Status;
     }
 
@@ -2675,7 +2744,7 @@ UpdateMftMirror(PNTFS_VCB Vcb)
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("ERROR: Couldn't find $DATA attribute!\n");
-        ExFreePoolWithTag(MirrorFileRecord, TAG_NTFS);
+        ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, MirrorFileRecord);
         return Status;
     }
 
@@ -2685,7 +2754,7 @@ UpdateMftMirror(PNTFS_VCB Vcb)
     {
         DPRINT1("ERROR: Couldn't find $DATA attribute!\n");
         ReleaseAttributeContext(MirrDataContext);
-        ExFreePoolWithTag(MirrorFileRecord, TAG_NTFS);
+        ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, MirrorFileRecord);
         return Status;
     }
 
@@ -2701,7 +2770,7 @@ UpdateMftMirror(PNTFS_VCB Vcb)
         DPRINT1("Error: Couldn't allocate memory for $DATA buffer!\n");
         ReleaseAttributeContext(MftDataContext);
         ReleaseAttributeContext(MirrDataContext);
-        ExFreePoolWithTag(MirrorFileRecord, TAG_NTFS);
+        ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, MirrorFileRecord);
         return STATUS_INSUFFICIENT_RESOURCES;
     }
 
@@ -2715,7 +2784,7 @@ UpdateMftMirror(PNTFS_VCB Vcb)
         ReleaseAttributeContext(MftDataContext);
         ReleaseAttributeContext(MirrDataContext);
         ExFreePoolWithTag(DataBuffer, TAG_NTFS);
-        ExFreePoolWithTag(MirrorFileRecord, TAG_NTFS);
+        ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, MirrorFileRecord);
         return STATUS_UNSUCCESSFUL;
     }
 
@@ -2736,7 +2805,7 @@ UpdateMftMirror(PNTFS_VCB Vcb)
     ReleaseAttributeContext(MftDataContext);
     ReleaseAttributeContext(MirrDataContext);
     ExFreePoolWithTag(DataBuffer, TAG_NTFS);
-    ExFreePoolWithTag(MirrorFileRecord, TAG_NTFS);
+    ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, MirrorFileRecord);
 
     return Status;
 }
@@ -2810,13 +2879,10 @@ BrowseSubNodeIndexEntries(PNTFS_VCB Vcb,
     // Is the bit for this node clear in the bitmap?
     if (!RtlCheckBit(Bitmap, NodeNumber))
     {
-        DPRINT1("File system corruption detected, node with VCN %I64u is being reused or is marked as deleted.\n", VCN);
+        DPRINT1("File system corruption detected, node with VCN %I64u is marked as deleted.\n", VCN);
         return STATUS_DATA_ERROR;
     }
 
-    // Clear the bit for this node so it can't be recursively referenced
-    RtlClearBits(Bitmap, NodeNumber, 1);
-
     // Allocate memory for the index record
     IndexRecord = ExAllocatePoolWithTag(NonPagedPool, IndexBlockSize, TAG_NTFS);
     if (!IndexRecord)
@@ -3102,9 +3168,7 @@ NtfsFindMftRecord(PDEVICE_EXTENSION Vcb,
            CaseSensitive ? "TRUE" : "FALSE",
            OutMFTIndex);
 
-    MftRecord = ExAllocatePoolWithTag(NonPagedPool,
-                                      Vcb->NtfsInfo.BytesPerFileRecord,
-                                      TAG_NTFS);
+    MftRecord = ExAllocateFromNPagedLookasideList(&Vcb->FileRecLookasideList);
     if (MftRecord == NULL)
     {
         return STATUS_INSUFFICIENT_RESOURCES;
@@ -3113,7 +3177,7 @@ NtfsFindMftRecord(PDEVICE_EXTENSION Vcb,
     Status = ReadFileRecord(Vcb, MFTIndex, MftRecord);
     if (!NT_SUCCESS(Status))
     {
-        ExFreePoolWithTag(MftRecord, TAG_NTFS);
+        ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, MftRecord);
         return Status;
     }
 
@@ -3121,7 +3185,7 @@ NtfsFindMftRecord(PDEVICE_EXTENSION Vcb,
     Status = FindAttribute(Vcb, MftRecord, AttributeIndexRoot, L"$I30", 4, &IndexRootCtx, NULL);
     if (!NT_SUCCESS(Status))
     {
-        ExFreePoolWithTag(MftRecord, TAG_NTFS);
+        ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, MftRecord);
         return Status;
     }
 
@@ -3129,7 +3193,7 @@ NtfsFindMftRecord(PDEVICE_EXTENSION Vcb,
     if (IndexRecord == NULL)
     {
         ReleaseAttributeContext(IndexRootCtx);
-        ExFreePoolWithTag(MftRecord, TAG_NTFS);
+        ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, MftRecord);
         return STATUS_INSUFFICIENT_RESOURCES;
     }
 
@@ -3156,7 +3220,7 @@ NtfsFindMftRecord(PDEVICE_EXTENSION Vcb,
                                 OutMFTIndex);
 
     ExFreePoolWithTag(IndexRecord, TAG_NTFS);
-    ExFreePoolWithTag(MftRecord, TAG_NTFS);
+    ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, MftRecord);
 
     return Status;
 }
@@ -3199,7 +3263,7 @@ NtfsLookupFileAt(PDEVICE_EXTENSION Vcb,
         FsRtlDissectName(Current, &Current, &Remaining);
     }
 
-    *FileRecord = ExAllocatePoolWithTag(NonPagedPool, Vcb->NtfsInfo.BytesPerFileRecord, TAG_NTFS);
+    *FileRecord = ExAllocateFromNPagedLookasideList(&Vcb->FileRecLookasideList);
     if (*FileRecord == NULL)
     {
         DPRINT("NtfsLookupFileAt: Can't allocate MFT record\n");
@@ -3210,7 +3274,7 @@ NtfsLookupFileAt(PDEVICE_EXTENSION Vcb,
     if (!NT_SUCCESS(Status))
     {
         DPRINT("NtfsLookupFileAt: Can't read MFT record\n");
-        ExFreePoolWithTag(*FileRecord, TAG_NTFS);
+        ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, *FileRecord);
         return Status;
     }
 
@@ -3314,7 +3378,7 @@ NtfsFindFileAt(PDEVICE_EXTENSION Vcb,
         return Status;
     }
 
-    *FileRecord = ExAllocatePoolWithTag(NonPagedPool, Vcb->NtfsInfo.BytesPerFileRecord, TAG_NTFS);
+    *FileRecord = ExAllocateFromNPagedLookasideList(&Vcb->FileRecLookasideList);
     if (*FileRecord == NULL)
     {
         DPRINT("NtfsFindFileAt: Can't allocate MFT record\n");
@@ -3325,7 +3389,7 @@ NtfsFindFileAt(PDEVICE_EXTENSION Vcb,
     if (!NT_SUCCESS(Status))
     {
         DPRINT("NtfsFindFileAt: Can't read MFT record\n");
-        ExFreePoolWithTag(*FileRecord, TAG_NTFS);
+        ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, *FileRecord);
         return Status;
     }