xref: /reactos/drivers/filesystems/btrfs/fastio.c (revision eb7fbc25)
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 
22c2c66affSColin Finck _Function_class_(FAST_IO_QUERY_BASIC_INFO)
23c2c66affSColin Finck #ifdef __REACTOS__
24c2c66affSColin Finck static BOOLEAN NTAPI fast_query_basic_info(PFILE_OBJECT FileObject, BOOLEAN wait, PFILE_BASIC_INFORMATION fbi,
25c2c66affSColin Finck                                            PIO_STATUS_BLOCK IoStatus, PDEVICE_OBJECT DeviceObject) {
26c2c66affSColin Finck #else
27c2c66affSColin Finck static BOOLEAN fast_query_basic_info(PFILE_OBJECT FileObject, BOOLEAN wait, PFILE_BASIC_INFORMATION fbi,
28c2c66affSColin Finck                                      PIO_STATUS_BLOCK IoStatus, PDEVICE_OBJECT DeviceObject) {
29c2c66affSColin Finck #endif
30c2c66affSColin Finck     fcb* fcb;
31c2c66affSColin Finck     ccb* ccb;
32c2c66affSColin Finck 
33c2c66affSColin Finck     FsRtlEnterFileSystem();
34c2c66affSColin Finck 
35c2c66affSColin Finck     TRACE("(%p, %u, %p, %p, %p)\n", FileObject, wait, fbi, IoStatus, DeviceObject);
36c2c66affSColin Finck 
37c2c66affSColin Finck     if (!FileObject) {
38c2c66affSColin Finck         FsRtlExitFileSystem();
39c2c66affSColin Finck         return FALSE;
40c2c66affSColin Finck     }
41c2c66affSColin Finck 
42c2c66affSColin Finck     fcb = FileObject->FsContext;
43c2c66affSColin Finck 
44c2c66affSColin Finck     if (!fcb) {
45c2c66affSColin Finck         FsRtlExitFileSystem();
46c2c66affSColin Finck         return FALSE;
47c2c66affSColin Finck     }
48c2c66affSColin Finck 
49c2c66affSColin Finck     ccb = FileObject->FsContext2;
50c2c66affSColin Finck 
51c2c66affSColin Finck     if (!ccb) {
52c2c66affSColin Finck         FsRtlExitFileSystem();
53c2c66affSColin Finck         return FALSE;
54c2c66affSColin Finck     }
55c2c66affSColin Finck 
56c2c66affSColin Finck     if (!(ccb->access & (FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES))) {
57c2c66affSColin Finck         FsRtlExitFileSystem();
58c2c66affSColin Finck         return FALSE;
59c2c66affSColin Finck     }
60c2c66affSColin Finck 
61c2c66affSColin Finck     if (fcb->ads) {
62c2c66affSColin Finck         if (!ccb->fileref || !ccb->fileref->parent || !ccb->fileref->parent->fcb) {
63c2c66affSColin Finck             FsRtlExitFileSystem();
64c2c66affSColin Finck             return FALSE;
65c2c66affSColin Finck         }
66c2c66affSColin Finck 
67c2c66affSColin Finck         fcb = ccb->fileref->parent->fcb;
68c2c66affSColin Finck     }
69c2c66affSColin Finck 
70c2c66affSColin Finck     if (!ExAcquireResourceSharedLite(fcb->Header.Resource, wait)) {
71c2c66affSColin Finck         FsRtlExitFileSystem();
72c2c66affSColin Finck         return FALSE;
73c2c66affSColin Finck     }
74c2c66affSColin Finck 
75c2c66affSColin Finck     if (fcb == fcb->Vcb->dummy_fcb) {
76c2c66affSColin Finck         LARGE_INTEGER time;
77c2c66affSColin Finck 
78c2c66affSColin Finck         KeQuerySystemTime(&time);
79c2c66affSColin Finck         fbi->CreationTime = fbi->LastAccessTime = fbi->LastWriteTime = fbi->ChangeTime = time;
80c2c66affSColin Finck     } else {
81c2c66affSColin Finck         fbi->CreationTime.QuadPart = unix_time_to_win(&fcb->inode_item.otime);
82c2c66affSColin Finck         fbi->LastAccessTime.QuadPart = unix_time_to_win(&fcb->inode_item.st_atime);
83c2c66affSColin Finck         fbi->LastWriteTime.QuadPart = unix_time_to_win(&fcb->inode_item.st_mtime);
84c2c66affSColin Finck         fbi->ChangeTime.QuadPart = unix_time_to_win(&fcb->inode_item.st_ctime);
85c2c66affSColin Finck     }
86c2c66affSColin Finck 
87c2c66affSColin Finck     fbi->FileAttributes = fcb->atts == 0 ? FILE_ATTRIBUTE_NORMAL : fcb->atts;
88c2c66affSColin Finck 
89c2c66affSColin Finck     IoStatus->Status = STATUS_SUCCESS;
90c2c66affSColin Finck     IoStatus->Information = sizeof(FILE_BASIC_INFORMATION);
91c2c66affSColin Finck 
92c2c66affSColin Finck     ExReleaseResourceLite(fcb->Header.Resource);
93c2c66affSColin Finck 
94c2c66affSColin Finck     FsRtlExitFileSystem();
95c2c66affSColin Finck 
96c2c66affSColin Finck     return TRUE;
97c2c66affSColin Finck }
98c2c66affSColin Finck 
99c2c66affSColin Finck _Function_class_(FAST_IO_QUERY_STANDARD_INFO)
100c2c66affSColin Finck #ifdef __REACTOS__
101c2c66affSColin Finck static BOOLEAN NTAPI fast_query_standard_info(PFILE_OBJECT FileObject, BOOLEAN wait, PFILE_STANDARD_INFORMATION fsi,
102c2c66affSColin Finck                                               PIO_STATUS_BLOCK IoStatus, PDEVICE_OBJECT DeviceObject) {
103c2c66affSColin Finck #else
104c2c66affSColin Finck static BOOLEAN fast_query_standard_info(PFILE_OBJECT FileObject, BOOLEAN wait, PFILE_STANDARD_INFORMATION fsi,
105c2c66affSColin Finck                                         PIO_STATUS_BLOCK IoStatus, PDEVICE_OBJECT DeviceObject) {
106c2c66affSColin Finck #endif
107c2c66affSColin Finck     fcb* fcb;
108c2c66affSColin Finck     ccb* ccb;
109c2c66affSColin Finck     BOOL ads;
110c2c66affSColin Finck     ULONG adssize;
111c2c66affSColin Finck 
112c2c66affSColin Finck     FsRtlEnterFileSystem();
113c2c66affSColin Finck 
114c2c66affSColin Finck     TRACE("(%p, %u, %p, %p, %p)\n", FileObject, wait, fsi, IoStatus, DeviceObject);
115c2c66affSColin Finck 
116c2c66affSColin Finck     if (!FileObject) {
117c2c66affSColin Finck         FsRtlExitFileSystem();
118c2c66affSColin Finck         return FALSE;
119c2c66affSColin Finck     }
120c2c66affSColin Finck 
121c2c66affSColin Finck     fcb = FileObject->FsContext;
122c2c66affSColin Finck     ccb = FileObject->FsContext2;
123c2c66affSColin Finck 
124c2c66affSColin Finck     if (!fcb) {
125c2c66affSColin Finck         FsRtlExitFileSystem();
126c2c66affSColin Finck         return FALSE;
127c2c66affSColin Finck     }
128c2c66affSColin Finck 
129c2c66affSColin Finck     if (!ExAcquireResourceSharedLite(fcb->Header.Resource, wait)) {
130c2c66affSColin Finck         FsRtlExitFileSystem();
131c2c66affSColin Finck         return FALSE;
132c2c66affSColin Finck     }
133c2c66affSColin Finck 
134c2c66affSColin Finck     ads = fcb->ads;
135c2c66affSColin Finck 
136c2c66affSColin Finck     if (ads) {
137c2c66affSColin Finck         struct _fcb* fcb2;
138c2c66affSColin Finck 
139c2c66affSColin Finck         if (!ccb || !ccb->fileref || !ccb->fileref->parent || !ccb->fileref->parent->fcb) {
140c2c66affSColin Finck             ExReleaseResourceLite(fcb->Header.Resource);
141c2c66affSColin Finck             FsRtlExitFileSystem();
142c2c66affSColin Finck             return FALSE;
143c2c66affSColin Finck         }
144c2c66affSColin Finck 
145c2c66affSColin Finck         adssize = fcb->adsdata.Length;
146c2c66affSColin Finck 
147c2c66affSColin Finck         fcb2 = ccb->fileref->parent->fcb;
148c2c66affSColin Finck 
149c2c66affSColin Finck         ExReleaseResourceLite(fcb->Header.Resource);
150c2c66affSColin Finck 
151c2c66affSColin Finck         fcb = fcb2;
152c2c66affSColin Finck 
153c2c66affSColin Finck         if (!ExAcquireResourceSharedLite(fcb->Header.Resource, wait)) {
154c2c66affSColin Finck             FsRtlExitFileSystem();
155c2c66affSColin Finck             return FALSE;
156c2c66affSColin Finck         }
157c2c66affSColin Finck 
158c2c66affSColin Finck         fsi->AllocationSize.QuadPart = fsi->EndOfFile.QuadPart = adssize;
159c2c66affSColin Finck         fsi->NumberOfLinks = fcb->inode_item.st_nlink;
160c2c66affSColin Finck         fsi->Directory = FALSE;
161c2c66affSColin Finck     } else {
162c2c66affSColin Finck         fsi->AllocationSize.QuadPart = fcb_alloc_size(fcb);
163c2c66affSColin Finck         fsi->EndOfFile.QuadPart = S_ISDIR(fcb->inode_item.st_mode) ? 0 : fcb->inode_item.st_size;
164c2c66affSColin Finck         fsi->NumberOfLinks = fcb->inode_item.st_nlink;
165c2c66affSColin Finck         fsi->Directory = S_ISDIR(fcb->inode_item.st_mode);
166c2c66affSColin Finck     }
167c2c66affSColin Finck 
168c2c66affSColin Finck     fsi->DeletePending = ccb->fileref ? ccb->fileref->delete_on_close : FALSE;
169c2c66affSColin Finck 
170c2c66affSColin Finck     IoStatus->Status = STATUS_SUCCESS;
171c2c66affSColin Finck     IoStatus->Information = sizeof(FILE_STANDARD_INFORMATION);
172c2c66affSColin Finck 
173c2c66affSColin Finck     ExReleaseResourceLite(fcb->Header.Resource);
174c2c66affSColin Finck 
175c2c66affSColin Finck     FsRtlExitFileSystem();
176c2c66affSColin Finck 
177c2c66affSColin Finck     return TRUE;
178c2c66affSColin Finck }
179c2c66affSColin Finck 
180c2c66affSColin Finck _Function_class_(FAST_IO_CHECK_IF_POSSIBLE)
181c2c66affSColin Finck #ifdef __REACTOS__
182c2c66affSColin Finck static BOOLEAN NTAPI fast_io_check_if_possible(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, ULONG Length, BOOLEAN Wait,
183c2c66affSColin Finck                                                ULONG LockKey, BOOLEAN CheckForReadOperation, PIO_STATUS_BLOCK IoStatus,
184c2c66affSColin Finck                                                PDEVICE_OBJECT DeviceObject) {
185c2c66affSColin Finck #else
186c2c66affSColin Finck static BOOLEAN fast_io_check_if_possible(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, ULONG Length, BOOLEAN Wait,
187c2c66affSColin Finck                                          ULONG LockKey, BOOLEAN CheckForReadOperation, PIO_STATUS_BLOCK IoStatus,
188c2c66affSColin Finck                                          PDEVICE_OBJECT DeviceObject) {
189c2c66affSColin Finck #endif
190c2c66affSColin Finck     fcb* fcb = FileObject->FsContext;
191c2c66affSColin Finck     LARGE_INTEGER len2;
192c2c66affSColin Finck 
193c2c66affSColin Finck     UNUSED(Wait);
194c2c66affSColin Finck     UNUSED(IoStatus);
195c2c66affSColin Finck     UNUSED(DeviceObject);
196c2c66affSColin Finck 
197c2c66affSColin Finck     len2.QuadPart = Length;
198c2c66affSColin Finck 
199c2c66affSColin Finck     if (CheckForReadOperation) {
200c2c66affSColin Finck         if (FsRtlFastCheckLockForRead(&fcb->lock, FileOffset, &len2, LockKey, FileObject, PsGetCurrentProcess()))
201c2c66affSColin Finck             return TRUE;
202c2c66affSColin Finck     } else {
203c2c66affSColin Finck         if (!fcb->Vcb->readonly && !is_subvol_readonly(fcb->subvol, NULL) && FsRtlFastCheckLockForWrite(&fcb->lock, FileOffset, &len2, LockKey, FileObject, PsGetCurrentProcess()))
204c2c66affSColin Finck             return TRUE;
205c2c66affSColin Finck     }
206c2c66affSColin Finck 
207c2c66affSColin Finck     return FALSE;
208c2c66affSColin Finck }
209c2c66affSColin Finck 
210c2c66affSColin Finck _Function_class_(FAST_IO_QUERY_NETWORK_OPEN_INFO)
211c2c66affSColin Finck #ifdef __REACTOS__
212c2c66affSColin Finck static BOOLEAN NTAPI fast_io_query_network_open_info(PFILE_OBJECT FileObject, BOOLEAN Wait, FILE_NETWORK_OPEN_INFORMATION* fnoi,
213c2c66affSColin Finck                                                      PIO_STATUS_BLOCK IoStatus, PDEVICE_OBJECT DeviceObject) {
214c2c66affSColin Finck #else
215c2c66affSColin Finck static BOOLEAN fast_io_query_network_open_info(PFILE_OBJECT FileObject, BOOLEAN Wait, FILE_NETWORK_OPEN_INFORMATION* fnoi,
216c2c66affSColin Finck                                                PIO_STATUS_BLOCK IoStatus, PDEVICE_OBJECT DeviceObject) {
217c2c66affSColin Finck #endif
218c2c66affSColin Finck     fcb* fcb;
219c2c66affSColin Finck     ccb* ccb;
220c2c66affSColin Finck     file_ref* fileref;
221c2c66affSColin Finck 
222c2c66affSColin Finck     FsRtlEnterFileSystem();
223c2c66affSColin Finck 
224c2c66affSColin Finck     TRACE("(%p, %u, %p, %p, %p)\n", FileObject, Wait, fnoi, IoStatus, DeviceObject);
225c2c66affSColin Finck 
226c2c66affSColin Finck     RtlZeroMemory(fnoi, sizeof(FILE_NETWORK_OPEN_INFORMATION));
227c2c66affSColin Finck 
228c2c66affSColin Finck     fcb = FileObject->FsContext;
229c2c66affSColin Finck 
230c2c66affSColin Finck     if (!fcb || fcb == fcb->Vcb->volume_fcb) {
231c2c66affSColin Finck         FsRtlExitFileSystem();
232c2c66affSColin Finck         return FALSE;
233c2c66affSColin Finck     }
234c2c66affSColin Finck 
235c2c66affSColin Finck     ccb = FileObject->FsContext2;
236c2c66affSColin Finck 
237c2c66affSColin Finck     if (!ccb) {
238c2c66affSColin Finck         FsRtlExitFileSystem();
239c2c66affSColin Finck         return FALSE;
240c2c66affSColin Finck     }
241c2c66affSColin Finck 
242c2c66affSColin Finck     fileref = ccb->fileref;
243c2c66affSColin Finck 
244c2c66affSColin Finck     if (fcb == fcb->Vcb->dummy_fcb) {
245c2c66affSColin Finck         LARGE_INTEGER time;
246c2c66affSColin Finck 
247c2c66affSColin Finck         KeQuerySystemTime(&time);
248c2c66affSColin Finck         fnoi->CreationTime = fnoi->LastAccessTime = fnoi->LastWriteTime = fnoi->ChangeTime = time;
249c2c66affSColin Finck     } else {
250c2c66affSColin Finck         INODE_ITEM* ii;
251c2c66affSColin Finck 
252c2c66affSColin Finck         if (fcb->ads) {
253c2c66affSColin Finck             if (!fileref || !fileref->parent) {
254c2c66affSColin Finck                 ERR("no fileref for stream\n");
255c2c66affSColin Finck                 FsRtlExitFileSystem();
256c2c66affSColin Finck                 return FALSE;
257c2c66affSColin Finck             }
258c2c66affSColin Finck 
259c2c66affSColin Finck             ii = &fileref->parent->fcb->inode_item;
260c2c66affSColin Finck         } else
261c2c66affSColin Finck             ii = &fcb->inode_item;
262c2c66affSColin Finck 
263c2c66affSColin Finck         fnoi->CreationTime.QuadPart = unix_time_to_win(&ii->otime);
264c2c66affSColin Finck         fnoi->LastAccessTime.QuadPart = unix_time_to_win(&ii->st_atime);
265c2c66affSColin Finck         fnoi->LastWriteTime.QuadPart = unix_time_to_win(&ii->st_mtime);
266c2c66affSColin Finck         fnoi->ChangeTime.QuadPart = unix_time_to_win(&ii->st_ctime);
267c2c66affSColin Finck     }
268c2c66affSColin Finck 
269c2c66affSColin Finck     if (fcb->ads) {
270c2c66affSColin Finck         fnoi->AllocationSize.QuadPart = fnoi->EndOfFile.QuadPart = fcb->adsdata.Length;
271c2c66affSColin Finck         fnoi->FileAttributes = fileref->parent->fcb->atts == 0 ? FILE_ATTRIBUTE_NORMAL : fileref->parent->fcb->atts;
272c2c66affSColin Finck     } else {
273c2c66affSColin Finck         fnoi->AllocationSize.QuadPart = fcb_alloc_size(fcb);
274c2c66affSColin Finck         fnoi->EndOfFile.QuadPart = S_ISDIR(fcb->inode_item.st_mode) ? 0 : fcb->inode_item.st_size;
275c2c66affSColin Finck         fnoi->FileAttributes = fcb->atts == 0 ? FILE_ATTRIBUTE_NORMAL : fcb->atts;
276c2c66affSColin Finck     }
277c2c66affSColin Finck 
278c2c66affSColin Finck     FsRtlExitFileSystem();
279c2c66affSColin Finck 
280c2c66affSColin Finck     return TRUE;
281c2c66affSColin Finck }
282c2c66affSColin Finck 
283c2c66affSColin Finck _Function_class_(FAST_IO_ACQUIRE_FOR_MOD_WRITE)
284c2c66affSColin Finck #ifdef __REACTOS__
285c2c66affSColin Finck static NTSTATUS NTAPI fast_io_acquire_for_mod_write(PFILE_OBJECT FileObject, PLARGE_INTEGER EndingOffset, struct _ERESOURCE **ResourceToRelease, PDEVICE_OBJECT DeviceObject) {
286c2c66affSColin Finck #else
287c2c66affSColin Finck static NTSTATUS fast_io_acquire_for_mod_write(PFILE_OBJECT FileObject, PLARGE_INTEGER EndingOffset, struct _ERESOURCE **ResourceToRelease, PDEVICE_OBJECT DeviceObject) {
288c2c66affSColin Finck #endif
289c2c66affSColin Finck     fcb* fcb;
290c2c66affSColin Finck 
291c2c66affSColin Finck     UNUSED(EndingOffset);
292c2c66affSColin Finck     UNUSED(DeviceObject);
293c2c66affSColin Finck 
294c2c66affSColin Finck     fcb = FileObject->FsContext;
295c2c66affSColin Finck 
296c2c66affSColin Finck     if (!fcb)
297c2c66affSColin Finck         return STATUS_INVALID_PARAMETER;
298c2c66affSColin Finck 
299*eb7fbc25SPierre Schweitzer     // Make sure we don't get interrupted by the flush thread, which can cause a deadlock
300c2c66affSColin Finck 
301*eb7fbc25SPierre Schweitzer     if (!ExAcquireResourceSharedLite(&fcb->Vcb->tree_lock, FALSE))
302c2c66affSColin Finck         return STATUS_CANT_WAIT;
303c2c66affSColin Finck 
304*eb7fbc25SPierre Schweitzer     // Ideally this would be PagingIoResource, but that doesn't play well with copy-on-write,
305*eb7fbc25SPierre Schweitzer     // as we can't guarantee that we won't need to do any reallocations.
306*eb7fbc25SPierre Schweitzer 
307*eb7fbc25SPierre Schweitzer     *ResourceToRelease = fcb->Header.Resource;
308*eb7fbc25SPierre Schweitzer 
309*eb7fbc25SPierre Schweitzer     if (!ExAcquireResourceExclusiveLite(*ResourceToRelease, FALSE)) {
310*eb7fbc25SPierre Schweitzer         ExReleaseResourceLite(&fcb->Vcb->tree_lock);
311*eb7fbc25SPierre Schweitzer         return STATUS_CANT_WAIT;
312*eb7fbc25SPierre Schweitzer     }
313*eb7fbc25SPierre Schweitzer 
314c2c66affSColin Finck     return STATUS_SUCCESS;
315c2c66affSColin Finck }
316c2c66affSColin Finck 
317c2c66affSColin Finck _Function_class_(FAST_IO_RELEASE_FOR_MOD_WRITE)
318c2c66affSColin Finck #ifdef __REACTOS__
319c2c66affSColin Finck static NTSTATUS NTAPI fast_io_release_for_mod_write(PFILE_OBJECT FileObject, struct _ERESOURCE *ResourceToRelease, PDEVICE_OBJECT DeviceObject) {
320c2c66affSColin Finck #else
321c2c66affSColin Finck static NTSTATUS fast_io_release_for_mod_write(PFILE_OBJECT FileObject, struct _ERESOURCE *ResourceToRelease, PDEVICE_OBJECT DeviceObject) {
322c2c66affSColin Finck #endif
323*eb7fbc25SPierre Schweitzer     fcb* fcb;
324*eb7fbc25SPierre Schweitzer 
325c2c66affSColin Finck     UNUSED(DeviceObject);
326c2c66affSColin Finck 
327*eb7fbc25SPierre Schweitzer     fcb = FileObject->FsContext;
328*eb7fbc25SPierre Schweitzer 
329c2c66affSColin Finck     ExReleaseResourceLite(ResourceToRelease);
330c2c66affSColin Finck 
331*eb7fbc25SPierre Schweitzer     ExReleaseResourceLite(&fcb->Vcb->tree_lock);
332*eb7fbc25SPierre Schweitzer 
333c2c66affSColin Finck     return STATUS_SUCCESS;
334c2c66affSColin Finck }
335c2c66affSColin Finck 
336c2c66affSColin Finck _Function_class_(FAST_IO_ACQUIRE_FOR_CCFLUSH)
337c2c66affSColin Finck #ifdef __REACTOS__
338c2c66affSColin Finck static NTSTATUS NTAPI fast_io_acquire_for_ccflush(PFILE_OBJECT FileObject, PDEVICE_OBJECT DeviceObject) {
339c2c66affSColin Finck #else
340c2c66affSColin Finck static NTSTATUS fast_io_acquire_for_ccflush(PFILE_OBJECT FileObject, PDEVICE_OBJECT DeviceObject) {
341c2c66affSColin Finck #endif
342c2c66affSColin Finck     UNUSED(FileObject);
343c2c66affSColin Finck     UNUSED(DeviceObject);
344c2c66affSColin Finck 
345c2c66affSColin Finck     IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
346c2c66affSColin Finck 
347c2c66affSColin Finck     return STATUS_SUCCESS;
348c2c66affSColin Finck }
349c2c66affSColin Finck 
350c2c66affSColin Finck _Function_class_(FAST_IO_RELEASE_FOR_CCFLUSH)
351c2c66affSColin Finck #ifdef __REACTOS__
352c2c66affSColin Finck static NTSTATUS NTAPI fast_io_release_for_ccflush(PFILE_OBJECT FileObject, PDEVICE_OBJECT DeviceObject) {
353c2c66affSColin Finck #else
354c2c66affSColin Finck static NTSTATUS fast_io_release_for_ccflush(PFILE_OBJECT FileObject, PDEVICE_OBJECT DeviceObject) {
355c2c66affSColin Finck #endif
356c2c66affSColin Finck     UNUSED(FileObject);
357c2c66affSColin Finck     UNUSED(DeviceObject);
358c2c66affSColin Finck 
359c2c66affSColin Finck     if (IoGetTopLevelIrp() == (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP)
360c2c66affSColin Finck         IoSetTopLevelIrp(NULL);
361c2c66affSColin Finck 
362c2c66affSColin Finck     return STATUS_SUCCESS;
363c2c66affSColin Finck }
364c2c66affSColin Finck 
365c2c66affSColin Finck _Function_class_(FAST_IO_WRITE)
366c2c66affSColin Finck #ifdef __REACTOS__
367c2c66affSColin Finck static BOOLEAN NTAPI fast_io_write(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, ULONG Length, BOOLEAN Wait, ULONG LockKey, PVOID Buffer, PIO_STATUS_BLOCK IoStatus, PDEVICE_OBJECT DeviceObject) {
368c2c66affSColin Finck #else
369c2c66affSColin Finck static BOOLEAN fast_io_write(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, ULONG Length, BOOLEAN Wait, ULONG LockKey, PVOID Buffer, PIO_STATUS_BLOCK IoStatus, PDEVICE_OBJECT DeviceObject) {
370c2c66affSColin Finck #endif
371c2c66affSColin Finck     if (FsRtlCopyWrite(FileObject, FileOffset, Length, Wait, LockKey, Buffer, IoStatus, DeviceObject)) {
372c2c66affSColin Finck         fcb* fcb = FileObject->FsContext;
373c2c66affSColin Finck 
374c2c66affSColin Finck         fcb->inode_item.st_size = fcb->Header.FileSize.QuadPart;
375c2c66affSColin Finck 
376c2c66affSColin Finck         return TRUE;
377c2c66affSColin Finck     }
378c2c66affSColin Finck 
379c2c66affSColin Finck     return FALSE;
380c2c66affSColin Finck }
381c2c66affSColin Finck 
382c2c66affSColin Finck void init_fast_io_dispatch(FAST_IO_DISPATCH** fiod) {
383c2c66affSColin Finck     RtlZeroMemory(&FastIoDispatch, sizeof(FastIoDispatch));
384c2c66affSColin Finck 
385c2c66affSColin Finck     FastIoDispatch.SizeOfFastIoDispatch = sizeof(FAST_IO_DISPATCH);
386c2c66affSColin Finck 
387c2c66affSColin Finck     FastIoDispatch.FastIoCheckIfPossible = fast_io_check_if_possible;
388c2c66affSColin Finck     FastIoDispatch.FastIoQueryBasicInfo = fast_query_basic_info;
389c2c66affSColin Finck     FastIoDispatch.FastIoQueryStandardInfo = fast_query_standard_info;
390c2c66affSColin Finck     FastIoDispatch.FastIoQueryNetworkOpenInfo = fast_io_query_network_open_info;
391c2c66affSColin Finck     FastIoDispatch.AcquireForModWrite = fast_io_acquire_for_mod_write;
392c2c66affSColin Finck     FastIoDispatch.ReleaseForModWrite = fast_io_release_for_mod_write;
393c2c66affSColin Finck     FastIoDispatch.AcquireForCcFlush = fast_io_acquire_for_ccflush;
394c2c66affSColin Finck     FastIoDispatch.ReleaseForCcFlush = fast_io_release_for_ccflush;
395c2c66affSColin Finck     FastIoDispatch.FastIoWrite = fast_io_write;
396c2c66affSColin Finck     FastIoDispatch.FastIoRead = FsRtlCopyRead;
397c2c66affSColin Finck     FastIoDispatch.MdlRead = FsRtlMdlReadDev;
398c2c66affSColin Finck     FastIoDispatch.MdlReadComplete = FsRtlMdlReadCompleteDev;
399c2c66affSColin Finck     FastIoDispatch.PrepareMdlWrite = FsRtlPrepareMdlWriteDev;
400c2c66affSColin Finck     FastIoDispatch.MdlWriteComplete = FsRtlMdlWriteCompleteDev;
401c2c66affSColin Finck 
402c2c66affSColin Finck     *fiod = &FastIoDispatch;
403c2c66affSColin Finck }
404