Add missing processor architecture cases
[reactos.git] / reactos / ntoskrnl / cc / copy.c
index 0835f25..163beff 100644 (file)
@@ -1,55 +1,65 @@
-/* $Id: copy.c,v 1.14 2003/02/13 22:24:18 hbirr Exp $
+/* $Id$
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
  * FILE:            ntoskrnl/cc/copy.c
  * PURPOSE:         Implements cache managers copy interface
- * PROGRAMMER:      Hartmut Birr
- * UPDATE HISTORY:
- *                  Created 05.10.2001
+ *
+ * PROGRAMMERS:     Hartmut Birr
  */
 
 /* INCLUDES ******************************************************************/
 
-#include <ddk/ntddk.h>
-#include <ddk/ntifs.h>
-#include <internal/mm.h>
-#include <internal/cc.h>
-#include <internal/pool.h>
-#include <internal/io.h>
-#include <ntos/minmax.h>
-
+#include <ntoskrnl.h>
 #define NDEBUG
 #include <internal/debug.h>
 
 /* GLOBALS *******************************************************************/
 
-#define ROUND_DOWN(N, S) ((N) - ((N) % (S)))
+static PFN_TYPE CcZeroPage = 0;
+
+#define MAX_ZERO_LENGTH        (256 * 1024)
+#define MAX_RW_LENGTH  (256 * 1024)
+
+#if defined(__GNUC__)
+/* void * alloca(size_t size); */
+#elif defined(_MSC_VER)
+void* _alloca(size_t size);
+#else
+#error Unknown compiler for alloca intrinsic stack allocation "function"
+#endif
+
+ULONG CcFastMdlReadWait;
+ULONG CcFastReadNotPossible;
+ULONG CcFastReadWait;
+ULONG CcFastReadNoWait;
+ULONG CcFastReadResourceMiss;
 
-static PHYSICAL_ADDRESS CcZeroPage = (PHYSICAL_ADDRESS)0LL;
 
 /* FUNCTIONS *****************************************************************/
 
-VOID 
+VOID
+NTAPI
 CcInitCacheZeroPage(VOID)
 {
    NTSTATUS Status;
 
-   Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &CcZeroPage);
+   Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE, &CcZeroPage);
    if (!NT_SUCCESS(Status))
    {
        DbgPrint("Can't allocate CcZeroPage.\n");
-       KeBugCheck(0);
+       KEBUGCHECKCC;
    }
    Status = MiZeroPage(CcZeroPage);
    if (!NT_SUCCESS(Status))
    {
        DbgPrint("Can't zero out CcZeroPage.\n");
-       KeBugCheck(0);
+       KEBUGCHECKCC;
    }
 }
 
 NTSTATUS
