2005-08-24 18:29:45 +00:00
|
|
|
/*
|
2000-07-07 02:14:14 +00:00
|
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
|
|
* PROJECT: ReactOS kernel
|
[FASTFAT]
- Implement vfatPrepareTargetForRename() that prepares for renaming. It tries to open target and deletes it if it exists and if allowed. And then, it opens the parent directory.
- Implement VfatSetRenameInformation() that actually does the renaming (call as SetInformationFile). It handles cases we we have (or we don't have) TargetDirectory provided. It sends notifications as appropriated on demands.
- Implement vfatRenameEntry() that renames an entry in place. So far, it only supports FATX entries renaming. FAT entries are a bit more complex. It falls back to vfatMoveEntry() in later cases.
- Implement VfatMoveEntry() that will move an entry accross directories (or in place for FAT). Its principles are simple: it deletes the entry in old parent, and recreate it in new parent, keeping file metadata & data.
- Modify VfatDelEntry() and VfatAddEntry() so that they can handle deleting an entry without touching its data and adding an entry with an already provided FCB and thus use the given metadata.
- Implement vfatDelFCBFromTable() which is just old code moved to new routine to allow reuse. It deletes a FCB entry from hash table. Doesn't deal with references!
- Implement vfatMakeFullName() which is mostly old code moved to new routine to allow reuse. It allocates buffer and copy data for FCB full name.
- Implement vfatUpdateFCB() that will update a FCB with new names and parent. It will remove anything related to old name and will recreate using new data. It will adjust references count.
- Modify vfatMakeFCBFromDirEntry() so that it calls vfatMakeFullName().
- Modify vfatReleaseFCB() so that it calls vfatDelFCBFromTable().
- Revert VfatOpenFile() to its previous features.
- Modify VfatCreateFile() to reimplement support for SL_OPEN_TARGET_DIRECTORY. It is way less hackish than previously. It also properly opens parent now, by incrementing its handle count and by setting appropriate access rights.
[KERNEL32]
- Rewritten MoveFileWithProgressW() to implement all the missing features that are used in Windows 2k3 including links and reparse points.
- Implemented BasepMoveFileDelayed() to replace deprecated add_boot_rename_entry(). This functions is matching the features implemented in SMSS.
- Implemented BasepMoveFileCopyProgress() which is used in MoveFileWithProgressW().
- Stubbed BasepNotifyTrackingService() which is not use at the moment (FastFAT, even in Windows doesn't provide such feature).
- Reimplemented ReplaceFileA(), MoveFileWithProgressA() to quit Winisms and use our internal helpers.
- Make MoveFileX() use MoveFileWithProgressX() directly.
- Fixed a few prototypes.
TL;DR:
This (huge) commit implements file and directory renaming in FastFAT driver. This allows getting rid of old implementation in kernel32 where files were force copied.
A feature is still missing, but Jérôme should implement it anytime soon (he prototyped it already): moving directories across volumes. This requires some work in BasepCopyFileExW().
Kudos to all the devs who helped me on this: Christoph, Hervé, Jérôme, Thomas.
This finally allows killing CR-52... It was about time!
svn path=/trunk/; revision=64836
2014-10-19 21:38:32 +00:00
|
|
|
* FILE: drivers/filesystems/fastfat/close.c
|
2000-07-07 02:14:14 +00:00
|
|
|
* PURPOSE: VFAT Filesystem
|
|
|
|
* PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
|
[FASTFAT] Implement delayed close
When we're about to close a file (ie, forget everything about it
and release any associated structure), actually delay it.
This allows keep data fresh in memory for faster reuse in case
it would be required. The effective closing will only happen after some time.
For specific operations, this will produce a real speed up in ReactOS.
For instance, with that patch, Winamp starts within seconds, instead of dozen
of minutes.
In most cases, it will bring ReactOS to performances it had before fixing
the huge leak in FastFAT (commit 94ead99) without leaking the whole FS.
For now, due to regressions, this is only activated for files and not
for directories. Once it gets fixed, it will be enabled for both.
CORE-14826
CORE-14917
2018-08-18 15:04:02 +00:00
|
|
|
* Pierre Schweitzer (pierre@reactos.org)
|
2000-07-07 02:14:14 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/* INCLUDES *****************************************************************/
|
|
|
|
|
|
|
|
#include "vfat.h"
|
|
|
|
|
2013-12-19 16:20:28 +00:00
|
|
|
#define NDEBUG
|
|
|
|
#include <debug.h>
|
|
|
|
|
2000-07-07 02:14:14 +00:00
|
|
|
/* FUNCTIONS ****************************************************************/
|
|
|
|
|
[FASTFAT] Implement delayed close
When we're about to close a file (ie, forget everything about it
and release any associated structure), actually delay it.
This allows keep data fresh in memory for faster reuse in case
it would be required. The effective closing will only happen after some time.
For specific operations, this will produce a real speed up in ReactOS.
For instance, with that patch, Winamp starts within seconds, instead of dozen
of minutes.
In most cases, it will bring ReactOS to performances it had before fixing
the huge leak in FastFAT (commit 94ead99) without leaking the whole FS.
For now, due to regressions, this is only activated for files and not
for directories. Once it gets fixed, it will be enabled for both.
CORE-14826
CORE-14917
2018-08-18 15:04:02 +00:00
|
|
|
VOID
|
|
|
|
VfatCommonCloseFile(
|
|
|
|
PDEVICE_EXTENSION DeviceExt,
|
|
|
|
PVFATFCB pFcb)
|
|
|
|
{
|
|
|
|
/* Nothing to do for volumes */
|
|
|
|
if (BooleanFlagOn(pFcb->Flags, FCB_IS_VOLUME))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If cache is still initialized, release it
|
|
|
|
* This only affects directories
|
|
|
|
*/
|
|
|
|
if (pFcb->OpenHandleCount == 0 && BooleanFlagOn(pFcb->Flags, FCB_CACHE_INITIALIZED))
|
|
|
|
{
|
|
|
|
PFILE_OBJECT tmpFileObject;
|
|
|
|
tmpFileObject = pFcb->FileObject;
|
|
|
|
if (tmpFileObject != NULL)
|
|
|
|
{
|
|
|
|
pFcb->FileObject = NULL;
|
|
|
|
CcUninitializeCacheMap(tmpFileObject, NULL, NULL);
|
|
|
|
ClearFlag(pFcb->Flags, FCB_CACHE_INITIALIZED);
|
|
|
|
ObDereferenceObject(tmpFileObject);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef KDBG
|
|
|
|
pFcb->Flags |= FCB_CLOSED;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Release the FCB, we likely cause its deletion */
|
|
|
|
vfatReleaseFCB(DeviceExt, pFcb);
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
VfatCloseWorker(
|
|
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
|
|
IN PVOID Context)
|
|
|
|
{
|
|
|
|
PLIST_ENTRY Entry;
|
|
|
|
PVFATFCB pFcb;
|
|
|
|
PDEVICE_EXTENSION Vcb;
|
|
|
|
PVFAT_CLOSE_CONTEXT CloseContext;
|
|
|
|
BOOLEAN ConcurrentDeletion;
|
|
|
|
|
|
|
|
/* Start removing work items */
|
|
|
|
ExAcquireFastMutex(&VfatGlobalData->CloseMutex);
|
|
|
|
while (!IsListEmpty(&VfatGlobalData->CloseListHead))
|
|
|
|
{
|
|
|
|
Entry = RemoveHeadList(&VfatGlobalData->CloseListHead);
|
|
|
|
CloseContext = CONTAINING_RECORD(Entry, VFAT_CLOSE_CONTEXT, CloseListEntry);
|
|
|
|
|
|
|
|
/* One less */
|
|
|
|
--VfatGlobalData->CloseCount;
|
|
|
|
/* Reset its entry to detect concurrent deletions */
|
|
|
|
InitializeListHead(&CloseContext->CloseListEntry);
|
|
|
|
ExReleaseFastMutex(&VfatGlobalData->CloseMutex);
|
|
|
|
|
|
|
|
/* Get the elements */
|
|
|
|
Vcb = CloseContext->Vcb;
|
|
|
|
pFcb = CloseContext->Fcb;
|
|
|
|
ExAcquireResourceExclusiveLite(&Vcb->DirResource, TRUE);
|
|
|
|
/* If it didn't got deleted in between */
|
|
|
|
if (BooleanFlagOn(pFcb->Flags, FCB_DELAYED_CLOSE))
|
|
|
|
{
|
|
|
|
/* Close it! */
|
|
|
|
DPRINT("Late closing: %wZ\n", &pFcb->PathNameU);
|
|
|
|
ClearFlag(pFcb->Flags, FCB_DELAYED_CLOSE);
|
|
|
|
pFcb->CloseContext = NULL;
|
|
|
|
VfatCommonCloseFile(Vcb, pFcb);
|
|
|
|
ConcurrentDeletion = FALSE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Otherwise, mark not to delete it */
|
|
|
|
ConcurrentDeletion = TRUE;
|
|
|
|
}
|
|
|
|
ExReleaseResourceLite(&Vcb->DirResource);
|
|
|
|
|
|
|
|
/* If we were the fastest, delete the context */
|
|
|
|
if (!ConcurrentDeletion)
|
|
|
|
{
|
|
|
|
ExFreeToPagedLookasideList(&VfatGlobalData->CloseContextLookasideList, CloseContext);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Lock again the list */
|
|
|
|
ExAcquireFastMutex(&VfatGlobalData->CloseMutex);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We're done, bye! */
|
|
|
|
VfatGlobalData->CloseWorkerRunning = FALSE;
|
|
|
|
ExReleaseFastMutex(&VfatGlobalData->CloseMutex);
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
VfatPostCloseFile(
|
|
|
|
PDEVICE_EXTENSION DeviceExt,
|
|
|
|
PFILE_OBJECT FileObject)
|
|
|
|
{
|
|
|
|
PVFAT_CLOSE_CONTEXT CloseContext;
|
|
|
|
|
|
|
|
/* Allocate a work item */
|
|
|
|
CloseContext = ExAllocateFromPagedLookasideList(&VfatGlobalData->CloseContextLookasideList);
|
|
|
|
if (CloseContext == NULL)
|
|
|
|
{
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set relevant fields */
|
|
|
|
CloseContext->Vcb = DeviceExt;
|
|
|
|
CloseContext->Fcb = FileObject->FsContext;
|
|
|
|
CloseContext->Fcb->CloseContext = CloseContext;
|
|
|
|
|
|
|
|
/* Acquire the lock to insert in list */
|
|
|
|
ExAcquireFastMutex(&VfatGlobalData->CloseMutex);
|
|
|
|
|
|
|
|
/* One more element */
|
|
|
|
InsertTailList(&VfatGlobalData->CloseListHead, &CloseContext->CloseListEntry);
|
|
|
|
++VfatGlobalData->CloseCount;
|
|
|
|
|
|
|
|
/* If we have more than 16 items in list, and no worker thread
|
|
|
|
* start a new one
|
|
|
|
*/
|
|
|
|
if (VfatGlobalData->CloseCount > 16 && !VfatGlobalData->CloseWorkerRunning)
|
|
|
|
{
|
|
|
|
VfatGlobalData->CloseWorkerRunning = TRUE;
|
|
|
|
IoQueueWorkItem(VfatGlobalData->CloseWorkItem, VfatCloseWorker, CriticalWorkQueue, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We're done */
|
|
|
|
ExReleaseFastMutex(&VfatGlobalData->CloseMutex);
|
|
|
|
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2000-07-07 02:14:14 +00:00
|
|
|
/*
|
|
|
|
* FUNCTION: Closes a file
|
|
|
|
*/
|
2013-12-09 10:35:15 +00:00
|
|
|
NTSTATUS
|
|
|
|
VfatCloseFile(
|
|
|
|
PDEVICE_EXTENSION DeviceExt,
|
|
|
|
PFILE_OBJECT FileObject)
|
2000-07-07 02:14:14 +00:00
|
|
|
{
|
2013-12-09 10:35:15 +00:00
|
|
|
PVFATFCB pFcb;
|
|
|
|
PVFATCCB pCcb;
|
|
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
|
|
|
|
DPRINT("VfatCloseFile(DeviceExt %p, FileObject %p)\n",
|
2014-04-18 12:07:55 +00:00
|
|
|
DeviceExt, FileObject);
|
2013-12-09 10:35:15 +00:00
|
|
|
|
|
|
|
/* FIXME : update entry in directory? */
|
|
|
|
pCcb = (PVFATCCB) (FileObject->FsContext2);
|
|
|
|
pFcb = (PVFATFCB) (FileObject->FsContext);
|
|
|
|
|
|
|
|
if (pFcb == NULL)
|
2001-08-14 20:47:30 +00:00
|
|
|
{
|
2013-12-09 10:35:15 +00:00
|
|
|
return STATUS_SUCCESS;
|
2001-08-14 20:47:30 +00:00
|
|
|
}
|
2005-05-08 02:16:32 +00:00
|
|
|
|
[FASTFAT] Implement delayed close
When we're about to close a file (ie, forget everything about it
and release any associated structure), actually delay it.
This allows keep data fresh in memory for faster reuse in case
it would be required. The effective closing will only happen after some time.
For specific operations, this will produce a real speed up in ReactOS.
For instance, with that patch, Winamp starts within seconds, instead of dozen
of minutes.
In most cases, it will bring ReactOS to performances it had before fixing
the huge leak in FastFAT (commit 94ead99) without leaking the whole FS.
For now, due to regressions, this is only activated for files and not
for directories. Once it gets fixed, it will be enabled for both.
CORE-14826
CORE-14917
2018-08-18 15:04:02 +00:00
|
|
|
if (pCcb)
|
2013-12-09 10:35:15 +00:00
|
|
|
{
|
[FASTFAT] Implement delayed close
When we're about to close a file (ie, forget everything about it
and release any associated structure), actually delay it.
This allows keep data fresh in memory for faster reuse in case
it would be required. The effective closing will only happen after some time.
For specific operations, this will produce a real speed up in ReactOS.
For instance, with that patch, Winamp starts within seconds, instead of dozen
of minutes.
In most cases, it will bring ReactOS to performances it had before fixing
the huge leak in FastFAT (commit 94ead99) without leaking the whole FS.
For now, due to regressions, this is only activated for files and not
for directories. Once it gets fixed, it will be enabled for both.
CORE-14826
CORE-14917
2018-08-18 15:04:02 +00:00
|
|
|
vfatDestroyCCB(pCcb);
|
2013-12-09 10:35:15 +00:00
|
|
|
}
|
2018-05-18 12:51:24 +00:00
|
|
|
|
[FASTFAT] Implement delayed close
When we're about to close a file (ie, forget everything about it
and release any associated structure), actually delay it.
This allows keep data fresh in memory for faster reuse in case
it would be required. The effective closing will only happen after some time.
For specific operations, this will produce a real speed up in ReactOS.
For instance, with that patch, Winamp starts within seconds, instead of dozen
of minutes.
In most cases, it will bring ReactOS to performances it had before fixing
the huge leak in FastFAT (commit 94ead99) without leaking the whole FS.
For now, due to regressions, this is only activated for files and not
for directories. Once it gets fixed, it will be enabled for both.
CORE-14826
CORE-14917
2018-08-18 15:04:02 +00:00
|
|
|
/* If we have to close immediately, or if delaying failed, close */
|
|
|
|
if (!BooleanFlagOn(pFcb->Flags, FCB_DELAYED_CLOSE) || !NT_SUCCESS(VfatPostCloseFile(DeviceExt, FileObject)))
|
|
|
|
{
|
|
|
|
VfatCommonCloseFile(DeviceExt, pFcb);
|
2013-12-09 10:35:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
FileObject->FsContext2 = NULL;
|
|
|
|
FileObject->FsContext = NULL;
|
|
|
|
FileObject->SectionObjectPointer = NULL;
|
2000-12-29 23:17:12 +00:00
|
|
|
|
2014-11-29 20:26:07 +00:00
|
|
|
#ifdef ENABLE_SWAPOUT
|
[FASTFAT] Implement delayed close
When we're about to close a file (ie, forget everything about it
and release any associated structure), actually delay it.
This allows keep data fresh in memory for faster reuse in case
it would be required. The effective closing will only happen after some time.
For specific operations, this will produce a real speed up in ReactOS.
For instance, with that patch, Winamp starts within seconds, instead of dozen
of minutes.
In most cases, it will bring ReactOS to performances it had before fixing
the huge leak in FastFAT (commit 94ead99) without leaking the whole FS.
For now, due to regressions, this is only activated for files and not
for directories. Once it gets fixed, it will be enabled for both.
CORE-14826
CORE-14917
2018-08-18 15:04:02 +00:00
|
|
|
if (BooleanFlagOn(pFcb->Flags, FCB_IS_VOLUME) && DeviceExt->OpenHandleCount == 0)
|
2014-11-10 22:11:36 +00:00
|
|
|
{
|
|
|
|
VfatCheckForDismount(DeviceExt, FALSE);
|
|
|
|
}
|
2014-11-29 20:26:07 +00:00
|
|
|
#endif
|
2014-11-10 22:11:36 +00:00
|
|
|
|
2013-12-09 10:35:15 +00:00
|
|
|
return Status;
|
2000-07-07 02:14:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* FUNCTION: Closes a file
|
|
|
|
*/
|
2013-12-09 10:35:15 +00:00
|
|
|
NTSTATUS
|
|
|
|
VfatClose(
|
|
|
|
PVFAT_IRP_CONTEXT IrpContext)
|
2000-07-07 02:14:14 +00:00
|
|
|
{
|
2013-12-09 10:35:15 +00:00
|
|
|
NTSTATUS Status;
|
2000-12-29 23:17:12 +00:00
|
|
|
|
2013-12-09 10:35:15 +00:00
|
|
|
DPRINT("VfatClose(DeviceObject %p, Irp %p)\n", IrpContext->DeviceObject, IrpContext->Irp);
|
2000-12-29 23:17:12 +00:00
|
|
|
|
2013-12-09 10:35:15 +00:00
|
|
|
if (IrpContext->DeviceObject == VfatGlobalData->DeviceObject)
|
2002-05-15 18:05:00 +00:00
|
|
|
{
|
2013-12-09 10:35:15 +00:00
|
|
|
DPRINT("Closing file system\n");
|
2015-05-15 16:03:29 +00:00
|
|
|
IrpContext->Irp->IoStatus.Information = 0;
|
|
|
|
return STATUS_SUCCESS;
|
2002-05-15 18:05:00 +00:00
|
|
|
}
|
2015-05-25 17:54:27 +00:00
|
|
|
if (!ExAcquireResourceExclusiveLite(&IrpContext->DeviceExt->DirResource, BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT)))
|
2013-12-09 10:35:15 +00:00
|
|
|
{
|
2015-05-15 16:03:29 +00:00
|
|
|
return VfatMarkIrpContextForQueue(IrpContext);
|
2013-12-09 10:35:15 +00:00
|
|
|
}
|
2001-11-02 22:47:36 +00:00
|
|
|
|
2013-12-09 10:35:15 +00:00
|
|
|
Status = VfatCloseFile(IrpContext->DeviceExt, IrpContext->FileObject);
|
|
|
|
ExReleaseResourceLite(&IrpContext->DeviceExt->DirResource);
|
2000-12-29 23:17:12 +00:00
|
|
|
|
2013-12-09 10:35:15 +00:00
|
|
|
IrpContext->Irp->IoStatus.Information = 0;
|
2000-12-29 23:17:12 +00:00
|
|
|
|
2013-12-09 10:35:15 +00:00
|
|
|
return Status;
|
2000-07-07 02:14:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* EOF */
|