1 /* Copyright (c) Mark Harmstone 2016
3 * This file is part of WinBtrfs.
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.
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.
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/>. */
18 #include "btrfs_drv.h"
20 FAST_IO_DISPATCH FastIoDispatch
;
22 static void STDCALL
acquire_file_for_create_section(PFILE_OBJECT FileObject
) {
23 TRACE("STUB: acquire_file_for_create_section\n");
26 static void STDCALL
release_file_for_create_section(PFILE_OBJECT FileObject
) {
27 TRACE("STUB: release_file_for_create_section\n");
30 static BOOLEAN STDCALL
fast_query_basic_info(PFILE_OBJECT FileObject
, BOOLEAN wait
, PFILE_BASIC_INFORMATION fbi
,
31 PIO_STATUS_BLOCK IoStatus
, PDEVICE_OBJECT DeviceObject
) {
35 TRACE("(%p, %u, %p, %p, %p)\n", FileObject
, wait
, fbi
, IoStatus
, DeviceObject
);
40 fcb
= FileObject
->FsContext
;
45 ccb
= FileObject
->FsContext2
;
50 if (!(ccb
->access
& (FILE_READ_ATTRIBUTES
| FILE_WRITE_ATTRIBUTES
)))
54 if (!ccb
|| !ccb
->fileref
|| !ccb
->fileref
->parent
|| !ccb
->fileref
->parent
->fcb
)
57 fcb
= ccb
->fileref
->parent
->fcb
;
60 FsRtlEnterFileSystem();
62 if (!ExAcquireResourceSharedLite(fcb
->Header
.Resource
, wait
)) {
63 FsRtlExitFileSystem();
67 fbi
->CreationTime
.QuadPart
= unix_time_to_win(&fcb
->inode_item
.otime
);
68 fbi
->LastAccessTime
.QuadPart
= unix_time_to_win(&fcb
->inode_item
.st_atime
);
69 fbi
->LastWriteTime
.QuadPart
= unix_time_to_win(&fcb
->inode_item
.st_mtime
);
70 fbi
->ChangeTime
.QuadPart
= unix_time_to_win(&fcb
->inode_item
.st_ctime
);
71 fbi
->FileAttributes
= fcb
->atts
;
73 IoStatus
->Status
= STATUS_SUCCESS
;
74 IoStatus
->Information
= sizeof(FILE_BASIC_INFORMATION
);
76 ExReleaseResourceLite(fcb
->Header
.Resource
);
78 FsRtlExitFileSystem();
83 static BOOLEAN STDCALL
fast_query_standard_info(PFILE_OBJECT FileObject
, BOOLEAN wait
, PFILE_STANDARD_INFORMATION fsi
,
84 PIO_STATUS_BLOCK IoStatus
, PDEVICE_OBJECT DeviceObject
) {
90 TRACE("(%p, %u, %p, %p, %p)\n", FileObject
, wait
, fsi
, IoStatus
, DeviceObject
);
95 fcb
= FileObject
->FsContext
;
96 ccb
= FileObject
->FsContext2
;
101 FsRtlEnterFileSystem();
103 if (!ExAcquireResourceSharedLite(fcb
->Header
.Resource
, wait
)) {
104 FsRtlExitFileSystem();
113 if (!ccb
|| !ccb
->fileref
|| !ccb
->fileref
->parent
|| !ccb
->fileref
->parent
->fcb
) {
114 ExReleaseResourceLite(fcb
->Header
.Resource
);
115 FsRtlExitFileSystem();
119 adssize
= fcb
->adsdata
.Length
;
121 fcb2
= ccb
->fileref
->parent
->fcb
;
123 ExReleaseResourceLite(fcb
->Header
.Resource
);
127 if (!ExAcquireResourceSharedLite(fcb
->Header
.Resource
, wait
)) {
128 FsRtlExitFileSystem();
132 fsi
->AllocationSize
.QuadPart
= fsi
->EndOfFile
.QuadPart
= adssize
;
133 fsi
->NumberOfLinks
= fcb
->inode_item
.st_nlink
;
134 fsi
->Directory
= S_ISDIR(fcb
->inode_item
.st_mode
);
136 fsi
->AllocationSize
.QuadPart
= S_ISDIR(fcb
->inode_item
.st_mode
) ? 0 : sector_align(fcb
->inode_item
.st_size
, fcb
->Vcb
->superblock
.sector_size
);
137 fsi
->EndOfFile
.QuadPart
= S_ISDIR(fcb
->inode_item
.st_mode
) ? 0 : fcb
->inode_item
.st_size
;
138 fsi
->NumberOfLinks
= fcb
->inode_item
.st_nlink
;
139 fsi
->Directory
= S_ISDIR(fcb
->inode_item
.st_mode
);
142 fsi
->DeletePending
= ccb
->fileref
? ccb
->fileref
->delete_on_close
: FALSE
;
144 IoStatus
->Status
= STATUS_SUCCESS
;
145 IoStatus
->Information
= sizeof(FILE_STANDARD_INFORMATION
);
147 ExReleaseResourceLite(fcb
->Header
.Resource
);
149 FsRtlExitFileSystem();
154 static BOOLEAN STDCALL
fast_io_query_open(PIRP Irp
, PFILE_NETWORK_OPEN_INFORMATION NetworkInformation
, PDEVICE_OBJECT DeviceObject
) {
155 TRACE("STUB: fast_io_query_open\n");
160 static BOOLEAN STDCALL
fast_io_check_if_possible(PFILE_OBJECT FileObject
, PLARGE_INTEGER FileOffset
, ULONG Length
, BOOLEAN Wait
,
161 ULONG LockKey
, BOOLEAN CheckForReadOperation
, PIO_STATUS_BLOCK IoStatus
,
162 PDEVICE_OBJECT DeviceObject
) {
163 fcb
* fcb
= FileObject
->FsContext
;
166 TRACE("(%p, %llx, %x, %x, %x, %x, %p, %p)\n", FileObject
, FileOffset
->QuadPart
, Length
, Wait
, LockKey
, CheckForReadOperation
, IoStatus
, DeviceObject
);
168 len2
.QuadPart
= Length
;
170 if (CheckForReadOperation
) {
171 if (FsRtlFastCheckLockForRead(&fcb
->lock
, FileOffset
, &len2
, LockKey
, FileObject
, PsGetCurrentProcess()))
174 if (!fcb
->Vcb
->readonly
&& !(fcb
->subvol
->root_item
.flags
& BTRFS_SUBVOL_READONLY
) && FsRtlFastCheckLockForWrite(&fcb
->lock
, FileOffset
, &len2
, LockKey
, FileObject
, PsGetCurrentProcess()))
181 static BOOLEAN STDCALL
fast_io_lock(PFILE_OBJECT FileObject
, PLARGE_INTEGER FileOffset
, PLARGE_INTEGER Length
, PEPROCESS ProcessId
, ULONG Key
, BOOLEAN FailImmediately
, BOOLEAN ExclusiveLock
, PIO_STATUS_BLOCK IoStatus
, PDEVICE_OBJECT DeviceObject
){
182 TRACE("STUB: fast_io_lock\n");
186 static BOOLEAN STDCALL
fast_io_unlock_single(PFILE_OBJECT FileObject
, PLARGE_INTEGER FileOffset
, PLARGE_INTEGER Length
, PEPROCESS ProcessId
, ULONG Key
, PIO_STATUS_BLOCK IoStatus
, PDEVICE_OBJECT DeviceObject
){
187 TRACE("STUB: fast_io_unlock_single\n");
191 static BOOLEAN STDCALL
fast_io_unlock_all(PFILE_OBJECT FileObject
, PEPROCESS ProcessId
, PIO_STATUS_BLOCK IoStatus
, PDEVICE_OBJECT DeviceObject
){
192 TRACE("STUB: fast_io_unlock_all\n");
196 static BOOLEAN STDCALL
fast_io_unlock_all_by_key(PFILE_OBJECT FileObject
, PVOID ProcessId
, ULONG Key
, PIO_STATUS_BLOCK IoStatus
, PDEVICE_OBJECT DeviceObject
){
197 TRACE("STUB: fast_io_unlock_all_by_key\n");
201 static BOOLEAN STDCALL
fast_io_device_control(PFILE_OBJECT FileObject
, BOOLEAN Wait
, PVOID InputBuffer OPTIONAL
, ULONG InputBufferLength
, PVOID OutputBuffer OPTIONAL
, ULONG OutputBufferLength
, ULONG IoControlCode
, PIO_STATUS_BLOCK IoStatus
, PDEVICE_OBJECT DeviceObject
){
202 TRACE("STUB: fast_io_device_control\n");
206 static VOID STDCALL
fast_io_detach_device(PDEVICE_OBJECT SourceDevice
, PDEVICE_OBJECT TargetDevice
){
207 TRACE("STUB: fast_io_detach_device\n");
210 static BOOLEAN STDCALL
fast_io_query_network_open_info(PFILE_OBJECT FileObject
, BOOLEAN Wait
, struct _FILE_NETWORK_OPEN_INFORMATION
*Buffer
, struct _IO_STATUS_BLOCK
*IoStatus
, PDEVICE_OBJECT DeviceObject
){
211 TRACE("STUB: fast_io_query_network_open_info\n");
215 static NTSTATUS STDCALL
fast_io_acquire_for_mod_write(PFILE_OBJECT FileObject
, PLARGE_INTEGER EndingOffset
, struct _ERESOURCE
**ResourceToRelease
, PDEVICE_OBJECT DeviceObject
) {
218 TRACE("(%p, %llx, %p, %p)\n", FileObject
, EndingOffset
->QuadPart
, ResourceToRelease
, DeviceObject
);
220 fcb
= FileObject
->FsContext
;
223 return STATUS_INVALID_PARAMETER
;
225 *ResourceToRelease
= fcb
->Header
.PagingIoResource
;
227 if (!ExAcquireResourceSharedLite(*ResourceToRelease
, FALSE
))
228 return STATUS_CANT_WAIT
;
230 return STATUS_SUCCESS
;
233 static BOOLEAN STDCALL
fast_io_read_compressed(PFILE_OBJECT FileObject
, PLARGE_INTEGER FileOffset
, ULONG Length
, ULONG LockKey
, PVOID Buffer
, PMDL
*MdlChain
, PIO_STATUS_BLOCK IoStatus
, struct _COMPRESSED_DATA_INFO
*CompressedDataInfo
, ULONG CompressedDataInfoLength
, PDEVICE_OBJECT DeviceObject
){
234 TRACE("STUB: fast_io_read_compressed\n");
238 static BOOLEAN STDCALL
fast_io_write_compressed(PFILE_OBJECT FileObject
, PLARGE_INTEGER FileOffset
, ULONG Length
, ULONG LockKey
, PVOID Buffer
, PMDL
*MdlChain
, PIO_STATUS_BLOCK IoStatus
, struct _COMPRESSED_DATA_INFO
*CompressedDataInfo
, ULONG CompressedDataInfoLength
, PDEVICE_OBJECT DeviceObject
){
239 TRACE("STUB: fast_io_write_compressed\n");
243 static BOOLEAN STDCALL
fast_io_mdl_read_complete_compressed(PFILE_OBJECT FileObject
, PMDL MdlChain
, PDEVICE_OBJECT DeviceObject
){
244 TRACE("STUB: fast_io_mdl_read_complete_compressed\n");
248 static BOOLEAN STDCALL
fast_io_mdl_write_complete_compressed(PFILE_OBJECT FileObject
, PLARGE_INTEGER FileOffset
, PMDL MdlChain
, PDEVICE_OBJECT DeviceObject
){
249 TRACE("STUB: fast_io_mdl_write_complete_compressed\n");
253 static NTSTATUS STDCALL
fast_io_release_for_mod_write(PFILE_OBJECT FileObject
, struct _ERESOURCE
*ResourceToRelease
, PDEVICE_OBJECT DeviceObject
){
254 TRACE("STUB: fast_io_release_for_mod_write\n");
255 return STATUS_NOT_IMPLEMENTED
;
258 static NTSTATUS STDCALL
fast_io_acquire_for_ccflush(PFILE_OBJECT FileObject
, PDEVICE_OBJECT DeviceObject
){
259 TRACE("STUB: fast_io_acquire_for_ccflush\n");
260 return STATUS_SUCCESS
;
263 static NTSTATUS STDCALL
fast_io_release_for_ccflush(PFILE_OBJECT FileObject
, PDEVICE_OBJECT DeviceObject
){
264 TRACE("STUB: fast_io_release_for_ccflush\n");
265 return STATUS_SUCCESS
;
268 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
) {
269 TRACE("(%p (%.*S), %llx, %x, %x, %x, %p, %p, %p)\n", FileObject
, FileObject
->FileName
.Length
/ sizeof(WCHAR
), FileObject
->FileName
.Buffer
,
270 *FileOffset
, Length
, Wait
, LockKey
, Buffer
, IoStatus
, DeviceObject
);
272 if (FsRtlCopyWrite(FileObject
, FileOffset
, Length
, Wait
, LockKey
, Buffer
, IoStatus
, DeviceObject
)) {
273 fcb
* fcb
= FileObject
->FsContext
;
275 fcb
->inode_item
.st_size
= fcb
->Header
.FileSize
.QuadPart
;
284 static BOOLEAN STDCALL
fast_io_read(PFILE_OBJECT FileObject
, PLARGE_INTEGER FileOffset
, ULONG Length
, BOOLEAN Wait
, ULONG LockKey
, PVOID Buffer
, PIO_STATUS_BLOCK IoStatus
, PDEVICE_OBJECT DeviceObject
) {
285 TRACE("(%p, %p, %x, %x, %x, %p, %p, %p)\n", FileObject
, FileOffset
, Length
, Wait
, LockKey
, Buffer
, IoStatus
, DeviceObject
);
287 return FsRtlCopyRead(FileObject
, FileOffset
, Length
, Wait
, LockKey
, Buffer
, IoStatus
, DeviceObject
);
290 static BOOLEAN STDCALL
fast_io_mdl_read(PFILE_OBJECT FileObject
, PLARGE_INTEGER FileOffset
, ULONG Length
, ULONG LockKey
, PMDL
* MdlChain
, PIO_STATUS_BLOCK IoStatus
, PDEVICE_OBJECT DeviceObject
) {
291 TRACE("(%p, %p, %x, %x, %p, %p, %p)\n", FileObject
, FileOffset
, Length
, LockKey
, MdlChain
, IoStatus
, DeviceObject
);
293 return FsRtlMdlReadDev(FileObject
, FileOffset
, Length
, LockKey
, MdlChain
, IoStatus
, DeviceObject
);
296 static BOOLEAN STDCALL
fast_io_mdl_read_complete(PFILE_OBJECT FileObject
, PMDL MdlChain
, PDEVICE_OBJECT DeviceObject
) {
297 TRACE("(%p, %p, %p)\n", FileObject
, MdlChain
, DeviceObject
);
299 return FsRtlMdlReadCompleteDev(FileObject
, MdlChain
, DeviceObject
);
302 static BOOLEAN STDCALL
fast_io_prepare_mdl_write(PFILE_OBJECT FileObject
, PLARGE_INTEGER FileOffset
, ULONG Length
, ULONG LockKey
, PMDL
* MdlChain
, PIO_STATUS_BLOCK IoStatus
, PDEVICE_OBJECT DeviceObject
) {
303 TRACE("(%p, %p, %x, %x, %p, %p, %p)\n", FileObject
, FileOffset
, Length
, LockKey
, MdlChain
, IoStatus
, DeviceObject
);
305 return FsRtlPrepareMdlWriteDev(FileObject
, FileOffset
, Length
, LockKey
, MdlChain
, IoStatus
, DeviceObject
);
308 static BOOLEAN STDCALL
fast_io_mdl_write_complete(PFILE_OBJECT FileObject
, PLARGE_INTEGER FileOffset
, PMDL MdlChain
, PDEVICE_OBJECT DeviceObject
) {
309 TRACE("(%p, %p, %p, %p)\n", FileObject
, FileOffset
, MdlChain
, DeviceObject
);
311 return FsRtlMdlWriteCompleteDev(FileObject
, FileOffset
, MdlChain
, DeviceObject
);
315 void __stdcall
init_fast_io_dispatch(FAST_IO_DISPATCH
** fiod
) {
316 RtlZeroMemory(&FastIoDispatch
, sizeof(FastIoDispatch
));
318 FastIoDispatch
.SizeOfFastIoDispatch
= sizeof(FAST_IO_DISPATCH
);
320 FastIoDispatch
.FastIoCheckIfPossible
= fast_io_check_if_possible
;
321 FastIoDispatch
.FastIoQueryBasicInfo
= fast_query_basic_info
;
322 FastIoDispatch
.FastIoQueryStandardInfo
= fast_query_standard_info
;
323 FastIoDispatch
.FastIoLock
= fast_io_lock
;
324 FastIoDispatch
.FastIoUnlockSingle
= fast_io_unlock_single
;
325 FastIoDispatch
.FastIoUnlockAll
= fast_io_unlock_all
;
326 FastIoDispatch
.FastIoUnlockAllByKey
= fast_io_unlock_all_by_key
;
327 FastIoDispatch
.FastIoDeviceControl
= fast_io_device_control
;
328 FastIoDispatch
.AcquireFileForNtCreateSection
= acquire_file_for_create_section
;
329 FastIoDispatch
.ReleaseFileForNtCreateSection
= release_file_for_create_section
;
330 FastIoDispatch
.FastIoDetachDevice
= fast_io_detach_device
;
331 FastIoDispatch
.FastIoQueryNetworkOpenInfo
= fast_io_query_network_open_info
;
332 FastIoDispatch
.AcquireForModWrite
= fast_io_acquire_for_mod_write
;
333 FastIoDispatch
.FastIoReadCompressed
= fast_io_read_compressed
;
334 FastIoDispatch
.FastIoWriteCompressed
= fast_io_write_compressed
;
335 FastIoDispatch
.MdlReadCompleteCompressed
= fast_io_mdl_read_complete_compressed
;
336 FastIoDispatch
.MdlWriteCompleteCompressed
= fast_io_mdl_write_complete_compressed
;
337 FastIoDispatch
.FastIoQueryOpen
= fast_io_query_open
;
338 FastIoDispatch
.ReleaseForModWrite
= fast_io_release_for_mod_write
;
339 FastIoDispatch
.AcquireForCcFlush
= fast_io_acquire_for_ccflush
;
340 FastIoDispatch
.ReleaseForCcFlush
= fast_io_release_for_ccflush
;
341 FastIoDispatch
.FastIoWrite
= fast_io_write
;
344 FastIoDispatch
.FastIoRead
= fast_io_read
;
345 FastIoDispatch
.MdlRead
= fast_io_mdl_read
;
346 FastIoDispatch
.MdlReadComplete
= fast_io_mdl_read_complete
;
347 FastIoDispatch
.PrepareMdlWrite
= fast_io_prepare_mdl_write
;
348 FastIoDispatch
.MdlWriteComplete
= fast_io_mdl_write_complete
;
350 FastIoDispatch
.FastIoRead
= FsRtlCopyRead
;
351 FastIoDispatch
.MdlRead
= FsRtlMdlReadDev
;
352 FastIoDispatch
.MdlReadComplete
= FsRtlMdlReadCompleteDev
;
353 FastIoDispatch
.PrepareMdlWrite
= FsRtlPrepareMdlWriteDev
;
354 FastIoDispatch
.MdlWriteComplete
= FsRtlMdlWriteCompleteDev
;
357 *fiod
= &FastIoDispatch
;