mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 18:15:11 +00:00
[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 svn path=/trunk/; revision=72145
This commit is contained in:
parent
bf98b09370
commit
2f3c2c58d2
3 changed files with 88 additions and 0 deletions
|
@ -427,6 +427,53 @@ vfatInitFCBFromDirEntry(
|
|||
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
|
||||
vfatUpdateFCB(
|
||||
PDEVICE_EXTENSION pVCB,
|
||||
|
|
|
@ -487,6 +487,36 @@ IsThereAChildOpened(PVFATFCB FCB)
|
|||
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 @@ VfatSetRenameInformation(
|
|||
}
|
||||
}
|
||||
|
||||
if (NT_SUCCESS(Status) && vfatFCBIsDirectory(FCB))
|
||||
{
|
||||
VfatRenameChildFCB(DeviceExt, FCB);
|
||||
}
|
||||
|
||||
ASSERT(OldReferences == OldParent->RefCount + 1); // removed file
|
||||
ASSERT(NewReferences == ParentFCB->RefCount - 1); // new file
|
||||
Cleanup:
|
||||
|
|
|
@ -817,6 +817,12 @@ vfatNewFCB(
|
|||
PDEVICE_EXTENSION pVCB,
|
||||
PUNICODE_STRING pFileNameU);
|
||||
|
||||
NTSTATUS
|
||||
vfatSetFCBNewDirName(
|
||||
PDEVICE_EXTENSION pVCB,
|
||||
PVFATFCB Fcb,
|
||||
PVFATFCB ParentFcb);
|
||||
|
||||
NTSTATUS
|
||||
vfatUpdateFCB(
|
||||
PDEVICE_EXTENSION pVCB,
|
||||
|
|
Loading…
Reference in a new issue