ReactOS  0.4.15-dev-1197-g8081ba9
read.c File Reference
#include "btrfs_drv.h"
#include "xxhash.h"
#include "crc32c.h"
Include dependency graph for read.c:

Go to the source code of this file.

Classes

struct  read_data_stripe
 
struct  read_data_context
 
struct  read_part_extent
 
struct  read_part
 
struct  comp_calc_job
 

Macros

#define LZO_PAGE_SIZE   4096
 

Enumerations

enum  read_data_status {
  ReadDataStatus_Pending, ReadDataStatus_Success, ReadDataStatus_Error, ReadDataStatus_MissingDevice,
  ReadDataStatus_Skip
}
 

Functions

 _Function_class_ (IO_COMPLETION_ROUTINE)
 
NTSTATUS check_csum (device_extension *Vcb, uint8_t *data, uint32_t sectors, void *csum)
 
void get_tree_checksum (device_extension *Vcb, tree_header *th, void *csum)
 
bool check_tree_checksum (device_extension *Vcb, tree_header *th)
 
void get_sector_csum (device_extension *Vcb, void *buf, void *csum)
 
bool check_sector_csum (device_extension *Vcb, void *buf, void *csum)
 
static NTSTATUS read_data_dup (device_extension *Vcb, uint8_t *buf, uint64_t addr, read_data_context *context, CHUNK_ITEM *ci, device **devices, uint64_t generation)
 
static NTSTATUS read_data_raid0 (device_extension *Vcb, uint8_t *buf, uint64_t addr, uint32_t length, read_data_context *context, CHUNK_ITEM *ci, device **devices, uint64_t generation, uint64_t offset)
 
static NTSTATUS read_data_raid10 (device_extension *Vcb, uint8_t *buf, uint64_t addr, uint32_t length, read_data_context *context, CHUNK_ITEM *ci, device **devices, uint64_t generation, uint64_t offset)
 
static NTSTATUS read_data_raid5 (device_extension *Vcb, uint8_t *buf, uint64_t addr, uint32_t length, read_data_context *context, CHUNK_ITEM *ci, device **devices, uint64_t offset, uint64_t generation, chunk *c, bool degraded)
 
void raid6_recover2 (uint8_t *sectors, uint16_t num_stripes, ULONG sector_size, uint16_t missing1, uint16_t missing2, uint8_t *out)
 
static NTSTATUS read_data_raid6 (device_extension *Vcb, uint8_t *buf, uint64_t addr, uint32_t length, read_data_context *context, CHUNK_ITEM *ci, device **devices, uint64_t offset, uint64_t generation, chunk *c, bool degraded)
 
NTSTATUS read_data (_In_ device_extension *Vcb, _In_ uint64_t addr, _In_ uint32_t length, _In_reads_bytes_opt_(length *sizeof(uint32_t)/Vcb->superblock.sector_size) void *csum, _In_ bool is_tree, _Out_writes_bytes_(length) uint8_t *buf, _In_opt_ chunk *c, _Out_opt_ chunk **pc, _In_opt_ PIRP Irp, _In_ uint64_t generation, _In_ bool file_read, _In_ ULONG priority)
 
NTSTATUS read_stream (fcb *fcb, uint8_t *data, uint64_t start, ULONG length, ULONG *pbr)
 
NTSTATUS read_file (fcb *fcb, uint8_t *data, uint64_t start, uint64_t length, ULONG *pbr, PIRP Irp)
 
NTSTATUS do_read (PIRP Irp, bool wait, ULONG *bytes_read)
 
 _Dispatch_type_ (IRP_MJ_READ)
 

Variables

bool diskacc
 
tPsUpdateDiskCounters fPsUpdateDiskCounters
 
tCcCopyReadEx fCcCopyReadEx
 
tFsRtlUpdateDiskCounters fFsRtlUpdateDiskCounters
 

Macro Definition Documentation

◆ LZO_PAGE_SIZE

#define LZO_PAGE_SIZE   4096

Definition at line 65 of file read.c.

Enumeration Type Documentation

◆ read_data_status

Enumerator
ReadDataStatus_Pending 
ReadDataStatus_Success 
ReadDataStatus_Error 
ReadDataStatus_MissingDevice 
ReadDataStatus_Skip 

Definition at line 22 of file read.c.

Function Documentation

◆ _Dispatch_type_()

_Dispatch_type_ ( IRP_MJ_READ  )

Definition at line 3515 of file read.c.

