update for HEAD-2003050101
[reactos.git] / ntoskrnl / cc / misc.c
1 /* INCLUDES ******************************************************************/
2
3 #include <ddk/ntddk.h>
4 #include <ddk/ntifs.h>
5 #include <internal/mm.h>
6 #include <internal/cc.h>
7 #include <internal/pool.h>
8 #include <internal/io.h>
9 #include <ntos/minmax.h>
10
11 #define NDEBUG
12 #include <internal/debug.h>
13
14 /* GLOBALS *******************************************************************/
15
16 #define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
17 #define ROUND_DOWN(N, S) (((N) % (S)) ? ROUND_UP(N, S) - S : N)
18
19 extern FAST_MUTEX ViewLock;
20 extern ULONG DirtyPageCount;
21
22 NTSTATUS CcRosInternalFreeCacheSegment(PCACHE_SEGMENT CacheSeg);
23
24 /* FUNCTIONS *****************************************************************/
25
26 /**********************************************************************
27  * NAME                                                 INTERNAL
28  *      CcMdlReadCompleteDev@8
29  *
30  * DESCRIPTION
31  *
32  * ARGUMENTS
33  *      MdlChain
34  *      DeviceObject
35  *      
36  * RETURN VALUE
37  *      None.
38  *
39  * NOTE
40  *      Used by CcMdlReadComplete@8 and FsRtl
41  */
42 VOID STDCALL
43 CcMdlReadCompleteDev (IN        PMDL            MdlChain,
44                       IN        PDEVICE_OBJECT  DeviceObject)
45 {
46   UNIMPLEMENTED;
47 }
48
49
50 /**********************************************************************
51  * NAME                                                 EXPORTED
52  *      CcMdlReadComplete@8
53  *
54  * DESCRIPTION
55  *
56  * ARGUMENTS
57  *
58  * RETURN VALUE
59  *      None.
60  *
61  * NOTE
62  *      From Bo Branten's ntifs.h v13.
63  */
64 VOID STDCALL
65 CcMdlReadComplete (IN   PFILE_OBJECT    FileObject,
66                    IN   PMDL            MdlChain)
67 {
68    PDEVICE_OBJECT       DeviceObject = NULL;
69    
70    DeviceObject = IoGetRelatedDeviceObject (FileObject);
71    /* FIXME: try fast I/O first */
72    CcMdlReadCompleteDev (MdlChain,
73                          DeviceObject);
74 }
75
76 VOID STDCALL
77 CcSetFileSizes (IN PFILE_OBJECT FileObject,
78                 IN PCC_FILE_SIZES FileSizes)
79 {
80   KIRQL oldirql;
81   PBCB Bcb;
82   PLIST_ENTRY current_entry;
83   PCACHE_SEGMENT current;
84   LIST_ENTRY FreeListHead;
85   NTSTATUS Status;
86
87   DPRINT("CcSetFileSizes(FileObject %x, FileSizes %x)\n", 
88          FileObject, FileSizes);
89   DPRINT("AllocationSize %d, FileSize %d, ValidDataLength %d\n",
90          (ULONG)FileSizes->AllocationSize.QuadPart,
91          (ULONG)FileSizes->FileSize.QuadPart,
92          (ULONG)FileSizes->ValidDataLength.QuadPart);
93
94   Bcb = FileObject->SectionObjectPointers->SharedCacheMap;
95   assert(Bcb);
96  
97   if (FileSizes->AllocationSize.QuadPart < Bcb->AllocationSize.QuadPart)
98   {
99      InitializeListHead(&FreeListHead);
100      ExAcquireFastMutex(&ViewLock);
101      KeAcquireSpinLock(&Bcb->BcbLock, &oldirql);
102
103      current_entry = Bcb->BcbSegmentListHead.Flink;
104      while (current_entry != &Bcb->BcbSegmentListHead)
105      {
106         current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, BcbSegmentListEntry);
107         current_entry = current_entry->Flink;
108         if (current->FileOffset > FileSizes->AllocationSize.QuadPart)
109         {
110            if (current->ReferenceCount == 0 || (current->ReferenceCount == 1 && current->Dirty))
111            {
112               RemoveEntryList(&current->BcbSegmentListEntry);
113               RemoveEntryList(&current->CacheSegmentListEntry);
114               RemoveEntryList(&current->CacheSegmentLRUListEntry);
115               if (current->Dirty)
116               {
117                  RemoveEntryList(&current->DirtySegmentListEntry);
118                  DirtyPageCount -= Bcb->CacheSegmentSize / PAGE_SIZE;
119               }
120               InsertHeadList(&FreeListHead, &current->BcbSegmentListEntry);
121            }
122            else
123            {
124               DPRINT1("Anyone has referenced a cache segment behind the new size.\n");
125               KeBugCheck(0);
126            }
127         }
128      }
129      
130      Bcb->AllocationSize = FileSizes->AllocationSize;
131      Bcb->FileSize = FileSizes->FileSize;
132      KeReleaseSpinLock(&Bcb->BcbLock, oldirql);
133      ExReleaseFastMutex(&ViewLock);
134
135      current_entry = FreeListHead.Flink;
136      while(current_entry != &FreeListHead)
137      {
138         current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, BcbSegmentListEntry);
139         current_entry = current_entry->Flink;
140         Status = CcRosInternalFreeCacheSegment(current);
141         if (!NT_SUCCESS(Status))
142         {
143            DPRINT1("CcRosInternalFreeCacheSegment failed, status = %x\n");
144            KeBugCheck(0);
145         }
146      }
147   }
148   else
149   {
150      KeAcquireSpinLock(&Bcb->BcbLock, &oldirql);
151      Bcb->AllocationSize = FileSizes->AllocationSize;
152      Bcb->FileSize = FileSizes->FileSize;
153      KeReleaseSpinLock(&Bcb->BcbLock, oldirql);
154   }
155 }
156