+NTAPI
 ReadCacheSegmentChain(PBCB Bcb, ULONG ReadOffset, ULONG Length,
                      PVOID Buffer)
 {
@@ -61,6 +71,9 @@ ReadCacheSegmentChain(PBCB Bcb, ULONG ReadOffset, ULONG Length,
   NTSTATUS Status;
   ULONG TempLength;
   KEVENT Event;
+  PMDL Mdl;
+
+  Mdl = alloca(MmSizeOfMdl(NULL, MAX_RW_LENGTH));
 
   Status = CcRosGetCacheSegmentChain(Bcb, ReadOffset, Length, &head);
   if (!NT_SUCCESS(Status))
@@ -78,8 +91,10 @@ ReadCacheSegmentChain(PBCB Bcb, ULONG ReadOffset, ULONG Length,
        {
          TempLength = min(Bcb->CacheSegmentSize, Length);
          memcpy(Buffer, current->BaseAddress, TempLength);
-         Buffer += TempLength;
-         Length = Length - TempLength; 
+
+         Buffer = (PVOID)((ULONG_PTR)Buffer + TempLength);
+
+         Length = Length - TempLength;
          previous = current;
          current = current->NextInChain;
          CcRosReleaseCacheSegment(Bcb, previous, TRUE, FALSE, FALSE);
@@ -91,9 +106,8 @@ ReadCacheSegmentChain(PBCB Bcb, ULONG ReadOffset, ULONG Length,
        {
          PCACHE_SEGMENT current2;
          ULONG current_size;
-         PMDL Mdl;
          ULONG i;
-         ULONG offset;
+         PPFN_TYPE MdlPages;
 
          /*
           * Count the maximum number of bytes we could read starting
@@ -101,31 +115,29 @@ ReadCacheSegmentChain(PBCB Bcb, ULONG ReadOffset, ULONG Length,
           */
          current2 = current;
          current_size = 0;
-         while (current2 != NULL && !current2->Valid)
+         while (current2 != NULL && !current2->Valid && current_size < MAX_RW_LENGTH)
            {
              current2 = current2->NextInChain;
              current_size += Bcb->CacheSegmentSize;
            }
-         
+
          /*
           * Create an MDL which contains all their pages.
           */
-         Mdl = MmCreateMdl(NULL, NULL, current_size);
+          MmInitializeMdl(Mdl, NULL, current_size);
          Mdl->MdlFlags |= (MDL_PAGES_LOCKED | MDL_IO_PAGE_READ);
          current2 = current;
-         offset = 0;
-         while (current2 != NULL && !current2->Valid)
+         current_size = 0;
+         MdlPages = (PPFN_TYPE)(Mdl + 1);
+         while (current2 != NULL && !current2->Valid && current_size < MAX_RW_LENGTH)
            {
-             for (i = 0; i < (Bcb->CacheSegmentSize / PAGE_SIZE); i++)
+             PVOID address = current2->BaseAddress;
+             for (i = 0; i < (Bcb->CacheSegmentSize / PAGE_SIZE); i++, address = RVA(address, PAGE_SIZE))
                {
-                 PVOID address;
-                 PHYSICAL_ADDRESS page;
-                 address = current2->BaseAddress + (i * PAGE_SIZE);
-                 page = MmGetPhysicalAddressForProcess(NULL, address);
-                 ((PULONG)(Mdl + 1))[offset] = page.u.LowPart;
-                 offset++;
+                 *MdlPages++ = MmGetPfnForProcess(NULL, address);
                }
              current2 = current2->NextInChain;
+             current_size += Bcb->CacheSegmentSize;
            }
 
          /*
@@ -143,6 +155,10 @@ ReadCacheSegmentChain(PBCB Bcb, ULONG ReadOffset, ULONG Length,
             KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
             Status = Iosb.Status;
          }
+          if (Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA)
+          {
+            MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
+         }
          if (!NT_SUCCESS(Status) && Status != STATUS_END_OF_FILE)
            {
              while (current != NULL)
@@ -153,22 +169,27 @@ ReadCacheSegmentChain(PBCB Bcb, ULONG ReadOffset, ULONG Length,
                }
              return(Status);
            }
-         while (current != NULL && !current->Valid)
+         current_size = 0;
+         while (current != NULL && !current->Valid && current_size < MAX_RW_LENGTH)
            {
              previous = current;
              current = current->NextInChain;
              TempLength = min(Bcb->CacheSegmentSize, Length);
              memcpy(Buffer, previous->BaseAddress, TempLength);
-             Buffer += TempLength;
-             Length = Length - TempLength; 
+
+             Buffer = (PVOID)((ULONG_PTR)Buffer + TempLength);
+
+             Length = Length - TempLength;
              CcRosReleaseCacheSegment(Bcb, previous, TRUE, FALSE, FALSE);
+             current_size += Bcb->CacheSegmentSize;
            }
        }
     }
   return(STATUS_SUCCESS);
 }
 
-NTSTATUS 
+NTSTATUS
+NTAPI
 ReadCacheSegment(PCACHE_SEGMENT CacheSeg)
 {
   ULONG Size;
@@ -179,15 +200,17 @@ ReadCacheSegment(PCACHE_SEGMENT CacheSeg)
   KEVENT Event;
 
   SegOffset.QuadPart = CacheSeg->FileOffset;
-  Size = CacheSeg->Bcb->AllocationSize.QuadPart - CacheSeg->FileOffset;
+  Size = (ULONG)(CacheSeg->Bcb->AllocationSize.QuadPart - CacheSeg->FileOffset);
   if (Size > CacheSeg->Bcb->CacheSegmentSize)
     {
       Size = CacheSeg->Bcb->CacheSegmentSize;
     }
-  Mdl = MmCreateMdl(NULL, CacheSeg->BaseAddress, Size);
+  Mdl = alloca(MmSizeOfMdl(CacheSeg->BaseAddress, Size));
+  MmInitializeMdl(Mdl, CacheSeg->BaseAddress, Size);
   MmBuildMdlForNonPagedPool(Mdl);
+  Mdl->MdlFlags |= MDL_IO_PAGE_READ;
   KeInitializeEvent(&Event, NotificationEvent, FALSE);
-  Status = IoPageRead(CacheSeg->Bcb->FileObject, Mdl, &SegOffset, & Event, &IoStatus); 
+  Status = IoPageRead(CacheSeg->Bcb->FileObject, Mdl, &SegOffset, & Event, &IoStatus);
   if (Status == STATUS_PENDING)
   {
      KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
@@ -196,19 +219,19 @@ ReadCacheSegment(PCACHE_SEGMENT CacheSeg)
 
   if (!NT_SUCCESS(Status) && Status != STATUS_END_OF_FILE)
     {
-      CcRosReleaseCacheSegment(CacheSeg->Bcb, CacheSeg, FALSE, FALSE, FALSE);
       DPRINT1("IoPageRead failed, Status %x\n", Status);
       return Status;
     }
   if (CacheSeg->Bcb->CacheSegmentSize > Size)
     {
-      memset (CacheSeg->BaseAddress + Size, 0, 
+      memset ((char*)CacheSeg->BaseAddress + Size, 0,
              CacheSeg->Bcb->CacheSegmentSize - Size);
     }
   return STATUS_SUCCESS;
 }
 
-NTSTATUS 
+NTSTATUS
+NTAPI
 WriteCacheSegment(PCACHE_SEGMENT CacheSeg)
 {
   ULONG Size;
@@ -220,21 +243,23 @@ WriteCacheSegment(PCACHE_SEGMENT CacheSeg)
 
   CacheSeg->Dirty = FALSE;
   SegOffset.QuadPart = CacheSeg->FileOffset;
-  Size = CacheSeg->Bcb->AllocationSize.QuadPart - CacheSeg->FileOffset;
+  Size = (ULONG)(CacheSeg->Bcb->AllocationSize.QuadPart - CacheSeg->FileOffset);
   if (Size > CacheSeg->Bcb->CacheSegmentSize)
     {
       Size = CacheSeg->Bcb->CacheSegmentSize;
     }
-  Mdl = MmCreateMdl(NULL, CacheSeg->BaseAddress, Size);
+  Mdl = alloca(MmSizeOfMdl(CacheSeg->BaseAddress, Size));
+  MmInitializeMdl(Mdl, CacheSeg->BaseAddress, Size);
   MmBuildMdlForNonPagedPool(Mdl);
+  Mdl->MdlFlags |= MDL_IO_PAGE_READ;
   KeInitializeEvent(&Event, NotificationEvent, FALSE);
-  Status = IoPageWrite(CacheSeg->Bcb->FileObject, Mdl, &SegOffset, &Event, &IoStatus);
+  Status = IoSynchronousPageWrite(CacheSeg->Bcb->FileObject, Mdl, &SegOffset, &Event, &IoStatus);
   if (Status == STATUS_PENDING)
   {
      KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
      Status = IoStatus.Status;
   }
-  if (!NT_SUCCESS(Status))
+  if (!NT_SUCCESS(Status) && (Status != STATUS_END_OF_FILE))
     {
       DPRINT1("IoPageWrite failed, Status %x\n", Status);
       CacheSeg->Dirty = TRUE;
@@ -243,6 +268,25 @@ WriteCacheSegment(PCACHE_SEGMENT CacheSeg)
   return(STATUS_SUCCESS);
 }
 
+
+/*
+ * @unimplemented
+ */
+BOOLEAN STDCALL
+CcCanIWrite (
+                       IN      PFILE_OBJECT    FileObject,
+                       IN      ULONG                   BytesToWrite,
+                       IN      BOOLEAN                 Wait,
+                       IN      BOOLEAN                 Retrying)
+{
+       UNIMPLEMENTED;
+       return FALSE;
+}
+
+
+/*
+ * @implemented
+ */
 BOOLEAN STDCALL
 CcCopyRead (IN PFILE_OBJECT FileObject,
            IN PLARGE_INTEGER FileOffset,
@@ -262,15 +306,15 @@ CcCopyRead (IN PFILE_OBJECT FileObject,
   KIRQL oldirql;
   PLIST_ENTRY current_entry;
   PCACHE_SEGMENT current;
-  
-  DPRINT("CcCopyRead(FileObject %x, FileOffset %x, "
-        "Length %d, Wait %d, Buffer %x, IoStatus %x)\n",
-        FileObject, (ULONG)FileOffset->QuadPart, Length, Wait,
+
+  DPRINT("CcCopyRead(FileObject 0x%p, FileOffset %I64x, "
+        "Length %d, Wait %d, Buffer 0x%p, IoStatus 0x%p)\n",
+        FileObject, FileOffset->QuadPart, Length, Wait,
         Buffer, IoStatus);
 
-  Bcb = FileObject->SectionObjectPointers->SharedCacheMap;
-  ReadOffset = FileOffset->QuadPart;
-  
+  Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
+  ReadOffset = (ULONG)FileOffset->QuadPart;
+
   DPRINT("AllocationSize %d, FileSize %d\n",
          (ULONG)Bcb->AllocationSize.QuadPart,
          (ULONG)Bcb->FileSize.QuadPart);
@@ -285,7 +329,7 @@ CcCopyRead (IN PFILE_OBJECT FileObject,
       current_entry = Bcb->BcbSegmentListHead.Flink;
       while (current_entry != &Bcb->BcbSegmentListHead)
        {
-         current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, 
+         current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT,
                                      BcbSegmentListEntry);
          if (!current->Valid && current->FileOffset < ReadOffset + Length
              && current->FileOffset + Bcb->CacheSegmentSize > ReadOffset)
@@ -305,7 +349,7 @@ CcCopyRead (IN PFILE_OBJECT FileObject,
     {
       TempLength = min (Length, Bcb->CacheSegmentSize - TempLength);
       Status = CcRosRequestCacheSegment(Bcb,
-                                       ROUND_DOWN(ReadOffset, 
+                                       ROUND_DOWN(ReadOffset,
                                                   Bcb->CacheSegmentSize),
                                        &BaseAddress, &Valid, &CacheSeg);
       if (!NT_SUCCESS(Status))
@@ -322,25 +366,27 @@ CcCopyRead (IN PFILE_OBJECT FileObject,
            {
              IoStatus->Information = 0;
              IoStatus->Status = Status;
+              CcRosReleaseCacheSegment(Bcb, CacheSeg, FALSE, FALSE, FALSE);
              return FALSE;
            }
        }
-      memcpy (Buffer, BaseAddress + ReadOffset % Bcb->CacheSegmentSize, 
+      memcpy (Buffer, (char*)BaseAddress + ReadOffset % Bcb->CacheSegmentSize,
              TempLength);
       CcRosReleaseCacheSegment(Bcb, CacheSeg, TRUE, FALSE, FALSE);
       ReadLength += TempLength;
       Length -= TempLength;
       ReadOffset += TempLength;
-      Buffer += TempLength;
-    }  
+      Buffer = (PVOID)((char*)Buffer + TempLength);
+    }
   while (Length > 0)
     {
-      TempLength = min(max(Bcb->CacheSegmentSize, 65536), Length);
+      TempLength = min(max(Bcb->CacheSegmentSize, MAX_RW_LENGTH), Length);
       ReadCacheSegmentChain(Bcb, ReadOffset, TempLength, Buffer);
       ReadLength += TempLength;
       Length -= TempLength;
       ReadOffset += TempLength;
-      Buffer += TempLength;
+
+      Buffer = (PVOID)((ULONG_PTR)Buffer + TempLength);
     }
   IoStatus->Status = STATUS_SUCCESS;
   IoStatus->Information = ReadLength;
@@ -348,6 +394,9 @@ CcCopyRead (IN PFILE_OBJECT FileObject,
   return TRUE;
 }
 
+/*
+ * @implemented
+ */
 BOOLEAN STDCALL
 CcCopyWrite (IN PFILE_OBJECT FileObject,
             IN PLARGE_INTEGER FileOffset,
@@ -365,11 +414,11 @@ CcCopyWrite (IN PFILE_OBJECT FileObject,
    PVOID BaseAddress;
    BOOLEAN Valid;
 
-   DPRINT("CcCopyWrite(FileObject %x, FileOffset %x, "
-         "Length %d, Wait %d, Buffer %x)\n",
-          FileObject, (ULONG)FileOffset->QuadPart, Length, Wait, Buffer);
+   DPRINT("CcCopyWrite(FileObject 0x%p, FileOffset %I64x, "
+         "Length %d, Wait %d, Buffer 0x%p)\n",
+          FileObject, FileOffset->QuadPart, Length, Wait, Buffer);
 
-   Bcb = FileObject->SectionObjectPointers->SharedCacheMap;
+   Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
    WriteOffset = (ULONG)FileOffset->QuadPart;
 
    if (!Wait)
@@ -379,14 +428,14 @@ CcCopyWrite (IN PFILE_OBJECT FileObject,
        current_entry = Bcb->BcbSegmentListHead.Flink;
        while (current_entry != &Bcb->BcbSegmentListHead)
         {
-          CacheSeg = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, 
+          CacheSeg = CONTAINING_RECORD(current_entry, CACHE_SEGMENT,
                                        BcbSegmentListEntry);
           if (!CacheSeg->Valid)
             {
-              if ((WriteOffset >= CacheSeg->FileOffset && 
+              if ((WriteOffset >= CacheSeg->FileOffset &&
                    WriteOffset < CacheSeg->FileOffset + Bcb->CacheSegmentSize)
-                  || (WriteOffset + Length > CacheSeg->FileOffset && 
-                      WriteOffset + Length <= CacheSeg->FileOffset + 
+                  || (WriteOffset + Length > CacheSeg->FileOffset &&
+                      WriteOffset + Length <= CacheSeg->FileOffset +
                       Bcb->CacheSegmentSize))
                 {
                   KeReleaseSpinLock(&Bcb->BcbLock, oldirql);
@@ -418,15 +467,16 @@ CcCopyWrite (IN PFILE_OBJECT FileObject,
               return(FALSE);
             }
         }
-       memcpy (BaseAddress + WriteOffset % Bcb->CacheSegmentSize, 
+       memcpy ((char*)BaseAddress + WriteOffset % Bcb->CacheSegmentSize,
               Buffer, TempLength);
        CcRosReleaseCacheSegment(Bcb, CacheSeg, TRUE, TRUE, FALSE);
-       
+
        Length -= TempLength;
        WriteOffset += TempLength;
-       Buffer += TempLength;
+
+       Buffer = (PVOID)((ULONG_PTR)Buffer + TempLength);
      }
-   
+
    while (Length > 0)
      {
        TempLength = min (Bcb->CacheSegmentSize, Length);
@@ -440,6 +490,7 @@ CcCopyWrite (IN PFILE_OBJECT FileObject,
         {
           if (!NT_SUCCESS(ReadCacheSegment(CacheSeg)))
             {
+               CcRosReleaseCacheSegment(Bcb, CacheSeg, FALSE, FALSE, FALSE);
               return FALSE;
             }
         }
@@ -447,11 +498,75 @@ CcCopyWrite (IN PFILE_OBJECT FileObject,
        CcRosReleaseCacheSegment(Bcb, CacheSeg, TRUE, TRUE, FALSE);
        Length -= TempLength;
        WriteOffset += TempLength;
-       Buffer += TempLength;
+
+       Buffer = (PVOID)((ULONG_PTR)Buffer + TempLength);
      }
    return(TRUE);
 }
 
+/*
+ * @unimplemented
+ */
+VOID
+STDCALL
+CcDeferWrite (
+       IN      PFILE_OBJECT            FileObject,
+       IN      PCC_POST_DEFERRED_WRITE PostRoutine,
+       IN      PVOID                   Context1,
+       IN      PVOID                   Context2,
+       IN      ULONG                   BytesToWrite,
+       IN      BOOLEAN                 Retrying
+       )
+{
+       UNIMPLEMENTED;
+}
+
+/*
+ * @unimplemented
+ */
+VOID
+STDCALL
+CcFastCopyRead (
+    IN  PFILE_OBJECT FileObject,
+    IN  ULONG FileOffset,
+    IN  ULONG Length,
+    IN  ULONG PageCount,
+    OUT PVOID Buffer,
+    OUT PIO_STATUS_BLOCK IoStatus
+       )
+{
+       UNIMPLEMENTED;
+}
+/*
+ * @unimplemented
+ */
+VOID
+STDCALL
+CcFastCopyWrite(
+    IN  PFILE_OBJECT FileObject,
+    IN  ULONG FileOffset,
+    IN  ULONG Length,
+    IN  PVOID Buffer)
+{
+       UNIMPLEMENTED;
+}
+
+/*
+ * @unimplemented
+ */
+NTSTATUS
+STDCALL
+CcWaitForCurrentLazyWriterActivity (
+    VOID
+    )
+{
+       UNIMPLEMENTED;
+       return STATUS_NOT_IMPLEMENTED;
+}
+
+/*
+ * @implemented
+ */
 BOOLEAN STDCALL
 CcZeroData (IN PFILE_OBJECT     FileObject,
            IN PLARGE_INTEGER   StartOffset,
@@ -461,61 +576,55 @@ CcZeroData (IN PFILE_OBJECT     FileObject,
   NTSTATUS Status;
   LARGE_INTEGER WriteOffset;
   ULONG Length;
+  ULONG CurrentLength;
   PMDL Mdl;
   ULONG i;
   IO_STATUS_BLOCK Iosb;
   KEVENT Event;
-  
-  DPRINT("CcZeroData(FileObject %x, StartOffset %I64x, EndOffset %I64x, "
-        "Wait %d\n", FileObject, StartOffset->QuadPart, EndOffset->QuadPart, 
+
+  DPRINT("CcZeroData(FileObject 0x%p, StartOffset %I64x, EndOffset %I64x, "
+        "Wait %d)\n", FileObject, StartOffset->QuadPart, EndOffset->QuadPart,
         Wait);
-  
+
   Length = EndOffset->u.LowPart - StartOffset->u.LowPart;
+  WriteOffset.QuadPart = StartOffset->QuadPart;
 
-  if (FileObject->SectionObjectPointers->SharedCacheMap == NULL)
+  if (FileObject->SectionObjectPointer->SharedCacheMap == NULL)
     {
       /* File is not cached */
-      WriteOffset.QuadPart = StartOffset->QuadPart;
-      
+
+      Mdl = alloca(MmSizeOfMdl(NULL, MAX_ZERO_LENGTH));
+
       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, 
-                               262144 - WriteOffset.u.LowPart % PAGE_SIZE);
-             WriteOffset.QuadPart += 
-               (262144 - WriteOffset.u.LowPart % PAGE_SIZE);
-             Length -= (262144 - WriteOffset.u.LowPart % PAGE_SIZE);
+             CurrentLength = MAX_ZERO_LENGTH - WriteOffset.u.LowPart % PAGE_SIZE;
            }
          else
            {
-             Mdl = 
-               MmCreateMdl(NULL, (PVOID)WriteOffset.u.LowPart, 
-                           Length - WriteOffset.u.LowPart % PAGE_SIZE);
-             WriteOffset.QuadPart += 
-               (Length - WriteOffset.u.LowPart % PAGE_SIZE);
-             Length = 0;
-           }
-         if (Mdl == NULL)
-           {
-             return(FALSE);
+             CurrentLength = Length;
            }
+          MmInitializeMdl(Mdl, (PVOID)WriteOffset.u.LowPart, CurrentLength);
          Mdl->MdlFlags |= (MDL_PAGES_LOCKED | MDL_IO_PAGE_READ);
          for (i = 0; i < ((Mdl->Size - sizeof(MDL)) / sizeof(ULONG)); i++)
            {
-             ((PULONG)(Mdl + 1))[i] = CcZeroPage.u.LowPart;
+             ((PPFN_TYPE)(Mdl + 1))[i] = CcZeroPage;
            }
           KeInitializeEvent(&Event, NotificationEvent, FALSE);
-         Status = IoPageWrite(FileObject, Mdl, StartOffset, &Event, &Iosb);
+         Status = IoSynchronousPageWrite(FileObject, Mdl, &WriteOffset, &Event, &Iosb);
           if (Status == STATUS_PENDING)
          {
              KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
              Status = Iosb.Status;
          }
+          MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
          if (!NT_SUCCESS(Status))
            {
              return(FALSE);
            }
+         WriteOffset.QuadPart += CurrentLength;
+         Length -= CurrentLength;
        }
     }
   else
@@ -526,13 +635,8 @@ CcZeroData (IN PFILE_OBJECT     FileObject,
       PLIST_ENTRY current_entry;
       PCACHE_SEGMENT CacheSeg, current, previous;
       ULONG TempLength;
-      ULONG Start;
-      ULONG count;
-      ULONG size;
-      PHYSICAL_ADDRESS page;
 
-      Start = StartOffset->u.LowPart;
-      Bcb = FileObject->SectionObjectPointers->SharedCacheMap;
+      Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
       if (Wait)
        {
           /* testing, if the requested datas are available */
@@ -540,14 +644,14 @@ CcZeroData (IN PFILE_OBJECT     FileObject,
          current_entry = Bcb->BcbSegmentListHead.Flink;
          while (current_entry != &Bcb->BcbSegmentListHead)
            {
-             CacheSeg = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, 
+             CacheSeg = CONTAINING_RECORD(current_entry, CACHE_SEGMENT,
                                           BcbSegmentListEntry);
              if (!CacheSeg->Valid)
                {
-                 if ((Start >= CacheSeg->FileOffset && 
-                      Start < CacheSeg->FileOffset + Bcb->CacheSegmentSize)
-                     || (Start + Length > CacheSeg->FileOffset && 
-                         Start + Length <= 
+                 if ((WriteOffset.u.LowPart >= CacheSeg->FileOffset &&
+                      WriteOffset.u.LowPart < CacheSeg->FileOffset + Bcb->CacheSegmentSize)
+                     || (WriteOffset.u.LowPart + Length > CacheSeg->FileOffset &&
+                         WriteOffset.u.LowPart + Length <=
                          CacheSeg->FileOffset + Bcb->CacheSegmentSize))
                    {
                      KeReleaseSpinLock(&Bcb->BcbLock, oldirql);
@@ -559,110 +663,65 @@ CcZeroData (IN PFILE_OBJECT     FileObject,
            }
          KeReleaseSpinLock(&Bcb->BcbLock, oldirql);
        }
-      
       while (Length > 0)
        {
-         ULONG RStart = ROUND_DOWN(Start, Bcb->CacheSegmentSize);
-         WriteOffset.QuadPart = ROUND_DOWN(Start, Bcb->CacheSegmentSize);
-         if (Start % Bcb->CacheSegmentSize + Length > 262144)
+          ULONG Offset;
+         Offset = WriteOffset.u.LowPart % Bcb->CacheSegmentSize;
+         if (Length + Offset > MAX_ZERO_LENGTH)
            {
-             Mdl = MmCreateMdl(NULL, NULL, 262144);
-             if (Mdl == NULL)
-               {
-                 return FALSE;
-               }
-             Status = CcRosGetCacheSegmentChain (Bcb, RStart,
-                                                 262144, &CacheSeg);
-             if (!NT_SUCCESS(Status))
-               {
-                 ExFreePool(Mdl);
-                 return(FALSE);
-               }
+             CurrentLength = MAX_ZERO_LENGTH - Offset;
            }
          else
            {
-             ULONG RLength;
-             RLength = Start % Bcb->CacheSegmentSize + Length;
-             RLength = ROUND_UP(RLength, Bcb->CacheSegmentSize);
-             Mdl = MmCreateMdl(NULL, (PVOID)RStart, RLength);
-             if (Mdl == NULL)
-               {
-                 return(FALSE);
-               }
-             Status = CcRosGetCacheSegmentChain (Bcb, RStart, RLength,
-                                                 &CacheSeg);
-             if (!NT_SUCCESS(Status))
-               {
-                 ExFreePool(Mdl);
-                 return(FALSE);
-               }
+             CurrentLength = Length;
+           }
+         Status = CcRosGetCacheSegmentChain (Bcb, WriteOffset.u.LowPart - Offset,
+                                             Offset + CurrentLength, &CacheSeg);
+         if (!NT_SUCCESS(Status))
+           {
+             return FALSE;
            }
-         Mdl->MdlFlags |= (MDL_PAGES_LOCKED|MDL_IO_PAGE_READ);
          current = CacheSeg;
-         count = 0;
+
          while (current != NULL)
            {
-             if ((Start % Bcb->CacheSegmentSize) != 0 || 
-                 Start % Bcb->CacheSegmentSize + Length < 
-                 Bcb->CacheSegmentSize)
-               {
+             Offset = WriteOffset.u.LowPart % Bcb->CacheSegmentSize;
+             if (Offset != 0 ||
+                  Offset + CurrentLength < Bcb->CacheSegmentSize)
+               {
                  if (!current->Valid)
                    {
-                     /* Segment lesen */
+                     /* read the segment */
                      Status = ReadCacheSegment(current);
                      if (!NT_SUCCESS(Status))
                        {
-                         DPRINT1("ReadCacheSegment failed, status %x\n", 
+                         DPRINT1("ReadCacheSegment failed, status %x\n",
                                  Status);
                        }
                    }
-                 TempLength = min (Length, Bcb->CacheSegmentSize - 
-                                   Start % Bcb->CacheSegmentSize);
-                 memset (current->BaseAddress + Start % Bcb->CacheSegmentSize,
-                         0, TempLength);
+                 TempLength = min (CurrentLength, Bcb->CacheSegmentSize - Offset);
                }
              else
-               {
+               {
                  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;
-             
-             size = ((Mdl->Size - sizeof(MDL)) / sizeof(ULONG));
-             for (i = 0; i < (Bcb->CacheSegmentSize / PAGE_SIZE) && 
-                    count < size; i++)
-               {
-                 PVOID Address;
-                 Address = 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 = current->NextInChain;
            }
-         current = CacheSeg;
+
+          current = CacheSeg;
          while (current != NULL)
            {
              previous = current;
              current = current->NextInChain;
-             CcRosReleaseCacheSegment(Bcb, previous, TRUE, FALSE, FALSE);
+             CcRosReleaseCacheSegment(Bcb, previous, TRUE, TRUE, FALSE);
            }
        }
     }
   return(TRUE);
 }
-