Author: pschweitzer
Date: Sun Aug  7 12:29:48 2016
New Revision: 72145

URL: http://svn.reactos.org/svn/reactos?rev=72145&view=rev
Log:
[FASTFAT]
After renaming a directory, rename any children FCB that would still exist in 
the FSD. This will allow next directory opening to properly work and open 
correct data.
This defeats corruption on directory renaming.
Unfortunately, this solution is not ideal and our driver should be reworked so 
that it quits using a hash table and it quits storing the whole path in the 
FCBs.

Deep thanks to Wim Hueskes and Thomas Faber for their help debugging the issue!

CORE-11377

Modified:
    trunk/reactos/drivers/filesystems/fastfat/fcb.c
    trunk/reactos/drivers/filesystems/fastfat/finfo.c
    trunk/reactos/drivers/filesystems/fastfat/vfat.h

Modified: trunk/reactos/drivers/filesystems/fastfat/fcb.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/fastfat/fcb.c?rev=72145&r1=72144&r2=72145&view=diff
==============================================================================
--- trunk/reactos/drivers/filesystems/fastfat/fcb.c     [iso-8859-1] (original)
+++ trunk/reactos/drivers/filesystems/fastfat/fcb.c     [iso-8859-1] Sun Aug  7 
12:29:48 2016
@@ -425,6 +425,53 @@
     Fcb->RFCB.FileSize.QuadPart = Size;
     Fcb->RFCB.ValidDataLength.QuadPart = Size;
     Fcb->RFCB.AllocationSize.QuadPart = ROUND_UP_64(Size, 
Vcb->FatInfo.BytesPerCluster);
+}
+
+NTSTATUS
+vfatSetFCBNewDirName(
+    PDEVICE_EXTENSION pVCB,
+    PVFATFCB Fcb,
+    PVFATFCB ParentFcb)
+{
+    NTSTATUS Status;
+    UNICODE_STRING NewNameU;
+
+    /* Get full path name */
+    Status = vfatMakeFullName(ParentFcb, &Fcb->LongNameU, &Fcb->ShortNameU, 
&NewNameU);
+    if (!NT_SUCCESS(Status))
+    {
+        return Status;
+    }
+
+    /* Delete old name */
+    if (Fcb->PathNameBuffer)
+    {
+        ExFreePoolWithTag(Fcb->PathNameBuffer, TAG_FCB);
+    }
+    Fcb->PathNameU = NewNameU;
+
+    /* Delete from table */
+    vfatDelFCBFromTable(pVCB, Fcb);
+
+    /* Split it properly */
+    Fcb->PathNameBuffer = Fcb->PathNameU.Buffer;
+    Fcb->DirNameU.Buffer = Fcb->PathNameU.Buffer;
+    vfatSplitPathName(&Fcb->PathNameU, &Fcb->DirNameU, &Fcb->LongNameU);
+
+    if (pVCB->Flags & VCB_IS_FATX)
+    {
+        Fcb->ShortHash.Hash = Fcb->Hash.Hash;
+    }
+    else
+    {
+        Fcb->ShortHash.Hash = vfatNameHash(0, &Fcb->DirNameU);
+        Fcb->ShortHash.Hash = vfatNameHash(Fcb->ShortHash.Hash, 
&Fcb->ShortNameU);
+    }
+
+    vfatAddFCBToTable(pVCB, Fcb);
+    vfatReleaseFCB(pVCB, ParentFcb);
+
+    return STATUS_SUCCESS;
 }
 
 NTSTATUS

Modified: trunk/reactos/drivers/filesystems/fastfat/finfo.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/fastfat/finfo.c?rev=72145&r1=72144&r2=72145&view=diff
==============================================================================
--- trunk/reactos/drivers/filesystems/fastfat/finfo.c   [iso-8859-1] (original)
+++ trunk/reactos/drivers/filesystems/fastfat/finfo.c   [iso-8859-1] Sun Aug  7 
12:29:48 2016
@@ -487,6 +487,36 @@
     return FALSE;
 }
 
+static
+VOID
+VfatRenameChildFCB(
+    PDEVICE_EXTENSION DeviceExt,
+    PVFATFCB FCB)
+{
+    PLIST_ENTRY Entry;
+    PVFATFCB Child;
+
+    if (IsListEmpty(&FCB->ParentListHead))
+        return;
+
+    for (Entry = FCB->ParentListHead.Flink; Entry != &FCB->ParentListHead; 
Entry = Entry->Flink)
+    {
+        NTSTATUS Status;
+
+        Child = CONTAINING_RECORD(Entry, VFATFCB, ParentListEntry);
+        DPRINT("Found %wZ with still %lu references (parent: %lu)!\n", 
&Child->PathNameU, Child->RefCount, FCB->RefCount);
+
+        Status = vfatSetFCBNewDirName(DeviceExt, Child, FCB);
+        if (!NT_SUCCESS(Status))
+            continue;
+
+        if (vfatFCBIsDirectory(Child))
+        {
+            VfatRenameChildFCB(DeviceExt, Child);
+        }
+    }
+}
+
 /*
  * FUNCTION: Set the file name information
  */
@@ -911,6 +941,11 @@
         }
     }
 
+    if (NT_SUCCESS(Status) && vfatFCBIsDirectory(FCB))
+    {
+        VfatRenameChildFCB(DeviceExt, FCB);
+    }
+
     ASSERT(OldReferences == OldParent->RefCount + 1); // removed file
     ASSERT(NewReferences == ParentFCB->RefCount - 1); // new file
 Cleanup:

Modified: trunk/reactos/drivers/filesystems/fastfat/vfat.h
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/fastfat/vfat.h?rev=72145&r1=72144&r2=72145&view=diff
==============================================================================
--- trunk/reactos/drivers/filesystems/fastfat/vfat.h    [iso-8859-1] (original)
+++ trunk/reactos/drivers/filesystems/fastfat/vfat.h    [iso-8859-1] Sun Aug  7 
12:29:48 2016
@@ -818,6 +818,12 @@
     PUNICODE_STRING pFileNameU);
 
 NTSTATUS
+vfatSetFCBNewDirName(
+    PDEVICE_EXTENSION pVCB,
+    PVFATFCB Fcb,
+    PVFATFCB ParentFcb);
+
+NTSTATUS
 vfatUpdateFCB(
     PDEVICE_EXTENSION pVCB,
     PVFATFCB Fcb,


Reply via email to