- Do not immediately write the zeroed region to the disk for a cached file.

- Fixed a problem, which does occur if the cluster size is lower than the segment size.

svn path=/trunk/; revision=9472
This commit is contained in:
Hartmut Birr 2004-05-22 18:28:18 +00:00
parent d805aabcae
commit ef7b36dd46

View file

@ -1,4 +1,4 @@
/* $Id: copy.c,v 1.20 2003/12/30 18:52:03 fireball Exp $ /* $Id: copy.c,v 1.21 2004/05/22 18:28:18 hbirr Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -32,6 +32,8 @@ static PHYSICAL_ADDRESS CcZeroPage = (PHYSICAL_ADDRESS)0LL;
static PHYSICAL_ADDRESS CcZeroPage = { 0 }; static PHYSICAL_ADDRESS CcZeroPage = { 0 };
#endif #endif
#define MAX_ZERO_LENGTH (256 * 1024)
/* FUNCTIONS *****************************************************************/ /* FUNCTIONS *****************************************************************/
VOID VOID
@ -354,15 +356,7 @@ CcCopyRead (IN PFILE_OBJECT FileObject,
ReadLength += TempLength; ReadLength += TempLength;
Length -= TempLength; Length -= TempLength;
ReadOffset += TempLength; ReadOffset += TempLength;
#if defined(__GNUC__) Buffer = (PVOID)((char*)Buffer + TempLength);
Buffer += TempLength;
#else
{
char* pTemp = Buffer;
pTemp += TempLength;
Buffer = pTemp;
}
#endif
} }
while (Length > 0) while (Length > 0)
{ {
@ -523,41 +517,35 @@ CcZeroData (IN PFILE_OBJECT FileObject,
NTSTATUS Status; NTSTATUS Status;
LARGE_INTEGER WriteOffset; LARGE_INTEGER WriteOffset;
ULONG Length; ULONG Length;
ULONG CurrentLength;
PMDL Mdl; PMDL Mdl;
ULONG i; ULONG i;
IO_STATUS_BLOCK Iosb; IO_STATUS_BLOCK Iosb;
KEVENT Event; KEVENT Event;
DPRINT("CcZeroData(FileObject %x, StartOffset %I64x, EndOffset %I64x, " DPRINT("CcZeroData(FileObject %x, StartOffset %I64x, EndOffset %I64x, "
"Wait %d\n", FileObject, StartOffset->QuadPart, EndOffset->QuadPart, "Wait %d)\n", FileObject, StartOffset->QuadPart, EndOffset->QuadPart,
Wait); Wait);
Length = EndOffset->u.LowPart - StartOffset->u.LowPart; Length = EndOffset->u.LowPart - StartOffset->u.LowPart;
WriteOffset.QuadPart = StartOffset->QuadPart;
if (FileObject->SectionObjectPointer->SharedCacheMap == NULL) if (FileObject->SectionObjectPointer->SharedCacheMap == NULL)
{ {
/* File is not cached */ /* File is not cached */
WriteOffset.QuadPart = StartOffset->QuadPart;
while (Length > 0) while (Length > 0)
{ {
if (Length + WriteOffset.u.LowPart % PAGE_SIZE > 262144) if (Length + WriteOffset.u.LowPart % PAGE_SIZE > MAX_ZERO_LENGTH)
{ {
Mdl = MmCreateMdl(NULL, (PVOID)WriteOffset.u.LowPart, CurrentLength = MAX_ZERO_LENGTH - WriteOffset.u.LowPart % PAGE_SIZE;
262144 - WriteOffset.u.LowPart % PAGE_SIZE);
WriteOffset.QuadPart +=
(262144 - WriteOffset.u.LowPart % PAGE_SIZE);
Length -= (262144 - WriteOffset.u.LowPart % PAGE_SIZE);
} }
else else
{ {
Mdl = CurrentLength = Length;
MmCreateMdl(NULL, (PVOID)WriteOffset.u.LowPart,
Length - WriteOffset.u.LowPart % PAGE_SIZE);
WriteOffset.QuadPart +=
(Length - WriteOffset.u.LowPart % PAGE_SIZE);
Length = 0;
} }
Mdl = MmCreateMdl(NULL, (PVOID)WriteOffset.u.LowPart, CurrentLength);
if (Mdl == NULL) if (Mdl == NULL)
{ {
return(FALSE); return(FALSE);
@ -568,7 +556,7 @@ CcZeroData (IN PFILE_OBJECT FileObject,
((PULONG)(Mdl + 1))[i] = CcZeroPage.u.LowPart; ((PULONG)(Mdl + 1))[i] = CcZeroPage.u.LowPart;
} }
KeInitializeEvent(&Event, NotificationEvent, FALSE); KeInitializeEvent(&Event, NotificationEvent, FALSE);
Status = IoPageWrite(FileObject, Mdl, StartOffset, &Event, &Iosb); Status = IoPageWrite(FileObject, Mdl, &WriteOffset, &Event, &Iosb);
if (Status == STATUS_PENDING) if (Status == STATUS_PENDING)
{ {
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
@ -578,6 +566,8 @@ CcZeroData (IN PFILE_OBJECT FileObject,
{ {
return(FALSE); return(FALSE);
} }
WriteOffset.QuadPart += CurrentLength;
Length -= CurrentLength;
} }
} }
else else
@ -588,12 +578,7 @@ CcZeroData (IN PFILE_OBJECT FileObject,
PLIST_ENTRY current_entry; PLIST_ENTRY current_entry;
PCACHE_SEGMENT CacheSeg, current, previous; PCACHE_SEGMENT CacheSeg, current, previous;
ULONG TempLength; ULONG TempLength;
ULONG Start;
ULONG count;
ULONG size;
PHYSICAL_ADDRESS page;
Start = StartOffset->u.LowPart;
Bcb = FileObject->SectionObjectPointer->SharedCacheMap; Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
if (Wait) if (Wait)
{ {
@ -606,10 +591,10 @@ CcZeroData (IN PFILE_OBJECT FileObject,
BcbSegmentListEntry); BcbSegmentListEntry);
if (!CacheSeg->Valid) if (!CacheSeg->Valid)
{ {
if ((Start >= CacheSeg->FileOffset && if ((WriteOffset.u.LowPart >= CacheSeg->FileOffset &&
Start < CacheSeg->FileOffset + Bcb->CacheSegmentSize) WriteOffset.u.LowPart < CacheSeg->FileOffset + Bcb->CacheSegmentSize)
|| (Start + Length > CacheSeg->FileOffset && || (WriteOffset.u.LowPart + Length > CacheSeg->FileOffset &&
Start + Length <= WriteOffset.u.LowPart + Length <=
CacheSeg->FileOffset + Bcb->CacheSegmentSize)) CacheSeg->FileOffset + Bcb->CacheSegmentSize))
{ {
KeReleaseSpinLock(&Bcb->BcbLock, oldirql); KeReleaseSpinLock(&Bcb->BcbLock, oldirql);
@ -621,56 +606,35 @@ CcZeroData (IN PFILE_OBJECT FileObject,
} }
KeReleaseSpinLock(&Bcb->BcbLock, oldirql); KeReleaseSpinLock(&Bcb->BcbLock, oldirql);
} }
while (Length > 0) while (Length > 0)
{ {
ULONG RStart = ROUND_DOWN(Start, Bcb->CacheSegmentSize); ULONG Offset;
WriteOffset.QuadPart = ROUND_DOWN(Start, Bcb->CacheSegmentSize); Offset = WriteOffset.u.LowPart % Bcb->CacheSegmentSize;
if (Start % Bcb->CacheSegmentSize + Length > 262144) if (Length + Offset > MAX_ZERO_LENGTH)
{ {
Mdl = MmCreateMdl(NULL, NULL, 262144); CurrentLength = MAX_ZERO_LENGTH - Offset;
if (Mdl == NULL)
{
return FALSE;
}
Status = CcRosGetCacheSegmentChain (Bcb, RStart,
262144, &CacheSeg);
if (!NT_SUCCESS(Status))
{
ExFreePool(Mdl);
return(FALSE);
}
} }
else else
{ {
ULONG RLength; CurrentLength = Length;
RLength = Start % Bcb->CacheSegmentSize + Length; }
RLength = ROUND_UP(RLength, Bcb->CacheSegmentSize); Status = CcRosGetCacheSegmentChain (Bcb, WriteOffset.u.LowPart - Offset,
Mdl = MmCreateMdl(NULL, (PVOID)RStart, RLength); Offset + CurrentLength, &CacheSeg);
if (Mdl == NULL) if (!NT_SUCCESS(Status))
{ {
return(FALSE); return FALSE;
}
Status = CcRosGetCacheSegmentChain (Bcb, RStart, RLength,
&CacheSeg);
if (!NT_SUCCESS(Status))
{
ExFreePool(Mdl);
return(FALSE);
}
} }
Mdl->MdlFlags |= (MDL_PAGES_LOCKED|MDL_IO_PAGE_READ);
current = CacheSeg; current = CacheSeg;
count = 0;
while (current != NULL) while (current != NULL)
{ {
if ((Start % Bcb->CacheSegmentSize) != 0 || Offset = WriteOffset.u.LowPart % Bcb->CacheSegmentSize;
Start % Bcb->CacheSegmentSize + Length < if (Offset != 0 ||
Bcb->CacheSegmentSize) Offset + CurrentLength < Bcb->CacheSegmentSize)
{ {
if (!current->Valid) if (!current->Valid)
{ {
/* Segment lesen */ /* read the segment */
Status = ReadCacheSegment(current); Status = ReadCacheSegment(current);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
@ -678,50 +642,27 @@ CcZeroData (IN PFILE_OBJECT FileObject,
Status); Status);
} }
} }
TempLength = min (Length, Bcb->CacheSegmentSize - TempLength = min (CurrentLength, Bcb->CacheSegmentSize - Offset);
Start % Bcb->CacheSegmentSize);
memset ((char*)current->BaseAddress + Start % Bcb->CacheSegmentSize,
0, TempLength);
} }
else else
{ {
TempLength = Bcb->CacheSegmentSize; TempLength = Bcb->CacheSegmentSize;
memset (current->BaseAddress, 0, Bcb->CacheSegmentSize);
} }
Start += TempLength; memset ((PUCHAR)current->BaseAddress + Offset, 0, TempLength);
WriteOffset.QuadPart += TempLength;
CurrentLength -= TempLength;
Length -= TempLength; Length -= TempLength;
size = ((Mdl->Size - sizeof(MDL)) / sizeof(ULONG)); current = current->NextInChain;
for (i = 0; i < (Bcb->CacheSegmentSize / PAGE_SIZE) && }
count < size; i++)
{ current = CacheSeg;
PVOID Address;
Address = (char*)current->BaseAddress + (i * PAGE_SIZE);
page =
MmGetPhysicalAddressForProcess(NULL, Address);
((PULONG)(Mdl + 1))[count++] = page.u.LowPart;
}
current = current->NextInChain;
}
/* Write the Segment */
KeInitializeEvent(&Event, NotificationEvent, FALSE);
Status = IoPageWrite(FileObject, Mdl, &WriteOffset, &Event, &Iosb);
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
Status = Iosb.Status;
}
if (!NT_SUCCESS(Status))
{
DPRINT1("IoPageWrite failed, status %x\n", Status);
}
current = CacheSeg;
while (current != NULL) while (current != NULL)
{ {
previous = current; previous = current;
current = current->NextInChain; current = current->NextInChain;
CcRosReleaseCacheSegment(Bcb, previous, TRUE, FALSE, FALSE); CcRosReleaseCacheSegment(Bcb, previous, TRUE, TRUE, FALSE);
} }
} }
} }