Something went wrong. Try again.
Reactos
Something went wrong. Try again.
4.6 kB · 164 lines
C
at master
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165/* Copyright (c) Mark Harmstone 2016-17 * * This file is part of WinBtrfs. * * WinBtrfs is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public Licence as published by * the Free Software Foundation, either version 3 of the Licence, or * (at your option) any later version. * * WinBtrfs is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public Licence for more details. * * You should have received a copy of the GNU Lesser General Public Licence * along with WinBtrfs. If not, see <http://www.gnu.org/licenses/>. */
#include "btrfs_drv.h"
typedef struct { device_extension* Vcb; PIRP Irp; WORK_QUEUE_ITEM item;} job_info;
NTSTATUS do_read_job(PIRP Irp) { NTSTATUS Status; ULONG bytes_read; bool top_level = is_top_level(Irp); PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); PFILE_OBJECT FileObject = IrpSp->FileObject; fcb* fcb = FileObject->FsContext; bool acquired_fcb_lock = false;
Irp->IoStatus.Information = 0;
if (!ExIsResourceAcquiredSharedLite(fcb->Header.Resource)) { ExAcquireResourceSharedLite(fcb->Header.Resource, true); acquired_fcb_lock = true; }
_SEH2_TRY { Status = do_read(Irp, true, &bytes_read); } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) { Status = _SEH2_GetExceptionCode(); } _SEH2_END;
if (acquired_fcb_lock) ExReleaseResourceLite(fcb->Header.Resource);
if (!NT_SUCCESS(Status)) ERR("do_read returned %08lx\n", Status);
Irp->IoStatus.Status = Status;
TRACE("read %Iu bytes\n", Irp->IoStatus.Information);
IoCompleteRequest(Irp, IO_NO_INCREMENT);
if (top_level) IoSetTopLevelIrp(NULL);
TRACE("returning %08lx\n", Status);
return Status;}
NTSTATUS do_write_job(device_extension* Vcb, PIRP Irp) { bool top_level = is_top_level(Irp); NTSTATUS Status;
_SEH2_TRY { Status = write_file(Vcb, Irp, true, true); } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) { Status = _SEH2_GetExceptionCode(); } _SEH2_END;
if (!NT_SUCCESS(Status)) ERR("write_file returned %08lx\n", Status);
Irp->IoStatus.Status = Status;
TRACE("wrote %Iu bytes\n", Irp->IoStatus.Information);
IoCompleteRequest(Irp, IO_NO_INCREMENT);
if (top_level) IoSetTopLevelIrp(NULL);
TRACE("returning %08lx\n", Status);
return Status;}
_Function_class_(WORKER_THREAD_ROUTINE)static void __stdcall do_job(void* context) { job_info* ji = context; PIO_STACK_LOCATION IrpSp = ji->Irp ? IoGetCurrentIrpStackLocation(ji->Irp) : NULL;
if (IrpSp->MajorFunction == IRP_MJ_READ) { do_read_job(ji->Irp); } else if (IrpSp->MajorFunction == IRP_MJ_WRITE) { do_write_job(ji->Vcb, ji->Irp); }
ExFreePool(ji);}
bool add_thread_job(device_extension* Vcb, PIRP Irp) { job_info* ji;
ji = ExAllocatePoolWithTag(NonPagedPool, sizeof(job_info), ALLOC_TAG); if (!ji) { ERR("out of memory\n"); return false; }
ji->Vcb = Vcb; ji->Irp = Irp;
if (!Irp->MdlAddress) { PMDL Mdl; LOCK_OPERATION op; ULONG len; PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
if (IrpSp->MajorFunction == IRP_MJ_READ) { op = IoWriteAccess; len = IrpSp->Parameters.Read.Length; } else if (IrpSp->MajorFunction == IRP_MJ_WRITE) { op = IoReadAccess; len = IrpSp->Parameters.Write.Length; } else { ERR("unexpected major function %u\n", IrpSp->MajorFunction); ExFreePool(ji); return false; }
Mdl = IoAllocateMdl(Irp->UserBuffer, len, false, false, Irp);
if (!Mdl) { ERR("out of memory\n"); ExFreePool(ji); return false; }
_SEH2_TRY { MmProbeAndLockPages(Mdl, Irp->RequestorMode, op); } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) { ERR("MmProbeAndLockPages raised status %08lx\n", _SEH2_GetExceptionCode());
IoFreeMdl(Mdl); Irp->MdlAddress = NULL; ExFreePool(ji);
_SEH2_YIELD(return FALSE); } _SEH2_END; }
ExInitializeWorkItem(&ji->item, do_job, ji); ExQueueWorkItem(&ji->item, DelayedWorkQueue);
return true;}