[FASTFAT] Start implementing FAT32 statistics support

Not fully perfect yet, chkdsk still complains.

CORE-3877
This commit is contained in:
Pierre Schweitzer 2018-06-09 12:36:43 +02:00
parent 04640f9264
commit 704baed2df
No known key found for this signature in database
GPG key ID: 7545556C3D585B0B
5 changed files with 114 additions and 0 deletions

View file

@ -1021,12 +1021,20 @@ FATDelEntry(
/* In case of moving, don't delete data */
if (MoveContext == NULL)
{
ULONG ClusterCount = 0;
while (CurrentCluster && CurrentCluster != 0xffffffff)
{
GetNextCluster(DeviceExt, CurrentCluster, &NextCluster);
/* FIXME: check status */
WriteCluster(DeviceExt, CurrentCluster, 0);
CurrentCluster = NextCluster;
ClusterCount++;
}
if (ClusterCount != 0 && DeviceExt->FatInfo.FatType == FAT32)
{
FAT32UpdateFreeClustersCount(DeviceExt, ClusterCount, TRUE);
}
}

View file

@ -1212,4 +1212,89 @@ FAT32SetDirtyStatus(
#endif
}
NTSTATUS
FAT32UpdateFreeClustersCount(
PDEVICE_EXTENSION DeviceExt,
ULONG Count,
BOOLEAN Freed)
{
LARGE_INTEGER Offset;
ULONG Length;
#ifdef VOLUME_IS_NOT_CACHED_WORK_AROUND_IT
NTSTATUS Status;
#else
PVOID Context;
#endif
struct _FsInfoSector * Sector;
/* We'll read (and then write) the fsinfo sector */
Offset.QuadPart = DeviceExt->FatInfo.FSInfoSector * DeviceExt->FatInfo.BytesPerSector;
Length = DeviceExt->FatInfo.BytesPerSector;
#ifndef VOLUME_IS_NOT_CACHED_WORK_AROUND_IT
/* Go through Cc for this */
_SEH2_TRY
{
CcPinRead(DeviceExt->VolumeFcb->FileObject, &Offset, Length, PIN_WAIT, &Context, (PVOID *)&Sector);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
_SEH2_YIELD(return _SEH2_GetExceptionCode());
}
_SEH2_END;
#else
/* No Cc, do it the old way:
* - Allocate a big enough buffer
* - And read the disk
*/
Sector = ExAllocatePoolWithTag(NonPagedPool, Length, TAG_VFAT);
if (Sector == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
Status = VfatReadDisk(DeviceExt->StorageDevice, &Offset, Length, (PUCHAR)Sector, FALSE);
if (!NT_SUCCESS(Status))
{
ExFreePoolWithTag(Sector, TAG_VFAT);
return Status;
}
#endif
/* Make sure we have a FSINFO sector */
if (Sector->ExtBootSignature2 != 0x41615252 ||
Sector->FSINFOSignature != 0x61417272 ||
Sector->Signatur2 != 0xaa550000)
{
ASSERT(FALSE);
#ifndef VOLUME_IS_NOT_CACHED_WORK_AROUND_IT
CcUnpinData(Context);
#else
ExFreePoolWithTag(Sector, TAG_VFAT);
#endif
return STATUS_DISK_CORRUPT_ERROR;
}
/* Update the free clusters count */
if (Freed)
{
Sector->FreeCluster += Count;
}
else
{
Sector->FreeCluster -= Count;
}
#ifndef VOLUME_IS_NOT_CACHED_WORK_AROUND_IT
/* Mark FSINFO sector dirty so that it gets written to the disk */
CcSetDirtyPinnedData(Context, NULL);
CcUnpinData(Context);
return STATUS_SUCCESS;
#else
/* Write back the FSINFO sector to the disk */
Status = VfatWriteDisk(DeviceExt->StorageDevice, &Offset, Length, (PUCHAR)Sector, FALSE);
ExFreePoolWithTag(Sector, TAG_VFAT);
return Status;
#endif
}
/* EOF */

View file

@ -1344,6 +1344,8 @@ VfatSetAllocationSizeInformation(
}
else if (NewSize + ClusterSize <= Fcb->RFCB.AllocationSize.u.LowPart)
{
ULONG ClusterCount;
DPRINT("Check for the ability to set file size\n");
if (!MmCanFileBeTruncated(FileObject->SectionObjectPointer,
(PLARGE_INTEGER)AllocationSize))
@ -1391,11 +1393,18 @@ VfatSetAllocationSizeInformation(
Status = STATUS_SUCCESS;
}
ClusterCount = 0;
while (NT_SUCCESS(Status) && 0xffffffff != Cluster && Cluster > 1)
{
Status = NextCluster(DeviceExt, FirstCluster, &NCluster, FALSE);
WriteCluster(DeviceExt, Cluster, 0);
Cluster = NCluster;
ClusterCount++;
}
if (ClusterCount != 0 && DeviceExt->FatInfo.FatType == FAT32)
{
FAT32UpdateFreeClustersCount(DeviceExt, ClusterCount, TRUE);
}
}
else

View file

@ -539,6 +539,12 @@ VfatWriteFileData(
Status = IrpContext->Irp->IoStatus.Status;
}
}
if (NT_SUCCESS(Status) && ClusterCount != 0 && DeviceExt->FatInfo.FatType == FAT32)
{
FAT32UpdateFreeClustersCount(DeviceExt, ClusterCount, FALSE);
}
return Status;
}

View file

@ -929,6 +929,12 @@ FAT32SetDirtyStatus(
PDEVICE_EXTENSION DeviceExt,
BOOLEAN DirtyStatus);
NTSTATUS
FAT32UpdateFreeClustersCount(
PDEVICE_EXTENSION DeviceExt,
ULONG Count,
BOOLEAN Freed);
/* fcb.c */
PVFATFCB