[FASTFAT] Start implementing FAT32 statistics support
authorPierre Schweitzer <pierre@reactos.org>
Sat, 9 Jun 2018 10:36:43 +0000 (12:36 +0200)
committerPierre Schweitzer <pierre@reactos.org>
Sat, 9 Jun 2018 10:36:43 +0000 (12:36 +0200)
Not fully perfect yet, chkdsk still complains.

CORE-3877

drivers/filesystems/fastfat/dirwr.c
drivers/filesystems/fastfat/fat.c
drivers/filesystems/fastfat/finfo.c
drivers/filesystems/fastfat/rw.c
drivers/filesystems/fastfat/vfat.h

index ab5d9b3..ac1b7a5 100644 (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);
         }
     }
 
index 95ef695..b291ff2 100644 (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 */
index af2e1ce..2840b13 100644 (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
index 043bafe..d78054e 100644 (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;
 }
 
index fcb22b9..64a9679 100644 (file)
@@ -929,6 +929,12 @@ FAT32SetDirtyStatus(
     PDEVICE_EXTENSION DeviceExt,
     BOOLEAN DirtyStatus);
 
+NTSTATUS
+FAT32UpdateFreeClustersCount(
+    PDEVICE_EXTENSION DeviceExt,
+    ULONG Count,
+    BOOLEAN Freed);
+
 /* fcb.c */
 
 PVFATFCB