mirror of
https://github.com/reactos/reactos.git
synced 2025-08-01 19:22:58 +00:00
[NTFS] - Allow for resizing an attribute in the middle of a file record. Add a helper function and minor improvements:
AddRun() - Allow for resizing the size of the data runs when the attribute isn't the last in the file record. Fix some comments. CreateIndexBufferFromBTreeNode(), CreateIndexRootFromBTree - Fix math of IndexSize when checking if the index buffer is too large. InternalSetResidentAttributeLength() - Allow changing the length of an attribute in the middle of a file record. Adjust the position of every attribute after the one being resized. +MoveAttributes() - Moves a block of attributes to a new location in the file Record. PrintAllVCNs() - Add consideration for an index allocation with a size of 0. WriteAttribute() - Add optional parameter for a pointer to the file record being written to. If passed a file record, WriteAttribute() will skip reading the file record from disk, and will update the file record in memory before returning. This helps callers that use the file record after writing an attribute to stay in-sync with what's on disk. svn path=/branches/GSoC_2016/NTFS/; revision=75554
This commit is contained in:
parent
4dfcd1d582
commit
d484d91eba
6 changed files with 222 additions and 107 deletions
|
@ -352,18 +352,35 @@ AddRun(PNTFS_VCB Vcb,
|
|||
PNTFS_ATTR_RECORD NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + NextAttributeOffset);
|
||||
PNTFS_ATTR_RECORD NewRecord;
|
||||
|
||||
DataRunMaxLength += Vcb->NtfsInfo.BytesPerFileRecord - NextAttributeOffset - (sizeof(ULONG) * 2);
|
||||
// Add free space at the end of the file record to DataRunMaxLength
|
||||
DataRunMaxLength += Vcb->NtfsInfo.BytesPerFileRecord - FileRecord->BytesInUse;
|
||||
|
||||
// Can we move the end of the attribute?
|
||||
if (NextAttribute->Type != AttributeEnd || DataRunMaxLength < RunBufferSize - 1)
|
||||
// Can we resize the attribute?
|
||||
if (DataRunMaxLength < RunBufferSize)
|
||||
{
|
||||
DPRINT1("FIXME: Need to create attribute list! Max Data Run Length available: %d\n", DataRunMaxLength);
|
||||
if (NextAttribute->Type != AttributeEnd)
|
||||
DPRINT1("There's another attribute after this one with type %0xlx\n", NextAttribute->Type);
|
||||
DPRINT1("FIXME: Need to create attribute list! Max Data Run Length available: %d, RunBufferSize: %d\n", DataRunMaxLength, RunBufferSize);
|
||||
ExFreePoolWithTag(RunBuffer, TAG_NTFS);
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
// Are there more attributes after the one we're resizing?
|
||||
if (NextAttribute->Type != AttributeEnd)
|
||||
{
|
||||
PNTFS_ATTR_RECORD FinalAttribute;
|
||||
|
||||
// Calculate where to move the trailing attributes
|
||||
ULONG_PTR MoveTo = (ULONG_PTR)DestinationAttribute + AttrContext->pRecord->NonResident.MappingPairsOffset + RunBufferSize;
|
||||
MoveTo = ALIGN_UP_BY(MoveTo, ATTR_RECORD_ALIGNMENT);
|
||||
|
||||
DPRINT1("Moving attribute(s) after this one starting with type 0x%lx\n", NextAttribute->Type);
|
||||
|
||||
// Move the trailing attributes; FinalAttribute will point to the end marker
|
||||
FinalAttribute = MoveAttributes(Vcb, NextAttribute, NextAttributeOffset, MoveTo);
|
||||
|
||||
// set the file record end
|
||||
SetFileRecordEnd(FileRecord, FinalAttribute, FILE_RECORD_END);
|
||||
}
|
||||
|
||||
// calculate position of end markers
|
||||
NextAttributeOffset = AttrOffset + AttrContext->pRecord->NonResident.MappingPairsOffset + RunBufferSize;
|
||||
NextAttributeOffset = ALIGN_UP_BY(NextAttributeOffset, ATTR_RECORD_ALIGNMENT);
|
||||
|
@ -371,20 +388,24 @@ AddRun(PNTFS_VCB Vcb,
|
|||
// Update the length of the destination attribute
|
||||
DestinationAttribute->Length = NextAttributeOffset - AttrOffset;
|
||||
|
||||
// Create a new copy of the attribute
|
||||
// Create a new copy of the attribute record
|
||||
NewRecord = ExAllocatePoolWithTag(NonPagedPool, DestinationAttribute->Length, TAG_NTFS);
|
||||
RtlCopyMemory(NewRecord, AttrContext->pRecord, AttrContext->pRecord->Length);
|
||||
NewRecord->Length = DestinationAttribute->Length;
|
||||
|
||||
// Free the old copy of the attribute, which won't be large enough
|
||||
// Free the old copy of the attribute record, which won't be large enough
|
||||
ExFreePoolWithTag(AttrContext->pRecord, TAG_NTFS);
|
||||
|
||||
// Set the attribute context's record to the new copy
|
||||
AttrContext->pRecord = NewRecord;
|
||||
|
||||
// End the file record
|
||||
NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + NextAttributeOffset);
|
||||
SetFileRecordEnd(FileRecord, NextAttribute, FILE_RECORD_END);
|
||||
// if NextAttribute is the AttributeEnd marker
|
||||
if (NextAttribute->Type == AttributeEnd)
|
||||
{
|
||||
// End the file record
|
||||
NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + NextAttributeOffset);
|
||||
SetFileRecordEnd(FileRecord, NextAttribute, FILE_RECORD_END);
|
||||
}
|
||||
}
|
||||
|
||||
// Update HighestVCN
|
||||
|
@ -397,7 +418,7 @@ AddRun(PNTFS_VCB Vcb,
|
|||
RunBuffer,
|
||||
RunBufferSize);
|
||||
|
||||
// Update the attribute copy in the attribute context
|
||||
// Update the attribute record in the attribute context
|
||||
RtlCopyMemory((PVOID)((ULONG_PTR)AttrContext->pRecord + AttrContext->pRecord->NonResident.MappingPairsOffset),
|
||||
RunBuffer,
|
||||
RunBufferSize);
|
||||
|
@ -827,7 +848,7 @@ FreeClusters(PNTFS_VCB Vcb,
|
|||
}
|
||||
|
||||
// update $BITMAP file on disk
|
||||
Status = WriteAttribute(Vcb, DataContext, 0, BitmapData, (ULONG)BitmapDataSize, &LengthWritten);
|
||||
Status = WriteAttribute(Vcb, DataContext, 0, BitmapData, (ULONG)BitmapDataSize, &LengthWritten, FileRecord);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ReleaseAttributeContext(DataContext);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue