[CDFS]
[reactos.git] / reactos / drivers / filesystems / btrfs / worker-thread.c
1 /* Copyright (c) Mark Harmstone 2016
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 typedef struct {
21 device_extension* Vcb;
22 PIRP Irp;
23 WORK_QUEUE_ITEM item;
24 } job_info;
25
26 void do_read_job(PIRP Irp) {
27 NTSTATUS Status;
28 ULONG bytes_read;
29 BOOL top_level = is_top_level(Irp);
30 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
31 PFILE_OBJECT FileObject = IrpSp->FileObject;
32 fcb* fcb = FileObject->FsContext;
33 BOOL fcb_lock = FALSE;
34
35 Irp->IoStatus.Information = 0;
36
37 if (!ExIsResourceAcquiredSharedLite(fcb->Header.Resource)) {
38 ExAcquireResourceSharedLite(fcb->Header.Resource, TRUE);
39 fcb_lock = TRUE;
40 }
41
42 Status = do_read(Irp, TRUE, &bytes_read);
43
44 if (fcb_lock)
45 ExReleaseResourceLite(fcb->Header.Resource);
46
47 Irp->IoStatus.Status = Status;
48
49 // // fastfat doesn't do this, but the Wine ntdll file test seems to think we ought to
50 // if (Irp->UserIosb)
51 // *Irp->UserIosb = Irp->IoStatus;
52
53 TRACE("Irp->IoStatus.Status = %08x\n", Irp->IoStatus.Status);
54 TRACE("Irp->IoStatus.Information = %lu\n", Irp->IoStatus.Information);
55 TRACE("returning %08x\n", Status);
56
57 IoCompleteRequest(Irp, IO_NO_INCREMENT);
58
59 if (top_level)
60 IoSetTopLevelIrp(NULL);
61 }
62
63 void do_write_job(device_extension* Vcb, PIRP Irp) {
64 BOOL top_level = is_top_level(Irp);
65 NTSTATUS Status;
66
67 _SEH2_TRY {
68 Status = write_file(Vcb, Irp, TRUE, TRUE);
69 } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
70 Status = _SEH2_GetExceptionCode();
71 } _SEH2_END;
72
73 if (!NT_SUCCESS(Status))
74 ERR("write_file returned %08x\n", Status);
75
76 Irp->IoStatus.Status = Status;
77
78 TRACE("wrote %u bytes\n", Irp->IoStatus.Information);
79
80 IoCompleteRequest(Irp, IO_NO_INCREMENT);
81
82 if (top_level)
83 IoSetTopLevelIrp(NULL);
84
85 TRACE("returning %08x\n", Status);
86 }
87
88 #ifdef __REACTOS__
89 static void NTAPI do_job(void* context) {
90 #else
91 static void do_job(void* context) {
92 #endif
93 job_info* ji = context;
94 PIO_STACK_LOCATION IrpSp = ji->Irp ? IoGetCurrentIrpStackLocation(ji->Irp) : NULL;
95
96 if (IrpSp->MajorFunction == IRP_MJ_READ) {
97 do_read_job(ji->Irp);
98 } else if (IrpSp->MajorFunction == IRP_MJ_WRITE) {
99 do_write_job(ji->Vcb, ji->Irp);
100 }
101
102 ExFreePool(ji);
103 }
104
105 BOOL add_thread_job(device_extension* Vcb, PIRP Irp) {
106 job_info* ji;
107
108 ji = ExAllocatePoolWithTag(NonPagedPool, sizeof(job_info), ALLOC_TAG);
109 if (!ji) {
110 ERR("out of memory\n");
111 return FALSE;
112 }
113
114 ji->Vcb = Vcb;
115 ji->Irp = Irp;
116
117 if (!Irp->MdlAddress) {
118 PMDL Mdl;
119 LOCK_OPERATION op;
120 ULONG len;
121 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
122
123 if (IrpSp->MajorFunction == IRP_MJ_READ) {
124 op = IoWriteAccess;
125 len = IrpSp->Parameters.Read.Length;
126 } else if (IrpSp->MajorFunction == IRP_MJ_WRITE) {
127 op = IoReadAccess;
128 len = IrpSp->Parameters.Write.Length;
129 } else {
130 ERR("unexpected major function %u\n", IrpSp->MajorFunction);
131 return FALSE;
132 }
133
134 Mdl = IoAllocateMdl(Irp->UserBuffer, len, FALSE, FALSE, Irp);
135
136 if (!Mdl) {
137 ERR("out of memory\n");
138 return FALSE;
139 }
140
141 _SEH2_TRY {
142 MmProbeAndLockPages(Mdl, Irp->RequestorMode, op);
143 } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
144 ERR("MmProbeAndLockPages raised status %08x\n", _SEH2_GetExceptionCode());
145
146 IoFreeMdl(Mdl);
147 Irp->MdlAddress = NULL;
148
149 _SEH2_YIELD(return FALSE);
150 } _SEH2_END;
151 }
152
153 ExInitializeWorkItem(&ji->item, do_job, ji);
154 ExQueueWorkItem(&ji->item, DelayedWorkQueue);
155
156 return TRUE;
157 }