https://git.reactos.org/?p=reactos.git;a=commitdiff;h=54c049bd6ef0a906aff0f…
commit 54c049bd6ef0a906aff0f434f724765f009485d8
Author: Pierre Schweitzer <pierre(a)reactos.org>
AuthorDate: Mon Apr 30 22:19:17 2018 +0200
Commit: Pierre Schweitzer <pierre(a)reactos.org>
CommitDate: Mon Apr 30 22:24:30 2018 +0200
[NTOKSNRL] Always flush dirty VACB.
Recent changes seem to show that it's not
required to be exclusive on VACB to be able
to flush it.
This commit goes with f2c44aa and fixes the
last issues going with copying huge files.
There are no longer BSODs (be it in Mm or Cc).
I could, with 750MB RAM extract a 2GB file from
a 53MB archive and copy a 2,5GB file from a VBox
share to the disk. Note that writes are often
deferred, so if copy works, it's not that fast for now.
Note that it also brings some beloved behavior from
Windows: copy times are totally unreliable now when
writes are deferred. Little remaining times when
actively copying, high remaining times when deferred
writes in action. And goes between both... Sorry! ;-)
https://xkcd.com/612/
CORE-9696
CORE-11175
---
ntoskrnl/cc/view.c | 13 -------------
1 file changed, 13 deletions(-)
diff --git a/ntoskrnl/cc/view.c b/ntoskrnl/cc/view.c
index d3c32f9046..9a7f716854 100644
--- a/ntoskrnl/cc/view.c
+++ b/ntoskrnl/cc/view.c
@@ -207,8 +207,6 @@ CcRosFlushDirtyPages (
while ((current_entry != &DirtyVacbListHead) && (Target > 0))
{
- ULONG Refs;
-
current = CONTAINING_RECORD(current_entry,
ROS_VACB,
DirtyVacbListEntry);
@@ -234,17 +232,6 @@ CcRosFlushDirtyPages (
ASSERT(current->Dirty);
- /* One reference is added above */
- Refs = CcRosVacbGetRefCount(current);
- if ((Refs > 3 && current->PinCount == 0) ||
- (Refs > 4 && current->PinCount > 1))
- {
- current->SharedCacheMap->Callbacks->ReleaseFromLazyWrite(
- current->SharedCacheMap->LazyWriteContext);
- CcRosVacbDecRefCount(current);
- continue;
- }
-
KeReleaseGuardedMutex(&ViewLock);
Status = CcRosFlushVacb(current);
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=74c5d8b6bd6e8668eaab5…
commit 74c5d8b6bd6e8668eaab5f6467c80cfc2d899825
Author: Pierre Schweitzer <pierre(a)reactos.org>
AuthorDate: Mon Apr 30 12:10:24 2018 +0200
Commit: Pierre Schweitzer <pierre(a)reactos.org>
CommitDate: Mon Apr 30 12:10:24 2018 +0200
[NTOSKRNL] Free unused VACB when required.
Same mechanism exists in Windows (even their Cc
is way different from ours...) where when Cc is
out of memory (in their case, out of VACB), we
will start scavenge old & unused VACB to free
some of the memory.
It's useful in case we're operating we big files
operations, we may run out of memory where to map
VACB for them, so start to scavenge VACB to free
some of that memory.
With this, I am able to install Qt 4.8.6 with 2,5GB of RAM,
scavenging acting when needed!
CORE-12081
CORE-14582
---
ntoskrnl/cc/view.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 99 insertions(+)
diff --git a/ntoskrnl/cc/view.c b/ntoskrnl/cc/view.c
index 5bd1f41411..d3c32f9046 100644
--- a/ntoskrnl/cc/view.c
+++ b/ntoskrnl/cc/view.c
@@ -699,6 +699,88 @@ CcRosMapVacbInKernelSpace(
return STATUS_SUCCESS;
}
+static
+BOOLEAN
+CcRosFreeUnusedVacb (
+ PULONG Count)
+{
+ ULONG cFreed;
+ BOOLEAN Freed;
+ KIRQL oldIrql;
+ PROS_VACB current;
+ LIST_ENTRY FreeList;
+ PLIST_ENTRY current_entry;
+
+ cFreed = 0;
+ Freed = FALSE;
+ InitializeListHead(&FreeList);
+
+ KeAcquireGuardedMutex(&ViewLock);
+
+ /* Browse all the available VACB */
+ current_entry = VacbLruListHead.Flink;
+ while (current_entry != &VacbLruListHead)
+ {
+ ULONG Refs;
+
+ current = CONTAINING_RECORD(current_entry,
+ ROS_VACB,
+ VacbLruListEntry);
+ current_entry = current_entry->Flink;
+
+ KeAcquireSpinLock(¤t->SharedCacheMap->CacheMapLock, &oldIrql);
+
+ /* Only deal with unused VACB, we will free them */
+ Refs = CcRosVacbGetRefCount(current);
+ if (Refs < 2)
+ {
+ ASSERT(!current->Dirty);
+ ASSERT(!current->MappedCount);
+ ASSERT(Refs == 1);
+
+ /* Reset and move to free list */
+ RemoveEntryList(¤t->CacheMapVacbListEntry);
+ RemoveEntryList(¤t->VacbLruListEntry);
+ InitializeListHead(¤t->VacbLruListEntry);
+ InsertHeadList(&FreeList, ¤t->CacheMapVacbListEntry);
+ }
+
+ KeReleaseSpinLock(¤t->SharedCacheMap->CacheMapLock, oldIrql);
+
+ }
+
+ KeReleaseGuardedMutex(&ViewLock);
+
+ /* And now, free any of the found VACB, that'll free memory! */
+ while (!IsListEmpty(&FreeList))
+ {
+ ULONG Refs;
+
+ current_entry = RemoveHeadList(&FreeList);
+ current = CONTAINING_RECORD(current_entry,
+ ROS_VACB,
+ CacheMapVacbListEntry);
+ InitializeListHead(¤t->CacheMapVacbListEntry);
+ Refs = CcRosVacbDecRefCount(current);
+ ASSERT(Refs == 0);
+ ++cFreed;
+ }
+
+ /* If we freed at least one VACB, return success */
+ if (cFreed != 0)
+ {
+ Freed = TRUE;
+ }
+
+ /* If caller asked for free count, return it */
+ if (Count != NULL)
+ {
+ *Count = cFreed;
+ }
+
+ return Freed;
+}
+
static
NTSTATUS
CcRosCreateVacb (
@@ -712,6 +794,7 @@ CcRosCreateVacb (
NTSTATUS Status;
KIRQL oldIrql;
ULONG Refs;
+ BOOLEAN Retried;
ASSERT(SharedCacheMap);
@@ -745,9 +828,25 @@ CcRosCreateVacb (
CcRosVacbIncRefCount(current);
+ Retried = FALSE;
+Retry:
+ /* Map VACB in kernel space */
Status = CcRosMapVacbInKernelSpace(current);
if (!NT_SUCCESS(Status))
{
+ ULONG Freed;
+ /* If no space left, try to prune unused VACB
+ * to recover space to map our VACB
+ * If it succeed, retry to map, otherwise
+ * just fail.
+ */
+ if (!Retried && CcRosFreeUnusedVacb(&Freed))
+ {
+ DPRINT("Prunned %d VACB, trying again\n", Freed);
+ Retried = TRUE;
+ goto Retry;
+ }
+
CcRosVacbDecRefCount(current);
ExFreeToNPagedLookasideList(&VacbLookasideList, current);
return Status;
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=2a7d16727a840b631076a…
commit 2a7d16727a840b631076aaaa1cd00d09b9a32a80
Author: Pierre Schweitzer <pierre(a)reactos.org>
AuthorDate: Sun Apr 29 20:42:24 2018 +0200
Commit: Pierre Schweitzer <pierre(a)reactos.org>
CommitDate: Sun Apr 29 20:42:53 2018 +0200
[FASTFAT] Implement write IOs defering.
Before any write operation that would involve caching, ask
the cache controler whether writing would make it exceed its memory
consumption. If so, queue the write operation for later execution.
In case the write operation can wait, then, the FSD operation will be
halted until the write is allowed.
I could test it successfully by copying huge files from a FAT volume to
another. The write is halted until some portions of the file is written
to the disk.
I could also properly install Qt (SDK) on ReactOS with this and less than 1GB RAM:
- https://www.heisspiter.net/~Pierre/rostests/Qt_OS.png
- https://www.heisspiter.net/~Pierre/rostests/Qt_OS2.png
CORE-12081
CORE-14582
CORE-14313
---
drivers/filesystems/fastfat/misc.c | 9 +++++++++
drivers/filesystems/fastfat/rw.c | 17 +++++++++++++++++
drivers/filesystems/fastfat/vfat.h | 7 +++++++
3 files changed, 33 insertions(+)
diff --git a/drivers/filesystems/fastfat/misc.c b/drivers/filesystems/fastfat/misc.c
index 7797f37ab2..0d291776b5 100644
--- a/drivers/filesystems/fastfat/misc.c
+++ b/drivers/filesystems/fastfat/misc.c
@@ -213,6 +213,15 @@ VfatDispatchRequest(
return Status;
}
+VOID
+NTAPI
+VfatHandleDeferredWrite(
+ IN PVOID IrpContext,
+ IN PVOID Unused)
+{
+ VfatDispatchRequest((PVFAT_IRP_CONTEXT)IrpContext);
+}
+
NTSTATUS
NTAPI
VfatBuildRequest(
diff --git a/drivers/filesystems/fastfat/rw.c b/drivers/filesystems/fastfat/rw.c
index 25114f25cf..4dd59933c4 100644
--- a/drivers/filesystems/fastfat/rw.c
+++ b/drivers/filesystems/fastfat/rw.c
@@ -895,6 +895,23 @@ VfatWrite(
}
}
+ if (!NoCache && !CcCanIWrite(IrpContext->FileObject, Length, CanWait,
+ BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_DEFERRED_WRITE)))
+ {
+ BOOLEAN Retrying;
+
+ Retrying = BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_DEFERRED_WRITE);
+ SetFlag(IrpContext->Flags, IRPCONTEXT_DEFERRED_WRITE);
+
+ Status = STATUS_PENDING;
+ CcDeferWrite(IrpContext->FileObject, VfatHandleDeferredWrite,
+ IrpContext, NULL, Length, Retrying);
+
+ DPRINT1("Dererring write!\n");
+
+ goto ByeBye;
+ }
+
if (IsVolume)
{
Resource = &IrpContext->DeviceExt->DirResource;
diff --git a/drivers/filesystems/fastfat/vfat.h b/drivers/filesystems/fastfat/vfat.h
index 5bb5289feb..cb38b16699 100644
--- a/drivers/filesystems/fastfat/vfat.h
+++ b/drivers/filesystems/fastfat/vfat.h
@@ -544,6 +544,7 @@ DOSDATE, *PDOSDATE;
#define IRPCONTEXT_COMPLETE 0x0002
#define IRPCONTEXT_QUEUE 0x0004
#define IRPCONTEXT_PENDINGRETURNED 0x0008
+#define IRPCONTEXT_DEFERRED_WRITE 0x0010
typedef struct
{
@@ -1085,6 +1086,12 @@ vfatReportChange(
IN ULONG FilterMatch,
IN ULONG Action);
+VOID
+NTAPI
+VfatHandleDeferredWrite(
+ IN PVOID IrpContext,
+ IN PVOID Unused);
+
/* pnp.c */
NTSTATUS