update for HEAD-2003091401
[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  */
43 VOID STDCALL
44 CcMdlReadCompleteDev (IN        PMDL            MdlChain,
45                       IN        PDEVICE_OBJECT  DeviceObject)
46 {
47   UNIMPLEMENTED;
48 }
49
50
51 /**********************************************************************
52  * NAME                                                 EXPORTED
53  *      CcMdlReadComplete@8
54  *
55  * DESCRIPTION
56  *
57  * ARGUMENTS
58  *
59  * RETURN VALUE
60  *      None.
61  *
62  * NOTE
63  *      From Bo Branten's ntifs.h v13.
64  *
65  * @unimplemented
66  */
67 VOID STDCALL
68 CcMdlReadComplete (IN   PFILE_OBJECT    FileObject,
69                    IN   PMDL            MdlChain)
70 {
71    PDEVICE_OBJECT       DeviceObject = NULL;
72    
73    DeviceObject = IoGetRelatedDeviceObject (FileObject);
74    /* FIXME: try fast I/O first */
75    CcMdlReadCompleteDev (MdlChain,
76                          DeviceObject);
77 }
78
79 /*
80  * @implemented
81  */
82 VOID STDCALL
83 CcSetFileSizes (IN PFILE_OBJECT FileObject,
84                 IN PCC_FILE_SIZES FileSizes)
85 {
86   KIRQL oldirql;
87   PBCB Bcb;
88   PLIST_ENTRY current_entry;
89   PCACHE_SEGMENT current;
90   LIST_ENTRY FreeListHead;
91   NTSTATUS Status;
92
93   DPRINT("CcSetFileSizes(FileObject %x, FileSizes %x)\n", 
94          FileObject, FileSizes);
95   DPRINT("AllocationSize %d, FileSize %d, ValidDataLength %d\n",
96          (ULONG)FileSizes->AllocationSize.QuadPart,
97          (ULONG)FileSizes->FileSize.QuadPart,
98          (ULONG)FileSizes->ValidDataLength.QuadPart);
99
100   Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
101   assert(Bcb);
102  
103   if (FileSizes->AllocationSize.QuadPart < Bcb->AllocationSize.QuadPart)
104   {
105      InitializeListHead(&FreeListHead);
106      ExAcquireFastMutex(&ViewLock);
107      KeAcquireSpinLock(&Bcb->BcbLock, &oldirql);
108
109      current_entry = Bcb->BcbSegmentListHead.Flink;
110      while (current_entry != &Bcb->BcbSegmentListHead)
111      {
112         current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, BcbSegmentListEntry);
113         current_entry = current_entry->Flink;
114         if (current->FileOffset > FileSizes->AllocationSize.QuadPart)
115         {
116            if (current->ReferenceCount == 0 || (current->ReferenceCount == 1 && current->Dirty))
117            {
118               RemoveEntryList(&current->BcbSegmentListEntry);
119               RemoveEntryList(&current->CacheSegmentListEntry);
120               RemoveEntryList(&current->CacheSegmentLRUListEntry);
121               if (current->Dirty)
122               {
123                  RemoveEntryList(&current->DirtySegmentListEntry);
124                  DirtyPageCount -= Bcb->CacheSegmentSize / PAGE_SIZE;
125               }
126               InsertHeadList(&FreeListHead, &current->BcbSegmentListEntry);
127            }
128            else
129            {
130               DPRINT1("Anyone has referenced a cache segment behind the new size.\n");
131               KEBUGCHECK(0);
132            }
133         }
134      }
135      
136      Bcb->AllocationSize = FileSizes->AllocationSize;
137      Bcb->FileSize = FileSizes->FileSize;
138      KeReleaseSpinLock(&Bcb->BcbLock, oldirql);
139      ExReleaseFastMutex(&ViewLock);
140
141      current_entry = FreeListHead.Flink;
142      while(current_entry != &FreeListHead)
143      {
144         current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, BcbSegmentListEntry);
145         current_entry = current_entry->Flink;
146         Status = CcRosInternalFreeCacheSegment(current);
147         if (!NT_SUCCESS(Status))
148         {
149            DPRINT1("CcRosInternalFreeCacheSegment failed, status = %x\n");
150            KEBUGCHECK(0);
151         }
152      }
153   }
154   else
155   {
156      KeAcquireSpinLock(&Bcb->BcbLock, &oldirql);
157      Bcb->AllocationSize = FileSizes->AllocationSize;
158      Bcb->FileSize = FileSizes->FileSize;
159      KeReleaseSpinLock(&Bcb->BcbLock, oldirql);
160   }
161 }
162