ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

copy.c
Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:       See COPYING in the top level directory
00003  * PROJECT:         ReactOS kernel
00004  * FILE:            ntoskrnl/cc/copy.c
00005  * PURPOSE:         Implements cache managers copy interface
00006  *
00007  * PROGRAMMERS:
00008  */
00009 
00010 /* INCLUDES ******************************************************************/
00011 
00012 #include <ntoskrnl.h>
00013 #define NDEBUG
00014 #include <debug.h>
00015 
00016 /* GLOBALS *******************************************************************/
00017 
00018 static PFN_NUMBER CcZeroPage = 0;
00019 
00020 #define MAX_ZERO_LENGTH (256 * 1024)
00021 #define MAX_RW_LENGTH   (256 * 1024)
00022 
00023 ULONG CcFastMdlReadWait;
00024 ULONG CcFastMdlReadNotPossible;
00025 ULONG CcFastReadNotPossible;
00026 ULONG CcFastReadWait;
00027 ULONG CcFastReadNoWait;
00028 ULONG CcFastReadResourceMiss;
00029 
00030 /* FUNCTIONS *****************************************************************/
00031 
00032 VOID
00033 NTAPI
00034 MiZeroPhysicalPage(
00035     IN PFN_NUMBER PageFrameIndex
00036 );
00037 
00038 VOID
00039 NTAPI
00040 CcInitCacheZeroPage(VOID)
00041 {
00042    NTSTATUS Status;
00043 
00044    MI_SET_USAGE(MI_USAGE_CACHE);
00045    //MI_SET_PROCESS2(PsGetCurrentProcess()->ImageFileName);
00046    Status = MmRequestPageMemoryConsumer(MC_SYSTEM, TRUE, &CcZeroPage);
00047    if (!NT_SUCCESS(Status))
00048    {
00049        DbgPrint("Can't allocate CcZeroPage.\n");
00050        KeBugCheck(CACHE_MANAGER);
00051    }
00052    MiZeroPhysicalPage(CcZeroPage);
00053 }
00054 
00055 NTSTATUS
00056 NTAPI
00057 ReadCacheSegmentChain(PBCB Bcb, ULONG ReadOffset, ULONG Length,
00058               PVOID Buffer)
00059 {
00060   PCACHE_SEGMENT head;
00061   PCACHE_SEGMENT current;
00062   PCACHE_SEGMENT previous;
00063   IO_STATUS_BLOCK Iosb;
00064   LARGE_INTEGER SegOffset;
00065   NTSTATUS Status;
00066   ULONG TempLength;
00067   KEVENT Event;
00068   PMDL Mdl;
00069 
00070   Mdl = _alloca(MmSizeOfMdl(NULL, MAX_RW_LENGTH));
00071 
00072   Status = CcRosGetCacheSegmentChain(Bcb, ReadOffset, Length, &head);
00073   if (!NT_SUCCESS(Status))
00074     {
00075       return(Status);
00076     }
00077   current = head;
00078   while (current != NULL)
00079     {
00080       /*
00081        * If the current segment is valid then copy it into the
00082        * user buffer.
00083        */
00084       if (current->Valid)
00085     {
00086       TempLength = min(Bcb->CacheSegmentSize, Length);
00087       memcpy(Buffer, current->BaseAddress, TempLength);
00088 
00089       Buffer = (PVOID)((ULONG_PTR)Buffer + TempLength);
00090 
00091       Length = Length - TempLength;
00092       previous = current;
00093       current = current->NextInChain;
00094       CcRosReleaseCacheSegment(Bcb, previous, TRUE, FALSE, FALSE);
00095     }
00096       /*
00097        * Otherwise read in as much as we can.
00098        */
00099       else
00100     {
00101       PCACHE_SEGMENT current2;
00102       ULONG current_size;
00103       ULONG i;
00104       PPFN_NUMBER MdlPages;
00105 
00106       /*
00107        * Count the maximum number of bytes we could read starting
00108        * from the current segment.
00109        */
00110       current2 = current;
00111       current_size = 0;
00112       while (current2 != NULL && !current2->Valid && current_size < MAX_RW_LENGTH)
00113         {
00114           current2 = current2->NextInChain;
00115           current_size += Bcb->CacheSegmentSize;
00116         }
00117 
00118       /*
00119        * Create an MDL which contains all their pages.
00120        */
00121           MmInitializeMdl(Mdl, NULL, current_size);
00122       Mdl->MdlFlags |= (MDL_PAGES_LOCKED | MDL_IO_PAGE_READ);
00123       current2 = current;
00124       current_size = 0;
00125       MdlPages = (PPFN_NUMBER)(Mdl + 1);
00126       while (current2 != NULL && !current2->Valid && current_size < MAX_RW_LENGTH)
00127         {
00128           PVOID address = current2->BaseAddress;
00129           for (i = 0; i < (Bcb->CacheSegmentSize / PAGE_SIZE); i++, address = RVA(address, PAGE_SIZE))
00130         {
00131           *MdlPages++ = MmGetPfnForProcess(NULL, address);
00132         }
00133           current2 = current2->NextInChain;
00134           current_size += Bcb->CacheSegmentSize;
00135         }
00136 
00137       /*
00138        * Read in the information.
00139        */
00140       SegOffset.QuadPart = current->FileOffset;
00141       KeInitializeEvent(&Event, NotificationEvent, FALSE);
00142       Status = IoPageRead(Bcb->FileObject,
00143                   Mdl,
00144                   &SegOffset,
00145                   &Event,
00146                   &Iosb);
00147       if (Status == STATUS_PENDING)
00148       {
00149          KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
00150          Status = Iosb.Status;
00151       }
00152           if (Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA)
00153           {
00154          MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
00155       }
00156       if (!NT_SUCCESS(Status) && Status != STATUS_END_OF_FILE)
00157         {
00158           while (current != NULL)
00159         {
00160           previous = current;
00161           current = current->NextInChain;
00162           CcRosReleaseCacheSegment(Bcb, previous, FALSE, FALSE, FALSE);
00163         }
00164           return(Status);
00165         }
00166       current_size = 0;
00167       while (current != NULL && !current->Valid && current_size < MAX_RW_LENGTH)
00168         {
00169           previous = current;
00170           current = current->NextInChain;
00171           TempLength = min(Bcb->CacheSegmentSize, Length);
00172           memcpy(Buffer, previous->BaseAddress, TempLength);
00173 
00174           Buffer = (PVOID)((ULONG_PTR)Buffer + TempLength);
00175 
00176           Length = Length - TempLength;
00177           CcRosReleaseCacheSegment(Bcb, previous, TRUE, FALSE, FALSE);
00178           current_size += Bcb->CacheSegmentSize;
00179         }
00180     }
00181     }
00182   return(STATUS_SUCCESS);
00183 }
00184 
00185 NTSTATUS
00186 NTAPI
00187 ReadCacheSegment(PCACHE_SEGMENT CacheSeg)
00188 {
00189     ULONG Size;
00190     PMDL Mdl;
00191     NTSTATUS Status;
00192     LARGE_INTEGER SegOffset;
00193     IO_STATUS_BLOCK IoStatus;
00194     KEVENT Event;
00195 
00196     SegOffset.QuadPart = CacheSeg->FileOffset;
00197     Size = (ULONG)(CacheSeg->Bcb->AllocationSize.QuadPart - CacheSeg->FileOffset);
00198     if (Size > CacheSeg->Bcb->CacheSegmentSize)
00199     {
00200         Size = CacheSeg->Bcb->CacheSegmentSize;
00201     }
00202 
00203     Mdl = IoAllocateMdl(CacheSeg->BaseAddress, Size, FALSE, FALSE, NULL);
00204     if (!Mdl)
00205     {
00206         return STATUS_INSUFFICIENT_RESOURCES;
00207     }
00208     MmBuildMdlForNonPagedPool(Mdl);
00209     Mdl->MdlFlags |= MDL_IO_PAGE_READ;
00210     KeInitializeEvent(&Event, NotificationEvent, FALSE);
00211     Status = IoPageRead(CacheSeg->Bcb->FileObject, Mdl, &SegOffset, &Event, &IoStatus);
00212     if (Status == STATUS_PENDING)
00213     {
00214         KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
00215         Status = IoStatus.Status;
00216     }
00217 
00218     IoFreeMdl(Mdl);
00219 
00220     if (!NT_SUCCESS(Status) && Status != STATUS_END_OF_FILE)
00221     {
00222         DPRINT1("IoPageRead failed, Status %x\n", Status);
00223         return Status;
00224     }
00225 
00226     if (CacheSeg->Bcb->CacheSegmentSize > Size)
00227     {
00228         RtlZeroMemory((char*)CacheSeg->BaseAddress + Size,
00229           CacheSeg->Bcb->CacheSegmentSize - Size);
00230     }
00231 
00232     return STATUS_SUCCESS;
00233 }
00234 
00235 NTSTATUS
00236 NTAPI
00237 WriteCacheSegment(PCACHE_SEGMENT CacheSeg)
00238 {
00239     ULONG Size;
00240     PMDL Mdl;
00241     NTSTATUS Status;
00242     IO_STATUS_BLOCK IoStatus;
00243     LARGE_INTEGER SegOffset;
00244     KEVENT Event;
00245 
00246     CacheSeg->Dirty = FALSE;
00247     SegOffset.QuadPart = CacheSeg->FileOffset;
00248     Size = (ULONG)(CacheSeg->Bcb->AllocationSize.QuadPart - CacheSeg->FileOffset);
00249     if (Size > CacheSeg->Bcb->CacheSegmentSize)
00250     {
00251         Size = CacheSeg->Bcb->CacheSegmentSize;
00252     }
00253     //
00254     // Nonpaged pool PDEs in ReactOS must actually be synchronized between the
00255     // MmGlobalPageDirectory and the real system PDE directory. What a mess...
00256     //
00257     {
00258         ULONG i = 0;
00259         do
00260         {
00261             MmGetPfnForProcess(NULL, (PVOID)((ULONG_PTR)CacheSeg->BaseAddress + (i << PAGE_SHIFT)));
00262         } while (++i < (Size >> PAGE_SHIFT));
00263     }
00264 
00265     Mdl = IoAllocateMdl(CacheSeg->BaseAddress, Size, FALSE, FALSE, NULL);
00266     if (!Mdl)
00267     {
00268         return STATUS_INSUFFICIENT_RESOURCES;
00269     }
00270     MmBuildMdlForNonPagedPool(Mdl);
00271     Mdl->MdlFlags |= MDL_IO_PAGE_READ;
00272     KeInitializeEvent(&Event, NotificationEvent, FALSE);
00273     Status = IoSynchronousPageWrite(CacheSeg->Bcb->FileObject, Mdl, &SegOffset, &Event, &IoStatus);
00274     if (Status == STATUS_PENDING)
00275     {
00276         KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
00277         Status = IoStatus.Status;
00278     }
00279     IoFreeMdl(Mdl);
00280     if (!NT_SUCCESS(Status) && (Status != STATUS_END_OF_FILE))
00281     {
00282         DPRINT1("IoPageWrite failed, Status %x\n", Status);
00283         CacheSeg->Dirty = TRUE;
00284         return Status;
00285     }
00286 
00287     return STATUS_SUCCESS;
00288 }
00289 
00290 
00291 /*
00292  * @unimplemented
00293  */
00294 BOOLEAN NTAPI
00295 CcCanIWrite (
00296             IN  PFILE_OBJECT    FileObject,
00297             IN  ULONG           BytesToWrite,
00298             IN  BOOLEAN         Wait,
00299             IN  BOOLEAN         Retrying)
00300 {
00301     UNIMPLEMENTED;
00302     return FALSE;
00303 }
00304 
00305 
00306 /*
00307  * @implemented
00308  */
00309 BOOLEAN NTAPI
00310 CcCopyRead (IN PFILE_OBJECT FileObject,
00311         IN PLARGE_INTEGER FileOffset,
00312         IN ULONG Length,
00313         IN BOOLEAN Wait,
00314         OUT PVOID Buffer,
00315         OUT PIO_STATUS_BLOCK IoStatus)
00316 {
00317   ULONG ReadOffset;
00318   ULONG TempLength;
00319   NTSTATUS Status = STATUS_SUCCESS;
00320   PVOID BaseAddress;
00321   PCACHE_SEGMENT CacheSeg;
00322   BOOLEAN Valid;
00323   ULONG ReadLength = 0;
00324   PBCB Bcb;
00325   KIRQL oldirql;
00326   PLIST_ENTRY current_entry;
00327   PCACHE_SEGMENT current;
00328 
00329   DPRINT("CcCopyRead(FileObject 0x%p, FileOffset %I64x, "
00330      "Length %d, Wait %d, Buffer 0x%p, IoStatus 0x%p)\n",
00331      FileObject, FileOffset->QuadPart, Length, Wait,
00332      Buffer, IoStatus);
00333 
00334   Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
00335   ReadOffset = (ULONG)FileOffset->QuadPart;
00336 
00337   DPRINT("AllocationSize %d, FileSize %d\n",
00338          (ULONG)Bcb->AllocationSize.QuadPart,
00339          (ULONG)Bcb->FileSize.QuadPart);
00340 
00341   /*
00342    * Check for the nowait case that all the cache segments that would
00343    * cover this read are in memory.
00344    */
00345   if (!Wait)
00346     {
00347       KeAcquireSpinLock(&Bcb->BcbLock, &oldirql);
00348       current_entry = Bcb->BcbSegmentListHead.Flink;
00349       while (current_entry != &Bcb->BcbSegmentListHead)
00350     {
00351       current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT,
00352                       BcbSegmentListEntry);
00353       if (!current->Valid && current->FileOffset < ReadOffset + Length
00354           && current->FileOffset + Bcb->CacheSegmentSize > ReadOffset)
00355         {
00356           KeReleaseSpinLock(&Bcb->BcbLock, oldirql);
00357           IoStatus->Status = STATUS_UNSUCCESSFUL;
00358           IoStatus->Information = 0;
00359           return FALSE;
00360         }
00361       current_entry = current_entry->Flink;
00362     }
00363       KeReleaseSpinLock(&Bcb->BcbLock, oldirql);
00364     }
00365 
00366   TempLength = ReadOffset % Bcb->CacheSegmentSize;
00367   if (TempLength != 0)
00368     {
00369       TempLength = min (Length, Bcb->CacheSegmentSize - TempLength);
00370       Status = CcRosRequestCacheSegment(Bcb,
00371                     ROUND_DOWN(ReadOffset,
00372                            Bcb->CacheSegmentSize),
00373                     &BaseAddress, &Valid, &CacheSeg);
00374       if (!NT_SUCCESS(Status))
00375     {
00376       IoStatus->Information = 0;
00377       IoStatus->Status = Status;
00378       DPRINT("CcRosRequestCacheSegment faild, Status %x\n", Status);
00379       return FALSE;
00380     }
00381       if (!Valid)
00382     {
00383       Status = ReadCacheSegment(CacheSeg);
00384       if (!NT_SUCCESS(Status))
00385         {
00386           IoStatus->Information = 0;
00387           IoStatus->Status = Status;
00388               CcRosReleaseCacheSegment(Bcb, CacheSeg, FALSE, FALSE, FALSE);
00389           return FALSE;
00390         }
00391     }
00392       memcpy (Buffer, (char*)BaseAddress + ReadOffset % Bcb->CacheSegmentSize,
00393           TempLength);
00394       CcRosReleaseCacheSegment(Bcb, CacheSeg, TRUE, FALSE, FALSE);
00395       ReadLength += TempLength;
00396       Length -= TempLength;
00397       ReadOffset += TempLength;
00398       Buffer = (PVOID)((char*)Buffer + TempLength);
00399     }
00400   while (Length > 0)
00401     {
00402       TempLength = min(max(Bcb->CacheSegmentSize, MAX_RW_LENGTH), Length);
00403       Status = ReadCacheSegmentChain(Bcb, ReadOffset, TempLength, Buffer);
00404       if (!NT_SUCCESS(Status))
00405         {
00406           IoStatus->Information = 0;
00407           IoStatus->Status = Status;
00408           DPRINT("ReadCacheSegmentChain failed, Status %x\n", Status);
00409           return FALSE;
00410         }
00411 
00412       ReadLength += TempLength;
00413       Length -= TempLength;
00414       ReadOffset += TempLength;
00415 
00416       Buffer = (PVOID)((ULONG_PTR)Buffer + TempLength);
00417     }
00418   IoStatus->Status = STATUS_SUCCESS;
00419   IoStatus->Information = ReadLength;
00420   DPRINT("CcCopyRead O.K.\n");
00421   return TRUE;
00422 }
00423 
00424 /*
00425  * @implemented
00426  */
00427 BOOLEAN NTAPI
00428 CcCopyWrite (IN PFILE_OBJECT FileObject,
00429          IN PLARGE_INTEGER FileOffset,
00430          IN ULONG Length,
00431          IN BOOLEAN Wait,
00432          IN PVOID Buffer)
00433 {
00434    NTSTATUS Status;
00435    ULONG WriteOffset;
00436    KIRQL oldirql;
00437    PBCB Bcb;
00438    PLIST_ENTRY current_entry;
00439    PCACHE_SEGMENT CacheSeg;
00440    ULONG TempLength;
00441    PVOID BaseAddress;
00442    BOOLEAN Valid;
00443 
00444    DPRINT("CcCopyWrite(FileObject 0x%p, FileOffset %I64x, "
00445       "Length %d, Wait %d, Buffer 0x%p)\n",
00446           FileObject, FileOffset->QuadPart, Length, Wait, Buffer);
00447 
00448    Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
00449    WriteOffset = (ULONG)FileOffset->QuadPart;
00450 
00451    if (!Wait)
00452      {
00453        /* testing, if the requested datas are available */
00454        KeAcquireSpinLock(&Bcb->BcbLock, &oldirql);
00455        current_entry = Bcb->BcbSegmentListHead.Flink;
00456        while (current_entry != &Bcb->BcbSegmentListHead)
00457      {
00458        CacheSeg = CONTAINING_RECORD(current_entry, CACHE_SEGMENT,
00459                     BcbSegmentListEntry);
00460        if (!CacheSeg->Valid)
00461          {
00462            if ((WriteOffset >= CacheSeg->FileOffset &&
00463             WriteOffset < CacheSeg->FileOffset + Bcb->CacheSegmentSize)
00464            || (WriteOffset + Length > CacheSeg->FileOffset &&
00465                WriteOffset + Length <= CacheSeg->FileOffset +
00466                Bcb->CacheSegmentSize))
00467          {
00468            KeReleaseSpinLock(&Bcb->BcbLock, oldirql);
00469            /* datas not available */
00470            return(FALSE);
00471          }
00472          }
00473        current_entry = current_entry->Flink;
00474      }
00475        KeReleaseSpinLock(&Bcb->BcbLock, oldirql);
00476      }
00477 
00478    TempLength = WriteOffset % Bcb->CacheSegmentSize;
00479    if (TempLength != 0)
00480      {
00481        ULONG ROffset;
00482        ROffset = ROUND_DOWN(WriteOffset, Bcb->CacheSegmentSize);
00483        TempLength = min (Length, Bcb->CacheSegmentSize - TempLength);
00484        Status = CcRosRequestCacheSegment(Bcb, ROffset,
00485                      &BaseAddress, &Valid, &CacheSeg);
00486        if (!NT_SUCCESS(Status))
00487      {
00488        return(FALSE);
00489      }
00490        if (!Valid)
00491      {
00492        if (!NT_SUCCESS(ReadCacheSegment(CacheSeg)))
00493          {
00494            return(FALSE);
00495          }
00496      }
00497        memcpy ((char*)BaseAddress + WriteOffset % Bcb->CacheSegmentSize,
00498            Buffer, TempLength);
00499        CcRosReleaseCacheSegment(Bcb, CacheSeg, TRUE, TRUE, FALSE);
00500 
00501        Length -= TempLength;
00502        WriteOffset += TempLength;
00503 
00504        Buffer = (PVOID)((ULONG_PTR)Buffer + TempLength);
00505      }
00506 
00507    while (Length > 0)
00508      {
00509        TempLength = min (Bcb->CacheSegmentSize, Length);
00510        Status = CcRosRequestCacheSegment(Bcb, WriteOffset,
00511                      &BaseAddress, &Valid, &CacheSeg);
00512        if (!NT_SUCCESS(Status))
00513      {
00514        return(FALSE);
00515      }
00516        if (!Valid && TempLength < Bcb->CacheSegmentSize)
00517      {
00518        if (!NT_SUCCESS(ReadCacheSegment(CacheSeg)))
00519          {
00520                CcRosReleaseCacheSegment(Bcb, CacheSeg, FALSE, FALSE, FALSE);
00521            return FALSE;
00522          }
00523      }
00524        memcpy (BaseAddress, Buffer, TempLength);
00525        CcRosReleaseCacheSegment(Bcb, CacheSeg, TRUE, TRUE, FALSE);
00526        Length -= TempLength;
00527        WriteOffset += TempLength;
00528 
00529        Buffer = (PVOID)((ULONG_PTR)Buffer + TempLength);
00530      }
00531    return(TRUE);
00532 }
00533 
00534 /*
00535  * @unimplemented
00536  */
00537 VOID
00538 NTAPI
00539 CcDeferWrite (
00540     IN  PFILE_OBJECT        FileObject,
00541     IN  PCC_POST_DEFERRED_WRITE PostRoutine,
00542     IN  PVOID           Context1,
00543     IN  PVOID           Context2,
00544     IN  ULONG           BytesToWrite,
00545     IN  BOOLEAN         Retrying
00546     )
00547 {
00548     UNIMPLEMENTED;
00549 }
00550 
00551 /*
00552  * @unimplemented
00553  */
00554 VOID
00555 NTAPI
00556 CcFastCopyRead (
00557     IN  PFILE_OBJECT FileObject,
00558     IN  ULONG FileOffset,
00559     IN  ULONG Length,
00560     IN  ULONG PageCount,
00561     OUT PVOID Buffer,
00562     OUT PIO_STATUS_BLOCK IoStatus
00563     )
00564 {
00565     UNIMPLEMENTED;
00566 }
00567 /*
00568  * @unimplemented
00569  */
00570 VOID
00571 NTAPI
00572 CcFastCopyWrite(
00573     IN  PFILE_OBJECT FileObject,
00574     IN  ULONG FileOffset,
00575     IN  ULONG Length,
00576     IN  PVOID Buffer)
00577 {
00578     UNIMPLEMENTED;
00579 }
00580 
00581 /*
00582  * @unimplemented
00583  */
00584 NTSTATUS
00585 NTAPI
00586 CcWaitForCurrentLazyWriterActivity (
00587     VOID
00588     )
00589 {
00590     UNIMPLEMENTED;
00591     return STATUS_NOT_IMPLEMENTED;
00592 }
00593 
00594 /*
00595  * @implemented
00596  */
00597 BOOLEAN NTAPI
00598 CcZeroData (IN PFILE_OBJECT     FileObject,
00599         IN PLARGE_INTEGER   StartOffset,
00600         IN PLARGE_INTEGER   EndOffset,
00601         IN BOOLEAN          Wait)
00602 {
00603   NTSTATUS Status;
00604   LARGE_INTEGER WriteOffset;
00605   ULONG Length;
00606   ULONG CurrentLength;
00607   PMDL Mdl;
00608   ULONG i;
00609   IO_STATUS_BLOCK Iosb;
00610   KEVENT Event;
00611 
00612   DPRINT("CcZeroData(FileObject 0x%p, StartOffset %I64x, EndOffset %I64x, "
00613      "Wait %d)\n", FileObject, StartOffset->QuadPart, EndOffset->QuadPart,
00614      Wait);
00615 
00616   Length = EndOffset->u.LowPart - StartOffset->u.LowPart;
00617   WriteOffset.QuadPart = StartOffset->QuadPart;
00618 
00619   if (FileObject->SectionObjectPointer->SharedCacheMap == NULL)
00620     {
00621       /* File is not cached */
00622 
00623       Mdl = _alloca(MmSizeOfMdl(NULL, MAX_ZERO_LENGTH));
00624 
00625       while (Length > 0)
00626     {
00627       if (Length + WriteOffset.u.LowPart % PAGE_SIZE > MAX_ZERO_LENGTH)
00628         {
00629           CurrentLength = MAX_ZERO_LENGTH - WriteOffset.u.LowPart % PAGE_SIZE;
00630         }
00631       else
00632         {
00633           CurrentLength = Length;
00634         }
00635           MmInitializeMdl(Mdl, (PVOID)(ULONG_PTR)WriteOffset.QuadPart, CurrentLength);
00636       Mdl->MdlFlags |= (MDL_PAGES_LOCKED | MDL_IO_PAGE_READ);
00637       for (i = 0; i < ((Mdl->Size - sizeof(MDL)) / sizeof(ULONG)); i++)
00638         {
00639           ((PPFN_NUMBER)(Mdl + 1))[i] = CcZeroPage;
00640         }
00641           KeInitializeEvent(&Event, NotificationEvent, FALSE);
00642       Status = IoSynchronousPageWrite(FileObject, Mdl, &WriteOffset, &Event, &Iosb);
00643           if (Status == STATUS_PENDING)
00644       {
00645              KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
00646              Status = Iosb.Status;
00647       }
00648         if (Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA)
00649         {
00650           MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
00651         }
00652       if (!NT_SUCCESS(Status))
00653         {
00654           return(FALSE);
00655         }
00656       WriteOffset.QuadPart += CurrentLength;
00657       Length -= CurrentLength;
00658     }
00659     }
00660   else
00661     {
00662       /* File is cached */
00663       KIRQL oldirql;
00664       PBCB Bcb;
00665       PLIST_ENTRY current_entry;
00666       PCACHE_SEGMENT CacheSeg, current, previous;
00667       ULONG TempLength;
00668 
00669       Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
00670       if (Wait)
00671     {
00672           /* testing, if the requested datas are available */
00673       KeAcquireSpinLock(&Bcb->BcbLock, &oldirql);
00674       current_entry = Bcb->BcbSegmentListHead.Flink;
00675       while (current_entry != &Bcb->BcbSegmentListHead)
00676         {
00677           CacheSeg = CONTAINING_RECORD(current_entry, CACHE_SEGMENT,
00678                        BcbSegmentListEntry);
00679           if (!CacheSeg->Valid)
00680         {
00681           if ((WriteOffset.u.LowPart >= CacheSeg->FileOffset &&
00682                WriteOffset.u.LowPart < CacheSeg->FileOffset + Bcb->CacheSegmentSize)
00683               || (WriteOffset.u.LowPart + Length > CacheSeg->FileOffset &&
00684               WriteOffset.u.LowPart + Length <=
00685               CacheSeg->FileOffset + Bcb->CacheSegmentSize))
00686             {
00687               KeReleaseSpinLock(&Bcb->BcbLock, oldirql);
00688               /* datas not available */
00689               return(FALSE);
00690             }
00691         }
00692           current_entry = current_entry->Flink;
00693         }
00694       KeReleaseSpinLock(&Bcb->BcbLock, oldirql);
00695     }
00696       while (Length > 0)
00697     {
00698           ULONG Offset;
00699       Offset = WriteOffset.u.LowPart % Bcb->CacheSegmentSize;
00700       if (Length + Offset > MAX_ZERO_LENGTH)
00701         {
00702           CurrentLength = MAX_ZERO_LENGTH - Offset;
00703         }
00704       else
00705         {
00706           CurrentLength = Length;
00707         }
00708       Status = CcRosGetCacheSegmentChain (Bcb, WriteOffset.u.LowPart - Offset,
00709                           Offset + CurrentLength, &CacheSeg);
00710       if (!NT_SUCCESS(Status))
00711         {
00712           return FALSE;
00713         }
00714       current = CacheSeg;
00715 
00716       while (current != NULL)
00717         {
00718           Offset = WriteOffset.u.LowPart % Bcb->CacheSegmentSize;
00719           if (Offset != 0 ||
00720                   Offset + CurrentLength < Bcb->CacheSegmentSize)
00721             {
00722           if (!current->Valid)
00723             {
00724               /* read the segment */
00725               Status = ReadCacheSegment(current);
00726               if (!NT_SUCCESS(Status))
00727             {
00728               DPRINT1("ReadCacheSegment failed, status %x\n",
00729                   Status);
00730             }
00731             }
00732           TempLength = min (CurrentLength, Bcb->CacheSegmentSize - Offset);
00733         }
00734           else
00735             {
00736           TempLength = Bcb->CacheSegmentSize;
00737         }
00738           memset ((PUCHAR)current->BaseAddress + Offset, 0, TempLength);
00739 
00740               WriteOffset.QuadPart += TempLength;
00741           CurrentLength -= TempLength;
00742           Length -= TempLength;
00743 
00744               current = current->NextInChain;
00745         }
00746 
00747           current = CacheSeg;
00748       while (current != NULL)
00749         {
00750           previous = current;
00751           current = current->NextInChain;
00752           CcRosReleaseCacheSegment(Bcb, previous, TRUE, TRUE, FALSE);
00753         }
00754     }
00755     }
00756   return(TRUE);
00757 }

Generated on Sun May 27 2012 04:18:11 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.