mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 18:15:11 +00:00
[NTFS]
Lay some groundwork for extending allocation size. +AddRun() - Unimplemented +GetLastClusterInDataRun() +NtfsAllocateClusters() svn path=/branches/GSoC_2016/NTFS/; revision=71696
This commit is contained in:
parent
84a1280fd6
commit
77fc65dc0e
4 changed files with 223 additions and 5 deletions
|
@ -35,6 +35,19 @@
|
|||
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
|
||||
NTSTATUS
|
||||
AddRun(PNTFS_ATTR_CONTEXT AttrContext,
|
||||
ULONGLONG NextAssignedCluster,
|
||||
ULONG RunLength)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
|
||||
if (!AttrContext->Record.IsNonResident)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
PUCHAR
|
||||
DecodeRun(PUCHAR DataRun,
|
||||
LONGLONG *DataRunOffset,
|
||||
|
@ -551,6 +564,50 @@ GetFileNameFromRecord(PDEVICE_EXTENSION Vcb,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
GetLastClusterInDataRun(PDEVICE_EXTENSION Vcb, PNTFS_ATTR_RECORD Attribute, PULONGLONG LastCluster)
|
||||
{
|
||||
LONGLONG DataRunOffset;
|
||||
ULONGLONG DataRunLength;
|
||||
LONGLONG DataRunStartLCN;
|
||||
|
||||
ULONGLONG LastLCN = 0;
|
||||
PUCHAR DataRun = (PUCHAR)Attribute + Attribute->NonResident.MappingPairsOffset;
|
||||
|
||||
if (!Attribute->IsNonResident)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
while (1)
|
||||
{
|
||||
DataRun = DecodeRun(DataRun, &DataRunOffset, &DataRunLength);
|
||||
|
||||
if (DataRunOffset == -1)
|
||||
{
|
||||
// sparse run
|
||||
if (*DataRun == 0)
|
||||
{
|
||||
// if it's the last run, return the last cluster of the last run
|
||||
*LastCluster = LastLCN + DataRunLength - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Normal data run.
|
||||
DataRunStartLCN = LastLCN + DataRunOffset;
|
||||
LastLCN = DataRunStartLCN;
|
||||
}
|
||||
|
||||
if (*DataRun == 0)
|
||||
{
|
||||
*LastCluster = LastLCN + DataRunLength - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
PSTANDARD_INFORMATION
|
||||
GetStandardInformationFromRecord(PDEVICE_EXTENSION Vcb,
|
||||
PFILE_RECORD_HEADER FileRecord)
|
||||
|
|
|
@ -151,7 +151,7 @@ FindAttribute(PDEVICE_EXTENSION Vcb,
|
|||
}
|
||||
|
||||
|
||||
ULONG
|
||||
ULONGLONG
|
||||
AttributeAllocatedLength(PNTFS_ATTR_RECORD AttrRecord)
|
||||
{
|
||||
if (AttrRecord->IsNonResident)
|
||||
|
@ -181,9 +181,49 @@ SetAttributeDataLength(PFILE_OBJECT FileObject,
|
|||
{
|
||||
if (AttrContext->Record.IsNonResident)
|
||||
{
|
||||
ULONG BytesPerCluster = Fcb->Vcb->NtfsInfo.BytesPerCluster;
|
||||
ULONGLONG AllocationSize = ROUND_UP(DataSize->QuadPart, BytesPerCluster);
|
||||
|
||||
// do we need to increase the allocation size?
|
||||
if (AttrContext->Record.NonResident.AllocatedSize < DataSize->QuadPart)
|
||||
{
|
||||
if (AttrContext->Record.NonResident.AllocatedSize < AllocationSize)
|
||||
{
|
||||
ULONG ExistingClusters = AttrContext->Record.NonResident.AllocatedSize / BytesPerCluster;
|
||||
ULONG ClustersNeeded = (AllocationSize / BytesPerCluster) - ExistingClusters;
|
||||
LARGE_INTEGER LastClusterInDataRun;
|
||||
ULONG NextAssignedCluster;
|
||||
ULONG AssignedClusters;
|
||||
|
||||
NTSTATUS Status = GetLastClusterInDataRun(Fcb->Vcb, &AttrContext->Record, &LastClusterInDataRun.QuadPart);
|
||||
|
||||
DPRINT1("GetLastClusterInDataRun returned: %I64u\n", LastClusterInDataRun.QuadPart);
|
||||
DPRINT1("Highest VCN of record: %I64u\n", AttrContext->Record.NonResident.HighestVCN);
|
||||
|
||||
while (ClustersNeeded > 0)
|
||||
{
|
||||
Status = NtfsAllocateClusters(Fcb->Vcb,
|
||||
LastClusterInDataRun.LowPart + 1,
|
||||
ClustersNeeded,
|
||||
&NextAssignedCluster,
|
||||
&AssignedClusters);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Error: Unable to allocate requested clusters!\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
// now we need to add the clusters we allocated to the data run
|
||||
Status = AddRun(AttrContext, NextAssignedCluster, AssignedClusters);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Error: Unable to add data run!\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
ClustersNeeded -= AssignedClusters;
|
||||
LastClusterInDataRun.LowPart = NextAssignedCluster + AssignedClusters - 1;
|
||||
}
|
||||
|
||||
DPRINT1("FixMe: Increasing allocation size is unimplemented!\n");
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
@ -459,7 +499,7 @@ WriteAttribute(PDEVICE_EXTENSION Vcb,
|
|||
PUCHAR SourceBuffer = Buffer;
|
||||
LONGLONG StartingOffset;
|
||||
|
||||
DPRINT("WriteAttribute(%p, %p, %I64U, %p, %lu)\n", Vcb, Context, Offset, Buffer, Length);
|
||||
DPRINT("WriteAttribute(%p, %p, %I64u, %p, %lu, %p)\n", Vcb, Context, Offset, Buffer, Length, RealLengthWritten);
|
||||
|
||||
// is this a resident attribute?
|
||||
if (!Context->Record.IsNonResident)
|
||||
|
|
|
@ -511,6 +511,11 @@ NtfsMarkIrpContextForQueue(PNTFS_IRP_CONTEXT IrpContext)
|
|||
//VOID
|
||||
//NtfsDumpAttribute(PATTRIBUTE Attribute);
|
||||
|
||||
NTSTATUS
|
||||
AddRun(PNTFS_ATTR_CONTEXT AttrContext,
|
||||
ULONGLONG NextAssignedCluster,
|
||||
ULONG RunLength);
|
||||
|
||||
PUCHAR
|
||||
DecodeRun(PUCHAR DataRun,
|
||||
LONGLONG *DataRunOffset,
|
||||
|
@ -529,6 +534,11 @@ GetFileNameFromRecord(PDEVICE_EXTENSION Vcb,
|
|||
PFILE_RECORD_HEADER FileRecord,
|
||||
UCHAR NameType);
|
||||
|
||||
NTSTATUS
|
||||
GetLastClusterInDataRun(PDEVICE_EXTENSION Vcb,
|
||||
PNTFS_ATTR_RECORD Attribute,
|
||||
PULONGLONG LastCluster);
|
||||
|
||||
PFILENAME_ATTRIBUTE
|
||||
GetBestFileNameFromRecord(PDEVICE_EXTENSION Vcb,
|
||||
PFILE_RECORD_HEADER FileRecord);
|
||||
|
@ -774,7 +784,7 @@ SetAttributeDataLength(PFILE_OBJECT FileObject,
|
|||
PFILE_RECORD_HEADER FileRecord,
|
||||
PLARGE_INTEGER DataSize);
|
||||
|
||||
ULONG
|
||||
ULONGLONG
|
||||
AttributeAllocatedLength(PNTFS_ATTR_RECORD AttrRecord);
|
||||
|
||||
BOOLEAN
|
||||
|
@ -915,6 +925,13 @@ NtfsWrite(PNTFS_IRP_CONTEXT IrpContext);
|
|||
|
||||
/* volinfo.c */
|
||||
|
||||
NTSTATUS
|
||||
NtfsAllocateClusters(PDEVICE_EXTENSION DeviceExt,
|
||||
ULONG FirstDesiredCluster,
|
||||
ULONG DesiredClusters,
|
||||
PULONG FirstAssignedCluster,
|
||||
PULONG AssignedClusters);
|
||||
|
||||
ULONGLONG
|
||||
NtfsGetFreeClusters(PDEVICE_EXTENSION DeviceExt);
|
||||
|
||||
|
|
|
@ -99,6 +99,110 @@ NtfsGetFreeClusters(PDEVICE_EXTENSION DeviceExt)
|
|||
return FreeClusters;
|
||||
}
|
||||
|
||||
/**
|
||||
* NtfsAllocateClusters
|
||||
* Allocates a run of clusters. The run allocated might be smaller than DesiredClusters.
|
||||
*/
|
||||
NTSTATUS
|
||||
NtfsAllocateClusters(PDEVICE_EXTENSION DeviceExt,
|
||||
ULONG FirstDesiredCluster,
|
||||
ULONG DesiredClusters,
|
||||
PULONG FirstAssignedCluster,
|
||||
PULONG AssignedClusters)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PFILE_RECORD_HEADER BitmapRecord;
|
||||
PNTFS_ATTR_CONTEXT DataContext;
|
||||
ULONGLONG BitmapDataSize;
|
||||
PCHAR BitmapData;
|
||||
ULONGLONG FreeClusters = 0;
|
||||
ULONG Read = 0;
|
||||
RTL_BITMAP Bitmap;
|
||||
|
||||
DPRINT1("NtfsAllocateClusters(%p, %lu, %lu, %p)\n", DeviceExt, DesiredClusters, FirstDesiredCluster, FirstAssignedCluster, AssignedClusters);
|
||||
|
||||
BitmapRecord = ExAllocatePoolWithTag(NonPagedPool,
|
||||
DeviceExt->NtfsInfo.BytesPerFileRecord,
|
||||
TAG_NTFS);
|
||||
if (BitmapRecord == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
Status = ReadFileRecord(DeviceExt, NTFS_FILE_BITMAP, BitmapRecord);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ExFreePoolWithTag(BitmapRecord, TAG_NTFS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Status = FindAttribute(DeviceExt, BitmapRecord, AttributeData, L"", 0, &DataContext, NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ExFreePoolWithTag(BitmapRecord, TAG_NTFS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
BitmapDataSize = AttributeDataLength(&DataContext->Record);
|
||||
BitmapDataSize = min(BitmapDataSize, 0xffffffff);
|
||||
ASSERT((BitmapDataSize * 8) >= DeviceExt->NtfsInfo.ClusterCount);
|
||||
BitmapData = ExAllocatePoolWithTag(NonPagedPool, ROUND_UP(BitmapDataSize, DeviceExt->NtfsInfo.BytesPerSector), TAG_NTFS);
|
||||
if (BitmapData == NULL)
|
||||
{
|
||||
ReleaseAttributeContext(DataContext);
|
||||
ExFreePoolWithTag(BitmapRecord, TAG_NTFS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DPRINT1("Total clusters: %I64x\n", DeviceExt->NtfsInfo.ClusterCount);
|
||||
DPRINT1("Total clusters in bitmap: %I64x\n", BitmapDataSize * 8);
|
||||
DPRINT1("Diff in size: %I64d B\n", ((BitmapDataSize * 8) - DeviceExt->NtfsInfo.ClusterCount) * DeviceExt->NtfsInfo.SectorsPerCluster * DeviceExt->NtfsInfo.BytesPerSector);
|
||||
|
||||
ReadAttribute(DeviceExt, DataContext, Read, (PCHAR)((ULONG_PTR)BitmapData + Read), (ULONG)BitmapDataSize);
|
||||
|
||||
RtlInitializeBitMap(&Bitmap, (PULONG)BitmapData, DeviceExt->NtfsInfo.ClusterCount);
|
||||
FreeClusters = RtlNumberOfClearBits(&Bitmap);
|
||||
|
||||
if (FreeClusters >= DesiredClusters)
|
||||
{
|
||||
// TODO: Observe MFT reservation zone
|
||||
|
||||
// Can we get one contiguous run?
|
||||
ULONG AssignedRun = RtlFindClearBitsAndSet(&Bitmap, DesiredClusters, FirstDesiredCluster);
|
||||
ULONG LengthWritten;
|
||||
|
||||
if (AssignedRun != 0xFFFFFFFF)
|
||||
{
|
||||
*FirstAssignedCluster = AssignedRun;
|
||||
*AssignedClusters = DesiredClusters;
|
||||
}
|
||||
else
|
||||
{
|
||||
// we can't get one contiguous run
|
||||
*AssignedClusters = RtlFindNextForwardRunClear(&Bitmap, FirstDesiredCluster, FirstAssignedCluster);
|
||||
|
||||
if (*AssignedClusters == 0)
|
||||
{
|
||||
// we couldn't find any runs starting at DesiredFirstCluster
|
||||
*AssignedClusters = RtlFindLongestRunClear(&Bitmap, FirstAssignedCluster);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Status = WriteAttribute(DeviceExt, DataContext, 0, BitmapData, (ULONG)BitmapDataSize, &LengthWritten);
|
||||
}
|
||||
else
|
||||
Status = STATUS_DISK_FULL;
|
||||
|
||||
|
||||
ReleaseAttributeContext(DataContext);
|
||||
|
||||
ExFreePoolWithTag(BitmapData, TAG_NTFS);
|
||||
ExFreePoolWithTag(BitmapRecord, TAG_NTFS);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
static
|
||||
NTSTATUS
|
||||
NtfsGetFsVolumeInformation(PDEVICE_OBJECT DeviceObject,
|
||||
|
|
Loading…
Reference in a new issue