1*c2c66affSColin Finck /* Copyright (c) Mark Harmstone 2016-17 2*c2c66affSColin Finck * 3*c2c66affSColin Finck * This file is part of WinBtrfs. 4*c2c66affSColin Finck * 5*c2c66affSColin Finck * WinBtrfs is free software: you can redistribute it and/or modify 6*c2c66affSColin Finck * it under the terms of the GNU Lesser General Public Licence as published by 7*c2c66affSColin Finck * the Free Software Foundation, either version 3 of the Licence, or 8*c2c66affSColin Finck * (at your option) any later version. 9*c2c66affSColin Finck * 10*c2c66affSColin Finck * WinBtrfs is distributed in the hope that it will be useful, 11*c2c66affSColin Finck * but WITHOUT ANY WARRANTY; without even the implied warranty of 12*c2c66affSColin Finck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13*c2c66affSColin Finck * GNU Lesser General Public Licence for more details. 14*c2c66affSColin Finck * 15*c2c66affSColin Finck * You should have received a copy of the GNU Lesser General Public Licence 16*c2c66affSColin Finck * along with WinBtrfs. If not, see <http://www.gnu.org/licenses/>. */ 17*c2c66affSColin Finck 18*c2c66affSColin Finck #include "btrfs_drv.h" 19*c2c66affSColin Finck 20*c2c66affSColin Finck #define SECTOR_BLOCK 16 21*c2c66affSColin Finck 22*c2c66affSColin Finck NTSTATUS add_calc_job(device_extension* Vcb, UINT8* data, UINT32 sectors, UINT32* csum, calc_job** pcj) { 23*c2c66affSColin Finck calc_job* cj; 24*c2c66affSColin Finck 25*c2c66affSColin Finck cj = ExAllocatePoolWithTag(NonPagedPool, sizeof(calc_job), ALLOC_TAG); 26*c2c66affSColin Finck if (!cj) { 27*c2c66affSColin Finck ERR("out of memory\n"); 28*c2c66affSColin Finck return STATUS_INSUFFICIENT_RESOURCES; 29*c2c66affSColin Finck } 30*c2c66affSColin Finck 31*c2c66affSColin Finck cj->data = data; 32*c2c66affSColin Finck cj->sectors = sectors; 33*c2c66affSColin Finck cj->csum = csum; 34*c2c66affSColin Finck cj->pos = 0; 35*c2c66affSColin Finck cj->done = 0; 36*c2c66affSColin Finck cj->refcount = 1; 37*c2c66affSColin Finck KeInitializeEvent(&cj->event, NotificationEvent, FALSE); 38*c2c66affSColin Finck 39*c2c66affSColin Finck ExAcquireResourceExclusiveLite(&Vcb->calcthreads.lock, TRUE); 40*c2c66affSColin Finck InsertTailList(&Vcb->calcthreads.job_list, &cj->list_entry); 41*c2c66affSColin Finck ExReleaseResourceLite(&Vcb->calcthreads.lock); 42*c2c66affSColin Finck 43*c2c66affSColin Finck KeSetEvent(&Vcb->calcthreads.event, 0, FALSE); 44*c2c66affSColin Finck KeClearEvent(&Vcb->calcthreads.event); 45*c2c66affSColin Finck 46*c2c66affSColin Finck *pcj = cj; 47*c2c66affSColin Finck 48*c2c66affSColin Finck return STATUS_SUCCESS; 49*c2c66affSColin Finck } 50*c2c66affSColin Finck 51*c2c66affSColin Finck void free_calc_job(calc_job* cj) { 52*c2c66affSColin Finck LONG rc = InterlockedDecrement(&cj->refcount); 53*c2c66affSColin Finck 54*c2c66affSColin Finck if (rc == 0) 55*c2c66affSColin Finck ExFreePool(cj); 56*c2c66affSColin Finck } 57*c2c66affSColin Finck 58*c2c66affSColin Finck static BOOL do_calc(device_extension* Vcb, calc_job* cj) { 59*c2c66affSColin Finck LONG pos, done; 60*c2c66affSColin Finck UINT32* csum; 61*c2c66affSColin Finck UINT8* data; 62*c2c66affSColin Finck ULONG blocksize, i; 63*c2c66affSColin Finck 64*c2c66affSColin Finck pos = InterlockedIncrement(&cj->pos) - 1; 65*c2c66affSColin Finck 66*c2c66affSColin Finck if ((UINT32)pos * SECTOR_BLOCK >= cj->sectors) 67*c2c66affSColin Finck return FALSE; 68*c2c66affSColin Finck 69*c2c66affSColin Finck csum = &cj->csum[pos * SECTOR_BLOCK]; 70*c2c66affSColin Finck data = cj->data + (pos * SECTOR_BLOCK * Vcb->superblock.sector_size); 71*c2c66affSColin Finck 72*c2c66affSColin Finck blocksize = min(SECTOR_BLOCK, cj->sectors - (pos * SECTOR_BLOCK)); 73*c2c66affSColin Finck for (i = 0; i < blocksize; i++) { 74*c2c66affSColin Finck *csum = ~calc_crc32c(0xffffffff, data, Vcb->superblock.sector_size); 75*c2c66affSColin Finck csum++; 76*c2c66affSColin Finck data += Vcb->superblock.sector_size; 77*c2c66affSColin Finck } 78*c2c66affSColin Finck 79*c2c66affSColin Finck done = InterlockedIncrement(&cj->done); 80*c2c66affSColin Finck 81*c2c66affSColin Finck if ((UINT32)done * SECTOR_BLOCK >= cj->sectors) { 82*c2c66affSColin Finck ExAcquireResourceExclusiveLite(&Vcb->calcthreads.lock, TRUE); 83*c2c66affSColin Finck RemoveEntryList(&cj->list_entry); 84*c2c66affSColin Finck ExReleaseResourceLite(&Vcb->calcthreads.lock); 85*c2c66affSColin Finck 86*c2c66affSColin Finck KeSetEvent(&cj->event, 0, FALSE); 87*c2c66affSColin Finck } 88*c2c66affSColin Finck 89*c2c66affSColin Finck return TRUE; 90*c2c66affSColin Finck } 91*c2c66affSColin Finck 92*c2c66affSColin Finck _Function_class_(KSTART_ROUTINE) 93*c2c66affSColin Finck #ifdef __REACTOS__ 94*c2c66affSColin Finck void NTAPI calc_thread(void* context) { 95*c2c66affSColin Finck #else 96*c2c66affSColin Finck void calc_thread(void* context) { 97*c2c66affSColin Finck #endif 98*c2c66affSColin Finck drv_calc_thread* thread = context; 99*c2c66affSColin Finck device_extension* Vcb = thread->DeviceObject->DeviceExtension; 100*c2c66affSColin Finck 101*c2c66affSColin Finck ObReferenceObject(thread->DeviceObject); 102*c2c66affSColin Finck 103*c2c66affSColin Finck while (TRUE) { 104*c2c66affSColin Finck KeWaitForSingleObject(&Vcb->calcthreads.event, Executive, KernelMode, FALSE, NULL); 105*c2c66affSColin Finck 106*c2c66affSColin Finck while (TRUE) { 107*c2c66affSColin Finck calc_job* cj; 108*c2c66affSColin Finck BOOL b; 109*c2c66affSColin Finck 110*c2c66affSColin Finck ExAcquireResourceExclusiveLite(&Vcb->calcthreads.lock, TRUE); 111*c2c66affSColin Finck 112*c2c66affSColin Finck if (IsListEmpty(&Vcb->calcthreads.job_list)) { 113*c2c66affSColin Finck ExReleaseResourceLite(&Vcb->calcthreads.lock); 114*c2c66affSColin Finck break; 115*c2c66affSColin Finck } 116*c2c66affSColin Finck 117*c2c66affSColin Finck cj = CONTAINING_RECORD(Vcb->calcthreads.job_list.Flink, calc_job, list_entry); 118*c2c66affSColin Finck cj->refcount++; 119*c2c66affSColin Finck 120*c2c66affSColin Finck ExReleaseResourceLite(&Vcb->calcthreads.lock); 121*c2c66affSColin Finck 122*c2c66affSColin Finck b = do_calc(Vcb, cj); 123*c2c66affSColin Finck 124*c2c66affSColin Finck free_calc_job(cj); 125*c2c66affSColin Finck 126*c2c66affSColin Finck if (!b) 127*c2c66affSColin Finck break; 128*c2c66affSColin Finck } 129*c2c66affSColin Finck 130*c2c66affSColin Finck if (thread->quit) 131*c2c66affSColin Finck break; 132*c2c66affSColin Finck } 133*c2c66affSColin Finck 134*c2c66affSColin Finck ObDereferenceObject(thread->DeviceObject); 135*c2c66affSColin Finck 136*c2c66affSColin Finck KeSetEvent(&thread->finished, 0, FALSE); 137*c2c66affSColin Finck 138*c2c66affSColin Finck PsTerminateSystemThread(STATUS_SUCCESS); 139*c2c66affSColin Finck } 140