3517  {
3518  device_extension* Vcb = DeviceObject->DeviceExtension;
3521  ULONG bytes_read = 0;
3522  NTSTATUS Status;
3523  bool top_level;
3524  fcb* fcb;
3525  ccb* ccb;
3526  bool acquired_fcb_lock = false, wait;
3527 
3529 
3530  top_level = is_top_level(Irp);
3531 
3532  TRACE("read\n");
3533 
3534  if (Vcb && Vcb->type == VCB_TYPE_VOLUME) {
3536  goto exit2;
3537  } else if (!Vcb || Vcb->type != VCB_TYPE_FS) {
3539  goto end;
3540  }
3541 
3542  Irp->IoStatus.Information = 0;
3543 
3545  CcMdlReadComplete(IrpSp->FileObject, Irp->MdlAddress);
3546 
3547  Irp->MdlAddress = NULL;
3549 
3550  goto exit;
3551  }
3552 
3553  fcb = FileObject->FsContext;
3554 
3555  if (!fcb) {
3556  ERR("fcb was NULL\n");
3558  goto exit;
3559  }
3560 
3561  ccb = FileObject->FsContext2;
3562 
3563  if (!ccb) {
3564  ERR("ccb was NULL\n");
3566  goto exit;
3567  }
3568 
3569  if (Irp->RequestorMode == UserMode && !(ccb->access & FILE_READ_DATA)) {
3570  WARN("insufficient privileges\n");
3572  goto exit;
3573  }
3574 
3575  if (fcb == Vcb->volume_fcb) {
3576  TRACE("reading volume FCB\n");
3577 
3579 
3580  Status = IoCallDriver(Vcb->Vpb->RealDevice, Irp);
3581 
3582  goto exit2;
3583  }
3584 
3585  if (!(Irp->Flags & IRP_PAGING_IO))
3587 
3588  wait = IoIsOperationSynchronous(Irp);
3589 
3590  // Don't offload jobs when doing paging IO - otherwise this can lead to
3591  // deadlocks in CcCopyRead.
3592  if (Irp->Flags & IRP_PAGING_IO)
3593  wait = true;
3594 
3595  if (!(Irp->Flags & IRP_PAGING_IO) && FileObject->SectionObjectPointer && FileObject->SectionObjectPointer->DataSectionObject) {
3597 
3598  CcFlushCache(FileObject->SectionObjectPointer, &IrpSp->Parameters.Read.ByteOffset, IrpSp->Parameters.Read.Length, &iosb);
3599  if (!NT_SUCCESS(iosb.Status)) {
3600  ERR("CcFlushCache returned %08lx\n", iosb.Status);
3601  return iosb.Status;
3602  }
3603  }
3604 
3605  if (!ExIsResourceAcquiredSharedLite(fcb->Header.Resource)) {
3606  if (!ExAcquireResourceSharedLite(fcb->Header.Resource, wait)) {
3609  goto exit;
3610  }
3611 
3612  acquired_fcb_lock = true;
3613  }
3614 
3615  Status = do_read(Irp, wait, &bytes_read);
3616 
3617  if (acquired_fcb_lock)
3618  ExReleaseResourceLite(fcb->Header.Resource);
3619 
3620 exit:
3621  if (FileObject->Flags & FO_SYNCHRONOUS_IO && !(Irp->Flags & IRP_PAGING_IO))
3622  FileObject->CurrentByteOffset.QuadPart = IrpSp->Parameters.Read.ByteOffset.QuadPart + (NT_SUCCESS(Status) ? bytes_read : 0);
3623 
3624 end:
3625  Irp->IoStatus.Status = Status;
3626 
3627  TRACE("Irp->IoStatus.Status = %08lx\n", Irp->IoStatus.Status);
3628  TRACE("Irp->IoStatus.Information = %Iu\n", Irp->IoStatus.Information);
3629  TRACE("returning %08lx\n", Status);
3630 
3631  if (Status != STATUS_PENDING)
3633  else {
3634  if (!add_thread_job(Vcb, Irp))
3635  Status = do_read_job(Irp);
3636  }
3637 
3638 exit2:
3639  if (top_level)
3641 
3643 
3644  return Status;
3645 }
static PIO_STATUS_BLOCK iosb
Definition: file.c:98
NTSTATUS do_read_job(PIRP Irp)
Definition: worker-thread.c:26
#define FsRtlEnterFileSystem
VOID NTAPI CcFlushCache(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN OPTIONAL PLARGE_INTEGER FileOffset, IN ULONG Length, OUT OPTIONAL PIO_STATUS_BLOCK IoStatus)
Definition: cachesub.c:222
#define FsRtlExitFileSystem
_In_ PIRP Irp
Definition: csq.h:116
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define WARN(fmt,...)
Definition: debug.h:112
LONG NTSTATUS
Definition: precomp.h:26
#define VCB_TYPE_FS
Definition: btrfs_drv.h:695
GLuint GLuint end
Definition: gl.h:1545
ACCESS_MASK access
Definition: btrfs_drv.h:398
BOOLEAN NTAPI IoIsOperationSynchronous(IN PIRP Irp)
Definition: irp.c:1882
bool is_top_level(_In_ PIRP Irp)
Definition: btrfs.c:279
NTSTATUS do_read(PIRP Irp, bool wait, ULONG *bytes_read)
Definition: read.c:3361
#define FO_SYNCHRONOUS_IO
Definition: iotypes.h:1756
#define IRP_MN_COMPLETE
Definition: iotypes.h:4399
#define FILE_READ_DATA
Definition: nt_native.h:628
VOID NTAPI CcMdlReadComplete(IN PFILE_OBJECT FileObject, IN PMDL MdlChain)
Definition: mdlsup.c:75
smooth NULL
Definition: ftsmooth.c:416
#define IoCompleteRequest
Definition: irp.c:1240
_Inout_ PFILE_OBJECT FileObject
Definition: cdprocs.h:588
FSRTL_ADVANCED_FCB_HEADER Header
Definition: btrfs_drv.h:294
bool add_thread_job(device_extension *Vcb, PIRP Irp)
#define TRACE(s)
Definition: solgame.cpp:4
struct _fcb fcb
Definition: btrfs_drv.h:1357
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
#define VCB_TYPE_VOLUME
Definition: btrfs_drv.h:697
#define Vcb
Definition: cdprocs.h:1415
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
* PFILE_OBJECT
Definition: iotypes.h:1978
Status
Definition: gdiplustypes.h:24
VOID NTAPI IoSetTopLevelIrp(IN PIRP Irp)
Definition: irp.c:2000
#define ERR(fmt,...)
Definition: debug.h:110
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2789
PFILE_OBJECT FileObject
Definition: iotypes.h:3148
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4137
_In_ PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:2464
NTSTATUS NTAPI IoCallDriver(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: irp.c:1218
#define IoSkipCurrentIrpStackLocation(Irp)
Definition: ntifs_ex.h:421
#define IRP_PAGING_IO
BOOLEAN NTAPI ExAcquireResourceSharedLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:885
static __inline POPLOCK fcb_oplock(fcb *fcb)
Definition: btrfs_drv.h:1683
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:581
ULONG NTAPI ExIsResourceAcquiredSharedLite(IN PERESOURCE Resource)
Definition: resource.c:1658
NTSTATUS NTAPI FsRtlCheckOplock(IN POPLOCK Oplock, IN PIRP Irp, IN PVOID Context, IN POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine OPTIONAL, IN POPLOCK_FS_PREPOST_IRP PostIrpRoutine OPTIONAL)
Definition: oplock.c:1172
void exit(int exitcode)
Definition: _exit.c:33
struct _ccb ccb
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:3107
return STATUS_SUCCESS
Definition: btrfs.c:3014
IoMarkIrpPending(Irp)
NTSTATUS vol_read(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: volume.c:144

◆ _Function_class_()

_Function_class_ ( IO_COMPLETION_ROUTINE  )

Definition at line 67 of file read.c.

68  {
69  read_data_stripe* stripe = conptr;
71 
73 
74  stripe->iosb = Irp->IoStatus;
75 
76  if (NT_SUCCESS(Irp->IoStatus.Status))
78  else
79  stripe->status = ReadDataStatus_Error;
80 
81  if (InterlockedDecrement(&context->stripes_left) == 0)
82  KeSetEvent(&context->Event, 0, false);
83 
85 }
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:68
Definition: http.c:7094
_In_ PIRP Irp
Definition: csq.h:116
Definition: write.c:111
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
#define UNUSED(x)
Definition: btrfs_drv.h:86
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define InterlockedDecrement
Definition: armddk.h:52
_In_ PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:2464

◆ check_csum()

NTSTATUS check_csum ( device_extension Vcb,
uint8_t data,
uint32_t  sectors,
void csum 
)

Definition at line 87 of file read.c.

87  {
88  void* csum2;
89 
90  csum2 = ExAllocatePoolWithTag(PagedPool, Vcb->csum_size * sectors, ALLOC_TAG);
91  if (!csum2) {
92  ERR("out of memory\n");
94  }
95 
96  do_calc_job(Vcb, data, sectors, csum2);
97 
98  if (RtlCompareMemory(csum2, csum, sectors * Vcb->csum_size) != sectors * Vcb->csum_size) {
99  ExFreePool(csum2);
100  return STATUS_CRC_ERROR;
101  }
102 
103  ExFreePool(csum2);
104 
105  return STATUS_SUCCESS;
106 }
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define ALLOC_TAG
Definition: btrfs_drv.h:91
void do_calc_job(device_extension *Vcb, uint8_t *data, uint32_t sectors, void *csum)
Definition: calcthread.c:141
#define Vcb
Definition: cdprocs.h:1415
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define STATUS_CRC_ERROR
Definition: udferr_usr.h:153
#define ERR(fmt,...)
Definition: debug.h:110
__u8 sectors[2]
Definition: mkdosfs.c:366
Definition: fs.h:216
return STATUS_SUCCESS
Definition: btrfs.c:3014
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465

Referenced by read_data_dup(), read_data_raid0(), read_data_raid10(), read_data_raid5(), and read_data_raid6().

◆ check_sector_csum()

bool check_sector_csum ( device_extension Vcb,
void buf,
void csum 
)

Definition at line 202 of file read.c.

202  {
203  switch (Vcb->superblock.csum_type) {
204  case CSUM_TYPE_CRC32C: {
205  uint32_t crc32 = ~calc_crc32c(0xffffffff, buf, Vcb->superblock.sector_size);
206 
207  return *(uint32_t*)csum == crc32;
208  }
209 
210  case CSUM_TYPE_XXHASH: {
211  uint64_t hash = XXH64(buf, Vcb->superblock.sector_size, 0);
212 
213  return *(uint64_t*)csum == hash;
214  }
215 
216  case CSUM_TYPE_SHA256: {
218 
219  calc_sha256(hash, buf, Vcb->superblock.sector_size);
220 
222  }
223 
224  case CSUM_TYPE_BLAKE2: {
226 
227  blake2b(hash, sizeof(hash), buf, Vcb->superblock.sector_size);
228 
230  }
231  }
232 
233  return false;
234 }
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
#define CSUM_TYPE_BLAKE2
Definition: btrfs.h:128
void blake2b(void *out, size_t outlen, const void *in, size_t inlen)
Definition: blake2b-ref.c:237
#define CSUM_TYPE_CRC32C
Definition: btrfs.h:125
void calc_sha256(uint8_t *hash, const void *input, size_t len)
Definition: sha256.c:126
#define SHA256_HASH_SIZE
Definition: btrfs_drv.h:1248
#define Vcb
Definition: cdprocs.h:1415
#define CSUM_TYPE_XXHASH
Definition: btrfs.h:126
crc_func calc_crc32c
Definition: crc32c.c:23
BYTE uint8_t
Definition: msvideo1.c:66
XXH_PUBLIC_API unsigned long long XXH64(const void *input, size_t len, unsigned long long seed)
Definition: xxhash.c:555
#define CSUM_TYPE_SHA256
Definition: btrfs.h:127
UINT64 uint64_t
Definition: types.h:77
UINT32 uint32_t
Definition: types.h:75
#define crc32(crc, buf, len)
Definition: inflate.c:1081
Definition: fs.h:216
#define BLAKE2_HASH_SIZE
Definition: btrfs_drv.h:1252
Definition: _hash_fun.h:40
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465

Referenced by read_data_dup(), read_data_raid0(), read_data_raid10(), read_data_raid5(), read_data_raid6(), scrub_extent_raid0(), scrub_extent_raid10(), scrub_raid5_stripe(), and scrub_raid6_stripe().

◆ check_tree_checksum()

bool check_tree_checksum ( device_extension Vcb,
tree_header th 
)

Definition at line 128 of file read.c.

128  {
129  switch (Vcb->superblock.csum_type) {
130  case CSUM_TYPE_CRC32C: {
131  uint32_t crc32 = ~calc_crc32c(0xffffffff, (uint8_t*)&th->fs_uuid, Vcb->superblock.node_size - sizeof(th->csum));
132 
133  if (crc32 == *((uint32_t*)th->csum))
134  return true;
135 
136  WARN("hash was %08x, expected %08x\n", crc32, *((uint32_t*)th->csum));
137 
138  break;
139  }
140 
141  case CSUM_TYPE_XXHASH: {
142  uint64_t hash = XXH64((uint8_t*)&th->fs_uuid, Vcb->superblock.node_size - sizeof(th->csum), 0);
143 
144  if (hash == *((uint64_t*)th->csum))
145  return true;
146 
147  WARN("hash was %I64x, expected %I64x\n", hash, *((uint64_t*)th->csum));
148 
149  break;
150  }
151 
152  case CSUM_TYPE_SHA256: {
154 
155  calc_sha256(hash, (uint8_t*)&th->fs_uuid, Vcb->superblock.node_size - sizeof(th->csum));
156 
158  return true;
159 
160  WARN("hash was invalid\n");
161 
162  break;
163  }
164 
165  case CSUM_TYPE_BLAKE2: {
167 
168  blake2b(hash, sizeof(hash), (uint8_t*)&th->fs_uuid, Vcb->superblock.node_size - sizeof(th->csum));
169 
171  return true;
172 
173  WARN("hash was invalid\n");
174 
175  break;
176  }
177  }
178 
179  return false;
180 }
#define CSUM_TYPE_BLAKE2
Definition: btrfs.h:128
void blake2b(void *out, size_t outlen, const void *in, size_t inlen)
Definition: blake2b-ref.c:237
#define WARN(fmt,...)
Definition: debug.h:112
uint8_t csum[32]
Definition: btrfs.h:147
#define CSUM_TYPE_CRC32C
Definition: btrfs.h:125
void calc_sha256(uint8_t *hash, const void *input, size_t len)
Definition: sha256.c:126
#define SHA256_HASH_SIZE
Definition: btrfs_drv.h:1248
#define Vcb
Definition: cdprocs.h:1415
#define CSUM_TYPE_XXHASH
Definition: btrfs.h:126
crc_func calc_crc32c
Definition: crc32c.c:23
BYTE uint8_t
Definition: msvideo1.c:66
XXH_PUBLIC_API unsigned long long XXH64(const void *input, size_t len, unsigned long long seed)
Definition: xxhash.c:555
#define CSUM_TYPE_SHA256
Definition: btrfs.h:127
UINT64 uint64_t
Definition: types.h:77
BTRFS_UUID fs_uuid
Definition: btrfs.h:148
UINT32 uint32_t
Definition: types.h:75
#define crc32(crc, buf, len)
Definition: inflate.c:1081
#define BLAKE2_HASH_SIZE
Definition: btrfs_drv.h:1252
Definition: _hash_fun.h:40
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465

Referenced by read_data_dup(), read_data_raid0(), read_data_raid10(), read_data_raid5(), read_data_raid6(), scrub_extent_dup(), scrub_extent_raid0(), scrub_extent_raid10(), scrub_raid5_stripe(), and scrub_raid6_stripe().

◆ do_read()

NTSTATUS do_read ( PIRP  Irp,
bool  wait,
ULONG bytes_read 
)

Definition at line 3361 of file read.c.

3361  {
3364  fcb* fcb = FileObject->FsContext;
3365  uint8_t* data = NULL;
3366  ULONG length = IrpSp->Parameters.Read.Length, addon = 0;
3367  uint64_t start = IrpSp->Parameters.Read.ByteOffset.QuadPart;
3368 
3369  *bytes_read = 0;
3370 
3371  if (!fcb || !fcb->Vcb || !fcb->subvol)
3372  return STATUS_INTERNAL_ERROR;
3373 
3374  TRACE("fcb = %p\n", fcb);
3375  TRACE("offset = %I64x, length = %lx\n", start, length);
3376  TRACE("paging_io = %s, no cache = %s\n", Irp->Flags & IRP_PAGING_IO ? "true" : "false", Irp->Flags & IRP_NOCACHE ? "true" : "false");
3377 
3378  if (!fcb->ads && fcb->type == BTRFS_TYPE_DIRECTORY)
3380 
3381  if (!(Irp->Flags & IRP_PAGING_IO) && !FsRtlCheckLockForReadAccess(&fcb->lock, Irp)) {
3382  WARN("tried to read locked region\n");
3384  }
3385 
3386  if (length == 0) {
3387  TRACE("tried to read zero bytes\n");
3388  return STATUS_SUCCESS;
3389  }
3390 
3391  if (start >= (uint64_t)fcb->Header.FileSize.QuadPart) {
3392  TRACE("tried to read with offset after file end (%I64x >= %I64x)\n", start, fcb->Header.FileSize.QuadPart);
3393  return STATUS_END_OF_FILE;
3394  }
3395 
3396  TRACE("FileObject %p fcb %p FileSize = %I64x st_size = %I64x (%p)\n", FileObject, fcb, fcb->Header.FileSize.QuadPart, fcb->inode_item.st_size, &fcb->inode_item.st_size);
3397 
3398  if (Irp->Flags & IRP_NOCACHE || !(IrpSp->MinorFunction & IRP_MN_MDL)) {
3400 
3401  if (Irp->MdlAddress && !data) {
3402  ERR("MmGetSystemAddressForMdlSafe returned NULL\n");
3404  }
3405 
3406  if (start >= (uint64_t)fcb->Header.ValidDataLength.QuadPart) {
3407  length = (ULONG)min(length, min(start + length, (uint64_t)fcb->Header.FileSize.QuadPart) - fcb->Header.ValidDataLength.QuadPart);
3409  Irp->IoStatus.Information = *bytes_read = length;
3410  return STATUS_SUCCESS;
3411  }
3412 
3413  if (length + start > (uint64_t)fcb->Header.ValidDataLength.QuadPart) {
3414  addon = (ULONG)(min(start + length, (uint64_t)fcb->Header.FileSize.QuadPart) - fcb->Header.ValidDataLength.QuadPart);
3415  RtlZeroMemory(data + (fcb->Header.ValidDataLength.QuadPart - start), addon);
3416  length = (ULONG)(fcb->Header.ValidDataLength.QuadPart - start);
3417  }
3418  }
3419 
3420  if (!(Irp->Flags & IRP_NOCACHE)) {
3422 
3423  _SEH2_TRY {
3424  if (!FileObject->PrivateCacheMap) {
3425  CC_FILE_SIZES ccfs;
3426 
3427  ccfs.AllocationSize = fcb->Header.AllocationSize;
3428  ccfs.FileSize = fcb->Header.FileSize;
3429  ccfs.ValidDataLength = fcb->Header.ValidDataLength;
3430 
3431  init_file_cache(FileObject, &ccfs);
3432  }
3433 
3434  if (IrpSp->MinorFunction & IRP_MN_MDL) {
3435  CcMdlRead(FileObject,&IrpSp->Parameters.Read.ByteOffset, length, &Irp->MdlAddress, &Irp->IoStatus);
3436  } else {
3437  if (fCcCopyReadEx) {
3438  TRACE("CcCopyReadEx(%p, %I64x, %lx, %u, %p, %p, %p)\n", FileObject, IrpSp->Parameters.Read.ByteOffset.QuadPart,
3439  length, wait, data, &Irp->IoStatus, Irp->Tail.Overlay.Thread);
3440  TRACE("sizes = %I64x, %I64x, %I64x\n", fcb->Header.AllocationSize.QuadPart, fcb->Header.FileSize.QuadPart, fcb->Header.ValidDataLength.QuadPart);
3441  if (!fCcCopyReadEx(FileObject, &IrpSp->Parameters.Read.ByteOffset, length, wait, data, &Irp->IoStatus, Irp->Tail.Overlay.Thread)) {
3442  TRACE("CcCopyReadEx could not wait\n");
3443 
3445  return STATUS_PENDING;
3446  }
3447  TRACE("CcCopyReadEx finished\n");
3448  } else {
3449  TRACE("CcCopyRead(%p, %I64x, %lx, %u, %p, %p)\n", FileObject, IrpSp->Parameters.Read.ByteOffset.QuadPart, length, wait, data, &Irp->IoStatus);
3450  TRACE("sizes = %I64x, %I64x, %I64x\n", fcb->Header.AllocationSize.QuadPart, fcb->Header.FileSize.QuadPart, fcb->Header.ValidDataLength.QuadPart);
3451  if (!CcCopyRead(FileObject, &IrpSp->Parameters.Read.ByteOffset, length, wait, data, &Irp->IoStatus)) {
3452  TRACE("CcCopyRead could not wait\n");
3453 
3455  return STATUS_PENDING;
3456  }
3457  TRACE("CcCopyRead finished\n");
3458  }
3459  }
3462  } _SEH2_END;
3463 
3464  if (NT_SUCCESS(Status)) {
3465  Status = Irp->IoStatus.Status;
3466  Irp->IoStatus.Information += addon;
3467  *bytes_read = (ULONG)Irp->IoStatus.Information;
3468  } else
3469  ERR("EXCEPTION - %08lx\n", Status);
3470 
3471  return Status;
3472  } else {
3473  NTSTATUS Status;
3474 
3475  if (!wait) {
3477  return STATUS_PENDING;
3478  }
3479 
3480  if (fcb->ads) {
3481  Status = read_stream(fcb, data, start, length, bytes_read);
3482 
3483  if (!NT_SUCCESS(Status))
3484  ERR("read_stream returned %08lx\n", Status);
3485  } else {
3486  Status = read_file(fcb, data, start, length, bytes_read, Irp);
3487 
3488  if (!NT_SUCCESS(Status))
3489  ERR("read_file returned %08lx\n", Status);
3490  }
3491 
3492  *bytes_read += addon;
3493  TRACE("read %lu bytes\n", *bytes_read);
3494 
3495  Irp->IoStatus.Information = *bytes_read;
3496 
3497  if (diskacc && Status != STATUS_PENDING) {
3498  PETHREAD thread = NULL;
3499 
3500  if (Irp->Tail.Overlay.Thread && !IoIsSystemThread(Irp->Tail.Overlay.Thread))
3501  thread = Irp->Tail.Overlay.Thread;
3502  else if (!IoIsSystemThread(PsGetCurrentThread()))
3506 
3507  if (thread)
3508  fPsUpdateDiskCounters(PsGetThreadProcess(thread), *bytes_read, 0, 1, 0, 0);
3509  }
3510 
3511  return Status;
3512  }
3513 }
BOOLEAN NTAPI IoIsSystemThread(IN PETHREAD Thread)
Definition: util.c:115
void init_file_cache(_In_ PFILE_OBJECT FileObject, _In_ CC_FILE_SIZES *ccfs)
Definition: btrfs.c:4028
VOID NTAPI CcMdlRead(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, OUT PMDL *MdlChain, OUT PIO_STATUS_BLOCK IoStatus)
Definition: mdlsup.c:64
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
_In_ PIRP Irp
Definition: csq.h:116
#define FSRTL_FLAG2_IS_PAGING_FILE
Definition: fsrtltypes.h:57
#define WARN(fmt,...)
Definition: debug.h:112
LONG NTSTATUS
Definition: precomp.h:26
#define IRP_NOCACHE
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
LARGE_INTEGER FileSize
Definition: cctypes.h:16
_SEH2_TRY
Definition: create.c:4226
#define STATUS_END_OF_FILE
Definition: shellext.h:67
PEPROCESS __stdcall PsGetThreadProcess(_In_ PETHREAD Thread)
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define BTRFS_TYPE_DIRECTORY
Definition: shellext.h:86
smooth NULL
Definition: ftsmooth.c:416
uint8_t type
Definition: btrfs_drv.h:302
tPsUpdateDiskCounters fPsUpdateDiskCounters
Definition: btrfs.c:95
_Inout_ PFILE_OBJECT FileObject
Definition: cdprocs.h:588
FILE_LOCK lock
Definition: btrfs_drv.h:305
FSRTL_ADVANCED_FCB_HEADER Header
Definition: btrfs_drv.h:294
uint64_t st_size
Definition: btrfs.h:282
#define TRACE(s)
Definition: solgame.cpp:4
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
BOOLEAN NTAPI FsRtlCheckLockForReadAccess(IN PFILE_LOCK FileLock, IN PIRP Irp)
Definition: filelock.c:676
static __inline void * map_user_buffer(PIRP Irp, ULONG priority)
Definition: btrfs_drv.h:985
PIRP NTAPI IoGetTopLevelIrp(VOID)
Definition: irp.c:1843
NTSTATUS read_stream(fcb *fcb, uint8_t *data, uint64_t start, ULONG length, ULONG *pbr)
Definition: read.c:2764
* PFILE_OBJECT
Definition: iotypes.h:1978
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
static HANDLE thread
Definition: service.c:33
Status
Definition: gdiplustypes.h:24
BOOLEAN NTAPI CcCopyRead(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN Wait, OUT PVOID Buffer, OUT PIO_STATUS_BLOCK IoStatus)
Definition: copysup.c:43
#define IRP_MN_MDL
Definition: iotypes.h:4398
LARGE_INTEGER ValidDataLength
Definition: cctypes.h:17
INODE_ITEM inode_item
Definition: btrfs_drv.h:303
BYTE uint8_t
Definition: msvideo1.c:66
NTSTATUS read_file(fcb *fcb, uint8_t *data, uint64_t start, uint64_t length, ULONG *pbr, PIRP Irp)
Definition: read.c:2828
#define ERR(fmt,...)
Definition: debug.h:110
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2789
PFILE_OBJECT FileObject
Definition: iotypes.h:3148
_SEH2_END
Definition: create.c:4400
UINT64 uint64_t
Definition: types.h:77
LARGE_INTEGER AllocationSize
Definition: cctypes.h:15
GLuint start
Definition: gl.h:1545
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4137
static const addon_info_t * addon
Definition: addons.c:59
struct _root * subvol
Definition: btrfs_drv.h:299
#define min(a, b)
Definition: monoChain.cc:55
#define IRP_PAGING_IO
bool ads
Definition: btrfs_drv.h:341
#define STATUS_FILE_LOCK_CONFLICT
Definition: ntstatus.h:320
tCcCopyReadEx fCcCopyReadEx
Definition: btrfs.c:96
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:3107
return STATUS_SUCCESS
Definition: btrfs.c:3014
IoMarkIrpPending(Irp)
struct _device_extension * Vcb
Definition: btrfs_drv.h:298
bool diskacc
Definition: btrfs.c:106

Referenced by _Dispatch_type_(), and do_read_job().

◆ get_sector_csum()

void get_sector_csum ( device_extension Vcb,
void buf,
void csum 
)

Definition at line 182 of file read.c.

182  {
183  switch (Vcb->superblock.csum_type) {
184  case CSUM_TYPE_CRC32C:
185  *(uint32_t*)csum = ~calc_crc32c(0xffffffff, buf, Vcb->superblock.sector_size);
186  break;
187 
188  case CSUM_TYPE_XXHASH:
189  *(uint64_t*)csum = XXH64(buf, Vcb->superblock.sector_size, 0);
190  break;
191 
192  case CSUM_TYPE_SHA256:
193  calc_sha256(csum, buf, Vcb->superblock.sector_size);
194  break;
195 
196  case CSUM_TYPE_BLAKE2:
197  blake2b(csum, BLAKE2_HASH_SIZE, buf, Vcb->superblock.sector_size);
198  break;
199  }
200 }
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
#define CSUM_TYPE_BLAKE2
Definition: btrfs.h:128
void blake2b(void *out, size_t outlen, const void *in, size_t inlen)
Definition: blake2b-ref.c:237
#define CSUM_TYPE_CRC32C
Definition: btrfs.h:125
void calc_sha256(uint8_t *hash, const void *input, size_t len)
Definition: sha256.c:126
#define Vcb
Definition: cdprocs.h:1415
#define CSUM_TYPE_XXHASH
Definition: btrfs.h:126
crc_func calc_crc32c
Definition: crc32c.c:23
XXH_PUBLIC_API unsigned long long XXH64(const void *input, size_t len, unsigned long long seed)
Definition: xxhash.c:555
#define CSUM_TYPE_SHA256
Definition: btrfs.h:127
UINT64 uint64_t
Definition: types.h:77
UINT32 uint32_t
Definition: types.h:75
Definition: fs.h:216
#define BLAKE2_HASH_SIZE
Definition: btrfs_drv.h:1252

Referenced by scrub_raid5_stripe(), and scrub_raid6_stripe().

◆ get_tree_checksum()

void get_tree_checksum ( device_extension Vcb,
tree_header th,
void csum 
)

Definition at line 108 of file read.c.

108  {
109  switch (Vcb->superblock.csum_type) {
110  case CSUM_TYPE_CRC32C:
111  *(uint32_t*)csum = ~calc_crc32c(0xffffffff, (uint8_t*)&th->fs_uuid, Vcb->superblock.node_size - sizeof(th->csum));
112  break;
113 
114  case CSUM_TYPE_XXHASH:
115  *(uint64_t*)csum = XXH64((uint8_t*)&th->fs_uuid, Vcb->superblock.node_size - sizeof(th->csum), 0);
116  break;
117 
118  case CSUM_TYPE_SHA256:
119  calc_sha256(csum, &th->fs_uuid, Vcb->superblock.node_size - sizeof(th->csum));
120  break;
121 
122  case CSUM_TYPE_BLAKE2:
123  blake2b(csum, BLAKE2_HASH_SIZE, (uint8_t*)&th->fs_uuid, Vcb->superblock.node_size - sizeof(th->csum));
124  break;
125  }
126 }
#define CSUM_TYPE_BLAKE2
Definition: btrfs.h:128
void blake2b(void *out, size_t outlen, const void *in, size_t inlen)
Definition: blake2b-ref.c:237
uint8_t csum[32]
Definition: btrfs.h:147
#define CSUM_TYPE_CRC32C
Definition: btrfs.h:125
void calc_sha256(uint8_t *hash, const void *input, size_t len)
Definition: sha256.c:126
#define Vcb
Definition: cdprocs.h:1415
#define CSUM_TYPE_XXHASH
Definition: btrfs.h:126
crc_func calc_crc32c
Definition: crc32c.c:23
BYTE uint8_t
Definition: msvideo1.c:66
XXH_PUBLIC_API unsigned long long XXH64(const void *input, size_t len, unsigned long long seed)
Definition: xxhash.c:555
#define CSUM_TYPE_SHA256
Definition: btrfs.h:127
UINT64 uint64_t
Definition: types.h:77
BTRFS_UUID fs_uuid
Definition: btrfs.h:148
UINT32 uint32_t
Definition: types.h:75
Definition: fs.h:216
#define BLAKE2_HASH_SIZE
Definition: btrfs_drv.h:1252

Referenced by scrub_extent_dup(), scrub_extent_raid10(), and scrub_raid6_stripe().

◆ raid6_recover2()

void raid6_recover2 ( uint8_t sectors,
uint16_t  num_stripes,
ULONG  sector_size,
uint16_t  missing1,
uint16_t  missing2,
uint8_t out 
)

Definition at line 933 of file read.c.

933  {
934  if (missing1 == num_stripes - 2 || missing2 == num_stripes - 2) { // reconstruct from q and data
935  uint16_t missing = missing1 == (num_stripes - 2) ? missing2 : missing1;
937 
938  stripe = num_stripes - 3;
939 
940  if (stripe == missing)
942  else
944 
945  do {
946  stripe--;
947 
949 
950  if (stripe != missing)
952  } while (stripe > 0);
953 
954  do_xor(out, sectors + ((num_stripes - 1) * sector_size), sector_size);
955 
956  if (missing != 0)
958  } else { // reconstruct from p and q
959  uint16_t x, y, stripe;
960  uint8_t gyx, gx, denom, a, b, *p, *q, *pxy, *qxy;
961  uint32_t j;
962 
963  stripe = num_stripes - 3;
964 
965  pxy = out + sector_size;
966  qxy = out;
967 
968  if (stripe == missing1 || stripe == missing2) {
971 
972  if (stripe == missing1)
973  x = stripe;
974  else
975  y = stripe;
976  } else {
979  }
980 
981  do {
982  stripe--;
983 
985 
986  if (stripe != missing1 && stripe != missing2) {
989  } else if (stripe == missing1)
990  x = stripe;
991  else if (stripe == missing2)
992  y = stripe;
993  } while (stripe > 0);
994 
995  gyx = gpow2(y > x ? (y-x) : (255-x+y));
996  gx = gpow2(255-x);
997 
998  denom = gdiv(1, gyx ^ 1);
999  a = gmul(gyx, denom);
1000  b = gmul(gx, denom);
1001 
1002  p = sectors + ((num_stripes - 2) * sector_size);
1003  q = sectors + ((num_stripes - 1) * sector_size);
1004 
1005  for (j = 0; j < sector_size; j++) {
1006  *qxy = gmul(a, *p ^ *pxy) ^ gmul(b, *q ^ *qxy);
1007 
1008  p++;
1009  q++;
1010  pxy++;
1011  qxy++;
1012  }
1013 
1015  do_xor(out + sector_size, sectors + ((num_stripes - 2) * sector_size), sector_size);
1016  }
1017 }
void galois_double(uint8_t *data, uint32_t len)
Definition: galois.c:109
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
static __inline void do_xor(uint8_t *buf1, uint8_t *buf2, uint32_t len)
Definition: btrfs_drv.h:1729
Definition: write.c:111
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
unsigned short int uint16_t
Definition: acefiex.h:54
void galois_divpower(uint8_t *data, uint8_t div, uint32_t readlen)
Definition: galois.c:55
uint8_t gpow2(uint8_t e)
Definition: galois.c:69
#define a
Definition: ke_i.h:78
#define b
Definition: ke_i.h:79
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
uint8_t gmul(uint8_t a, uint8_t b)
Definition: galois.c:73
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
static FILE * out
Definition: regtests2xml.c:44
GLdouble GLdouble GLdouble GLdouble q
Definition: gl.h:2063
BYTE uint8_t
Definition: msvideo1.c:66
__u8 sector_size[2]
Definition: mkdosfs.c:361
__u8 sectors[2]
Definition: mkdosfs.c:366
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
UINT32 uint32_t
Definition: types.h:75
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
GLfloat GLfloat p
Definition: glext.h:8902
uint8_t gdiv(uint8_t a, uint8_t b)
Definition: galois.c:80

Referenced by partial_stripe_read(), and read_data_raid6().

◆ read_data()

NTSTATUS read_data ( _In_ device_extension Vcb,
_In_ uint64_t  addr,
_In_ uint32_t  length,
_In_reads_bytes_opt_(length *sizeof(uint32_t)/Vcb->superblock.sector_size) void csum,
_In_ bool  is_tree,
_Out_writes_bytes_(length) uint8_t buf,
_In_opt_ chunk c,
_Out_opt_ chunk **  pc,
_In_opt_ PIRP  Irp,
_In_ uint64_t  generation,
_In_ bool  file_read,
_In_ ULONG  priority 
)

Definition at line 1512 of file read.c.

1514  {
1515  CHUNK_ITEM* ci;
1516  CHUNK_ITEM_STRIPE* cis;
1518  uint64_t type, offset, total_reading = 0;
1519  NTSTATUS Status;
1520  device** devices = NULL;
1521  uint16_t i, startoffstripe, allowed_missing, missing_devices = 0;
1522  uint8_t* dummypage = NULL;
1523  PMDL dummy_mdl = NULL;
1524  bool need_to_wait;
1525  uint64_t lockaddr, locklen;
1526 
1527  if (Vcb->log_to_phys_loaded) {
1528  if (!c) {
1530 
1531  if (!c) {
1532  ERR("get_chunk_from_address failed\n");
1533  return STATUS_INTERNAL_ERROR;
1534  }
1535  }
1536 
1537  ci = c->chunk_item;
1538  offset = c->offset;
1539  devices = c->devices;
1540 
1541  if (pc)
1542  *pc = c;
1543  } else {
1544  LIST_ENTRY* le = Vcb->sys_chunks.Flink;
1545 
1546  ci = NULL;
1547 
1548  c = NULL;
1549  while (le != &Vcb->sys_chunks) {
1551 
1552  if (sc->key.obj_id == 0x100 && sc->key.obj_type == TYPE_CHUNK_ITEM && sc->key.offset <= addr) {
1553  CHUNK_ITEM* chunk_item = sc->data;
1554 
1555  if ((addr - sc->key.offset) < chunk_item->size && chunk_item->num_stripes > 0) {
1556  ci = chunk_item;
1557  offset = sc->key.offset;
1558  cis = (CHUNK_ITEM_STRIPE*)&chunk_item[1];
1559 
1561  if (!devices) {
1562  ERR("out of memory\n");
1564  }
1565 
1566  for (i = 0; i < ci->num_stripes; i++) {
1567  devices[i] = find_device_from_uuid(Vcb, &cis[i].dev_uuid);
1568  }
1569 
1570  break;
1571  }
1572  }
1573 
1574  le = le->Flink;
1575  }
1576 
1577  if (!ci) {
1578  ERR("could not find chunk for %I64x in bootstrap\n", addr);
1579  return STATUS_INTERNAL_ERROR;
1580  }
1581 
1582  if (pc)
1583  *pc = NULL;
1584  }
1585 
1586  if (ci->type & BLOCK_FLAG_DUPLICATE) {
1588  allowed_missing = ci->num_stripes - 1;
1589  } else if (ci->type & BLOCK_FLAG_RAID0) {
1591  allowed_missing = 0;
1592  } else if (ci->type & BLOCK_FLAG_RAID1) {
1594  allowed_missing = 1;
1595  } else if (ci->type & BLOCK_FLAG_RAID10) {
1597  allowed_missing = 1;
1598  } else if (ci->type & BLOCK_FLAG_RAID5) {
1600  allowed_missing = 1;
1601  } else if (ci->type & BLOCK_FLAG_RAID6) {
1603  allowed_missing = 2;
1604  } else if (ci->type & BLOCK_FLAG_RAID1C3) {
1606  allowed_missing = 2;
1607  } else if (ci->type & BLOCK_FLAG_RAID1C4) {
1609  allowed_missing = 3;
1610  } else { // SINGLE
1612  allowed_missing = 0;
1613  }
1614 
1615  cis = (CHUNK_ITEM_STRIPE*)&ci[1];
1616 
1619 
1621  if (!context.stripes) {
1622  ERR("out of memory\n");
1624  }
1625 
1626  if (c && (type == BLOCK_FLAG_RAID5 || type == BLOCK_FLAG_RAID6)) {
1627  get_raid56_lock_range(c, addr, length, &lockaddr, &locklen);
1628  chunk_lock_range(Vcb, c, lockaddr, locklen);
1629  }
1630 
1631  RtlZeroMemory(context.stripes, sizeof(read_data_stripe) * ci->num_stripes);
1632 
1633  context.buflen = length;
1634  context.num_stripes = ci->num_stripes;
1635  context.stripes_left = context.num_stripes;
1636  context.sector_size = Vcb->superblock.sector_size;
1637  context.csum = csum;
1638  context.tree = is_tree;
1639  context.type = type;
1640 
1641  if (type == BLOCK_FLAG_RAID0) {
1642  uint64_t startoff, endoff;
1643  uint16_t endoffstripe, stripe;
1644  uint32_t *stripeoff, pos;
1645  PMDL master_mdl;
1646  PFN_NUMBER* pfns;
1647 
1648  // FIXME - test this still works if page size isn't the same as sector size
1649 
1650  // This relies on the fact that MDLs are followed in memory by the page file numbers,
1651  // so with a bit of jiggery-pokery you can trick your disks into deinterlacing your RAID0
1652  // data for you without doing a memcpy yourself.
1653  // MDLs are officially opaque, so this might very well break in future versions of Windows.
1654 
1655  get_raid0_offset(addr - offset, ci->stripe_length, ci->num_stripes, &startoff, &startoffstripe);
1656  get_raid0_offset(addr + length - offset - 1, ci->stripe_length, ci->num_stripes, &endoff, &endoffstripe);
1657 
1658  if (file_read) {
1659  // Unfortunately we can't avoid doing at least one memcpy, as Windows can give us an MDL
1660  // with duplicated dummy PFNs, which confuse check_csum. Ah well.
1661  // See https://msdn.microsoft.com/en-us/library/windows/hardware/Dn614012.aspx if you're interested.
1662 
1664 
1665  if (!context.va) {
1666  ERR("out of memory\n");
1668  goto exit;
1669  }
1670  } else
1671  context.va = buf;
1672 
1673  master_mdl = IoAllocateMdl(context.va, length, false, false, NULL);
1674  if (!master_mdl) {
1675  ERR("out of memory\n");
1677  goto exit;
1678  }
1679 
1681 
1682  _SEH2_TRY {
1686  } _SEH2_END;
1687 
1688  if (!NT_SUCCESS(Status)) {
1689  ERR("MmProbeAndLockPages threw exception %08lx\n", Status);
1690  IoFreeMdl(master_mdl);
1691  goto exit;
1692  }
1693 
1694  pfns = (PFN_NUMBER*)(master_mdl + 1);
1695 
1696  for (i = 0; i < ci->num_stripes; i++) {
1697  if (startoffstripe > i)
1698  context.stripes[i].stripestart = startoff - (startoff % ci->stripe_length) + ci->stripe_length;
1699  else if (startoffstripe == i)
1700  context.stripes[i].stripestart = startoff;
1701  else
1702  context.stripes[i].stripestart = startoff - (startoff % ci->stripe_length);
1703 
1704  if (endoffstripe > i)
1705  context.stripes[i].stripeend = endoff - (endoff % ci->stripe_length) + ci->stripe_length;
1706  else if (endoffstripe == i)
1707  context.stripes[i].stripeend = endoff + 1;
1708  else
1709  context.stripes[i].stripeend = endoff - (endoff % ci->stripe_length);
1710 
1711  if (context.stripes[i].stripestart != context.stripes[i].stripeend) {
1712  context.stripes[i].mdl = IoAllocateMdl(context.va, (ULONG)(context.stripes[i].stripeend - context.stripes[i].stripestart), false, false, NULL);
1713 
1714  if (!context.stripes[i].mdl) {
1715  ERR("IoAllocateMdl failed\n");
1716  MmUnlockPages(master_mdl);
1717  IoFreeMdl(master_mdl);
1719  goto exit;
1720  }
1721  }
1722  }
1723 
1724  stripeoff = ExAllocatePoolWithTag(NonPagedPool, sizeof(uint32_t) * ci->num_stripes, ALLOC_TAG);
1725  if (!stripeoff) {
1726  ERR("out of memory\n");
1727  MmUnlockPages(master_mdl);
1728  IoFreeMdl(master_mdl);
1730  goto exit;
1731  }
1732 
1733  RtlZeroMemory(stripeoff, sizeof(uint32_t) * ci->num_stripes);
1734 
1735  pos = 0;
1736  stripe = startoffstripe;
1737  while (pos < length) {
1738  PFN_NUMBER* stripe_pfns = (PFN_NUMBER*)(context.stripes[stripe].mdl + 1);
1739 
1740  if (pos == 0) {
1741  uint32_t readlen = (uint32_t)min(context.stripes[stripe].stripeend - context.stripes[stripe].stripestart, ci->stripe_length - (context.stripes[stripe].stripestart % ci->stripe_length));
1742 
1743  RtlCopyMemory(stripe_pfns, pfns, readlen * sizeof(PFN_NUMBER) >> PAGE_SHIFT);
1744 
1745  stripeoff[stripe] += readlen;
1746  pos += readlen;
1747  } else if (length - pos < ci->stripe_length) {
1748  RtlCopyMemory(&stripe_pfns[stripeoff[stripe] >> PAGE_SHIFT], &pfns[pos >> PAGE_SHIFT], (length - pos) * sizeof(PFN_NUMBER) >> PAGE_SHIFT);
1749 
1750  pos = length;
1751  } else {
1752  RtlCopyMemory(&stripe_pfns[stripeoff[stripe] >> PAGE_SHIFT], &pfns[pos >> PAGE_SHIFT], (ULONG)(ci->stripe_length * sizeof(PFN_NUMBER) >> PAGE_SHIFT));
1753 
1754  stripeoff[stripe] += (uint32_t)ci->stripe_length;
1755  pos += (uint32_t)ci->stripe_length;
1756  }
1757 
1758  stripe = (stripe + 1) % ci->num_stripes;
1759  }
1760 
1761  MmUnlockPages(master_mdl);
1762  IoFreeMdl(master_mdl);
1763 
1764  ExFreePool(stripeoff);
1765  } else if (type == BLOCK_FLAG_RAID10) {
1766  uint64_t startoff, endoff;
1767  uint16_t endoffstripe, j, stripe;
1768  ULONG orig_ls;
1769  PMDL master_mdl;
1770  PFN_NUMBER* pfns;
1771  uint32_t* stripeoff, pos;
1772  read_data_stripe** stripes;
1773 
1774  if (c)
1775  orig_ls = c->last_stripe;
1776  else
1777  orig_ls = 0;
1778 
1779  get_raid0_offset(addr - offset, ci->stripe_length, ci->num_stripes / ci->sub_stripes, &startoff, &startoffstripe);
1780  get_raid0_offset(addr + length - offset - 1, ci->stripe_length, ci->num_stripes / ci->sub_stripes, &endoff, &endoffstripe);
1781 
1782  if ((ci->num_stripes % ci->sub_stripes) != 0) {
1783  ERR("chunk %I64x: num_stripes %x was not a multiple of sub_stripes %x!\n", offset, ci->num_stripes, ci->sub_stripes);
1785  goto exit;
1786  }
1787 
1788  if (file_read) {
1790 
1791  if (!context.va) {
1792  ERR("out of memory\n");
1794  goto exit;
1795  }
1796  } else
1797  context.va = buf;
1798 
1799  context.firstoff = (uint16_t)((startoff % ci->stripe_length) / Vcb->superblock.sector_size);
1800  context.startoffstripe = startoffstripe;
1801  context.sectors_per_stripe = (uint16_t)(ci->stripe_length / Vcb->superblock.sector_size);
1802 
1803  startoffstripe *= ci->sub_stripes;
1804  endoffstripe *= ci->sub_stripes;
1805 
1806  if (c)
1807  c->last_stripe = (orig_ls + 1) % ci->sub_stripes;
1808 
1809  master_mdl = IoAllocateMdl(context.va, length, false, false, NULL);
1810  if (!master_mdl) {
1811  ERR("out of memory\n");
1813  goto exit;
1814  }
1815 
1817 
1818  _SEH2_TRY {
1822  } _SEH2_END;
1823 
1824  if (!NT_SUCCESS(Status)) {
1825  ERR("MmProbeAndLockPages threw exception %08lx\n", Status);
1826  IoFreeMdl(master_mdl);
1827  goto exit;
1828  }
1829 
1830  pfns = (PFN_NUMBER*)(master_mdl + 1);
1831 
1833  if (!stripes) {
1834  ERR("out of memory\n");
1835  MmUnlockPages(master_mdl);
1836  IoFreeMdl(master_mdl);
1838  goto exit;
1839  }
1840 
1841  RtlZeroMemory(stripes, sizeof(read_data_stripe*) * ci->num_stripes / ci->sub_stripes);
1842 
1843  for (i = 0; i < ci->num_stripes; i += ci->sub_stripes) {
1844  uint64_t sstart, send;
1845  bool stripeset = false;
1846 
1847  if (startoffstripe > i)
1848  sstart = startoff - (startoff % ci->stripe_length) + ci->stripe_length;
1849  else if (startoffstripe == i)
1850  sstart = startoff;
1851  else
1852  sstart = startoff - (startoff % ci->stripe_length);
1853 
1854  if (endoffstripe > i)
1855  send = endoff - (endoff % ci->stripe_length) + ci->stripe_length;
1856  else if (endoffstripe == i)
1857  send = endoff + 1;
1858  else
1859  send = endoff - (endoff % ci->stripe_length);
1860 
1861  for (j = 0; j < ci->sub_stripes; j++) {
1862  if (j == orig_ls && devices[i+j] && devices[i+j]->devobj) {
1863  context.stripes[i+j].stripestart = sstart;
1864  context.stripes[i+j].stripeend = send;
1865  stripes[i / ci->sub_stripes] = &context.stripes[i+j];
1866 
1867  if (sstart != send) {
1868  context.stripes[i+j].mdl = IoAllocateMdl(context.va, (ULONG)(send - sstart), false, false, NULL);
1869 
1870  if (!context.stripes[i+j].mdl) {
1871  ERR("IoAllocateMdl failed\n");
1872  MmUnlockPages(master_mdl);
1873  IoFreeMdl(master_mdl);
1875  goto exit;
1876  }
1877  }
1878 
1879  stripeset = true;
1880  } else
1881  context.stripes[i+j].status = ReadDataStatus_Skip;
1882  }
1883 
1884  if (!stripeset) {
1885  for (j = 0; j < ci->sub_stripes; j++) {
1886  if (devices[i+j] && devices[i+j]->devobj) {
1887  context.stripes[i+j].stripestart = sstart;
1888  context.stripes[i+j].stripeend = send;
1889  context.stripes[i+j].status = ReadDataStatus_Pending;
1890  stripes[i / ci->sub_stripes] = &context.stripes[i+j];
1891 
1892  if (sstart != send) {
1893  context.stripes[i+j].mdl = IoAllocateMdl(context.va, (ULONG)(send - sstart), false, false, NULL);
1894 
1895  if (!context.stripes[i+j].mdl) {
1896  ERR("IoAllocateMdl failed\n");
1897  MmUnlockPages(master_mdl);
1898  IoFreeMdl(master_mdl);
1900  goto exit;
1901  }
1902  }
1903 
1904  stripeset = true;
1905  break;
1906  }
1907  }
1908 
1909  if (!stripeset) {
1910  ERR("could not find stripe to read\n");
1912  goto exit;
1913  }
1914  }
1915  }
1916 
1917  stripeoff = ExAllocatePoolWithTag(NonPagedPool, sizeof(uint32_t) * ci->num_stripes / ci->sub_stripes, ALLOC_TAG);
1918  if (!stripeoff) {
1919  ERR("out of memory\n");
1920  MmUnlockPages(master_mdl);
1921  IoFreeMdl(master_mdl);
1923  goto exit;
1924  }
1925 
1926  RtlZeroMemory(stripeoff, sizeof(uint32_t) * ci->num_stripes / ci->sub_stripes);
1927 
1928  pos = 0;
1929  stripe = startoffstripe / ci->sub_stripes;
1930  while (pos < length) {
1931  PFN_NUMBER* stripe_pfns = (PFN_NUMBER*)(stripes[stripe]->mdl + 1);
1932 
1933  if (pos == 0) {
1934  uint32_t readlen = (uint32_t)min(stripes[stripe]->stripeend - stripes[stripe]->stripestart,
1935  ci->stripe_length - (stripes[stripe]->stripestart % ci->stripe_length));
1936 
1937  RtlCopyMemory(stripe_pfns, pfns, readlen * sizeof(PFN_NUMBER) >> PAGE_SHIFT);
1938 
1939  stripeoff[stripe] += readlen;
1940  pos += readlen;
1941  } else if (length - pos < ci->stripe_length) {
1942  RtlCopyMemory(&stripe_pfns[stripeoff[stripe] >> PAGE_SHIFT], &pfns[pos >> PAGE_SHIFT], (length - pos) * sizeof(PFN_NUMBER) >> PAGE_SHIFT);
1943 
1944  pos = length;
1945  } else {
1946  RtlCopyMemory(&stripe_pfns[stripeoff[stripe] >> PAGE_SHIFT], &pfns[pos >> PAGE_SHIFT], (ULONG)(ci->stripe_length * sizeof(PFN_NUMBER) >> PAGE_SHIFT));
1947 
1948  stripeoff[stripe] += (ULONG)ci->stripe_length;
1949  pos += (ULONG)ci->stripe_length;
1950  }
1951 
1952  stripe = (stripe + 1) % (ci->num_stripes / ci->sub_stripes);
1953  }
1954 
1955  MmUnlockPages(master_mdl);
1956  IoFreeMdl(master_mdl);
1957 
1958  ExFreePool(stripeoff);
1959  ExFreePool(stripes);
1960  } else if (type == BLOCK_FLAG_DUPLICATE) {
1961  uint64_t orig_ls;
1962 
1963  if (c)
1964  orig_ls = i = c->last_stripe;
1965  else
1966  orig_ls = i = 0;
1967 
1968  while (!devices[i] || !devices[i]->devobj) {
1969  i = (i + 1) % ci->num_stripes;
1970 
1971  if (i == orig_ls) {
1972  ERR("no devices available to service request\n");
1974  goto exit;
1975  }
1976  }
1977 
1978  if (c)
1979  c->last_stripe = (i + 1) % ci->num_stripes;
1980 
1981  context.stripes[i].stripestart = addr - offset;
1982  context.stripes[i].stripeend = context.stripes[i].stripestart + length;
1983 
1984  if (file_read) {
1986 
1987  if (!context.va) {
1988  ERR("out of memory\n");
1990  goto exit;
1991  }
1992 
1993  context.stripes[i].mdl = IoAllocateMdl(context.va, length, false, false, NULL);
1994  if (!context.stripes[i].mdl) {
1995  ERR("IoAllocateMdl failed\n");
1997  goto exit;
1998  }
1999 
2000  MmBuildMdlForNonPagedPool(context.stripes[i].mdl);
2001  } else {
2002  context.stripes[i].mdl = IoAllocateMdl(buf, length, false, false, NULL);
2003 
2004  if (!context.stripes[i].mdl) {
2005  ERR("IoAllocateMdl failed\n");
2007  goto exit;
2008  }
2009 
2011 
2012  _SEH2_TRY {
2016  } _SEH2_END;
2017 
2018  if (!NT_SUCCESS(Status)) {
2019  ERR("MmProbeAndLockPages threw exception %08lx\n", Status);
2020  goto exit;
2021  }
2022  }
2023  } else if (type == BLOCK_FLAG_RAID5) {
2024  uint64_t startoff, endoff;
2025  uint16_t endoffstripe, parity;
2026  uint32_t *stripeoff, pos;
2027  PMDL master_mdl;
2028  PFN_NUMBER *pfns, dummy;
2029  bool need_dummy = false;
2030 
2031  get_raid0_offset(addr - offset, ci->stripe_length, ci->num_stripes - 1, &startoff, &startoffstripe);
2032  get_raid0_offset(addr + length - offset - 1, ci->stripe_length, ci->num_stripes - 1, &endoff, &endoffstripe);
2033 
2034  if (file_read) {
2036 
2037  if (!context.va) {
2038  ERR("out of memory\n");
2040  goto exit;
2041  }
2042  } else
2043  context.va = buf;
2044 
2045  master_mdl = IoAllocateMdl(context.va, length, false, false, NULL);
2046  if (!master_mdl) {
2047  ERR("out of memory\n");
2049  goto exit;
2050  }
2051 
2053 
2054  _SEH2_TRY {
2058  } _SEH2_END;
2059 
2060  if (!NT_SUCCESS(Status)) {
2061  ERR("MmProbeAndLockPages threw exception %08lx\n", Status);
2062  IoFreeMdl(master_mdl);
2063  goto exit;
2064  }
2065 
2066  pfns = (PFN_NUMBER*)(master_mdl + 1);
2067 
2068  pos = 0;
2069  while (pos < length) {
2070  parity = (((addr - offset + pos) / ((ci->num_stripes - 1) * ci->stripe_length)) + ci->num_stripes - 1) % ci->num_stripes;
2071 
2072  if (pos == 0) {
2073  uint16_t stripe = (parity + startoffstripe + 1) % ci->num_stripes;
2074  ULONG skip, readlen;
2075 
2076  i = startoffstripe;
2077  while (stripe != parity) {
2078  if (i == startoffstripe) {
2079  readlen = min(length, (ULONG)(ci->stripe_length - (startoff % ci->stripe_length)));
2080 
2081  context.stripes[stripe].stripestart = startoff;
2082  context.stripes[stripe].stripeend = startoff + readlen;
2083 
2084  pos += readlen;
2085 
2086  if (pos == length)
2087  break;
2088  } else {
2089  readlen = min(length - pos, (ULONG)ci->stripe_length);
2090 
2091  context.stripes[stripe].stripestart = startoff - (startoff % ci->stripe_length);
2092  context.stripes[stripe].stripeend = context.stripes[stripe].stripestart + readlen;
2093 
2094  pos += readlen;
2095 
2096  if (pos == length)
2097  break;
2098  }
2099 
2100  i++;
2101  stripe = (stripe + 1) % ci->num_stripes;
2102  }
2103 
2104  if (pos == length)
2105  break;
2106 
2107  for (i = 0; i < startoffstripe; i++) {
2108  uint16_t stripe2 = (parity + i + 1) % ci->num_stripes;
2109 
2110  context.stripes[stripe2].stripestart = context.stripes[stripe2].stripeend = startoff - (startoff % ci->stripe_length) + ci->stripe_length;
2111  }
2112 
2113  context.stripes[parity].stripestart = context.stripes[parity].stripeend = startoff - (startoff % ci->stripe_length) + ci->stripe_length;
2114 
2115  if (length - pos > ci->num_stripes * (ci->num_stripes - 1) * ci->stripe_length) {
2116  skip = (ULONG)(((length - pos) / (ci->num_stripes * (ci->num_stripes - 1) * ci->stripe_length)) - 1);
2117 
2118  for (i = 0; i < ci->num_stripes; i++) {
2119  context.stripes[i].stripeend += skip * ci->num_stripes * ci->stripe_length;
2120  }
2121 
2122  pos += (uint32_t)(skip * (ci->num_stripes - 1) * ci->num_stripes * ci->stripe_length);
2123  need_dummy = true;
2124  }
2125  } else if (length - pos >= ci->stripe_length * (ci->num_stripes - 1)) {
2126  for (i = 0; i < ci->num_stripes; i++) {
2127  context.stripes[i].stripeend += ci->stripe_length;
2128  }
2129 
2130  pos += (uint32_t)(ci->stripe_length * (ci->num_stripes - 1));
2131  need_dummy = true;
2132  } else {
2133  uint16_t stripe = (parity + 1) % ci->num_stripes;
2134 
2135  i = 0;
2136  while (stripe != parity) {
2137  if (endoffstripe == i) {
2138  context.stripes[stripe].stripeend = endoff + 1;
2139  break;
2140  } else if (endoffstripe > i)
2141  context.stripes[stripe].stripeend = endoff - (endoff % ci->stripe_length) + ci->stripe_length;
2142 
2143  i++;
2144  stripe = (stripe + 1) % ci->num_stripes;
2145  }
2146 
2147  break;
2148  }
2149  }
2150 
2151  for (i = 0; i < ci->num_stripes; i++) {
2152  if (context.stripes[i].stripestart != context.stripes[i].stripeend) {
2153  context.stripes[i].mdl = IoAllocateMdl(context.va, (ULONG)(context.stripes[i].stripeend - context.stripes[i].stripestart),
2154  false, false, NULL);
2155 
2156  if (!context.stripes[i].mdl) {
2157  ERR("IoAllocateMdl failed\n");
2158  MmUnlockPages(master_mdl);
2159  IoFreeMdl(master_mdl);
2161  goto exit;
2162  }
2163  }
2164  }
2165 
2166  if (need_dummy) {
2168  if (!dummypage) {
2169  ERR("out of memory\n");
2170  MmUnlockPages(master_mdl);
2171  IoFreeMdl(master_mdl);
2173  goto exit;
2174  }
2175 
2176  dummy_mdl = IoAllocateMdl(dummypage, PAGE_SIZE, false, false, NULL);
2177  if (!dummy_mdl) {
2178  ERR("IoAllocateMdl failed\n");
2179  MmUnlockPages(master_mdl);
2180  IoFreeMdl(master_mdl);
2182  goto exit;
2183  }
2184 
2185  MmBuildMdlForNonPagedPool(dummy_mdl);
2186 
2187  dummy = *(PFN_NUMBER*)(dummy_mdl + 1);
2188  }
2189 
2190  stripeoff = ExAllocatePoolWithTag(NonPagedPool, sizeof(uint32_t) * ci->num_stripes, ALLOC_TAG);
2191  if (!stripeoff) {
2192  ERR("out of memory\n");
2193  MmUnlockPages(master_mdl);
2194  IoFreeMdl(master_mdl);
2196  goto exit;
2197  }
2198 
2199  RtlZeroMemory(stripeoff, sizeof(uint32_t) * ci->num_stripes);
2200 
2201  pos = 0;
2202 
2203  while (pos < length) {
2204  PFN_NUMBER* stripe_pfns;
2205 
2206  parity = (((addr - offset + pos) / ((ci->num_stripes - 1) * ci->stripe_length)) + ci->num_stripes - 1) % ci->num_stripes;
2207 
2208  if (pos == 0) {
2209  uint16_t stripe = (parity + startoffstripe + 1) % ci->num_stripes;
2210  uint32_t readlen = min(length - pos, (uint32_t)min(context.stripes[stripe].stripeend - context.stripes[stripe].stripestart,
2211  ci->stripe_length - (context.stripes[stripe].stripestart % ci->stripe_length)));
2212 
2213  stripe_pfns = (PFN_NUMBER*)(context.stripes[stripe].mdl + 1);
2214 
2215  RtlCopyMemory(stripe_pfns, pfns, readlen * sizeof(PFN_NUMBER) >> PAGE_SHIFT);
2216 
2217  stripeoff[stripe] = readlen;
2218  pos += readlen;
2219 
2220  stripe = (stripe + 1) % ci->num_stripes;
2221 
2222  while (stripe != parity) {
2223  stripe_pfns = (PFN_NUMBER*)(context.stripes[stripe].mdl + 1);
2224  readlen = min(length - pos, (uint32_t)min(context.stripes[stripe].stripeend - context.stripes[stripe].stripestart, ci->stripe_length));
2225 
2226  if (readlen == 0)
2227  break;
2228 
2229  RtlCopyMemory(stripe_pfns, &pfns[pos >> PAGE_SHIFT], readlen * sizeof(PFN_NUMBER) >> PAGE_SHIFT);
2230 
2231  stripeoff[stripe] = readlen;
2232  pos += readlen;
2233 
2234  stripe = (stripe + 1) % ci->num_stripes;
2235  }
2236  } else if (length - pos >= ci->stripe_length * (ci->num_stripes - 1)) {
2237  uint16_t stripe = (parity + 1) % ci->num_stripes;
2238  ULONG k;
2239 
2240  while (stripe != parity) {
2241  stripe_pfns = (PFN_NUMBER*)(context.stripes[stripe].mdl + 1);
2242 
2243  RtlCopyMemory(&stripe_pfns[stripeoff[stripe] >> PAGE_SHIFT], &pfns[pos >> PAGE_SHIFT], (ULONG)(ci->stripe_length * sizeof(PFN_NUMBER) >> PAGE_SHIFT));
2244 
2245  stripeoff[stripe] += (uint32_t)ci->stripe_length;
2246  pos += (uint32_t)ci->stripe_length;
2247 
2248  stripe = (stripe + 1) % ci->num_stripes;
2249  }
2250 
2251  stripe_pfns = (PFN_NUMBER*)(context.stripes[parity].mdl + 1);
2252 
2253  for (k = 0; k < ci->stripe_length >> PAGE_SHIFT; k++) {
2254  stripe_pfns[stripeoff[parity] >> PAGE_SHIFT] = dummy;
2255  stripeoff[parity] += PAGE_SIZE;
2256  }
2257  } else {
2258  uint16_t stripe = (parity + 1) % ci->num_stripes;
2259  uint32_t readlen;
2260 
2261  while (pos < length) {
2262  stripe_pfns = (PFN_NUMBER*)(context.stripes[stripe].mdl + 1);
2263  readlen = min(length - pos, (ULONG)min(context.stripes[stripe].stripeend - context.stripes[stripe].stripestart, ci->stripe_length));
2264 
2265  if (readlen == 0)
2266  break;
2267 
2268  RtlCopyMemory(&stripe_pfns[stripeoff[stripe] >> PAGE_SHIFT], &pfns[pos >> PAGE_SHIFT], readlen * sizeof(PFN_NUMBER) >> PAGE_SHIFT);
2269 
2270  stripeoff[stripe] += readlen;
2271  pos += readlen;
2272 
2273  stripe = (stripe + 1) % ci->num_stripes;
2274  }
2275  }
2276  }
2277 
2278  MmUnlockPages(master_mdl);
2279  IoFreeMdl(master_mdl);
2280 
2281  ExFreePool(stripeoff);
2282  } else if (type == BLOCK_FLAG_RAID6) {
2283  uint64_t startoff, endoff;
2284  uint16_t endoffstripe, parity1;
2285  uint32_t *stripeoff, pos;
2286  PMDL master_mdl;
2287  PFN_NUMBER *pfns, dummy;
2288  bool need_dummy = false;
2289 
2290  get_raid0_offset(addr - offset, ci->stripe_length, ci->num_stripes - 2, &startoff, &startoffstripe);
2291  get_raid0_offset(addr + length - offset - 1, ci->stripe_length, ci->num_stripes - 2, &endoff, &endoffstripe);
2292 
2293  if (file_read) {
2295 
2296  if (!context.va) {
2297  ERR("out of memory\n");
2299  goto exit;
2300  }
2301  } else
2302  context.va = buf;
2303 
2304  master_mdl = IoAllocateMdl(context.va, length, false, false, NULL);
2305  if (!master_mdl) {
2306  ERR("out of memory\n");
2308  goto exit;
2309  }
2310 
2312 
2313  _SEH2_TRY {
2317  } _SEH2_END;
2318 
2319  if (!NT_SUCCESS(Status)) {
2320  ERR("MmProbeAndLockPages threw exception %08lx\n", Status);
2321  IoFreeMdl(master_mdl);
2322  goto exit;
2323  }
2324 
2325  pfns = (PFN_NUMBER*)(master_mdl + 1);
2326 
2327  pos = 0;
2328  while (pos < length) {
2329  parity1 = (((addr - offset + pos) / ((ci->num_stripes - 2) * ci->stripe_length)) + ci->num_stripes - 2) % ci->num_stripes;
2330 
2331  if (pos == 0) {
2332  uint16_t stripe = (parity1 + startoffstripe + 2) % ci->num_stripes, parity2;
2333  ULONG skip, readlen;
2334 
2335  i = startoffstripe;
2336  while (stripe != parity1) {
2337  if (i == startoffstripe) {
2338  readlen = (ULONG)min(length, ci->stripe_length - (startoff % ci->stripe_length));
2339 
2340  context.stripes[stripe].stripestart = startoff;
2341  context.stripes[stripe].stripeend = startoff + readlen;
2342 
2343  pos += readlen;
2344 
2345  if (pos == length)
2346  break;
2347  } else {
2348  readlen = min(length - pos, (ULONG)ci->stripe_length);
2349 
2350  context.stripes[stripe].stripestart = startoff - (startoff % ci->stripe_length);
2351  context.stripes[stripe].stripeend = context.stripes[stripe].stripestart + readlen;
2352 
2353  pos += readlen;
2354 
2355  if (pos == length)
2356  break;
2357  }
2358 
2359  i++;
2360  stripe = (stripe + 1) % ci->num_stripes;
2361  }
2362 
2363  if (pos == length)
2364  break;
2365 
2366  for (i = 0; i < startoffstripe; i++) {
2367  uint16_t stripe2 = (parity1 + i + 2) % ci->num_stripes;
2368 
2369  context.stripes[stripe2].stripestart = context.stripes[stripe2].stripeend = startoff - (startoff % ci->stripe_length) + ci->stripe_length;
2370  }
2371 
2372  context.stripes[parity1].stripestart = context.stripes[parity1].stripeend = startoff - (startoff % ci->stripe_length) + ci->stripe_length;
2373 
2374  parity2 = (parity1 + 1) % ci->num_stripes;
2375  context.stripes[parity2].stripestart = context.stripes[parity2].stripeend = startoff - (startoff % ci->stripe_length) + ci->stripe_length;
2376 
2377  if (length - pos > ci->num_stripes * (ci->num_stripes - 2) * ci->stripe_length) {
2378  skip = (ULONG)(((length - pos) / (ci->num_stripes * (ci->num_stripes - 2) * ci->stripe_length)) - 1);
2379 
2380  for (i = 0; i < ci->num_stripes; i++) {
2381  context.stripes[i].stripeend += skip * ci->num_stripes * ci->stripe_length;
2382  }
2383 
2384  pos += (uint32_t)(skip * (ci->num_stripes - 2) * ci->num_stripes * ci->stripe_length);
2385  need_dummy = true;
2386  }
2387  } else if (length - pos >= ci->stripe_length * (ci->num_stripes - 2)) {
2388  for (i = 0; i < ci->num_stripes; i++) {
2389  context.stripes[i].stripeend += ci->stripe_length;
2390  }
2391 
2392  pos += (uint32_t)(ci->stripe_length * (ci->num_stripes - 2));
2393  need_dummy = true;
2394  } else {
2395  uint16_t stripe = (parity1 + 2) % ci->num_stripes;
2396 
2397  i = 0;
2398  while (stripe != parity1) {
2399  if (endoffstripe == i) {
2400  context.stripes[stripe].stripeend = endoff + 1;
2401  break;
2402  } else if (endoffstripe > i)
2403  context.stripes[stripe].stripeend = endoff - (endoff % ci->stripe_length) + ci->stripe_length;
2404 
2405  i++;
2406  stripe = (stripe + 1) % ci->num_stripes;
2407  }
2408 
2409  break;
2410  }
2411  }
2412 
2413  for (i = 0; i < ci->num_stripes; i++) {
2414  if (context.stripes[i].stripestart != context.stripes[i].stripeend) {
2415  context.stripes[i].mdl = IoAllocateMdl(context.va, (ULONG)(context.stripes[i].stripeend - context.stripes[i].stripestart), false, false, NULL);
2416 
2417  if (!context.stripes[i].mdl) {
2418  ERR("IoAllocateMdl failed\n");
2419  MmUnlockPages(master_mdl);
2420  IoFreeMdl(master_mdl);
2422  goto exit;
2423  }
2424  }
2425  }
2426 
2427  if (need_dummy) {
2429  if (!dummypage) {
2430  ERR("out of memory\n");
2431  MmUnlockPages(master_mdl);
2432  IoFreeMdl(master_mdl);
2434  goto exit;
2435  }
2436 
2437  dummy_mdl = IoAllocateMdl(dummypage, PAGE_SIZE, false, false, NULL);
2438  if (!dummy_mdl) {
2439  ERR("IoAllocateMdl failed\n");
2440  MmUnlockPages(master_mdl);
2441  IoFreeMdl(master_mdl);
2443  goto exit;
2444  }
2445 
2446  MmBuildMdlForNonPagedPool(dummy_mdl);
2447 
2448  dummy = *(PFN_NUMBER*)(dummy_mdl + 1);
2449  }
2450 
2451  stripeoff = ExAllocatePoolWithTag(NonPagedPool, sizeof(uint32_t) * ci->num_stripes, ALLOC_TAG);
2452  if (!stripeoff) {
2453  ERR("out of memory\n");
2454  MmUnlockPages(master_mdl);
2455  IoFreeMdl(master_mdl);
2457  goto exit;
2458  }
2459 
2460  RtlZeroMemory(stripeoff, sizeof(uint32_t) * ci->num_stripes);
2461 
2462  pos = 0;
2463 
2464  while (pos < length) {
2465  PFN_NUMBER* stripe_pfns;
2466 
2467  parity1 = (((addr - offset + pos) / ((ci->num_stripes - 2) * ci->stripe_length)) + ci->num_stripes - 2) % ci->num_stripes;
2468 
2469  if (pos == 0) {
2470  uint16_t stripe = (parity1 + startoffstripe + 2) % ci->num_stripes;
2471  uint32_t readlen = min(length - pos, (uint32_t)min(context.stripes[stripe].stripeend - context.stripes[stripe].stripestart,
2472  ci->stripe_length - (context.stripes[stripe].stripestart % ci->stripe_length)));
2473 
2474  stripe_pfns = (PFN_NUMBER*)(context.stripes[stripe].mdl + 1);
2475 
2476  RtlCopyMemory(stripe_pfns, pfns, readlen * sizeof(PFN_NUMBER) >> PAGE_SHIFT);
2477 
2478  stripeoff[stripe] = readlen;
2479  pos += readlen;
2480 
2481  stripe = (stripe + 1) % ci->num_stripes;
2482 
2483  while (stripe != parity1) {
2484  stripe_pfns = (PFN_NUMBER*)(context.stripes[stripe].mdl + 1);
2485  readlen = (uint32_t)min(length - pos, min(context.stripes[stripe].stripeend - context.stripes[stripe].stripestart, ci->stripe_length));
2486 
2487  if (readlen == 0)
2488  break;
2489 
2490  RtlCopyMemory(stripe_pfns, &pfns[pos >> PAGE_SHIFT], readlen * sizeof(PFN_NUMBER) >> PAGE_SHIFT);
2491 
2492  stripeoff[stripe] = readlen;
2493  pos += readlen;
2494 
2495  stripe = (stripe + 1) % ci->num_stripes;
2496  }
2497  } else if (length - pos >= ci->stripe_length * (ci->num_stripes - 2)) {
2498  uint16_t stripe = (parity1 + 2) % ci->num_stripes;
2499  uint16_t parity2 = (parity1 + 1) % ci->num_stripes;
2500  ULONG k;
2501 
2502  while (stripe != parity1) {
2503  stripe_pfns = (PFN_NUMBER*)(context.stripes[stripe].mdl + 1);
2504 
2505  RtlCopyMemory(&stripe_pfns[stripeoff[stripe] >> PAGE_SHIFT], &pfns[pos >> PAGE_SHIFT], (ULONG)(ci->stripe_length * sizeof(PFN_NUMBER) >> PAGE_SHIFT));
2506 
2507  stripeoff[stripe] += (uint32_t)ci->stripe_length;
2508  pos += (uint32_t)ci->stripe_length;
2509 
2510  stripe = (stripe + 1) % ci->num_stripes;
2511  }
2512 
2513  stripe_pfns = (PFN_NUMBER*)(context.stripes[parity1].mdl + 1);
2514 
2515  for (k = 0; k < ci->stripe_length >> PAGE_SHIFT; k++) {
2516  stripe_pfns[stripeoff[parity1] >> PAGE_SHIFT] = dummy;
2517  stripeoff[parity1] += PAGE_SIZE;
2518  }
2519 
2520  stripe_pfns = (PFN_NUMBER*)(context.stripes[parity2].mdl + 1);
2521 
2522  for (k = 0; k < ci->stripe_length >> PAGE_SHIFT; k++) {
2523  stripe_pfns[stripeoff[parity2] >> PAGE_SHIFT] = dummy;
2524  stripeoff[parity2] += PAGE_SIZE;
2525  }
2526  } else {
2527  uint16_t stripe = (parity1 + 2) % ci->num_stripes;
2528  uint32_t readlen;
2529 
2530  while (pos < length) {
2531  stripe_pfns = (PFN_NUMBER*)(context.stripes[stripe].mdl + 1);
2532  readlen = (uint32_t)min(length - pos, min(context.stripes[stripe].stripeend - context.stripes[stripe].stripestart, ci->stripe_length));
2533 
2534  if (readlen == 0)
2535  break;
2536 
2537  RtlCopyMemory(&stripe_pfns[stripeoff[stripe] >> PAGE_SHIFT], &pfns[pos >> PAGE_SHIFT], readlen * sizeof(PFN_NUMBER) >> PAGE_SHIFT);
2538 
2539  stripeoff[stripe] += readlen;
2540  pos += readlen;
2541 
2542  stripe = (stripe + 1) % ci->num_stripes;
2543  }
2544  }
2545  }
2546 
2547  MmUnlockPages(master_mdl);
2548  IoFreeMdl(master_mdl);
2549 
2550  ExFreePool(stripeoff);
2551  }
2552 
2553  context.address = addr;
2554 
2555  for (i = 0; i < ci->num_stripes; i++) {
2556  if (!devices[i] || !devices[i]->devobj || context.stripes[i].stripestart == context.stripes[i].stripeend) {
2557  context.stripes[i].status = ReadDataStatus_MissingDevice;
2558  context.stripes_left--;
2559 
2560  if (!devices[i] || !devices[i]->devobj)
2561  missing_devices++;
2562  }
2563  }
2564 
2565  if (missing_devices > allowed_missing) {
2566  ERR("not enough devices to service request (%u missing)\n", missing_devices);
2568  goto exit;
2569  }
2570 
2571  for (i = 0; i < ci->num_stripes; i++) {
2573 
2574  if (devices[i] && devices[i]->devobj && context.stripes[i].stripestart != context.stripes[i].stripeend && context.stripes[i].status != ReadDataStatus_Skip) {
2575  context.stripes[i].context = (struct read_data_context*)&context;
2576 
2577  if (type == BLOCK_FLAG_RAID10) {
2578  context.stripes[i].stripenum = i / ci->sub_stripes;
2579  }
2580 
2581  if (!Irp) {
2582  context.stripes[i].Irp = IoAllocateIrp(devices[i]->devobj->StackSize, false);
2583 
2584  if (!context.stripes[i].Irp) {
2585  ERR("IoAllocateIrp failed\n");
2587  goto exit;
2588  }
2589  } else {
2590  context.stripes[i].Irp = IoMakeAssociatedIrp(Irp, devices[i]->devobj->StackSize);
2591 
2592  if (!context.stripes[i].Irp) {
2593  ERR("IoMakeAssociatedIrp failed\n");
2595  goto exit;
2596  }
2597  }
2598 
2599  IrpSp = IoGetNextIrpStackLocation(context.stripes[i].Irp);
2602  IrpSp->FileObject = devices[i]->fileobj;
2603 
2604  if (devices[i]->devobj->Flags & DO_BUFFERED_IO) {
2605  context.stripes[i].Irp->AssociatedIrp.SystemBuffer = ExAllocatePoolWithTag(NonPagedPool, (ULONG)(context.stripes[i].stripeend - context.stripes[i].stripestart), ALLOC_TAG);
2606  if (!context.stripes[i].Irp->AssociatedIrp.SystemBuffer) {
2607  ERR("out of memory\n");
2609  goto exit;
2610  }
2611 
2613 
2614  context.stripes[i].Irp->UserBuffer = MmGetSystemAddressForMdlSafe(context.stripes[i].mdl, priority);
2615  } else if (devices[i]->devobj->Flags & DO_DIRECT_IO)
2616  context.stripes[i].Irp->MdlAddress = context.stripes[i].mdl;
2617  else
2618  context.stripes[i].Irp->UserBuffer = MmGetSystemAddressForMdlSafe(context.stripes[i].mdl, priority);
2619 
2620  IrpSp->Parameters.Read.Length = (ULONG)(context.stripes[i].stripeend - context.stripes[i].stripestart);
2621  IrpSp->Parameters.Read.ByteOffset.QuadPart = context.stripes[i].stripestart + cis[i].offset;
2622 
2623  total_reading += IrpSp->Parameters.Read.Length;
2624 
2625  context.stripes[i].Irp->UserIosb = &context.stripes[i].iosb;
2626 
2627  IoSetCompletionRoutine(context.stripes[i].Irp, read_data_completion, &context.stripes[i], true, true, true);
2628 
2629  context.stripes[i].status = ReadDataStatus_Pending;
2630  }
2631  }
2632 
2633  need_to_wait = false;
2634  for (i = 0; i < ci->num_stripes; i++) {
2635  if (context.stripes[i].status != ReadDataStatus_MissingDevice && context.stripes[i].status != ReadDataStatus_Skip) {
2636  IoCallDriver(devices[i]->devobj, context.stripes[i].Irp);
2637  need_to_wait = true;
2638  }
2639  }
2640 
2641  if (need_to_wait)
2643 
2644  if (diskacc)
2645  fFsRtlUpdateDiskCounters(total_reading, 0);
2646 
2647  // check if any of the devices return a "user-induced" error
2648 
2649  for (i = 0; i < ci->num_stripes; i++) {
2650  if (context.stripes[i].status == ReadDataStatus_Error && IoIsErrorUserInduced(context.stripes[i].iosb.Status)) {
2651  Status = context.stripes[i].iosb.Status;
2652  goto exit;
2653  }
2654  }
2655 
2656  if (type == BLOCK_FLAG_RAID0) {
2657  Status = read_data_raid0(Vcb, file_read ? context.va : buf, addr, length, &context, ci, devices, generation, offset);
2658  if (!NT_SUCCESS(Status)) {
2659  ERR("read_data_raid0 returned %08lx\n", Status);
2660 
2661  if (file_read)
2662  ExFreePool(context.va);
2663 
2664  goto exit;
2665  }
2666 
2667  if (file_read) {
2669  ExFreePool(context.va);
2670  }
2671  } else if (type == BLOCK_FLAG_RAID10) {
2672  Status = read_data_raid10(Vcb, file_read ? context.va : buf, addr, length, &context, ci, devices, generation, offset);
2673 
2674  if (!NT_SUCCESS(Status)) {
2675  ERR("read_data_raid10 returned %08lx\n", Status);
2676 
2677  if (file_read)
2678  ExFreePool(context.va);
2679 
2680  goto exit;
2681  }
2682 
2683  if (file_read) {
2685  ExFreePool(context.va);
2686  }
2687  } else if (type == BLOCK_FLAG_DUPLICATE) {
2688  Status = read_data_dup(Vcb, file_read ? context.va : buf, addr, &context, ci, devices, generation);
2689  if (!NT_SUCCESS(Status)) {
2690  ERR("read_data_dup returned %08lx\n", Status);
2691 
2692  if (file_read)
2693  ExFreePool(context.va);
2694 
2695  goto exit;
2696  }
2697 
2698  if (file_read) {
2700  ExFreePool(context.va);
2701  }
2702  } else if (type == BLOCK_FLAG_RAID5) {
2703  Status = read_data_raid5(Vcb, file_read ? context.va : buf, addr, length, &context, ci, devices, offset, generation, c, missing_devices > 0 ? true : false);
2704  if (!NT_SUCCESS(Status)) {
2705  ERR("read_data_raid5 returned %08lx\n", Status);
2706 
2707  if (file_read)
2708  ExFreePool(context.va);
2709 
2710  goto exit;
2711  }
2712 
2713  if (file_read) {
2715  ExFreePool(context.va);
2716  }
2717  } else if (type == BLOCK_FLAG_RAID6) {
2718  Status = read_data_raid6(Vcb, file_read ? context.va : buf, addr, length, &context, ci, devices, offset, generation, c, missing_devices > 0 ? true : false);
2719  if (!NT_SUCCESS(Status)) {
2720  ERR("read_data_raid6 returned %08lx\n", Status);
2721 
2722  if (file_read)
2723  ExFreePool(context.va);
2724 
2725  goto exit;
2726  }
2727 
2728  if (file_read) {
2730  ExFreePool(context.va);
2731  }
2732  }
2733 
2734 exit:
2735  if (c && (type == BLOCK_FLAG_RAID5 || type == BLOCK_FLAG_RAID6))
2736  chunk_unlock_range(Vcb, c, lockaddr, locklen);
2737 
2738  if (dummy_mdl)
2739  IoFreeMdl(dummy_mdl);
2740 
2741  if (dummypage)
2742  ExFreePool(dummypage);
2743 
2744  for (i = 0; i < ci->num_stripes; i++) {
2745  if (context.stripes[i].mdl) {
2746  if (context.stripes[i].mdl->MdlFlags & MDL_PAGES_LOCKED)
2747  MmUnlockPages(context.stripes[i].mdl);
2748 
2749  IoFreeMdl(context.stripes[i].mdl);
2750  }
2751 
2752  if (context.stripes[i].Irp)
2753  IoFreeIrp(context.stripes[i].Irp);
2754  }
2755 
2756  ExFreePool(context.stripes);
2757 
2758  if (!Vcb->log_to_phys_loaded)
2760 
2761  return Status;
2762 }
uint64_t obj_id
Definition: btrfs.h:137
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
uint8_t obj_type
Definition: btrfs.h:138
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
uint16_t sub_stripes
Definition: btrfs.h:336
Definition: http.c:7094
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
_In_ PIRP Irp
Definition: csq.h:116
const char * devices
Definition: diskspace.c:793
VOID NTAPI MmBuildMdlForNonPagedPool(IN PMDL Mdl)
Definition: mdlsup.c:428
#define IoIsErrorUserInduced(Status)
Definition: iofuncs.h:2813
#define TYPE_CHUNK_ITEM
Definition: btrfs.h:44
LONG NTSTATUS
Definition: precomp.h:26
GLintptr offset
Definition: glext.h:5920
Definition: write.c:111
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
void get_raid56_lock_range(chunk *c, uint64_t address, uint64_t length, uint64_t *lockaddr, uint64_t *locklen)
Definition: write.c:2166
uint64_t stripe_length
Definition: btrfs.h:330
VOID NTAPI MmUnlockPages(IN PMDL Mdl)
Definition: mdlsup.c:1439
unsigned short int uint16_t
Definition: acefiex.h:54
#define uint16_t
Definition: nsiface.idl:60
#define MmGetSystemAddressForMdlSafe(_Mdl, _Priority)
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
uint64_t offset
Definition: btrfs.h:139
_Post_satisfies_ static stripe __inline void get_raid0_offset(_In_ uint64_t off, _In_ uint64_t stripe_length, _In_ uint16_t num_stripes, _Out_ uint64_t *stripeoff, _Out_ uint16_t *stripe)
Definition: btrfs_drv.h:1005
#define DO_DIRECT_IO
Definition: env_spec_w32.h:396
_SEH2_TRY
Definition: create.c:4226
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:498
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
#define ALLOC_TAG
Definition: btrfs_drv.h:91
uint64_t offset
Definition: btrfs.h:341
uint64_t size
Definition: btrfs.h:328
while(1)
Definition: macro.lex.yy.c:740
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
ULONG PFN_NUMBER
Definition: ke.h:8
Definition: devices.h:37
void chunk_unlock_range(_In_ device_extension *Vcb, _In_ chunk *c, _In_ uint64_t start, _In_ uint64_t length)
Definition: btrfs.c:5794
#define BLOCK_FLAG_RAID1C3
Definition: btrfs.h:83
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
smooth NULL
Definition: ftsmooth.c:416
static NTSTATUS read_data_dup(device_extension *Vcb, uint8_t *buf, uint64_t addr, read_data_context *context, CHUNK_ITEM *ci, device **devices, uint64_t generation)
Definition: read.c:236
#define BLOCK_FLAG_RAID10
Definition: shellext.h:81
PIRP NTAPI IoMakeAssociatedIrp(IN PIRP Irp, IN CCHAR StackSize)
Definition: irp.c:1925
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define BLOCK_FLAG_RAID0
Definition: shellext.h:78
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define MDL_PAGES_LOCKED
Definition: mmtypes.h:19
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
INT WSAAPI send(IN SOCKET s, IN CONST CHAR FAR *buf, IN INT len, IN INT flags)
Definition: send.c:23
#define DO_BUFFERED_IO
Definition: env_spec_w32.h:394
#define Vcb
Definition: cdprocs.h:1415
const GLubyte * c
Definition: glext.h:8905
void chunk_lock_range(_In_ device_extension *Vcb, _In_ chunk *c, _In_ uint64_t start, _In_ uint64_t length)
Definition: btrfs.c:5747
#define BLOCK_FLAG_RAID6
Definition: shellext.h:83
_Ret_maybenull_ device * find_device_from_uuid(_In_ device_extension *Vcb, _In_ BTRFS_UUID *uuid)
Definition: btrfs.c:3232
VOID NTAPI IoFreeMdl(PMDL Mdl)
Definition: iomdl.c:146
#define BLOCK_FLAG_RAID1C4
Definition: btrfs.h:84
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
static NTSTATUS read_data_raid6(device_extension *Vcb, uint8_t *buf, uint64_t addr, uint32_t length, read_data_context *context, CHUNK_ITEM *ci, device **devices, uint64_t offset, uint64_t generation, chunk *c, bool degraded)
Definition: read.c:1019
Status
Definition: gdiplustypes.h:24
GLenum const GLvoid * addr
Definition: glext.h:9621
#define PAGE_SIZE
Definition: env_spec_w32.h:49
Definition: typedefs.h:119
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2691
BYTE uint8_t
Definition: msvideo1.c:66
PMDL NTAPI IoAllocateMdl(IN PVOID VirtualAddress, IN ULONG Length, IN BOOLEAN SecondaryBuffer, IN BOOLEAN ChargeQuota, IN PIRP Irp)
Definition: iomdl.c:22
#define ERR(fmt,...)
Definition: debug.h:110
chunk * get_chunk_from_address(device_extension *Vcb, uint64_t address)
Definition: write.c:89
PFILE_OBJECT FileObject
Definition: iotypes.h:3148
_SEH2_END
Definition: create.c:4400
UINT64 uint64_t
Definition: types.h:77
#define IRP_INPUT_OPERATION
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define IRP_BUFFERED_IO
VOID NTAPI MmProbeAndLockPages(IN PMDL Mdl, IN KPROCESSOR_MODE AccessMode, IN LOCK_OPERATION Operation)
Definition: mdlsup.c:935
static NTSTATUS read_data_raid5(device_extension *Vcb, uint8_t *buf, uint64_t addr, uint32_t length, read_data_context *context, CHUNK_ITEM *ci, device **devices, uint64_t offset, uint64_t generation, chunk *c, bool degraded)
Definition: read.c:655
unsigned char dummy
Definition: maze.c:118
_In_ uint64_t _In_ uint64_t _In_ uint64_t generation
Definition: btrfs.c:2929
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4137
tFsRtlUpdateDiskCounters fFsRtlUpdateDiskCounters
Definition: btrfs.c:99
#define min(a, b)
Definition: monoChain.cc:55
Definition: list.h:27
NTSTATUS NTAPI IoCallDriver(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: irp.c:1218
UINT32 uint32_t
Definition: types.h:75
#define STATUS_UNEXPECTED_IO_ERROR
Definition: ntstatus.h:469
#define IRP_MJ_READ
Definition: rdpdr.c:46
#define skip(...)
Definition: atltest.h:64
#define IRP_DEALLOCATE_BUFFER
VOID NTAPI IoFreeIrp(IN PIRP Irp)
Definition: irp.c:1666
#define c
Definition: ke_i.h:80
unsigned int ULONG
Definition: retypes.h:1
static NTSTATUS read_data_raid10(device_extension *Vcb, uint8_t *buf, uint64_t addr, uint32_t length, read_data_context *context, CHUNK_ITEM *ci, device **devices, uint64_t generation, uint64_t offset)
Definition: read.c:470
uint16_t num_stripes
Definition: btrfs.h:335
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
static int priority
Definition: timer.c:163
PIRP NTAPI IoAllocateIrp(IN CCHAR StackSize, IN BOOLEAN ChargeQuota)
Definition: irp.c:615
static NTSTATUS read_data_raid0(device_extension *Vcb, uint8_t *buf, uint64_t addr, uint32_t length, read_data_context *context, CHUNK_ITEM *ci, device **devices, uint64_t generation, uint64_t offset)
Definition: read.c:398
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define BLOCK_FLAG_DUPLICATE
Definition: shellext.h:80
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
void exit(int exitcode)
Definition: _exit.c:33
#define BLOCK_FLAG_RAID5
Definition: shellext.h:82
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:3107
uint64_t type
Definition: btrfs.h:331
#define uint32_t
Definition: nsiface.idl:61
return STATUS_SUCCESS
Definition: btrfs.c:3014
void * data
Definition: btrfs_drv.h:631
int k
Definition: mpi.c:3369
#define IRP_MN_NORMAL
Definition: iotypes.h:4396
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
void * csum
Definition: write.c:2807
bool diskacc
Definition: btrfs.c:106
#define BLOCK_FLAG_RAID1
Definition: shellext.h:79
#define STATUS_DEVICE_NOT_READY
Definition: shellext.h:70

Referenced by read_file().

◆ read_data_dup()

static NTSTATUS read_data_dup ( device_extension Vcb,
uint8_t buf,
uint64_t  addr,
read_data_context context,
CHUNK_ITEM ci,
device **  devices,
uint64_t  generation 
)
static

Definition at line 236 of file read.c.

237  {
238  ULONG i;
239  bool checksum_error = false;
240  uint16_t j, stripe = 0;
242  CHUNK_ITEM_STRIPE* cis = (CHUNK_ITEM_STRIPE*)&ci[1];
243 
244  for (j = 0; j < ci->num_stripes; j++) {
245  if (context->stripes[j].status == ReadDataStatus_Error) {
246  WARN("stripe %u returned error %08lx\n", j, context->stripes[j].iosb.Status);
248  return context->stripes[j].iosb.Status;
249  } else if (context->stripes[j].status == ReadDataStatus_Success) {
250  stripe = j;
251  break;
252  }
253  }
254 
255  if (context->stripes[stripe].status != ReadDataStatus_Success)
256  return STATUS_INTERNAL_ERROR;
257 
258  if (context->tree) {
259  tree_header* th = (tree_header*)buf;
260 
261  if (th->address != context->address || !check_tree_checksum(Vcb, th)) {
262  checksum_error = true;
264  } else if (generation != 0 && th->generation != generation) {
265  checksum_error = true;
267  }
268  } else if (context->csum) {
269  Status = check_csum(Vcb, buf, (ULONG)context->stripes[stripe].Irp->IoStatus.Information / context->sector_size, context->csum);
270 
271  if (Status == STATUS_CRC_ERROR) {
272  checksum_error = true;
274  } else if (!NT_SUCCESS(Status)) {
275  ERR("check_csum returned %08lx\n", Status);
276  return Status;
277  }
278  }
279 
280  if (!checksum_error)
281  return STATUS_SUCCESS;
282 
283  if (ci->num_stripes == 1)
284  return STATUS_CRC_ERROR;
285 
286  if (context->tree) {
287  tree_header* t2;
288  bool recovered = false;
289 
290  t2 = ExAllocatePoolWithTag(NonPagedPool, Vcb->superblock.node_size, ALLOC_TAG);
291  if (!t2) {
292  ERR("out of memory\n");
294  }
295 
296  for (j = 0; j < ci->num_stripes; j++) {
297  if (j != stripe && devices[j] && devices[j]->devobj) {
298  Status = sync_read_phys(devices[j]->devobj, devices[j]->fileobj, cis[j].offset + context->stripes[stripe].stripestart,
299  Vcb->superblock.node_size, (uint8_t*)t2, false);
300  if (!NT_SUCCESS(Status)) {
301  WARN("sync_read_phys returned %08lx\n", Status);
303  } else {
304  bool checksum_error = !check_tree_checksum(Vcb, t2);
305 
306  if (t2->address == addr && !checksum_error && (generation == 0 || t2->generation == generation)) {
307  RtlCopyMemory(buf, t2, Vcb->superblock.node_size);
308  ERR("recovering from checksum error at %I64x, device %I64x\n", addr, devices[stripe]->devitem.dev_id);
309  recovered = true;
310 
311  if (!Vcb->readonly && !devices[stripe]->readonly) { // write good data over bad
312  Status = write_data_phys(devices[stripe]->devobj, devices[stripe]->fileobj, cis[stripe].offset + context->stripes[stripe].stripestart,
313  t2, Vcb->superblock.node_size);
314  if (!NT_SUCCESS(Status)) {
315  WARN("write_data_phys returned %08lx\n", Status);
317  }
318  }
319 
320  break;
321  } else if (t2->address != addr || checksum_error)
323  else
325  }
326  }
327  }
328 
329  if (!recovered) {
330  ERR("unrecoverable checksum error at %I64x\n", addr);
331  ExFreePool(t2);
332  return STATUS_CRC_ERROR;
333  }
334 
335  ExFreePool(t2);
336  } else {
337  ULONG sectors = (ULONG)context->stripes[stripe].Irp->IoStatus.Information / Vcb->superblock.sector_size;
338  uint8_t* sector;
339  void* ptr = context->csum;
340 
341  sector = ExAllocatePoolWithTag(NonPagedPool, Vcb->superblock.sector_size, ALLOC_TAG);
342  if (!sector) {
343  ERR("out of memory\n");
345  }
346 
347  for (i = 0; i < sectors; i++) {
348  if (!check_sector_csum(Vcb, buf + (i * Vcb->superblock.sector_size), ptr)) {
349  bool recovered = false;
350 
351  for (j = 0; j < ci->num_stripes; j++) {
352  if (j != stripe && devices[j] && devices[j]->devobj) {
353  Status = sync_read_phys(devices[j]->devobj, devices[j]->fileobj,
354  cis[j].offset + context->stripes[stripe].stripestart + UInt32x32To64(i, Vcb->superblock.sector_size),
355  Vcb->superblock.sector_size, sector, false);
356  if (!NT_SUCCESS(Status)) {
357  WARN("sync_read_phys returned %08lx\n", Status);
359  } else {
360  if (check_sector_csum(Vcb, sector, ptr)) {
361  RtlCopyMemory(buf + (i * Vcb->superblock.sector_size), sector, Vcb->superblock.sector_size);
362  ERR("recovering from checksum error at %I64x, device %I64x\n", addr + UInt32x32To64(i, Vcb->superblock.sector_size), devices[stripe]->devitem.dev_id);
363  recovered = true;
364 
365  if (!Vcb->readonly && !devices[stripe]->readonly) { // write good data over bad
366  Status = write_data_phys(devices[stripe]->devobj, devices[stripe]->fileobj,
367  cis[stripe].offset + context->stripes[stripe].stripestart + UInt32x32To64(i, Vcb->superblock.sector_size),
368  sector, Vcb->superblock.sector_size);
369  if (!NT_SUCCESS(Status)) {
370  WARN("write_data_phys returned %08lx\n", Status);
372  }
373  }
374 
375  break;
376  } else
378  }
379  }
380  }
381 
382  if (!recovered) {
383  ERR("unrecoverable checksum error at %I64x\n", addr + UInt32x32To64(i, Vcb->superblock.sector_size));
385  return STATUS_CRC_ERROR;
386  }
387  }
388 
389  ptr = (uint8_t*)ptr + Vcb->csum_size;
390  }
391 
393  }
394 
395  return STATUS_SUCCESS;
396 }
uint32_t sector
Definition: isohybrid.c:61
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
Definition: http.c:7094
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
const char * devices
Definition: diskspace.c:793
#define WARN(fmt,...)
Definition: debug.h:112
LONG NTSTATUS
Definition: precomp.h:26
GLintptr offset
Definition: glext.h:5920
Definition: write.c:111
unsigned short int uint16_t
Definition: acefiex.h:54
bool check_sector_csum(device_extension *Vcb, void *buf, void *csum)
Definition: read.c:202
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
#define ALLOC_TAG
Definition: btrfs_drv.h:91
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
uint64_t address
Definition: btrfs.h:149
static PVOID ptr
Definition: dispmode.c:27
uint64_t generation
Definition: btrfs.h:152
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define BTRFS_DEV_STAT_CORRUPTION_ERRORS
Definition: btrfs.h:530
NTSTATUS write_data_phys(_In_ PDEVICE_OBJECT device, _In_ PFILE_OBJECT fileobj, _In_ uint64_t address, _In_reads_bytes_(length) void *data, _In_ uint32_t length)
Definition: flushthread.c:65
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define BTRFS_DEV_STAT_GENERATION_ERRORS
Definition: btrfs.h:531
#define Vcb
Definition: cdprocs.h:1415
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
Status
Definition: gdiplustypes.h:24
GLenum const GLvoid * addr
Definition: glext.h:9621
#define STATUS_CRC_ERROR
Definition: udferr_usr.h:153
BYTE uint8_t
Definition: msvideo1.c:66
NTSTATUS sync_read_phys(_In_ PDEVICE_OBJECT DeviceObject, _In_ PFILE_OBJECT FileObject, _In_ uint64_t StartingOffset, _In_ ULONG Length, _Out_writes_bytes_(Length) PUCHAR Buffer, _In_ bool override)
Definition: btrfs.c:2668
#define BTRFS_DEV_STAT_READ_ERRORS
Definition: btrfs.h:528
#define ERR(fmt,...)
Definition: debug.h:110
void log_device_error(_In_ device_extension *Vcb, _Inout_ device *dev, _In_ int error)
Definition: btrfs.c:5817
_In_ uint64_t _In_ uint64_t _In_ uint64_t generation
Definition: btrfs.c:2929
__u8 sectors[2]
Definition: mkdosfs.c:366
#define BTRFS_DEV_STAT_WRITE_ERRORS
Definition: btrfs.h:527
unsigned int ULONG
Definition: retypes.h:1
NTSTATUS check_csum(device_extension *Vcb, uint8_t *data, uint32_t sectors, void *csum)
Definition: read.c:87
uint16_t num_stripes
Definition: btrfs.h:335
return STATUS_SUCCESS
Definition: btrfs.c:3014
#define UInt32x32To64(a, b)
Definition: intsafe.h:250
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
bool check_tree_checksum(device_extension *Vcb, tree_header *th)
Definition: read.c:128

Referenced by read_data().

◆ read_data_raid0()

static NTSTATUS read_data_raid0 ( device_extension Vcb,
uint8_t buf,
uint64_t  addr,
uint32_t  length,
read_data_context context,
CHUNK_ITEM ci,
device **  devices,
uint64_t  generation,
uint64_t  offset 
)
static

Definition at line 398 of file read.c.

399  {
400  uint64_t i;
401 
402  for (i = 0; i < ci->num_stripes; i++) {
403  if (context->stripes[i].status == ReadDataStatus_Error) {
404  WARN("stripe %I64u returned error %08lx\n", i, context->stripes[i].iosb.Status);
406  return context->stripes[i].iosb.Status;
407  }
408  }
409 
410  if (context->tree) { // shouldn't happen, as trees shouldn't cross stripe boundaries
411  tree_header* th = (tree_header*)buf;
412  bool checksum_error = !check_tree_checksum(Vcb, th);
413 
414  if (checksum_error || addr != th->address || (generation != 0 && generation != th->generation)) {
415  uint64_t off;
417 
419 
420  ERR("unrecoverable checksum error at %I64x, device %I64x\n", addr, devices[stripe]->devitem.dev_id);
421 
422  if (checksum_error) {
424  return STATUS_CRC_ERROR;
425  } else if (addr != th->address) {
426  WARN("address of tree was %I64x, not %I64x as expected\n", th->address, addr);
428  return STATUS_CRC_ERROR;
429  } else if (generation != 0 && generation != th->generation) {
430  WARN("generation of tree was %I64x, not %I64x as expected\n", th->generation, generation);
432  return STATUS_CRC_ERROR;
433  }
434  }
435  } else if (context->csum) {
437 
438  Status = check_csum(Vcb, buf, length / Vcb->superblock.sector_size, context->csum);
439 
440  if (Status == STATUS_CRC_ERROR) {
441  void* ptr = context->csum;
442 
443  for (i = 0; i < length / Vcb->superblock.sector_size; i++) {
444  if (!check_sector_csum(Vcb, buf + (i * Vcb->superblock.sector_size), ptr)) {
445  uint64_t off;
447 
448  get_raid0_offset(addr - offset + UInt32x32To64(i, Vcb->superblock.sector_size), ci->stripe_length, ci->num_stripes, &off, &stripe);
449 
450  ERR("unrecoverable checksum error at %I64x, device %I64x\n", addr, devices[stripe]->devitem.dev_id);
451 
453 
454  return Status;
455  }
456 
457  ptr = (uint8_t*)ptr + Vcb->csum_size;
458  }
459 
460  return Status;
461  } else if (!NT_SUCCESS(Status)) {
462  ERR("check_csum returned %08lx\n", Status);
463  return Status;
464  }
465  }
466 
467  return STATUS_SUCCESS;
468 }
Definition: http.c:7094
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
const char * devices
Definition: diskspace.c:793
#define WARN(fmt,...)
Definition: debug.h:112
LONG NTSTATUS
Definition: precomp.h:26
GLintptr offset
Definition: glext.h:5920
Definition: write.c:111
uint64_t stripe_length
Definition: btrfs.h:330
unsigned short int uint16_t
Definition: acefiex.h:54
_Post_satisfies_ static stripe __inline void get_raid0_offset(_In_ uint64_t off, _In_ uint64_t stripe_length, _In_ uint16_t num_stripes, _Out_ uint64_t *stripeoff, _Out_ uint16_t *stripe)
Definition: btrfs_drv.h:1005
bool check_sector_csum(device_extension *Vcb, void *buf, void *csum)
Definition: read.c:202
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
uint64_t address
Definition: btrfs.h:149
static PVOID ptr
Definition: dispmode.c:27
uint64_t generation
Definition: btrfs.h:152
#define BTRFS_DEV_STAT_CORRUPTION_ERRORS
Definition: btrfs.h:530
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define BTRFS_DEV_STAT_GENERATION_ERRORS
Definition: btrfs.h:531
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
#define Vcb
Definition: cdprocs.h:1415
Status
Definition: gdiplustypes.h:24
GLenum const GLvoid * addr
Definition: glext.h:9621
#define STATUS_CRC_ERROR
Definition: udferr_usr.h:153
BYTE uint8_t
Definition: msvideo1.c:66
#define BTRFS_DEV_STAT_READ_ERRORS
Definition: btrfs.h:528
#define ERR(fmt,...)
Definition: debug.h:110
UINT64 uint64_t
Definition: types.h:77
void log_device_error(_In_ device_extension *Vcb, _Inout_ device *dev, _In_ int error)
Definition: btrfs.c:5817
_In_ uint64_t _In_ uint64_t _In_ uint64_t generation
Definition: btrfs.c:2929
NTSTATUS check_csum(device_extension *Vcb, uint8_t *data, uint32_t sectors, void *csum)
Definition: read.c:87
uint16_t num_stripes
Definition: btrfs.h:335
return STATUS_SUCCESS
Definition: btrfs.c:3014
#define UInt32x32To64(a, b)
Definition: intsafe.h:250
bool check_tree_checksum(device_extension *Vcb, tree_header *th)
Definition: read.c:128
off
Definition: i386-dis.c:3909

Referenced by read_data().

◆ read_data_raid10()

static NTSTATUS read_data_raid10 ( device_extension Vcb,
uint8_t buf,
uint64_t  addr,
uint32_t  length,
read_data_context context,
CHUNK_ITEM ci,
device **  devices,
uint64_t  generation,
uint64_t  offset 
)
static

Definition at line 470 of file read.c.

471  {
472  uint64_t i;
473  uint16_t j, stripe;
475  bool checksum_error = false;
476  CHUNK_ITEM_STRIPE* cis = (CHUNK_ITEM_STRIPE*)&ci[1];
477 
478  for (j = 0; j < ci->num_stripes; j++) {
479  if (context->stripes[j].status == ReadDataStatus_Error) {
480  WARN("stripe %u returned error %08lx\n", j, context->stripes[j].iosb.Status);
482  return context->stripes[j].iosb.Status;
483  } else if (context->stripes[j].status == ReadDataStatus_Success)
484  stripe = j;
485  }
486 
487  if (context->tree) {
488  tree_header* th = (tree_header*)buf;
489 
490  if (!check_tree_checksum(Vcb, th)) {
491  checksum_error = true;
493  } else if (addr != th->address) {
494  WARN("address of tree was %I64x, not %I64x as expected\n", th->address, addr);
495  checksum_error = true;
497  } else if (generation != 0 && generation != th->generation) {
498  WARN("generation of tree was %I64x, not %I64x as expected\n", th->generation, generation);
499  checksum_error = true;
501  }
502  } else if (context->csum) {
503  Status = check_csum(Vcb, buf, length / Vcb->superblock.sector_size, context->csum);
504 
505  if (Status == STATUS_CRC_ERROR)
506  checksum_error = true;
507  else if (!NT_SUCCESS(Status)) {
508  ERR("check_csum returned %08lx\n", Status);
509  return Status;
510  }
511  }
512 
513  if (!checksum_error)
514  return STATUS_SUCCESS;
515 
516  if (context->tree) {
517  tree_header* t2;
518  uint64_t off;
519  uint16_t badsubstripe = 0;
520  bool recovered = false;
521 
522  t2 = ExAllocatePoolWithTag(NonPagedPool, Vcb->superblock.node_size, ALLOC_TAG);
523  if (!t2) {
524  ERR("out of memory\n");
526  }
527 
529 
530  stripe *= ci->sub_stripes;
531 
532  for (j = 0; j < ci->sub_stripes; j++) {
533  if (context->stripes[stripe + j].status == ReadDataStatus_Success) {
534  badsubstripe = j;
535  break;
536  }
537  }
538 
539  for (j = 0; j < ci->sub_stripes; j++) {
540  if (context->stripes[stripe + j].status != ReadDataStatus_Success && devices[stripe + j] && devices[stripe + j]->devobj) {
541  Status = sync_read_phys(devices[stripe + j]->devobj, devices[stripe + j]->fileobj, cis[stripe + j].offset + off,
542  Vcb->superblock.node_size, (uint8_t*)t2, false);
543  if (!NT_SUCCESS(Status)) {
544  WARN("sync_read_phys returned %08lx\n", Status);
546  } else {
547  bool checksum_error = !check_tree_checksum(Vcb, t2);
548 
549  if (t2->address == addr && !checksum_error && (generation == 0 || t2->generation == generation)) {
550  RtlCopyMemory(buf, t2, Vcb->superblock.node_size);
551  ERR("recovering from checksum error at %I64x, device %I64x\n", addr, devices[stripe + j]->devitem.dev_id);
552  recovered = true;
553 
554  if (!Vcb->readonly && !devices[stripe + badsubstripe]->readonly && devices[stripe + badsubstripe]->devobj) { // write good data over bad
555  Status = write_data_phys(devices[stripe + badsubstripe]->devobj, devices[stripe + badsubstripe]->fileobj,
556  cis[stripe + badsubstripe].offset + off, t2, Vcb->superblock.node_size);
557  if (!NT_SUCCESS(Status)) {
558  WARN("write_data_phys returned %08lx\n", Status);
560  }
561  }
562 
563  break;
564  } else if (t2->address != addr || checksum_error)
566  else
568  }
569  }
570  }
571 
572  if (!recovered) {
573  ERR("unrecoverable checksum error at %I64x\n", addr);
574  ExFreePool(t2);
575  return STATUS_CRC_ERROR;
576  }
577 
578  ExFreePool(t2);
579  } else {
580  ULONG sectors = length / Vcb->superblock.sector_size;
581  uint8_t* sector;
582  void* ptr = context->csum;
583 
584  sector = ExAllocatePoolWithTag(NonPagedPool, Vcb->superblock.sector_size, ALLOC_TAG);
585  if (!sector) {
586  ERR("out of memory\n");
588  }
589 
590  for (i = 0; i < sectors; i++) {
591  if (!check_sector_csum(Vcb, buf + (i * Vcb->superblock.sector_size), ptr)) {
592  uint64_t off;
593  uint16_t stripe2, badsubstripe = 0;
594  bool recovered = false;
595 
596  get_raid0_offset(addr - offset + UInt32x32To64(i, Vcb->superblock.sector_size), ci->stripe_length,
597  ci->num_stripes / ci->sub_stripes, &off, &stripe2);
598 
599  stripe2 *= ci->sub_stripes;
600 
601  for (j = 0; j < ci->sub_stripes; j++) {
602  if (context->stripes[stripe2 + j].status == ReadDataStatus_Success) {
603  badsubstripe = j;
604  break;
605  }
606  }
607 
609 
610  for (j = 0; j < ci->sub_stripes; j++) {
611  if (context->stripes[stripe2 + j].status != ReadDataStatus_Success && devices[stripe2 + j] && devices[stripe2 + j]->devobj) {
612  Status = sync_read_phys(devices[stripe2 + j]->devobj, devices[stripe2 + j]->fileobj, cis[stripe2 + j].offset + off,
613  Vcb->superblock.sector_size, sector, false);
614  if (!NT_SUCCESS(Status)) {
615  WARN("sync_read_phys returned %08lx\n", Status);
617  } else {
618  if (check_sector_csum(Vcb, sector, ptr)) {
619  RtlCopyMemory(buf + (i * Vcb->superblock.sector_size), sector, Vcb->superblock.sector_size);
620  ERR("recovering from checksum error at %I64x, device %I64x\n", addr + UInt32x32To64(i, Vcb->superblock.sector_size), devices[stripe2 + j]->devitem.dev_id);
621  recovered = true;
622 
623  if (!Vcb->readonly && !devices[stripe2 + badsubstripe]->readonly && devices[stripe2 + badsubstripe]->devobj) { // write good data over bad
624  Status = write_data_phys(devices[stripe2 + badsubstripe]->devobj, devices[stripe2 + badsubstripe]->fileobj,
625  cis[stripe2 + badsubstripe].offset + off, sector, Vcb->superblock.sector_size);
626  if (!NT_SUCCESS(Status)) {
627  WARN("write_data_phys returned %08lx\n", Status);
628  log_device_error(Vcb, devices[stripe2 + badsubstripe], BTRFS_DEV_STAT_READ_ERRORS);
629  }
630  }
631 
632  break;
633  } else
635  }
636  }
637  }
638 
639  if (!recovered) {
640  ERR("unrecoverable checksum error at %I64x\n", addr + UInt32x32To64(i, Vcb->superblock.sector_size));
642  return STATUS_CRC_ERROR;
643  }
644  }
645 
646  ptr = (uint8_t*)ptr + Vcb->csum_size;
647  }
648 
650  }
651 
652  return STATUS_SUCCESS;
653 }
uint32_t sector
Definition: isohybrid.c:61
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
uint16_t sub_stripes
Definition: btrfs.h:336
Definition: http.c:7094
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
const char * devices
Definition: diskspace.c:793
#define WARN(fmt,...)
Definition: debug.h:112
LONG NTSTATUS
Definition: precomp.h:26
GLintptr offset
Definition: glext.h:5920
Definition: write.c:111
uint64_t stripe_length
Definition: btrfs.h:330
unsigned short int uint16_t
Definition: acefiex.h:54
_Post_satisfies_ static stripe __inline void get_raid0_offset(_In_ uint64_t off, _In_ uint64_t stripe_length, _In_ uint16_t num_stripes, _Out_ uint64_t *stripeoff, _Out_ uint16_t *stripe)
Definition: btrfs_drv.h:1005
bool check_sector_csum(device_extension *Vcb, void *buf, void *csum)
Definition: read.c:202
#define ALLOC_TAG
Definition: btrfs_drv.h:91
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
uint64_t address
Definition: btrfs.h:149
static PVOID ptr
Definition: dispmode.c:27
uint64_t generation
Definition: btrfs.h:152
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define BTRFS_DEV_STAT_CORRUPTION_ERRORS
Definition: btrfs.h:530
NTSTATUS write_data_phys(_In_ PDEVICE_OBJECT device, _In_ PFILE_OBJECT fileobj, _In_ uint64_t address, _In_reads_bytes_(length) void *data, _In_ uint32_t length)
Definition: flushthread.c:65
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define BTRFS_DEV_STAT_GENERATION_ERRORS
Definition: btrfs.h:531
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
#define Vcb
Definition: cdprocs.h:1415
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
Status
Definition: gdiplustypes.h:24
GLenum const GLvoid * addr
Definition: glext.h:9621
#define STATUS_CRC_ERROR
Definition: udferr_usr.h:153
BYTE uint8_t
Definition: msvideo1.c:66
NTSTATUS sync_read_phys(_In_ PDEVICE_OBJECT DeviceObject, _In_ PFILE_OBJECT FileObject, _In_ uint64_t StartingOffset, _In_ ULONG Length, _Out_writes_bytes_(Length) PUCHAR Buffer, _In_ bool override)
Definition: btrfs.c:2668
#define BTRFS_DEV_STAT_READ_ERRORS
Definition: btrfs.h:528
#define ERR(fmt,...)
Definition: debug.h:110
UINT64 uint64_t
Definition: types.h:77
void log_device_error(_In_ device_extension *Vcb, _Inout_ device *dev, _In_ int error)
Definition: btrfs.c:5817
_In_ uint64_t _In_ uint64_t _In_ uint64_t generation
Definition: btrfs.c:2929
__u8 sectors[2]
Definition: mkdosfs.c:366
#define BTRFS_DEV_STAT_WRITE_ERRORS
Definition: btrfs.h:527
unsigned int ULONG
Definition: retypes.h:1
NTSTATUS check_csum(device_extension *Vcb, uint8_t *data, uint32_t sectors, void *csum)
Definition: read.c:87
uint16_t num_stripes
Definition: btrfs.h:335
return STATUS_SUCCESS
Definition: btrfs.c:3014
#define UInt32x32To64(a, b)
Definition: intsafe.h:250
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
bool check_tree_checksum(device_extension *Vcb, tree_header *th)
Definition: read.c:128
off
Definition: i386-dis.c:3909

Referenced by read_data().

◆ read_data_raid5()

static NTSTATUS read_data_raid5 ( device_extension Vcb,
uint8_t buf,
uint64_t  addr,
uint32_t  length,
read_data_context context,
CHUNK_ITEM ci,
device **  devices,
uint64_t  offset,
uint64_t  generation,
chunk c,
bool  degraded 
)
static

Definition at line 655 of file read.c.

656  {
657  ULONG i;
659  bool checksum_error = false;
660  CHUNK_ITEM_STRIPE* cis = (CHUNK_ITEM_STRIPE*)&ci[1];
661  uint16_t j, stripe;
662  bool no_success = true;
663 
664  for (j = 0; j < ci->num_stripes; j++) {
665  if (context->stripes[j].status == ReadDataStatus_Error) {
666  WARN("stripe %u returned error %08lx\n", j, context->stripes[j].iosb.Status);
668  return context->stripes[j].iosb.Status;
669  } else if (context->stripes[j].status == ReadDataStatus_Success) {
670  stripe = j;
671  no_success = false;
672  }
673  }
674 
675  if (c) { // check partial stripes
676  LIST_ENTRY* le;
677  uint64_t ps_length = (ci->num_stripes - 1) * ci->stripe_length;
678 
679  ExAcquireResourceSharedLite(&c->partial_stripes_lock, true);
680 
681  le = c->partial_stripes.Flink;
682  while (le != &c->partial_stripes) {
684 
685  if (ps->address + ps_length > addr && ps->address < addr + length) {
686  ULONG runlength, index;
687 
688  runlength = RtlFindFirstRunClear(&ps->bmp, &index);
689 
690  while (runlength != 0) {
691 #ifdef __REACTOS__
692  uint64_t runstart, runend, start, end;
693 #endif
694  if (index >= ps->bmplen)
695  break;
696 
697  if (index + runlength >= ps->bmplen) {
698  runlength = ps->bmplen - index;
699 
700  if (runlength == 0)
701  break;
702  }
703 
704 #ifndef __REACTOS__
705  uint64_t runstart = ps->address + (index * Vcb->superblock.sector_size);
706  uint64_t runend = runstart + (runlength * Vcb->superblock.sector_size);
707  uint64_t start = max(runstart, addr);
708  uint64_t end = min(runend, addr + length);
709 #else
710  runstart = ps->address + (index * Vcb->superblock.sector_size);
711  runend = runstart + (runlength * Vcb->superblock.sector_size);
712  start = max(runstart, addr);
713  end = min(runend, addr + length);
714 #endif
715 
716  if (end > start)
717  RtlCopyMemory(buf + start - addr, &ps->data[start - ps->address], (ULONG)(end - start));
718 
719  runlength = RtlFindNextForwardRunClear(&ps->bmp, index + runlength, &index);
720  }
721  } else if (ps->address >= addr + length)
722  break;
723 
724  le = le->Flink;
725  }
726 
727  ExReleaseResourceLite(&c->partial_stripes_lock);
728  }
729 
730  if (context->tree) {
731  tree_header* th = (tree_header*)buf;
732 
733  if (addr != th->address || !check_tree_checksum(Vcb, th)) {
734  checksum_error = true;
735  if (!no_success && !degraded)
737  } else if (generation != 0 && generation != th->generation) {
738  checksum_error = true;
739  if (!no_success && !degraded)
741  }
742  } else if (context->csum) {
743  Status = check_csum(Vcb, buf, length / Vcb->superblock.sector_size, context->csum);
744 
745  if (Status == STATUS_CRC_ERROR) {
746  if (!degraded)
747  WARN("checksum error\n");
748  checksum_error = true;
749  } else if (!NT_SUCCESS(Status)) {
750  ERR("check_csum returned %08lx\n", Status);
751  return Status;
752  }
753  } else if (degraded)
754  checksum_error = true;
755 
756  if (!checksum_error)
757  return STATUS_SUCCESS;
758 
759  if (context->tree) {
760  uint16_t parity;
761  uint64_t off;
762  bool recovered = false, first = true, failed = false;
763  uint8_t* t2;
764 
765  t2 = ExAllocatePoolWithTag(NonPagedPool, Vcb->superblock.node_size * 2, ALLOC_TAG);
766  if (!t2) {
767  ERR("out of memory\n");
769  }
770 
772 
773  parity = (((addr - offset) / ((ci->num_stripes - 1) * ci->stripe_length)) + ci->num_stripes - 1) % ci->num_stripes;
774 
775  stripe = (parity + stripe + 1) % ci->num_stripes;
776 
777  for (j = 0; j < ci->num_stripes; j++) {
778  if (j != stripe) {
779  if (devices[j] && devices[j]->devobj) {
780  if (first) {
781  Status = sync_read_phys(devices[j]->devobj, devices[j]->fileobj, cis[j].offset + off, Vcb->superblock.node_size, t2, false);
782  if (!NT_SUCCESS(Status)) {
783  ERR("sync_read_phys returned %08lx\n", Status);
785  failed = true;
786  break;
787  }
788 
789  first = false;
790  } else {
791  Status = sync_read_phys(devices[j]->devobj, devices[j]->fileobj, cis[j].offset + off, Vcb->superblock.node_size, t2 + Vcb->superblock.node_size, false);
792  if (!NT_SUCCESS(Status)) {
793  ERR("sync_read_phys returned %08lx\n", Status);
795  failed = true;
796  break;
797  }
798 
799  do_xor(t2, t2 + Vcb->superblock.node_size, Vcb->superblock.node_size);
800  }
801  } else {
802  failed = true;
803  break;
804  }
805  }
806  }
807 
808  if (!failed) {
809  tree_header* t3 = (tree_header*)t2;
810 
811  if (t3->address == addr && check_tree_checksum(Vcb, t3) && (generation == 0 || t3->generation == generation)) {
812  RtlCopyMemory(buf, t2, Vcb->superblock.node_size);
813 
814  if (!degraded)
815  ERR("recovering from checksum error at %I64x, device %I64x\n", addr, devices[stripe]->devitem.dev_id);
816 
817  recovered = true;
818 
819  if (!Vcb->readonly && devices[stripe] && !devices[stripe]->readonly && devices[stripe]->devobj) { // write good data over bad
820  Status = write_data_phys(devices[stripe]->devobj, devices[stripe]->fileobj, cis[stripe].offset + off, t2, Vcb->superblock.node_size);
821  if (!NT_SUCCESS(Status)) {
822  WARN("write_data_phys returned %08lx\n", Status);
824  }
825  }
826  }
827  }
828 
829  if (!recovered) {
830  ERR("unrecoverable checksum error at %I64x\n", addr);
831  ExFreePool(t2);
832  return STATUS_CRC_ERROR;
833  }
834 
835  ExFreePool(t2);
836  } else {
837  ULONG sectors = length / Vcb->superblock.sector_size;
838  uint8_t* sector;
839  void* ptr = context->csum;
840 
841  sector = ExAllocatePoolWithTag(NonPagedPool, Vcb->superblock.sector_size * 2, ALLOC_TAG);
842  if (!sector) {
843  ERR("out of memory\n");
845  }
846 
847  for (i = 0; i < sectors; i++) {
848  uint16_t parity;
849  uint64_t off;
850 
851  get_raid0_offset(addr - offset + UInt32x32To64(i, Vcb->superblock.sector_size), ci->stripe_length,
852  ci->num_stripes - 1, &off, &stripe);
853 
854  parity = (((addr - offset + UInt32x32To64(i, Vcb->superblock.sector_size)) / ((ci->num_stripes - 1) * ci->stripe_length)) + ci->num_stripes - 1) % ci->num_stripes;
855 
856  stripe = (parity + stripe + 1) % ci->num_stripes;
857 
858  if (!devices[stripe] || !devices[stripe]->devobj || (ptr && !check_sector_csum(Vcb, buf + (i * Vcb->superblock.sector_size), ptr))) {
859  bool recovered = false, first = true, failed = false;
860 
861  if (devices[stripe] && devices[stripe]->devobj)
863 
864  for (j = 0; j < ci->num_stripes; j++) {
865  if (j != stripe) {
866  if (devices[j] && devices[j]->devobj) {
867  if (first) {
868  Status = sync_read_phys(devices[j]->devobj, devices[j]->fileobj, cis[j].offset + off, Vcb->superblock.sector_size, sector, false);
869  if (!NT_SUCCESS(Status)) {
870  ERR("sync_read_phys returned %08lx\n", Status);
871  failed = true;
873  break;
874  }
875 
876  first = false;
877  } else {
878  Status = sync_read_phys(devices[j]->devobj, devices[j]->fileobj, cis[j].offset + off, Vcb->superblock.sector_size,
879  sector + Vcb->superblock.sector_size, false);
880  if (!NT_SUCCESS(Status)) {
881  ERR("sync_read_phys returned %08lx\n", Status);
882  failed = true;
884  break;
885  }
886 
887  do_xor(sector, sector + Vcb->superblock.sector_size, Vcb->superblock.sector_size);
888  }
889  } else {
890  failed = true;
891  break;
892  }
893  }
894  }
895 
896  if (!failed) {
897  if (!ptr || check_sector_csum(Vcb, sector, ptr)) {
898  RtlCopyMemory(buf + (i * Vcb->superblock.sector_size), sector, Vcb->superblock.sector_size);
899 
900  if (!degraded)
901  ERR("recovering from checksum error at %I64x, device %I64x\n", addr + UInt32x32To64(i, Vcb->superblock.sector_size), devices[stripe]->devitem.dev_id);
902 
903  recovered = true;
904 
905  if (!Vcb->readonly && devices[stripe] && !devices[stripe]->readonly && devices[stripe]->devobj) { // write good data over bad
906  Status = write_data_phys(devices[stripe]->devobj, devices[stripe]->fileobj, cis[stripe].offset + off,
907  sector, Vcb->superblock.sector_size);
908  if (!NT_SUCCESS(Status)) {
909  WARN("write_data_phys returned %08lx\n", Status);
911  }
912  }
913  }
914  }
915 
916  if (!recovered) {
917  ERR("unrecoverable checksum error at %I64x\n", addr + UInt32x32To64(i, Vcb->superblock.sector_size));
919  return STATUS_CRC_ERROR;
920  }
921  }
922 
923  if (ptr)
924  ptr = (uint8_t*)ptr + Vcb->csum_size;
925  }
926 
928  }
929 
930  return STATUS_SUCCESS;
931 }
uint32_t sector
Definition: isohybrid.c:61
#define max(a, b)
Definition: svc.c:63
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
static __inline void do_xor(uint8_t *buf1, uint8_t *buf2, uint32_t len)
Definition: btrfs_drv.h:1729
Definition: http.c:7094
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
const char * devices
Definition: diskspace.c:793
const GLint * first
Definition: glext.h:5794
#define WARN(fmt,...)
Definition: debug.h:112
LONG NTSTATUS
Definition: precomp.h:26
GLintptr offset
Definition: glext.h:5920
Definition: write.c:111
uint64_t address
Definition: btrfs_drv.h:562
uint64_t stripe_length
Definition: btrfs.h:330
GLuint GLuint end
Definition: gl.h:1545
RTL_BITMAP bmp
Definition: btrfs_drv.h:565
unsigned short int uint16_t
Definition: acefiex.h:54
_Post_satisfies_ static stripe __inline void get_raid0_offset(_In_ uint64_t off, _In_ uint64_t stripe_length, _In_ uint16_t num_stripes, _Out_ uint64_t *stripeoff, _Out_ uint16_t *stripe)
Definition: btrfs_drv.h:1005
bool check_sector_csum(device_extension *Vcb, void *buf, void *csum)
Definition: read.c:202
#define ALLOC_TAG
Definition: btrfs_drv.h:91
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
uint64_t address
Definition: btrfs.h:149
static PVOID ptr
Definition: dispmode.c:27
uint64_t generation
Definition: btrfs.h:152
GLuint index
Definition: glext.h:6031
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define BTRFS_DEV_STAT_CORRUPTION_ERRORS
Definition: btrfs.h:530
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
NTSTATUS write_data_phys(_In_ PDEVICE_OBJECT device, _In_ PFILE_OBJECT fileobj, _In_ uint64_t address, _In_reads_bytes_(length) void *data, _In_ uint32_t length)
Definition: flushthread.c:65
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define BTRFS_DEV_STAT_GENERATION_ERRORS
Definition: btrfs.h:531
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
#define Vcb
Definition: cdprocs.h:1415
const GLubyte * c
Definition: glext.h:8905
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
Status
Definition: gdiplustypes.h:24
GLenum const GLvoid * addr
Definition: glext.h:9621
#define index(s, c)
Definition: various.h:29
uint8_t data[1]
Definition: btrfs_drv.h:567
Definition: typedefs.h:119
#define STATUS_CRC_ERROR
Definition: udferr_usr.h:153
BYTE uint8_t
Definition: msvideo1.c:66
NTSTATUS sync_read_phys(_In_ PDEVICE_OBJECT DeviceObject, _In_ PFILE_OBJECT FileObject, _In_ uint64_t StartingOffset, _In_ ULONG Length, _Out_writes_bytes_(Length) PUCHAR Buffer, _In_ bool override)
Definition: btrfs.c:2668
#define BTRFS_DEV_STAT_READ_ERRORS
Definition: btrfs.h:528
#define ERR(fmt,...)
Definition: debug.h:110
UINT64 uint64_t
Definition: types.h:77
void log_device_error(_In_ device_extension *Vcb, _Inout_ device *dev, _In_ int error)
Definition: btrfs.c:5817
GLuint start
Definition: gl.h:1545
_In_ uint64_t _In_ uint64_t _In_ uint64_t generation
Definition: btrfs.c:2929
NTSYSAPI ULONG NTAPI RtlFindFirstRunClear(_In_ PRTL_BITMAP BitMapHeader, _Out_ PULONG StartingIndex)
#define min(a, b)
Definition: monoChain.cc:55
Definition: list.h:27
__u8 sectors[2]
Definition: mkdosfs.c:366
BOOLEAN NTAPI ExAcquireResourceSharedLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:885
NTSYSAPI ULONG WINAPI RtlFindNextForwardRunClear(PCRTL_BITMAP, ULONG, PULONG)
#define BTRFS_DEV_STAT_WRITE_ERRORS
Definition: btrfs.h:527
unsigned int ULONG
Definition: retypes.h:1
NTSTATUS check_csum(device_extension *Vcb, uint8_t *data, uint32_t sectors, void *csum)
Definition: read.c:87
uint16_t num_stripes
Definition: btrfs.h:335
return STATUS_SUCCESS
Definition: btrfs.c:3014
#define UInt32x32To64(a, b)
Definition: intsafe.h:250
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
bool check_tree_checksum(device_extension *Vcb, tree_header *th)
Definition: read.c:128
off
Definition: i386-dis.c: