1 /* Copyright (c) Mark Harmstone 2016-17 2 * 3 * This file is part of WinBtrfs. 4 * 5 * WinBtrfs is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU Lesser General Public Licence as published by 7 * the Free Software Foundation, either version 3 of the Licence, or 8 * (at your option) any later version. 9 * 10 * WinBtrfs is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU Lesser General Public Licence for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public Licence 16 * along with WinBtrfs. If not, see <http://www.gnu.org/licenses/>. */ 17 18 #include "btrfs_drv.h" 19 20 CACHE_MANAGER_CALLBACKS* cache_callbacks; 21 22 #ifdef __REACTOS__ 23 static BOOLEAN NTAPI acquire_for_lazy_write(PVOID Context, BOOLEAN Wait) { 24 #else 25 static BOOLEAN acquire_for_lazy_write(PVOID Context, BOOLEAN Wait) { 26 #endif 27 PFILE_OBJECT FileObject = Context; 28 fcb* fcb = FileObject->FsContext; 29 30 TRACE("(%p, %u)\n", Context, Wait); 31 32 if (!ExAcquireResourceSharedLite(&fcb->Vcb->tree_lock, Wait)) 33 return FALSE; 34 35 if (!ExAcquireResourceExclusiveLite(fcb->Header.Resource, Wait)) { 36 ExReleaseResourceLite(&fcb->Vcb->tree_lock); 37 return FALSE; 38 } 39 40 fcb->lazy_writer_thread = KeGetCurrentThread(); 41 42 IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP); 43 44 return TRUE; 45 } 46 47 #ifdef __REACTOS__ 48 static void NTAPI release_from_lazy_write(PVOID Context) { 49 #else 50 static void release_from_lazy_write(PVOID Context) { 51 #endif 52 PFILE_OBJECT FileObject = Context; 53 fcb* fcb = FileObject->FsContext; 54 55 TRACE("(%p)\n", Context); 56 57 fcb->lazy_writer_thread = NULL; 58 59 ExReleaseResourceLite(fcb->Header.Resource); 60 61 ExReleaseResourceLite(&fcb->Vcb->tree_lock); 62 63 if (IoGetTopLevelIrp() == (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP) 64 IoSetTopLevelIrp(NULL); 65 } 66 67 #ifdef __REACTOS__ 68 static BOOLEAN NTAPI acquire_for_read_ahead(PVOID Context, BOOLEAN Wait) { 69 #else 70 static BOOLEAN acquire_for_read_ahead(PVOID Context, BOOLEAN Wait) { 71 #endif 72 PFILE_OBJECT FileObject = Context; 73 fcb* fcb = FileObject->FsContext; 74 75 TRACE("(%p, %u)\n", Context, Wait); 76 77 if (!ExAcquireResourceSharedLite(fcb->Header.Resource, Wait)) 78 return FALSE; 79 80 IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP); 81 82 return TRUE; 83 } 84 85 #ifdef __REACTOS__ 86 static void NTAPI release_from_read_ahead(PVOID Context) { 87 #else 88 static void release_from_read_ahead(PVOID Context) { 89 #endif 90 PFILE_OBJECT FileObject = Context; 91 fcb* fcb = FileObject->FsContext; 92 93 TRACE("(%p)\n", Context); 94 95 ExReleaseResourceLite(fcb->Header.Resource); 96 97 if (IoGetTopLevelIrp() == (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP) 98 IoSetTopLevelIrp(NULL); 99 } 100 101 NTSTATUS init_cache() { 102 cache_callbacks = ExAllocatePoolWithTag(NonPagedPool, sizeof(CACHE_MANAGER_CALLBACKS), ALLOC_TAG); 103 if (!cache_callbacks) { 104 ERR("out of memory\n"); 105 return STATUS_INSUFFICIENT_RESOURCES; 106 } 107 108 cache_callbacks->AcquireForLazyWrite = acquire_for_lazy_write; 109 cache_callbacks->ReleaseFromLazyWrite = release_from_lazy_write; 110 cache_callbacks->AcquireForReadAhead = acquire_for_read_ahead; 111 cache_callbacks->ReleaseFromReadAhead = release_from_read_ahead; 112 113 return STATUS_SUCCESS; 114 } 115 116 void free_cache() { 117 ExFreePool(cache_callbacks); 118 } 119