xref: /reactos/drivers/filesystems/btrfs/fastio.c (revision 6e0cf03d)
1c2c66affSColin Finck /* Copyright (c) Mark Harmstone 2016-17
2c2c66affSColin Finck  *
3c2c66affSColin Finck  * This file is part of WinBtrfs.
4c2c66affSColin Finck  *
5c2c66affSColin Finck  * WinBtrfs is free software: you can redistribute it and/or modify
6c2c66affSColin Finck  * it under the terms of the GNU Lesser General Public Licence as published by
7c2c66affSColin Finck  * the Free Software Foundation, either version 3 of the Licence, or
8c2c66affSColin Finck  * (at your option) any later version.
9c2c66affSColin Finck  *
10c2c66affSColin Finck  * WinBtrfs is distributed in the hope that it will be useful,
11c2c66affSColin Finck  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12c2c66affSColin Finck  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13c2c66affSColin Finck  * GNU Lesser General Public Licence for more details.
14c2c66affSColin Finck  *
15c2c66affSColin Finck  * You should have received a copy of the GNU Lesser General Public Licence
16c2c66affSColin Finck  * along with WinBtrfs.  If not, see <http://www.gnu.org/licenses/>. */
17c2c66affSColin Finck 
18c2c66affSColin Finck #include "btrfs_drv.h"
19c2c66affSColin Finck 
20c2c66affSColin Finck FAST_IO_DISPATCH FastIoDispatch;
21c2c66affSColin Finck 
_Function_class_(FAST_IO_QUERY_BASIC_INFO)22c2c66affSColin Finck _Function_class_(FAST_IO_QUERY_BASIC_INFO)
23318da0c1SPierre Schweitzer static BOOLEAN __stdcall fast_query_basic_info(PFILE_OBJECT FileObject, BOOLEAN wait, PFILE_BASIC_INFORMATION fbi,
24c2c66affSColin Finck                                                PIO_STATUS_BLOCK IoStatus, PDEVICE_OBJECT DeviceObject) {
25c2c66affSColin Finck     fcb* fcb;
26c2c66affSColin Finck     ccb* ccb;
27c2c66affSColin Finck 
2806042735SVincent Franchomme     UNUSED(DeviceObject);
2906042735SVincent Franchomme 
30c2c66affSColin Finck     FsRtlEnterFileSystem();
31c2c66affSColin Finck 
32c2c66affSColin Finck     TRACE("(%p, %u, %p, %p, %p)\n", FileObject, wait, fbi, IoStatus, DeviceObject);
33c2c66affSColin Finck 
34c2c66affSColin Finck     if (!FileObject) {
35c2c66affSColin Finck         FsRtlExitFileSystem();
36318da0c1SPierre Schweitzer         return false;
37c2c66affSColin Finck     }
38c2c66affSColin Finck 
39c2c66affSColin Finck     fcb = FileObject->FsContext;
40c2c66affSColin Finck 
41c2c66affSColin Finck     if (!fcb) {
42c2c66affSColin Finck         FsRtlExitFileSystem();
43318da0c1SPierre Schweitzer         return false;
44c2c66affSColin Finck     }
45c2c66affSColin Finck 
46c2c66affSColin Finck     ccb = FileObject->FsContext2;
47c2c66affSColin Finck 
48c2c66affSColin Finck     if (!ccb) {
49c2c66affSColin Finck         FsRtlExitFileSystem();
50318da0c1SPierre Schweitzer         return false;
51c2c66affSColin Finck     }
52c2c66affSColin Finck 
53c2c66affSColin Finck     if (!(ccb->access & (FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES))) {
54c2c66affSColin Finck         FsRtlExitFileSystem();
55318da0c1SPierre Schweitzer         return false;
56c2c66affSColin Finck     }
57c2c66affSColin Finck 
58c2c66affSColin Finck     if (fcb->ads) {
59c2c66affSColin Finck         if (!ccb->fileref || !ccb->fileref->parent || !ccb->fileref->parent->fcb) {
60c2c66affSColin Finck             FsRtlExitFileSystem();
61318da0c1SPierre Schweitzer             return false;
62c2c66affSColin Finck         }
63c2c66affSColin Finck 
64c2c66affSColin Finck         fcb = ccb->fileref->parent->fcb;
65c2c66affSColin Finck     }
66c2c66affSColin Finck 
67c2c66affSColin Finck     if (!ExAcquireResourceSharedLite(fcb->Header.Resource, wait)) {
68c2c66affSColin Finck         FsRtlExitFileSystem();
69318da0c1SPierre Schweitzer         return false;
70c2c66affSColin Finck     }
71c2c66affSColin Finck 
72c2c66affSColin Finck     if (fcb == fcb->Vcb->dummy_fcb) {
73c2c66affSColin Finck         LARGE_INTEGER time;
74c2c66affSColin Finck 
75c2c66affSColin Finck         KeQuerySystemTime(&time);
76c2c66affSColin Finck         fbi->CreationTime = fbi->LastAccessTime = fbi->LastWriteTime = fbi->ChangeTime = time;
77c2c66affSColin Finck     } else {
78c2c66affSColin Finck         fbi->CreationTime.QuadPart = unix_time_to_win(&fcb->inode_item.otime);
79c2c66affSColin Finck         fbi->LastAccessTime.QuadPart = unix_time_to_win(&fcb->inode_item.st_atime);
80c2c66affSColin Finck         fbi->LastWriteTime.QuadPart = unix_time_to_win(&fcb->inode_item.st_mtime);
81c2c66affSColin Finck         fbi->ChangeTime.QuadPart = unix_time_to_win(&fcb->inode_item.st_ctime);
82c2c66affSColin Finck     }
83c2c66affSColin Finck 
84c2c66affSColin Finck     fbi->FileAttributes = fcb->atts == 0 ? FILE_ATTRIBUTE_NORMAL : fcb->atts;
85c2c66affSColin Finck 
86c2c66affSColin Finck     IoStatus->Status = STATUS_SUCCESS;
87c2c66affSColin Finck     IoStatus->Information = sizeof(FILE_BASIC_INFORMATION);
88c2c66affSColin Finck 
89c2c66affSColin Finck     ExReleaseResourceLite(fcb->Header.Resource);
90c2c66affSColin Finck 
91c2c66affSColin Finck     FsRtlExitFileSystem();
92c2c66affSColin Finck 
93318da0c1SPierre Schweitzer     return true;
94c2c66affSColin Finck }
95c2c66affSColin Finck 
_Function_class_(FAST_IO_QUERY_STANDARD_INFO)96c2c66affSColin Finck _Function_class_(FAST_IO_QUERY_STANDARD_INFO)
97318da0c1SPierre Schweitzer static BOOLEAN __stdcall fast_query_standard_info(PFILE_OBJECT FileObject, BOOLEAN wait, PFILE_STANDARD_INFORMATION fsi,
98c2c66affSColin Finck                                                   PIO_STATUS_BLOCK IoStatus, PDEVICE_OBJECT DeviceObject) {
99c2c66affSColin Finck     fcb* fcb;
100c2c66affSColin Finck     ccb* ccb;
101318da0c1SPierre Schweitzer     bool ads;
102c2c66affSColin Finck     ULONG adssize;
103c2c66affSColin Finck 
10406042735SVincent Franchomme     UNUSED(DeviceObject);
10506042735SVincent Franchomme 
106c2c66affSColin Finck     FsRtlEnterFileSystem();
107c2c66affSColin Finck 
108c2c66affSColin Finck     TRACE("(%p, %u, %p, %p, %p)\n", FileObject, wait, fsi, IoStatus, DeviceObject);
109c2c66affSColin Finck 
110c2c66affSColin Finck     if (!FileObject) {
111c2c66affSColin Finck         FsRtlExitFileSystem();
112318da0c1SPierre Schweitzer         return false;
113c2c66affSColin Finck     }
114c2c66affSColin Finck 
115c2c66affSColin Finck     fcb = FileObject->FsContext;
116c2c66affSColin Finck     ccb = FileObject->FsContext2;
117c2c66affSColin Finck 
118c2c66affSColin Finck     if (!fcb) {
119c2c66affSColin Finck         FsRtlExitFileSystem();
120318da0c1SPierre Schweitzer         return false;
121c2c66affSColin Finck     }
122c2c66affSColin Finck 
123c2c66affSColin Finck     if (!ExAcquireResourceSharedLite(fcb->Header.Resource, wait)) {
124c2c66affSColin Finck         FsRtlExitFileSystem();
125318da0c1SPierre Schweitzer         return false;
126c2c66affSColin Finck     }
127c2c66affSColin Finck 
128c2c66affSColin Finck     ads = fcb->ads;
129c2c66affSColin Finck 
130c2c66affSColin Finck     if (ads) {
131c2c66affSColin Finck         struct _fcb* fcb2;
132c2c66affSColin Finck 
133c2c66affSColin Finck         if (!ccb || !ccb->fileref || !ccb->fileref->parent || !ccb->fileref->parent->fcb) {
134c2c66affSColin Finck             ExReleaseResourceLite(fcb->Header.Resource);
135c2c66affSColin Finck             FsRtlExitFileSystem();
136318da0c1SPierre Schweitzer             return false;
137c2c66affSColin Finck         }
138c2c66affSColin Finck 
139c2c66affSColin Finck         adssize = fcb->adsdata.Length;
140c2c66affSColin Finck 
141c2c66affSColin Finck         fcb2 = ccb->fileref->parent->fcb;
142c2c66affSColin Finck 
143c2c66affSColin Finck         ExReleaseResourceLite(fcb->Header.Resource);
144c2c66affSColin Finck 
145c2c66affSColin Finck         fcb = fcb2;
146c2c66affSColin Finck 
147c2c66affSColin Finck         if (!ExAcquireResourceSharedLite(fcb->Header.Resource, wait)) {
148c2c66affSColin Finck             FsRtlExitFileSystem();
149318da0c1SPierre Schweitzer             return false;
150c2c66affSColin Finck         }
151c2c66affSColin Finck 
152c2c66affSColin Finck         fsi->AllocationSize.QuadPart = fsi->EndOfFile.QuadPart = adssize;
153c2c66affSColin Finck         fsi->NumberOfLinks = fcb->inode_item.st_nlink;
154318da0c1SPierre Schweitzer         fsi->Directory = false;
155c2c66affSColin Finck     } else {
156c2c66affSColin Finck         fsi->AllocationSize.QuadPart = fcb_alloc_size(fcb);
157c2c66affSColin Finck         fsi->EndOfFile.QuadPart = S_ISDIR(fcb->inode_item.st_mode) ? 0 : fcb->inode_item.st_size;
158c2c66affSColin Finck         fsi->NumberOfLinks = fcb->inode_item.st_nlink;
159c2c66affSColin Finck         fsi->Directory = S_ISDIR(fcb->inode_item.st_mode);
160c2c66affSColin Finck     }
161c2c66affSColin Finck 
162318da0c1SPierre Schweitzer     fsi->DeletePending = ccb->fileref ? ccb->fileref->delete_on_close : false;
163c2c66affSColin Finck 
164c2c66affSColin Finck     IoStatus->Status = STATUS_SUCCESS;
165c2c66affSColin Finck     IoStatus->Information = sizeof(FILE_STANDARD_INFORMATION);
166c2c66affSColin Finck 
167c2c66affSColin Finck     ExReleaseResourceLite(fcb->Header.Resource);
168c2c66affSColin Finck 
169c2c66affSColin Finck     FsRtlExitFileSystem();
170c2c66affSColin Finck 
171318da0c1SPierre Schweitzer     return true;
172c2c66affSColin Finck }
173c2c66affSColin Finck 
_Function_class_(FAST_IO_CHECK_IF_POSSIBLE)174c2c66affSColin Finck _Function_class_(FAST_IO_CHECK_IF_POSSIBLE)
175318da0c1SPierre Schweitzer static BOOLEAN __stdcall fast_io_check_if_possible(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, ULONG Length, BOOLEAN Wait,
176c2c66affSColin Finck                                                    ULONG LockKey, BOOLEAN CheckForReadOperation, PIO_STATUS_BLOCK IoStatus,
177c2c66affSColin Finck                                                    PDEVICE_OBJECT DeviceObject) {
178c2c66affSColin Finck     fcb* fcb = FileObject->FsContext;
179c2c66affSColin Finck     LARGE_INTEGER len2;
180c2c66affSColin Finck 
181c2c66affSColin Finck     UNUSED(Wait);
182c2c66affSColin Finck     UNUSED(IoStatus);
183c2c66affSColin Finck     UNUSED(DeviceObject);
184c2c66affSColin Finck 
185c2c66affSColin Finck     len2.QuadPart = Length;
186c2c66affSColin Finck 
187c2c66affSColin Finck     if (CheckForReadOperation) {
188c2c66affSColin Finck         if (FsRtlFastCheckLockForRead(&fcb->lock, FileOffset, &len2, LockKey, FileObject, PsGetCurrentProcess()))
189318da0c1SPierre Schweitzer             return true;
190c2c66affSColin Finck     } else {
191c2c66affSColin Finck         if (!fcb->Vcb->readonly && !is_subvol_readonly(fcb->subvol, NULL) && FsRtlFastCheckLockForWrite(&fcb->lock, FileOffset, &len2, LockKey, FileObject, PsGetCurrentProcess()))
192318da0c1SPierre Schweitzer             return true;
193c2c66affSColin Finck     }
194c2c66affSColin Finck 
195318da0c1SPierre Schweitzer     return false;
196c2c66affSColin Finck }
197c2c66affSColin Finck 
_Function_class_(FAST_IO_QUERY_NETWORK_OPEN_INFO)198c2c66affSColin Finck _Function_class_(FAST_IO_QUERY_NETWORK_OPEN_INFO)
199318da0c1SPierre Schweitzer static BOOLEAN __stdcall fast_io_query_network_open_info(PFILE_OBJECT FileObject, BOOLEAN Wait, FILE_NETWORK_OPEN_INFORMATION* fnoi,
200c2c66affSColin Finck                                                          PIO_STATUS_BLOCK IoStatus, PDEVICE_OBJECT DeviceObject) {
201c2c66affSColin Finck     fcb* fcb;
202c2c66affSColin Finck     ccb* ccb;
203c2c66affSColin Finck     file_ref* fileref;
204c2c66affSColin Finck 
20506042735SVincent Franchomme     UNUSED(Wait);
20606042735SVincent Franchomme     UNUSED(IoStatus); // FIXME - really? What about IoStatus->Information?
20706042735SVincent Franchomme     UNUSED(DeviceObject);
20806042735SVincent Franchomme 
209c2c66affSColin Finck     FsRtlEnterFileSystem();
210c2c66affSColin Finck 
211c2c66affSColin Finck     TRACE("(%p, %u, %p, %p, %p)\n", FileObject, Wait, fnoi, IoStatus, DeviceObject);
212c2c66affSColin Finck 
213c2c66affSColin Finck     RtlZeroMemory(fnoi, sizeof(FILE_NETWORK_OPEN_INFORMATION));
214c2c66affSColin Finck 
215c2c66affSColin Finck     fcb = FileObject->FsContext;
216c2c66affSColin Finck 
217c2c66affSColin Finck     if (!fcb || fcb == fcb->Vcb->volume_fcb) {
218c2c66affSColin Finck         FsRtlExitFileSystem();
219318da0c1SPierre Schweitzer         return false;
220c2c66affSColin Finck     }
221c2c66affSColin Finck 
222c2c66affSColin Finck     ccb = FileObject->FsContext2;
223c2c66affSColin Finck 
224c2c66affSColin Finck     if (!ccb) {
225c2c66affSColin Finck         FsRtlExitFileSystem();
226318da0c1SPierre Schweitzer         return false;
227c2c66affSColin Finck     }
228c2c66affSColin Finck 
229c2c66affSColin Finck     fileref = ccb->fileref;
230c2c66affSColin Finck 
231c2c66affSColin Finck     if (fcb == fcb->Vcb->dummy_fcb) {
232c2c66affSColin Finck         LARGE_INTEGER time;
233c2c66affSColin Finck 
234c2c66affSColin Finck         KeQuerySystemTime(&time);
235c2c66affSColin Finck         fnoi->CreationTime = fnoi->LastAccessTime = fnoi->LastWriteTime = fnoi->ChangeTime = time;
236c2c66affSColin Finck     } else {
237c2c66affSColin Finck         INODE_ITEM* ii;
238c2c66affSColin Finck 
239c2c66affSColin Finck         if (fcb->ads) {
240c2c66affSColin Finck             if (!fileref || !fileref->parent) {
241c2c66affSColin Finck                 ERR("no fileref for stream\n");
242c2c66affSColin Finck                 FsRtlExitFileSystem();
243318da0c1SPierre Schweitzer                 return false;
244c2c66affSColin Finck             }
245c2c66affSColin Finck 
246c2c66affSColin Finck             ii = &fileref->parent->fcb->inode_item;
247c2c66affSColin Finck         } else
248c2c66affSColin Finck             ii = &fcb->inode_item;
249c2c66affSColin Finck 
250c2c66affSColin Finck         fnoi->CreationTime.QuadPart = unix_time_to_win(&ii->otime);
251c2c66affSColin Finck         fnoi->LastAccessTime.QuadPart = unix_time_to_win(&ii->st_atime);
252c2c66affSColin Finck         fnoi->LastWriteTime.QuadPart = unix_time_to_win(&ii->st_mtime);
253c2c66affSColin Finck         fnoi->ChangeTime.QuadPart = unix_time_to_win(&ii->st_ctime);
254c2c66affSColin Finck     }
255c2c66affSColin Finck 
256c2c66affSColin Finck     if (fcb->ads) {
257c2c66affSColin Finck         fnoi->AllocationSize.QuadPart = fnoi->EndOfFile.QuadPart = fcb->adsdata.Length;
258c2c66affSColin Finck         fnoi->FileAttributes = fileref->parent->fcb->atts == 0 ? FILE_ATTRIBUTE_NORMAL : fileref->parent->fcb->atts;
259c2c66affSColin Finck     } else {
260c2c66affSColin Finck         fnoi->AllocationSize.QuadPart = fcb_alloc_size(fcb);
261c2c66affSColin Finck         fnoi->EndOfFile.QuadPart = S_ISDIR(fcb->inode_item.st_mode) ? 0 : fcb->inode_item.st_size;
262c2c66affSColin Finck         fnoi->FileAttributes = fcb->atts == 0 ? FILE_ATTRIBUTE_NORMAL : fcb->atts;
263c2c66affSColin Finck     }
264c2c66affSColin Finck 
265c2c66affSColin Finck     FsRtlExitFileSystem();
266c2c66affSColin Finck 
267318da0c1SPierre Schweitzer     return true;
268c2c66affSColin Finck }
269c2c66affSColin Finck 
_Function_class_(FAST_IO_ACQUIRE_FOR_MOD_WRITE)270c2c66affSColin Finck _Function_class_(FAST_IO_ACQUIRE_FOR_MOD_WRITE)
271318da0c1SPierre Schweitzer static NTSTATUS __stdcall fast_io_acquire_for_mod_write(PFILE_OBJECT FileObject, PLARGE_INTEGER EndingOffset,
272318da0c1SPierre Schweitzer                                                         struct _ERESOURCE **ResourceToRelease, PDEVICE_OBJECT DeviceObject) {
273c2c66affSColin Finck     fcb* fcb;
274c2c66affSColin Finck 
275318da0c1SPierre Schweitzer     TRACE("(%p, %I64x, %p, %p)\n", FileObject, EndingOffset ? EndingOffset->QuadPart : 0, ResourceToRelease, DeviceObject);
276318da0c1SPierre Schweitzer 
277c2c66affSColin Finck     UNUSED(EndingOffset);
278c2c66affSColin Finck     UNUSED(DeviceObject);
279c2c66affSColin Finck 
280c2c66affSColin Finck     fcb = FileObject->FsContext;
281c2c66affSColin Finck 
282c2c66affSColin Finck     if (!fcb)
283c2c66affSColin Finck         return STATUS_INVALID_PARAMETER;
284c2c66affSColin Finck 
285eb7fbc25SPierre Schweitzer     // Make sure we don't get interrupted by the flush thread, which can cause a deadlock
286c2c66affSColin Finck 
287318da0c1SPierre Schweitzer     if (!ExAcquireResourceSharedLite(&fcb->Vcb->tree_lock, false))
288c2c66affSColin Finck         return STATUS_CANT_WAIT;
289c2c66affSColin Finck 
290318da0c1SPierre Schweitzer     if (!ExAcquireResourceExclusiveLite(fcb->Header.Resource, false)) {
291318da0c1SPierre Schweitzer         ExReleaseResourceLite(&fcb->Vcb->tree_lock);
292318da0c1SPierre Schweitzer         TRACE("returning STATUS_CANT_WAIT\n");
293318da0c1SPierre Schweitzer         return STATUS_CANT_WAIT;
294318da0c1SPierre Schweitzer     }
295318da0c1SPierre Schweitzer 
296eb7fbc25SPierre Schweitzer     // Ideally this would be PagingIoResource, but that doesn't play well with copy-on-write,
297eb7fbc25SPierre Schweitzer     // as we can't guarantee that we won't need to do any reallocations.
298eb7fbc25SPierre Schweitzer 
299eb7fbc25SPierre Schweitzer     *ResourceToRelease = fcb->Header.Resource;
300eb7fbc25SPierre Schweitzer 
301318da0c1SPierre Schweitzer     TRACE("returning STATUS_SUCCESS\n");
302eb7fbc25SPierre Schweitzer 
303c2c66affSColin Finck     return STATUS_SUCCESS;
304c2c66affSColin Finck }
305c2c66affSColin Finck 
_Function_class_(FAST_IO_RELEASE_FOR_MOD_WRITE)306c2c66affSColin Finck _Function_class_(FAST_IO_RELEASE_FOR_MOD_WRITE)
307318da0c1SPierre Schweitzer static NTSTATUS __stdcall fast_io_release_for_mod_write(PFILE_OBJECT FileObject, struct _ERESOURCE *ResourceToRelease,
308318da0c1SPierre Schweitzer                                                         PDEVICE_OBJECT DeviceObject) {
309eb7fbc25SPierre Schweitzer     fcb* fcb;
310eb7fbc25SPierre Schweitzer 
311318da0c1SPierre Schweitzer     TRACE("(%p, %p, %p)\n", FileObject, ResourceToRelease, DeviceObject);
312318da0c1SPierre Schweitzer 
313c2c66affSColin Finck     UNUSED(DeviceObject);
314c2c66affSColin Finck 
315eb7fbc25SPierre Schweitzer     fcb = FileObject->FsContext;
316eb7fbc25SPierre Schweitzer 
317c2c66affSColin Finck     ExReleaseResourceLite(ResourceToRelease);
318c2c66affSColin Finck 
319eb7fbc25SPierre Schweitzer     ExReleaseResourceLite(&fcb->Vcb->tree_lock);
320eb7fbc25SPierre Schweitzer 
321c2c66affSColin Finck     return STATUS_SUCCESS;
322c2c66affSColin Finck }
323c2c66affSColin Finck 
_Function_class_(FAST_IO_ACQUIRE_FOR_CCFLUSH)324c2c66affSColin Finck _Function_class_(FAST_IO_ACQUIRE_FOR_CCFLUSH)
325318da0c1SPierre Schweitzer static NTSTATUS __stdcall fast_io_acquire_for_ccflush(PFILE_OBJECT FileObject, PDEVICE_OBJECT DeviceObject) {
326c2c66affSColin Finck     UNUSED(FileObject);
327c2c66affSColin Finck     UNUSED(DeviceObject);
328c2c66affSColin Finck 
329c2c66affSColin Finck     IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
330c2c66affSColin Finck 
331c2c66affSColin Finck     return STATUS_SUCCESS;
332c2c66affSColin Finck }
333c2c66affSColin Finck 
_Function_class_(FAST_IO_RELEASE_FOR_CCFLUSH)334c2c66affSColin Finck _Function_class_(FAST_IO_RELEASE_FOR_CCFLUSH)
335318da0c1SPierre Schweitzer static NTSTATUS __stdcall fast_io_release_for_ccflush(PFILE_OBJECT FileObject, PDEVICE_OBJECT DeviceObject) {
336c2c66affSColin Finck     UNUSED(FileObject);
337c2c66affSColin Finck     UNUSED(DeviceObject);
338c2c66affSColin Finck 
339c2c66affSColin Finck     if (IoGetTopLevelIrp() == (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP)
340c2c66affSColin Finck         IoSetTopLevelIrp(NULL);
341c2c66affSColin Finck 
342c2c66affSColin Finck     return STATUS_SUCCESS;
343c2c66affSColin Finck }
344c2c66affSColin Finck 
_Function_class_(FAST_IO_WRITE)345c2c66affSColin Finck _Function_class_(FAST_IO_WRITE)
346318da0c1SPierre Schweitzer static BOOLEAN __stdcall fast_io_write(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, ULONG Length, BOOLEAN Wait, ULONG LockKey, PVOID Buffer, PIO_STATUS_BLOCK IoStatus, PDEVICE_OBJECT DeviceObject) {
347c2c66affSColin Finck     fcb* fcb = FileObject->FsContext;
34862e630deSPierre Schweitzer     bool ret;
349c2c66affSColin Finck 
35062e630deSPierre Schweitzer     FsRtlEnterFileSystem();
351c2c66affSColin Finck 
35262e630deSPierre Schweitzer     if (!ExAcquireResourceSharedLite(&fcb->Vcb->tree_lock, Wait)) {
35362e630deSPierre Schweitzer         FsRtlExitFileSystem();
35462e630deSPierre Schweitzer         return false;
355c2c66affSColin Finck     }
356c2c66affSColin Finck 
35762e630deSPierre Schweitzer     ret = FsRtlCopyWrite(FileObject, FileOffset, Length, Wait, LockKey, Buffer, IoStatus, DeviceObject);
35862e630deSPierre Schweitzer 
35962e630deSPierre Schweitzer     if (ret)
36062e630deSPierre Schweitzer         fcb->inode_item.st_size = fcb->Header.FileSize.QuadPart;
36162e630deSPierre Schweitzer 
36262e630deSPierre Schweitzer     ExReleaseResourceLite(&fcb->Vcb->tree_lock);
36362e630deSPierre Schweitzer 
36462e630deSPierre Schweitzer     FsRtlExitFileSystem();
36562e630deSPierre Schweitzer 
36662e630deSPierre Schweitzer     return ret;
36762e630deSPierre Schweitzer }
36862e630deSPierre Schweitzer 
_Function_class_(FAST_IO_LOCK)369318da0c1SPierre Schweitzer _Function_class_(FAST_IO_LOCK)
370318da0c1SPierre Schweitzer static BOOLEAN __stdcall fast_io_lock(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, PLARGE_INTEGER Length, PEPROCESS ProcessId,
371318da0c1SPierre Schweitzer                                       ULONG Key, BOOLEAN FailImmediately, BOOLEAN ExclusiveLock, PIO_STATUS_BLOCK IoStatus,
372318da0c1SPierre Schweitzer                                       PDEVICE_OBJECT DeviceObject) {
373318da0c1SPierre Schweitzer     BOOLEAN ret;
374318da0c1SPierre Schweitzer     fcb* fcb = FileObject->FsContext;
375318da0c1SPierre Schweitzer 
37606042735SVincent Franchomme     UNUSED(DeviceObject);
37706042735SVincent Franchomme 
378194ea909SVictor Perevertkin     TRACE("(%p, %I64x, %I64x, %p, %lx, %u, %u, %p, %p)\n", FileObject, FileOffset ? FileOffset->QuadPart : 0, Length ? Length->QuadPart : 0,
379318da0c1SPierre Schweitzer           ProcessId, Key, FailImmediately, ExclusiveLock, IoStatus, DeviceObject);
380318da0c1SPierre Schweitzer 
381318da0c1SPierre Schweitzer     if (fcb->type != BTRFS_TYPE_FILE) {
382318da0c1SPierre Schweitzer         WARN("can only lock files\n");
383318da0c1SPierre Schweitzer         IoStatus->Status = STATUS_INVALID_PARAMETER;
384318da0c1SPierre Schweitzer         IoStatus->Information = 0;
385318da0c1SPierre Schweitzer         return true;
386318da0c1SPierre Schweitzer     }
387318da0c1SPierre Schweitzer 
388318da0c1SPierre Schweitzer     FsRtlEnterFileSystem();
389318da0c1SPierre Schweitzer     ExAcquireResourceSharedLite(fcb->Header.Resource, true);
390318da0c1SPierre Schweitzer 
391318da0c1SPierre Schweitzer     ret = FsRtlFastLock(&fcb->lock, FileObject, FileOffset, Length, ProcessId, Key, FailImmediately,
392318da0c1SPierre Schweitzer                         ExclusiveLock, IoStatus, NULL, false);
393318da0c1SPierre Schweitzer 
394318da0c1SPierre Schweitzer     if (ret)
395318da0c1SPierre Schweitzer         fcb->Header.IsFastIoPossible = fast_io_possible(fcb);
396318da0c1SPierre Schweitzer 
397318da0c1SPierre Schweitzer     ExReleaseResourceLite(fcb->Header.Resource);
398318da0c1SPierre Schweitzer     FsRtlExitFileSystem();
399318da0c1SPierre Schweitzer 
400318da0c1SPierre Schweitzer     return ret;
401318da0c1SPierre Schweitzer }
402318da0c1SPierre Schweitzer 
_Function_class_(FAST_IO_UNLOCK_SINGLE)403318da0c1SPierre Schweitzer _Function_class_(FAST_IO_UNLOCK_SINGLE)
404318da0c1SPierre Schweitzer static BOOLEAN __stdcall fast_io_unlock_single(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, PLARGE_INTEGER Length, PEPROCESS ProcessId,
405318da0c1SPierre Schweitzer                                                ULONG Key, PIO_STATUS_BLOCK IoStatus, PDEVICE_OBJECT DeviceObject) {
406318da0c1SPierre Schweitzer     fcb* fcb = FileObject->FsContext;
407318da0c1SPierre Schweitzer 
40806042735SVincent Franchomme     UNUSED(DeviceObject);
40906042735SVincent Franchomme 
410194ea909SVictor Perevertkin     TRACE("(%p, %I64x, %I64x, %p, %lx, %p, %p)\n", FileObject, FileOffset ? FileOffset->QuadPart : 0, Length ? Length->QuadPart : 0,
411318da0c1SPierre Schweitzer           ProcessId, Key, IoStatus, DeviceObject);
412318da0c1SPierre Schweitzer 
413318da0c1SPierre Schweitzer     IoStatus->Information = 0;
414318da0c1SPierre Schweitzer 
415318da0c1SPierre Schweitzer     if (fcb->type != BTRFS_TYPE_FILE) {
416318da0c1SPierre Schweitzer         WARN("can only lock files\n");
417318da0c1SPierre Schweitzer         IoStatus->Status = STATUS_INVALID_PARAMETER;
418318da0c1SPierre Schweitzer         return true;
419318da0c1SPierre Schweitzer     }
420318da0c1SPierre Schweitzer 
421318da0c1SPierre Schweitzer     FsRtlEnterFileSystem();
422318da0c1SPierre Schweitzer 
423318da0c1SPierre Schweitzer     IoStatus->Status = FsRtlFastUnlockSingle(&fcb->lock, FileObject, FileOffset, Length, ProcessId, Key, NULL, false);
424318da0c1SPierre Schweitzer 
425318da0c1SPierre Schweitzer     fcb->Header.IsFastIoPossible = fast_io_possible(fcb);
426318da0c1SPierre Schweitzer 
427318da0c1SPierre Schweitzer     FsRtlExitFileSystem();
428318da0c1SPierre Schweitzer 
429318da0c1SPierre Schweitzer     return true;
430318da0c1SPierre Schweitzer }
431318da0c1SPierre Schweitzer 
_Function_class_(FAST_IO_UNLOCK_ALL)432318da0c1SPierre Schweitzer _Function_class_(FAST_IO_UNLOCK_ALL)
433318da0c1SPierre Schweitzer static BOOLEAN __stdcall fast_io_unlock_all(PFILE_OBJECT FileObject, PEPROCESS ProcessId, PIO_STATUS_BLOCK IoStatus, PDEVICE_OBJECT DeviceObject) {
434318da0c1SPierre Schweitzer     fcb* fcb = FileObject->FsContext;
435318da0c1SPierre Schweitzer 
43606042735SVincent Franchomme     UNUSED(DeviceObject);
43706042735SVincent Franchomme 
438318da0c1SPierre Schweitzer     TRACE("(%p, %p, %p, %p)\n", FileObject, ProcessId, IoStatus, DeviceObject);
439318da0c1SPierre Schweitzer 
440318da0c1SPierre Schweitzer     IoStatus->Information = 0;
441318da0c1SPierre Schweitzer 
442318da0c1SPierre Schweitzer     if (fcb->type != BTRFS_TYPE_FILE) {
443318da0c1SPierre Schweitzer         WARN("can only lock files\n");
444318da0c1SPierre Schweitzer         IoStatus->Status = STATUS_INVALID_PARAMETER;
445318da0c1SPierre Schweitzer         return true;
446318da0c1SPierre Schweitzer     }
447318da0c1SPierre Schweitzer 
448318da0c1SPierre Schweitzer     FsRtlEnterFileSystem();
449318da0c1SPierre Schweitzer 
450318da0c1SPierre Schweitzer     ExAcquireResourceSharedLite(fcb->Header.Resource, true);
451318da0c1SPierre Schweitzer 
452318da0c1SPierre Schweitzer     IoStatus->Status = FsRtlFastUnlockAll(&fcb->lock, FileObject, ProcessId, NULL);
453318da0c1SPierre Schweitzer 
454318da0c1SPierre Schweitzer     fcb->Header.IsFastIoPossible = fast_io_possible(fcb);
455318da0c1SPierre Schweitzer 
456318da0c1SPierre Schweitzer     ExReleaseResourceLite(fcb->Header.Resource);
457318da0c1SPierre Schweitzer 
458318da0c1SPierre Schweitzer     FsRtlExitFileSystem();
459318da0c1SPierre Schweitzer 
460318da0c1SPierre Schweitzer     return true;
461318da0c1SPierre Schweitzer }
462318da0c1SPierre Schweitzer 
_Function_class_(FAST_IO_UNLOCK_ALL_BY_KEY)463318da0c1SPierre Schweitzer _Function_class_(FAST_IO_UNLOCK_ALL_BY_KEY)
464318da0c1SPierre Schweitzer static BOOLEAN __stdcall fast_io_unlock_all_by_key(PFILE_OBJECT FileObject, PVOID ProcessId, ULONG Key,
465318da0c1SPierre Schweitzer                                                    PIO_STATUS_BLOCK IoStatus, PDEVICE_OBJECT DeviceObject) {
466318da0c1SPierre Schweitzer     fcb* fcb = FileObject->FsContext;
467318da0c1SPierre Schweitzer 
46806042735SVincent Franchomme     UNUSED(DeviceObject);
46906042735SVincent Franchomme 
470194ea909SVictor Perevertkin     TRACE("(%p, %p, %lx, %p, %p)\n", FileObject, ProcessId, Key, IoStatus, DeviceObject);
471318da0c1SPierre Schweitzer 
472318da0c1SPierre Schweitzer     IoStatus->Information = 0;
473318da0c1SPierre Schweitzer 
474318da0c1SPierre Schweitzer     if (fcb->type != BTRFS_TYPE_FILE) {
475318da0c1SPierre Schweitzer         WARN("can only lock files\n");
476318da0c1SPierre Schweitzer         IoStatus->Status = STATUS_INVALID_PARAMETER;
477318da0c1SPierre Schweitzer         return true;
478318da0c1SPierre Schweitzer     }
479318da0c1SPierre Schweitzer 
480318da0c1SPierre Schweitzer     FsRtlEnterFileSystem();
481318da0c1SPierre Schweitzer 
482318da0c1SPierre Schweitzer     ExAcquireResourceSharedLite(fcb->Header.Resource, true);
483318da0c1SPierre Schweitzer 
484318da0c1SPierre Schweitzer     IoStatus->Status = FsRtlFastUnlockAllByKey(&fcb->lock, FileObject, ProcessId, Key, NULL);
485318da0c1SPierre Schweitzer 
486318da0c1SPierre Schweitzer     fcb->Header.IsFastIoPossible = fast_io_possible(fcb);
487318da0c1SPierre Schweitzer 
488318da0c1SPierre Schweitzer     ExReleaseResourceLite(fcb->Header.Resource);
489318da0c1SPierre Schweitzer 
490318da0c1SPierre Schweitzer     FsRtlExitFileSystem();
491318da0c1SPierre Schweitzer 
492318da0c1SPierre Schweitzer     return true;
493c2c66affSColin Finck }
494c2c66affSColin Finck 
495c982533eSVincent Franchomme #ifdef __REACTOS__
_Function_class_(FAST_IO_ACQUIRE_FILE)496c982533eSVincent Franchomme _Function_class_(FAST_IO_ACQUIRE_FILE)
497c982533eSVincent Franchomme #endif /* __REACTOS__ */
498*6e0cf03dSVincent Franchomme static void __stdcall fast_io_acquire_for_create_section(_In_ PFILE_OBJECT FileObject) {
499c982533eSVincent Franchomme     fcb* fcb;
500c982533eSVincent Franchomme 
501c982533eSVincent Franchomme     TRACE("(%p)\n", FileObject);
502c982533eSVincent Franchomme 
503c982533eSVincent Franchomme     if (!FileObject)
504c982533eSVincent Franchomme         return;
505c982533eSVincent Franchomme 
506c982533eSVincent Franchomme     fcb = FileObject->FsContext;
507c982533eSVincent Franchomme 
508c982533eSVincent Franchomme     if (!fcb)
509c982533eSVincent Franchomme         return;
510c982533eSVincent Franchomme 
511c982533eSVincent Franchomme     ExAcquireResourceSharedLite(&fcb->Vcb->tree_lock, true);
512c982533eSVincent Franchomme     ExAcquireResourceExclusiveLite(fcb->Header.Resource, true);
513c982533eSVincent Franchomme }
514c982533eSVincent Franchomme 
515c982533eSVincent Franchomme #ifdef __REACTOS__
_Function_class_(FAST_IO_RELEASE_FILE)516c982533eSVincent Franchomme _Function_class_(FAST_IO_RELEASE_FILE)
517c982533eSVincent Franchomme #endif /* __REACTOS__ */
518*6e0cf03dSVincent Franchomme static void __stdcall fast_io_release_for_create_section(_In_ PFILE_OBJECT FileObject) {
519c982533eSVincent Franchomme     fcb* fcb;
520c982533eSVincent Franchomme 
521c982533eSVincent Franchomme     TRACE("(%p)\n", FileObject);
522c982533eSVincent Franchomme 
523c982533eSVincent Franchomme     if (!FileObject)
524c982533eSVincent Franchomme         return;
525c982533eSVincent Franchomme 
526c982533eSVincent Franchomme     fcb = FileObject->FsContext;
527c982533eSVincent Franchomme 
528c982533eSVincent Franchomme     if (!fcb)
529c982533eSVincent Franchomme         return;
530c982533eSVincent Franchomme 
531c982533eSVincent Franchomme     ExReleaseResourceLite(fcb->Header.Resource);
532c982533eSVincent Franchomme     ExReleaseResourceLite(&fcb->Vcb->tree_lock);
533c982533eSVincent Franchomme }
534c982533eSVincent Franchomme 
init_fast_io_dispatch(FAST_IO_DISPATCH ** fiod)535c2c66affSColin Finck void init_fast_io_dispatch(FAST_IO_DISPATCH** fiod) {
536c2c66affSColin Finck     RtlZeroMemory(&FastIoDispatch, sizeof(FastIoDispatch));
537c2c66affSColin Finck 
538c2c66affSColin Finck     FastIoDispatch.SizeOfFastIoDispatch = sizeof(FAST_IO_DISPATCH);
539c2c66affSColin Finck 
540c2c66affSColin Finck     FastIoDispatch.FastIoCheckIfPossible = fast_io_check_if_possible;
541318da0c1SPierre Schweitzer     FastIoDispatch.FastIoRead = FsRtlCopyRead;
542318da0c1SPierre Schweitzer     FastIoDispatch.FastIoWrite = fast_io_write;
543c2c66affSColin Finck     FastIoDispatch.FastIoQueryBasicInfo = fast_query_basic_info;
544c2c66affSColin Finck     FastIoDispatch.FastIoQueryStandardInfo = fast_query_standard_info;
545318da0c1SPierre Schweitzer     FastIoDispatch.FastIoLock = fast_io_lock;
546318da0c1SPierre Schweitzer     FastIoDispatch.FastIoUnlockSingle = fast_io_unlock_single;
547318da0c1SPierre Schweitzer     FastIoDispatch.FastIoUnlockAll = fast_io_unlock_all;
548318da0c1SPierre Schweitzer     FastIoDispatch.FastIoUnlockAllByKey = fast_io_unlock_all_by_key;
549c982533eSVincent Franchomme     FastIoDispatch.AcquireFileForNtCreateSection = fast_io_acquire_for_create_section;
550c982533eSVincent Franchomme     FastIoDispatch.ReleaseFileForNtCreateSection = fast_io_release_for_create_section;
551c2c66affSColin Finck     FastIoDispatch.FastIoQueryNetworkOpenInfo = fast_io_query_network_open_info;
552c2c66affSColin Finck     FastIoDispatch.AcquireForModWrite = fast_io_acquire_for_mod_write;
553c2c66affSColin Finck     FastIoDispatch.MdlRead = FsRtlMdlReadDev;
554c2c66affSColin Finck     FastIoDispatch.MdlReadComplete = FsRtlMdlReadCompleteDev;
555c2c66affSColin Finck     FastIoDispatch.PrepareMdlWrite = FsRtlPrepareMdlWriteDev;
556c2c66affSColin Finck     FastIoDispatch.MdlWriteComplete = FsRtlMdlWriteCompleteDev;
557318da0c1SPierre Schweitzer     FastIoDispatch.ReleaseForModWrite = fast_io_release_for_mod_write;
558318da0c1SPierre Schweitzer     FastIoDispatch.AcquireForCcFlush = fast_io_acquire_for_ccflush;
559318da0c1SPierre Schweitzer     FastIoDispatch.ReleaseForCcFlush = fast_io_release_for_ccflush;
560c2c66affSColin Finck 
561c2c66affSColin Finck     *fiod = &FastIoDispatch;
562c2c66affSColin Finck }
563