1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS kernel 4 * FILE: ntoskrnl/cc/pin.c 5 * PURPOSE: Implements cache managers pinning interface 6 * 7 * PROGRAMMERS: 8 */ 9 10 /* INCLUDES ******************************************************************/ 11 12 #include <ntoskrnl.h> 13 #define NDEBUG 14 #include <internal/debug.h> 15 16 /* GLOBALS *******************************************************************/ 17 18 extern NPAGED_LOOKASIDE_LIST iBcbLookasideList; 19 20 /* FUNCTIONS *****************************************************************/ 21 22 /* 23 * @implemented 24 */ 25 BOOLEAN STDCALL 26 CcMapData (IN PFILE_OBJECT FileObject, 27 IN PLARGE_INTEGER FileOffset, 28 IN ULONG Length, 29 IN ULONG Flags, 30 OUT PVOID *pBcb, 31 OUT PVOID *pBuffer) 32 { 33 ULONG ReadOffset; 34 BOOLEAN Valid; 35 PBCB Bcb; 36 PCACHE_SEGMENT CacheSeg; 37 NTSTATUS Status; 38 PINTERNAL_BCB iBcb; 39 ULONG ROffset; 40 41 DPRINT("CcMapData(FileObject 0x%p, FileOffset %I64x, Length %d, Flags %d," 42 " pBcb 0x%p, pBuffer 0x%p)\n", FileObject, FileOffset->QuadPart, 43 Length, Flags, pBcb, pBuffer); 44 45 ReadOffset = (ULONG)FileOffset->QuadPart; 46 47 ASSERT(FileObject); 48 ASSERT(FileObject->SectionObjectPointer); 49 ASSERT(FileObject->SectionObjectPointer->SharedCacheMap); 50 51 Bcb = FileObject->SectionObjectPointer->SharedCacheMap; 52 ASSERT(Bcb); 53 54 DPRINT("AllocationSize %I64x, FileSize %I64x\n", 55 Bcb->AllocationSize.QuadPart, 56 Bcb->FileSize.QuadPart); 57 58 if (ReadOffset % Bcb->CacheSegmentSize + Length > Bcb->CacheSegmentSize) 59 { 60 return(FALSE); 61 } 62 ROffset = ROUND_DOWN (ReadOffset, Bcb->CacheSegmentSize); 63 Status = CcRosRequestCacheSegment(Bcb, 64 ROffset, 65 pBuffer, 66 &Valid, 67 &CacheSeg); 68 if (!NT_SUCCESS(Status)) 69 { 70 return(FALSE); 71 } 72 if (!Valid) 73 { 74 if (!(Flags & MAP_WAIT)) 75 { 76 CcRosReleaseCacheSegment(Bcb, CacheSeg, FALSE, FALSE, FALSE); 77 return(FALSE); 78 } 79 if (!NT_SUCCESS(ReadCacheSegment(CacheSeg))) 80 { 81 CcRosReleaseCacheSegment(Bcb, CacheSeg, FALSE, FALSE, FALSE); 82 return(FALSE); 83 } 84 } 85 86 *pBuffer = (PVOID)((ULONG_PTR)(*pBuffer) + (ReadOffset % Bcb->CacheSegmentSize)); 87 iBcb = ExAllocateFromNPagedLookasideList(&iBcbLookasideList); 88 if (iBcb == NULL) 89 { 90 CcRosReleaseCacheSegment(Bcb, CacheSeg, TRUE, FALSE, FALSE); 91 return FALSE; 92 } 93 memset(iBcb, 0, sizeof(INTERNAL_BCB)); 94 iBcb->PFCB.NodeTypeCode = 0xDE45; /* Undocumented (CAPTIVE_PUBLIC_BCB_NODETYPECODE) */ 95 iBcb->PFCB.NodeByteSize = sizeof(PUBLIC_BCB); 96 iBcb->PFCB.MappedLength = Length; 97 iBcb->PFCB.MappedFileOffset = *FileOffset; 98 iBcb->CacheSegment = CacheSeg; 99 iBcb->Dirty = FALSE; 100 iBcb->RefCount = 1; 101 *pBcb = (PVOID)iBcb; 102 return(TRUE); 103 } 104 105 /* 106 * @unimplemented 107 */ 108 BOOLEAN 109 STDCALL 110 CcPinMappedData ( 111 IN PFILE_OBJECT FileObject, 112 IN PLARGE_INTEGER FileOffset, 113 IN ULONG Length, 114 IN ULONG Flags, 115 OUT PVOID * Bcb 116 ) 117 { 118 /* no-op for current implementation. */ 119 return TRUE; 120 } 121 122 /* 123 * @unimplemented 124 */ 125 BOOLEAN 126 STDCALL 127 CcPinRead ( 128 IN PFILE_OBJECT FileObject, 129 IN PLARGE_INTEGER FileOffset, 130 IN ULONG Length, 131 IN ULONG Flags, 132 OUT PVOID * Bcb, 133 OUT PVOID * Buffer 134 ) 135 { 136 if (CcMapData(FileObject, FileOffset, Length, Flags, Bcb, Buffer)) 137 { 138 if (CcPinMappedData(FileObject, FileOffset, Length, Flags, Bcb)) 139 return TRUE; 140 else 141 CcUnpinData(Bcb); 142 } 143 return FALSE; 144 } 145 146 /* 147 * @unimplemented 148 */ 149 BOOLEAN 150 STDCALL 151 CcPreparePinWrite ( 152 IN PFILE_OBJECT FileObject, 153 IN PLARGE_INTEGER FileOffset, 154 IN ULONG Length, 155 IN BOOLEAN Zero, 156 IN ULONG Flags, 157 OUT PVOID * Bcb, 158 OUT PVOID * Buffer 159 ) 160 { 161 /* 162 * FIXME: This is function is similar to CcPinRead, but doesn't 163 * read the data if they're not present. Instead it should just 164 * prepare the cache segments and zero them out if Zero == TRUE. 165 * 166 * For now calling CcPinRead is better than returning error or 167 * just having UNIMPLEMENTED here. 168 */ 169 return CcPinRead(FileObject, FileOffset, Length, Flags, Bcb, Buffer); 170 } 171 172 /* 173 * @implemented 174 */ 175 VOID STDCALL 176 CcSetDirtyPinnedData (IN PVOID Bcb, 177 IN PLARGE_INTEGER Lsn) 178 { 179 PINTERNAL_BCB iBcb = Bcb; 180 iBcb->Dirty = TRUE; 181 } 182 183 184 /* 185 * @implemented 186 */ 187 VOID STDCALL 188 CcUnpinData (IN PVOID Bcb) 189 { 190 PINTERNAL_BCB iBcb = Bcb; 191 CcRosReleaseCacheSegment(iBcb->CacheSegment->Bcb, iBcb->CacheSegment, TRUE, 192 iBcb->Dirty, FALSE); 193 if (--iBcb->RefCount == 0) 194 { 195 ExFreeToNPagedLookasideList(&iBcbLookasideList, iBcb); 196 } 197 } 198 199 /* 200 * @unimplemented 201 */ 202 VOID 203 STDCALL 204 CcUnpinDataForThread ( 205 IN PVOID Bcb, 206 IN ERESOURCE_THREAD ResourceThreadId 207 ) 208 { 209 UNIMPLEMENTED; 210 } 211 212 /* 213 * @implemented 214 */ 215 VOID 216 STDCALL 217 CcRepinBcb ( 218 IN PVOID Bcb 219 ) 220 { 221 PINTERNAL_BCB iBcb = Bcb; 222 iBcb->RefCount++; 223 } 224 225 /* 226 * @unimplemented 227 */ 228 VOID 229 STDCALL 230 CcUnpinRepinnedBcb ( 231 IN PVOID Bcb, 232 IN BOOLEAN WriteThrough, 233 IN PIO_STATUS_BLOCK IoStatus 234 ) 235 { 236 PINTERNAL_BCB iBcb = Bcb; 237 238 if (--iBcb->RefCount == 0) 239 { 240 IoStatus->Information = 0; 241 if (WriteThrough) 242 { 243 ExAcquirePushLockExclusive(&iBcb->CacheSegment->Lock); 244 if (iBcb->CacheSegment->Dirty) 245 { 246 IoStatus->Status = CcRosFlushCacheSegment(iBcb->CacheSegment); 247 } 248 else 249 { 250 IoStatus->Status = STATUS_SUCCESS; 251 } 252 ExReleasePushLockExclusive(&iBcb->CacheSegment->Lock); 253 } 254 else 255 { 256 IoStatus->Status = STATUS_SUCCESS; 257 } 258 259 ExFreeToNPagedLookasideList(&iBcbLookasideList, iBcb); 260 } 261 } 262