From 704baed2df04470ab134cef207847764e3d95e2e Mon Sep 17 00:00:00 2001 From: Pierre Schweitzer Date: Sat, 9 Jun 2018 12:36:43 +0200 Subject: [PATCH] [FASTFAT] Start implementing FAT32 statistics support Not fully perfect yet, chkdsk still complains. CORE-3877 --- drivers/filesystems/fastfat/dirwr.c | 8 +++ drivers/filesystems/fastfat/fat.c | 85 +++++++++++++++++++++++++++++ drivers/filesystems/fastfat/finfo.c | 9 +++ drivers/filesystems/fastfat/rw.c | 6 ++ drivers/filesystems/fastfat/vfat.h | 6 ++ 5 files changed, 114 insertions(+) diff --git a/drivers/filesystems/fastfat/dirwr.c b/drivers/filesystems/fastfat/dirwr.c index ab5d9b3ee4d..ac1b7a5549c 100644 --- a/drivers/filesystems/fastfat/dirwr.c +++ b/drivers/filesystems/fastfat/dirwr.c @@ -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); } } diff --git a/drivers/filesystems/fastfat/fat.c b/drivers/filesystems/fastfat/fat.c index 95ef6958d55..b291ff2843d 100644 --- a/drivers/filesystems/fastfat/fat.c +++ b/drivers/filesystems/fastfat/fat.c @@ -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 */ diff --git a/drivers/filesystems/fastfat/finfo.c b/drivers/filesystems/fastfat/finfo.c index af2e1ce62a2..2840b1369be 100644 --- a/drivers/filesystems/fastfat/finfo.c +++ b/drivers/filesystems/fastfat/finfo.c @@ -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 diff --git a/drivers/filesystems/fastfat/rw.c b/drivers/filesystems/fastfat/rw.c index 043bafef6c2..d78054eced0 100644 --- a/drivers/filesystems/fastfat/rw.c +++ b/drivers/filesystems/fastfat/rw.c @@ -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; } diff --git a/drivers/filesystems/fastfat/vfat.h b/drivers/filesystems/fastfat/vfat.h index fcb22b9c5a3..64a96796a0a 100644 --- a/drivers/filesystems/fastfat/vfat.h +++ b/drivers/filesystems/fastfat/vfat.h @@ -929,6 +929,12 @@ FAT32SetDirtyStatus( PDEVICE_EXTENSION DeviceExt, BOOLEAN DirtyStatus); +NTSTATUS +FAT32UpdateFreeClustersCount( + PDEVICE_EXTENSION DeviceExt, + ULONG Count, + BOOLEAN Freed); + /* fcb.c */ PVFATFCB