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 void do_read_job(PIRP Irp
) {
23 BOOL top_level
= is_top_level(Irp
);
25 Irp
->IoStatus
.Information
= 0;
27 Status
= do_read(Irp
, TRUE
, &bytes_read
);
29 Irp
->IoStatus
.Status
= Status
;
31 // // fastfat doesn't do this, but the Wine ntdll file test seems to think we ought to
33 // *Irp->UserIosb = Irp->IoStatus;
35 TRACE("Irp->IoStatus.Status = %08x\n", Irp
->IoStatus
.Status
);
36 TRACE("Irp->IoStatus.Information = %lu\n", Irp
->IoStatus
.Information
);
37 TRACE("returning %08x\n", Status
);
39 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
42 IoSetTopLevelIrp(NULL
);
45 void do_write_job(device_extension
* Vcb
, PIRP Irp
) {
46 BOOL top_level
= is_top_level(Irp
);
50 Status
= write_file(Vcb
, Irp
, TRUE
, TRUE
);
51 } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER
) {
52 Status
= _SEH2_GetExceptionCode();
55 Irp
->IoStatus
.Status
= Status
;
57 TRACE("wrote %u bytes\n", Irp
->IoStatus
.Information
);
59 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
62 IoSetTopLevelIrp(NULL
);
64 TRACE("returning %08x\n", Status
);
67 static void do_job(drv_thread
* thread
, LIST_ENTRY
* le
) {
68 thread_job
* tj
= CONTAINING_RECORD(le
, thread_job
, list_entry
);
69 PIO_STACK_LOCATION IrpSp
= IoGetCurrentIrpStackLocation(tj
->Irp
);
71 if (IrpSp
->MajorFunction
== IRP_MJ_READ
) {
73 } else if (IrpSp
->MajorFunction
== IRP_MJ_WRITE
) {
74 do_write_job(thread
->DeviceObject
->DeviceExtension
, tj
->Irp
);
76 ERR("unsupported major function %x\n", IrpSp
->MajorFunction
);
77 tj
->Irp
->IoStatus
.Status
= STATUS_INTERNAL_ERROR
;
78 tj
->Irp
->IoStatus
.Information
= 0;
79 IoCompleteRequest(tj
->Irp
, IO_NO_INCREMENT
);
85 void STDCALL
worker_thread(void* context
) {
86 drv_thread
* thread
= context
;
89 ObReferenceObject(thread
->DeviceObject
);
92 KeWaitForSingleObject(&thread
->event
, Executive
, KernelMode
, FALSE
, NULL
);
94 FsRtlEnterFileSystem();
98 device_extension
* Vcb
= thread
->DeviceObject
->DeviceExtension
;
100 KeAcquireSpinLock(&thread
->spin_lock
, &irql
);
102 if (IsListEmpty(&thread
->jobs
)) {
103 KeReleaseSpinLock(&thread
->spin_lock
, irql
);
107 le
= thread
->jobs
.Flink
;
110 KeReleaseSpinLock(&thread
->spin_lock
, irql
);
112 InterlockedDecrement(&Vcb
->threads
.pending_jobs
);
116 FsRtlExitFileSystem();
122 ObDereferenceObject(thread
->DeviceObject
);
124 KeSetEvent(&thread
->finished
, 0, FALSE
);
126 PsTerminateSystemThread(STATUS_SUCCESS
);