ReactOS  0.4.15-dev-4914-g2220e56
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)
 
 __attribute__ ((nonnull(1, 2)))
 
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

◆ __attribute__()

__attribute__ ( (nonnull(1, 2))  )

Definition at line 2730 of file read.c.

2731  {
2732  ULONG readlen;
2733 
2734  TRACE("(%p, %p, %I64x, %lx, %p)\n", fcb, data, start, length, pbr);
2735 
2736  if (pbr) *pbr = 0;
2737 
2738  if (start >= fcb->adsdata.Length) {
2739  TRACE("tried to read beyond end of stream\n");
2740  return STATUS_END_OF_FILE;
2741  }
2742 
2743  if (length == 0) {
2744  WARN("tried to read zero bytes\n");
2745  return STATUS_SUCCESS;
2746  }
2747 
2748  if (start + length < fcb->adsdata.Length)
2749  readlen = length;
2750  else
2751  readlen = fcb->adsdata.Length - (ULONG)start;
2752 
2753  if (readlen > 0)
2754  RtlCopyMemory(data, fcb->adsdata.Buffer + start, readlen);
2755 
2756  if (pbr) *pbr = readlen;
2757 
2758  return STATUS_SUCCESS;
2759 }
#define WARN(fmt,...)
Definition: debug.h:112
#define STATUS_END_OF_FILE
Definition: shellext.h:67
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
#define TRACE(s)
Definition: solgame.cpp:4
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLuint start
Definition: gl.h:1545
ANSI_STRING adsdata
Definition: btrfs_drv.h:334
unsigned int ULONG
Definition: retypes.h:1
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define STATUS_SUCCESS
Definition: shellext.h:65

◆ _Dispatch_type_()

_Dispatch_type_ ( IRP_MJ_READ  )

Definition at line 3505 of file read.c.

3507  {
3508  device_extension* Vcb = DeviceObject->DeviceExtension;
3511  ULONG bytes_read = 0;
3512  NTSTATUS Status;
3513  bool top_level;
3514  fcb* fcb;
3515  ccb* ccb;
3516  bool acquired_fcb_lock = false, wait;
3517 
3519 
3520  top_level = is_top_level(Irp);
3521 
3522  TRACE("read\n");
3523 
3524  if (Vcb && Vcb->type == VCB_TYPE_VOLUME) {
3526  goto exit2;
3527  } else if (!Vcb || Vcb->type != VCB_TYPE_FS) {
3529  goto end;
3530  }
3531 
3532  Irp->IoStatus.Information = 0;
3533 
3535  CcMdlReadComplete(IrpSp->FileObject, Irp->MdlAddress);
3536 
3537  Irp->MdlAddress = NULL;
3539 
3540  goto exit;
3541  }
3542 
3543  fcb = FileObject->FsContext;
3544 
3545  if (!fcb) {
3546  ERR("fcb was NULL\n");
3548  goto exit;
3549  }
3550 
3551  ccb = FileObject->FsContext2;
3552 
3553  if (!ccb) {
3554  ERR("ccb was NULL\n");
3556  goto exit;
3557  }
3558 
3559  if (Irp->RequestorMode == UserMode && !(ccb->access & FILE_READ_DATA)) {
3560  WARN("insufficient privileges\n");
3562  goto exit;
3563  }
3564 
3565  if (fcb == Vcb->volume_fcb) {
3566  TRACE("reading volume FCB\n");
3567 
3569 
3570  Status = IoCallDriver(Vcb->Vpb->RealDevice, Irp);
3571 
3572  goto exit2;
3573  }
3574 
3575  if (!(Irp->Flags & IRP_PAGING_IO))
3577 
3578  wait = IoIsOperationSynchronous(Irp);
3579 
3580  // Don't offload jobs when doing paging IO - otherwise this can lead to
3581  // deadlocks in CcCopyRead.
3582  if (Irp->Flags & IRP_PAGING_IO)
3583  wait = true;
3584 
3585  if (!(Irp->Flags & IRP_PAGING_IO) && FileObject->SectionObjectPointer && FileObject->SectionObjectPointer->DataSectionObject) {
3587 
3588  CcFlushCache(FileObject->SectionObjectPointer, &IrpSp->Parameters.Read.ByteOffset, IrpSp->Parameters.Read.Length, &iosb);
3589  if (!NT_SUCCESS(iosb.Status)) {
3590  ERR("CcFlushCache returned %08lx\n", iosb.Status);
3591  return iosb.Status;
3592  }
3593  }
3594 
3595  if (!ExIsResourceAcquiredSharedLite(fcb->Header.Resource)) {
3596  if (!ExAcquireResourceSharedLite(fcb->Header.Resource, wait)) {
3599  goto exit;
3600  }
3601 
3602  acquired_fcb_lock = true;
3603  }
3604 
3605  Status = do_read(Irp, wait, &bytes_read);
3606 
3607  if (acquired_fcb_lock)
3608  ExReleaseResourceLite(fcb->Header.Resource);
3609 
3610 exit:
3611  if (FileObject->Flags & FO_SYNCHRONOUS_IO && !(Irp->Flags & IRP_PAGING_IO))
3612  FileObject->CurrentByteOffset.QuadPart = IrpSp->Parameters.Read.ByteOffset.QuadPart + (NT_SUCCESS(Status) ? bytes_read : 0);
3613 
3614 end:
3615  Irp->IoStatus.Status = Status;
3616 
3617  TRACE("Irp->IoStatus.Status = %08lx\n", Irp->IoStatus.Status);
3618  TRACE("Irp->IoStatus.Information = %Iu\n", Irp->IoStatus.Information);
3619  TRACE("returning %08lx\n", Status);
3620 
3621  if (Status != STATUS_PENDING)
3623  else {
3624  if (!add_thread_job(Vcb, Irp))
3625  Status = do_read_job(Irp);
3626  }
3627 
3628 exit2:
3629  if (top_level)
3631 
3633 
3634  return Status;
3635 }
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
#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:679
ACCESS_MASK access
Definition: btrfs_drv.h:382
BOOLEAN NTAPI IoIsOperationSynchronous(IN PIRP Irp)
Definition: irp.c:1882
bool is_top_level(_In_ PIRP Irp)
Definition: btrfs.c:277
NTSTATUS do_read(PIRP Irp, bool wait, ULONG *bytes_read)
Definition: read.c:3328
#define FO_SYNCHRONOUS_IO
Definition: iotypes.h:1776
#define IRP_MN_COMPLETE
Definition: iotypes.h:4420
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_In_ PIRP Irp
Definition: csq.h:116
#define FILE_READ_DATA
Definition: nt_native.h:628
VOID NTAPI CcMdlReadComplete(IN PFILE_OBJECT FileObject, IN PMDL MdlChain)
Definition: mdlsup.c:75
#define IoCompleteRequest
Definition: irp.c:1240
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:547
FSRTL_ADVANCED_FCB_HEADER Header
Definition: btrfs_drv.h:283
Status
Definition: gdiplustypes.h:24
bool add_thread_job(device_extension *Vcb, PIRP Irp)
#define TRACE(s)
Definition: solgame.cpp:4
struct _fcb fcb
Definition: btrfs_drv.h:1355
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
#define VCB_TYPE_VOLUME
Definition: btrfs_drv.h:681
#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:1998
GLuint GLuint end
Definition: gl.h:1545
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:2793
PFILE_OBJECT FileObject
Definition: iotypes.h:3169
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4137
#define NULL
Definition: types.h:112
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:1670
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:598
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:1170
#define STATUS_SUCCESS
Definition: shellext.h:65
void exit(int exitcode)
Definition: _exit.c:33
struct _ccb ccb
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:3128
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:7251
Definition: write.c:113
if(dx==0 &&dy==0)
Definition: linetemp.h:174
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_In_ PIRP Irp
Definition: csq.h:116
#define UNUSED(x)
Definition: btrfs_drv.h:82
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define InterlockedDecrement
Definition: armddk.h:52

◆ 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:87
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: ffs.h:52
#define STATUS_SUCCESS
Definition: shellext.h:65
#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 }
#define CSUM_TYPE_BLAKE2
Definition: btrfs.h:135
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:132
void calc_sha256(uint8_t *hash, const void *input, size_t len)
Definition: sha256.c:126
#define SHA256_HASH_SIZE
Definition: btrfs_drv.h:1239
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
#define Vcb
Definition: cdprocs.h:1415
#define CSUM_TYPE_XXHASH
Definition: btrfs.h:133
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:134
UINT64 uint64_t
Definition: types.h:77
UINT32 uint32_t
Definition: types.h:75
#define crc32(crc, buf, len)
Definition: inflate.c:1081
Definition: ffs.h:52
#define BLAKE2_HASH_SIZE
Definition: btrfs_drv.h:1243
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:135
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:154
#define CSUM_TYPE_CRC32C
Definition: btrfs.h:132
void calc_sha256(uint8_t *hash, const void *input, size_t len)
Definition: sha256.c:126
#define SHA256_HASH_SIZE
Definition: btrfs_drv.h:1239
#define Vcb
Definition: cdprocs.h:1415
#define CSUM_TYPE_XXHASH
Definition: btrfs.h:133
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:134
UINT64 uint64_t
Definition: types.h:77
BTRFS_UUID fs_uuid
Definition: btrfs.h:155
UINT32 uint32_t
Definition: types.h:75
#define crc32(crc, buf, len)
Definition: inflate.c:1081
#define BLAKE2_HASH_SIZE
Definition: btrfs_drv.h:1243
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 3328 of file read.c.

3328  {
3331  fcb* fcb = FileObject->FsContext;
3332  uint8_t* data = NULL;
3333  ULONG length = IrpSp->Parameters.Read.Length, addon = 0;
3334  uint64_t start = IrpSp->Parameters.Read.ByteOffset.QuadPart;
3335 
3336  *bytes_read = 0;
3337 
3338  if (!fcb || !fcb->Vcb || !fcb->subvol)
3339  return STATUS_INTERNAL_ERROR;
3340 
3341  TRACE("fcb = %p\n", fcb);
3342  TRACE("offset = %I64x, length = %lx\n", start, length);
3343  TRACE("paging_io = %s, no cache = %s\n", Irp->Flags & IRP_PAGING_IO ? "true" : "false", Irp->Flags & IRP_NOCACHE ? "true" : "false");
3344 
3345  if (!fcb->ads && fcb->type == BTRFS_TYPE_DIRECTORY)
3347 
3348  if (!(Irp->Flags & IRP_PAGING_IO) && !FsRtlCheckLockForReadAccess(&fcb->lock, Irp)) {
3349  WARN("tried to read locked region\n");
3351  }
3352 
3353  if (length == 0) {
3354  TRACE("tried to read zero bytes\n");
3355  return STATUS_SUCCESS;
3356  }
3357 
3358  if (start >= (uint64_t)fcb->Header.FileSize.QuadPart) {
3359  TRACE("tried to read with offset after file end (%I64x >= %I64x)\n", start, fcb->Header.FileSize.QuadPart);
3360  return STATUS_END_OF_FILE;
3361  }
3362 
3363  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);
3364 
3365  if (!(Irp->Flags & IRP_NOCACHE) && IrpSp->MinorFunction & IRP_MN_MDL) {
3367 
3368  _SEH2_TRY {
3369  if (!FileObject->PrivateCacheMap) {
3370  CC_FILE_SIZES ccfs;
3371 
3372  ccfs.AllocationSize = fcb->Header.AllocationSize;
3373  ccfs.FileSize = fcb->Header.FileSize;
3374  ccfs.ValidDataLength = fcb->Header.ValidDataLength;
3375 
3376  init_file_cache(FileObject, &ccfs);
3377  }
3378 
3379  CcMdlRead(FileObject, &IrpSp->Parameters.Read.ByteOffset, length, &Irp->MdlAddress, &Irp->IoStatus);
3382  } _SEH2_END;
3383 
3384  if (NT_SUCCESS(Status)) {
3385  Status = Irp->IoStatus.Status;
3386  Irp->IoStatus.Information += addon;
3387  *bytes_read = (ULONG)Irp->IoStatus.Information;
3388  } else
3389  ERR("EXCEPTION - %08lx\n", Status);
3390 
3391  return Status;
3392  }
3393 
3395 
3396  if (Irp->MdlAddress && !data) {
3397  ERR("MmGetSystemAddressForMdlSafe returned NULL\n");
3399  }
3400 
3401  if (start >= (uint64_t)fcb->Header.ValidDataLength.QuadPart) {
3402  length = (ULONG)min(length, min(start + length, (uint64_t)fcb->Header.FileSize.QuadPart) - fcb->Header.ValidDataLength.QuadPart);
3404  Irp->IoStatus.Information = *bytes_read = length;
3405  return STATUS_SUCCESS;
3406  }
3407 
3408  if (length + start > (uint64_t)fcb->Header.ValidDataLength.QuadPart) {
3409  addon = (ULONG)(min(start + length, (uint64_t)fcb->Header.FileSize.QuadPart) - fcb->Header.ValidDataLength.QuadPart);
3410  RtlZeroMemory(data + (fcb->Header.ValidDataLength.QuadPart - start), addon);
3411  length = (ULONG)(fcb->Header.ValidDataLength.QuadPart - start);
3412  }
3413 
3414  if (!(Irp->Flags & IRP_NOCACHE)) {
3416 
3417  _SEH2_TRY {
3418  if (!FileObject->PrivateCacheMap) {
3419  CC_FILE_SIZES ccfs;
3420 
3421  ccfs.AllocationSize = fcb->Header.AllocationSize;
3422  ccfs.FileSize = fcb->Header.FileSize;
3423  ccfs.ValidDataLength = fcb->Header.ValidDataLength;
3424 
3425  init_file_cache(FileObject, &ccfs);
3426  }
3427 
3428  if (fCcCopyReadEx) {
3429  TRACE("CcCopyReadEx(%p, %I64x, %lx, %u, %p, %p, %p)\n", FileObject, IrpSp->Parameters.Read.ByteOffset.QuadPart,
3430  length, wait, data, &Irp->IoStatus, Irp->Tail.Overlay.Thread);
3431  TRACE("sizes = %I64x, %I64x, %I64x\n", fcb->Header.AllocationSize.QuadPart, fcb->Header.FileSize.QuadPart, fcb->Header.ValidDataLength.QuadPart);
3432  if (!fCcCopyReadEx(FileObject, &IrpSp->Parameters.Read.ByteOffset, length, wait, data, &Irp->IoStatus, Irp->Tail.Overlay.Thread)) {
3433  TRACE("CcCopyReadEx could not wait\n");
3434 
3436  return STATUS_PENDING;
3437  }
3438  TRACE("CcCopyReadEx finished\n");
3439  } else {
3440  TRACE("CcCopyRead(%p, %I64x, %lx, %u, %p, %p)\n", FileObject, IrpSp->Parameters.Read.ByteOffset.QuadPart, length, wait, data, &Irp->IoStatus);
3441  TRACE("sizes = %I64x, %I64x, %I64x\n", fcb->Header.AllocationSize.QuadPart, fcb->Header.FileSize.QuadPart, fcb->Header.ValidDataLength.QuadPart);
3442  if (!CcCopyRead(FileObject, &IrpSp->Parameters.Read.ByteOffset, length, wait, data, &Irp->IoStatus)) {
3443  TRACE("CcCopyRead could not wait\n");
3444 
3446  return STATUS_PENDING;
3447  }
3448  TRACE("CcCopyRead finished\n");
3449  }
3452  } _SEH2_END;
3453 
3454  if (NT_SUCCESS(Status)) {
3455  Status = Irp->IoStatus.Status;
3456  Irp->IoStatus.Information += addon;
3457  *bytes_read = (ULONG)Irp->IoStatus.Information;
3458  } else
3459  ERR("EXCEPTION - %08lx\n", Status);
3460 
3461  return Status;
3462  } else {
3463  NTSTATUS Status;
3464 
3465  if (!wait) {
3467  return STATUS_PENDING;
3468  }
3469 
3470  if (fcb->ads) {
3471  Status = read_stream(fcb, data, start, length, bytes_read);
3472 
3473  if (!NT_SUCCESS(Status))
3474  ERR("read_stream returned %08lx\n", Status);
3475  } else {
3476  Status = read_file(fcb, data, start, length, bytes_read, Irp);
3477 
3478  if (!NT_SUCCESS(Status))
3479  ERR("read_file returned %08lx\n", Status);
3480  }
3481 
3482  *bytes_read += addon;
3483  TRACE("read %lu bytes\n", *bytes_read);
3484 
3485  Irp->IoStatus.Information = *bytes_read;
3486 
3487  if (diskacc && Status != STATUS_PENDING) {
3488  PETHREAD thread = NULL;
3489 
3490  if (Irp->Tail.Overlay.Thread && !IoIsSystemThread(Irp->Tail.Overlay.Thread))
3491  thread = Irp->Tail.Overlay.Thread;
3492  else if (!IoIsSystemThread(PsGetCurrentThread()))
3496 
3497  if (thread)
3498  fPsUpdateDiskCounters(PsGetThreadProcess(thread), *bytes_read, 0, 1, 0, 0);
3499  }
3500 
3501  return Status;
3502  }
3503 }
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:4038
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
#define FSRTL_FLAG2_IS_PAGING_FILE
Definition: fsrtltypes.h:57
#define WARN(fmt,...)
Definition: debug.h:112
LONG NTSTATUS
Definition: precomp.h:26
NTSTATUS read_file(fcb *fcb, uint8_t *data, uint64_t start, uint64_t length, ULONG *pbr, PIRP Irp) __attribute__((nonnull(1
#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
_In_ PIRP Irp
Definition: csq.h:116
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
#define BTRFS_TYPE_DIRECTORY
Definition: shellext.h:86
uint8_t type
Definition: btrfs_drv.h:291
tPsUpdateDiskCounters fPsUpdateDiskCounters
Definition: btrfs.c:89
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:547
FILE_LOCK lock
Definition: btrfs_drv.h:294
FSRTL_ADVANCED_FCB_HEADER Header
Definition: btrfs_drv.h:283
Status
Definition: gdiplustypes.h:24
uint64_t st_size
Definition: btrfs.h:289
#define TRACE(s)
Definition: solgame.cpp:4
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
BOOLEAN NTAPI FsRtlCheckLockForReadAccess(IN PFILE_LOCK FileLock, IN PIRP Irp)
Definition: filelock.c:672
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
static __inline void * map_user_buffer(PIRP Irp, ULONG priority)
Definition: btrfs_drv.h:969
PIRP NTAPI IoGetTopLevelIrp(VOID)
Definition: irp.c:1843
* PFILE_OBJECT
Definition: iotypes.h:1998
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
static HANDLE thread
Definition: service.c:33
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:4419
LARGE_INTEGER ValidDataLength
Definition: cctypes.h:17
INODE_ITEM inode_item
Definition: btrfs_drv.h:292
BYTE uint8_t
Definition: msvideo1.c:66
#define ERR(fmt,...)
Definition: debug.h:110
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2793
PFILE_OBJECT FileObject
Definition: iotypes.h:3169
_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:288
#define min(a, b)
Definition: monoChain.cc:55
#define NULL
Definition: types.h:112
HRESULT read_stream(BSCallback *, IStream *, void *, DWORD, DWORD *) DECLSPEC_HIDDEN
Definition: navigate.c:602
#define IRP_PAGING_IO
bool ads
Definition: btrfs_drv.h:330
#define STATUS_FILE_LOCK_CONFLICT
Definition: ntstatus.h:320
tCcCopyReadEx fCcCopyReadEx
Definition: btrfs.c:90
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:40
#define STATUS_SUCCESS
Definition: shellext.h:65
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:165
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:3128
IoMarkIrpPending(Irp)
struct _device_extension * Vcb
Definition: btrfs_drv.h:287
bool diskacc
Definition: btrfs.c:100

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 }
#define CSUM_TYPE_BLAKE2
Definition: btrfs.h:135
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:132
void calc_sha256(uint8_t *hash, const void *input, size_t len)
Definition: sha256.c:126
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
#define Vcb
Definition: cdprocs.h:1415
#define CSUM_TYPE_XXHASH
Definition: btrfs.h:133
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:134
UINT64 uint64_t
Definition: types.h:77
UINT32 uint32_t
Definition: types.h:75
Definition: ffs.h:52
#define BLAKE2_HASH_SIZE
Definition: btrfs_drv.h:1243

Referenced by add_csum_sparse_extents(), 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:135
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:154
#define CSUM_TYPE_CRC32C
Definition: btrfs.h:132
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:133
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:134
UINT64 uint64_t
Definition: types.h:77
BTRFS_UUID fs_uuid
Definition: btrfs.h:155
UINT32 uint32_t
Definition: types.h:75
Definition: ffs.h:52
#define BLAKE2_HASH_SIZE
Definition: btrfs_drv.h:1243

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 918 of file read.c.

918  {
919  if (missing1 == num_stripes - 2 || missing2 == num_stripes - 2) { // reconstruct from q and data
920  uint16_t missing = missing1 == (num_stripes - 2) ? missing2 : missing1;
922 
923  stripe = num_stripes - 3;
924 
925  if (stripe == missing)
927  else
929 
930  do {
931  stripe--;
932 
934 
935  if (stripe != missing)
937  } while (stripe > 0);
938 
939  do_xor(out, sectors + ((num_stripes - 1) * sector_size), sector_size);
940 
941  if (missing != 0)
943  } else { // reconstruct from p and q
944  uint16_t x = missing1, y = missing2, stripe;
945  uint8_t gyx, gx, denom, a, b, *p, *q, *pxy, *qxy;
946  uint32_t j;
947 
948  stripe = num_stripes - 3;
949 
950  pxy = out + sector_size;
951  qxy = out;
952 
953  if (stripe == missing1 || stripe == missing2) {
956  } else {
959  }
960 
961  do {
962  stripe--;
963 
965 
966  if (stripe != missing1 && stripe != missing2) {
969  }
970  } while (stripe > 0);
971 
972  gyx = gpow2(y > x ? (y-x) : (255-x+y));
973  gx = gpow2(255-x);
974 
975  denom = gdiv(1, gyx ^ 1);
976  a = gmul(gyx, denom);
977  b = gmul(gx, denom);
978 
979  p = sectors + ((num_stripes - 2) * sector_size);
980  q = sectors + ((num_stripes - 1) * sector_size);
981 
982  for (j = 0; j < sector_size; j++) {
983  *qxy = gmul(a, *p ^ *pxy) ^ gmul(b, *q ^ *qxy);
984 
985  p++;
986  q++;
987  pxy++;
988  qxy++;
989  }
990 
992  do_xor(out + sector_size, sectors + ((num_stripes - 2) * sector_size), sector_size);
993  }
994 }
void galois_double(uint8_t *data, uint32_t len)
Definition: galois.c:109
Definition: write.c:113
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
xor_func do_xor
Definition: btrfs.c:126
__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
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
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 1478 of file read.c.

1480  {
1481  CHUNK_ITEM* ci;
1482  CHUNK_ITEM_STRIPE* cis;
1484  uint64_t type, offset, total_reading = 0;
1485  NTSTATUS Status;
1486  device** devices = NULL;
1487  uint16_t i, startoffstripe, allowed_missing, missing_devices = 0;
1488  uint8_t* dummypage = NULL;
1489  PMDL dummy_mdl = NULL;
1490  bool need_to_wait;
1491  uint64_t lockaddr, locklen;
1492 
1493  if (Vcb->log_to_phys_loaded) {
1494  if (!c) {
1496 
1497  if (!c) {
1498  ERR("get_chunk_from_address failed\n");
1499  return STATUS_INTERNAL_ERROR;
1500  }
1501  }
1502 
1503  ci = c->chunk_item;
1504  offset = c->offset;
1505  devices = c->devices;
1506 
1507  if (pc)
1508  *pc = c;
1509  } else {
1510  LIST_ENTRY* le = Vcb->sys_chunks.Flink;
1511 
1512  ci = NULL;
1513 
1514  c = NULL;
1515  while (le != &Vcb->sys_chunks) {
1517 
1518  if (sc->key.obj_id == 0x100 && sc->key.obj_type == TYPE_CHUNK_ITEM && sc->key.offset <= addr) {
1519  CHUNK_ITEM* chunk_item = sc->data;
1520 
1521  if ((addr - sc->key.offset) < chunk_item->size && chunk_item->num_stripes > 0) {
1522  ci = chunk_item;
1523  offset = sc->key.offset;
1524  cis = (CHUNK_ITEM_STRIPE*)&chunk_item[1];
1525 
1527  if (!devices) {
1528  ERR("out of memory\n");
1530  }
1531 
1532  for (i = 0; i < ci->num_stripes; i++) {
1533  devices[i] = find_device_from_uuid(Vcb, &cis[i].dev_uuid);
1534  }
1535 
1536  break;
1537  }
1538  }
1539 
1540  le = le->Flink;
1541  }
1542 
1543  if (!ci) {
1544  ERR("could not find chunk for %I64x in bootstrap\n", addr);
1545  return STATUS_INTERNAL_ERROR;
1546  }
1547 
1548  if (pc)
1549  *pc = NULL;
1550  }
1551 
1552  if (ci->type & BLOCK_FLAG_DUPLICATE) {
1554  allowed_missing = ci->num_stripes - 1;
1555  } else if (ci->type & BLOCK_FLAG_RAID0) {
1557  allowed_missing = 0;
1558  } else if (ci->type & BLOCK_FLAG_RAID1) {
1560  allowed_missing = 1;
1561  } else if (ci->type & BLOCK_FLAG_RAID10) {
1563  allowed_missing = 1;
1564  } else if (ci->type & BLOCK_FLAG_RAID5) {
1566  allowed_missing = 1;
1567  } else if (ci->type & BLOCK_FLAG_RAID6) {
1569  allowed_missing = 2;
1570  } else if (ci->type & BLOCK_FLAG_RAID1C3) {
1572  allowed_missing = 2;
1573  } else if (ci->type & BLOCK_FLAG_RAID1C4) {
1575  allowed_missing = 3;
1576  } else { // SINGLE
1578  allowed_missing = 0;
1579  }
1580 
1581  cis = (CHUNK_ITEM_STRIPE*)&ci[1];
1582 
1585 
1587  if (!context.stripes) {
1588  ERR("out of memory\n");
1590  }
1591 
1592  if (c && (type == BLOCK_FLAG_RAID5 || type == BLOCK_FLAG_RAID6)) {
1593  get_raid56_lock_range(c, addr, length, &lockaddr, &locklen);
1594  chunk_lock_range(Vcb, c, lockaddr, locklen);
1595  }
1596 
1597  RtlZeroMemory(context.stripes, sizeof(read_data_stripe) * ci->num_stripes);
1598 
1599  context.buflen = length;
1600  context.num_stripes = ci->num_stripes;
1601  context.stripes_left = context.num_stripes;
1602  context.sector_size = Vcb->superblock.sector_size;
1603  context.csum = csum;
1604  context.tree = is_tree;
1605  context.type = type;
1606 
1607  if (type == BLOCK_FLAG_RAID0) {
1608  uint64_t startoff, endoff;
1609  uint16_t endoffstripe, stripe;
1610  uint32_t *stripeoff, pos;
1611  PMDL master_mdl;
1612  PFN_NUMBER* pfns;
1613 
1614  // FIXME - test this still works if page size isn't the same as sector size
1615 
1616  // This relies on the fact that MDLs are followed in memory by the page file numbers,
1617  // so with a bit of jiggery-pokery you can trick your disks into deinterlacing your RAID0
1618  // data for you without doing a memcpy yourself.
1619  // MDLs are officially opaque, so this might very well break in future versions of Windows.
1620 
1621  get_raid0_offset(addr - offset, ci->stripe_length, ci->num_stripes, &startoff, &startoffstripe);
1622  get_raid0_offset(addr + length - offset - 1, ci->stripe_length, ci->num_stripes, &endoff, &endoffstripe);
1623 
1624  if (file_read) {
1625  // Unfortunately we can't avoid doing at least one memcpy, as Windows can give us an MDL
1626  // with duplicated dummy PFNs, which confuse check_csum. Ah well.
1627  // See https://msdn.microsoft.com/en-us/library/windows/hardware/Dn614012.aspx if you're interested.
1628 
1630 
1631  if (!context.va) {
1632  ERR("out of memory\n");
1634  goto exit;
1635  }
1636  } else
1637  context.va = buf;
1638 
1639  master_mdl = IoAllocateMdl(context.va, length, false, false, NULL);
1640  if (!master_mdl) {
1641  ERR("out of memory\n");
1643  goto exit;
1644  }
1645 
1647 
1648  _SEH2_TRY {
1652  } _SEH2_END;
1653 
1654  if (!NT_SUCCESS(Status)) {
1655  ERR("MmProbeAndLockPages threw exception %08lx\n", Status);
1656  IoFreeMdl(master_mdl);
1657  goto exit;
1658  }
1659 
1660  pfns = (PFN_NUMBER*)(master_mdl + 1);
1661 
1662  for (i = 0; i < ci->num_stripes; i++) {
1663  if (startoffstripe > i)
1664  context.stripes[i].stripestart = startoff - (startoff % ci->stripe_length) + ci->stripe_length;
1665  else if (startoffstripe == i)
1666  context.stripes[i].stripestart = startoff;
1667  else
1668  context.stripes[i].stripestart = startoff - (startoff % ci->stripe_length);
1669 
1670  if (endoffstripe > i)
1671  context.stripes[i].stripeend = endoff - (endoff % ci->stripe_length) + ci->stripe_length;
1672  else if (endoffstripe == i)
1673  context.stripes[i].stripeend = endoff + 1;
1674  else
1675  context.stripes[i].stripeend = endoff - (endoff % ci->stripe_length);
1676 
1677  if (context.stripes[i].stripestart != context.stripes[i].stripeend) {
1678  context.stripes[i].mdl = IoAllocateMdl(context.va, (ULONG)(context.stripes[i].stripeend - context.stripes[i].stripestart), false, false, NULL);
1679 
1680  if (!context.stripes[i].mdl) {
1681  ERR("IoAllocateMdl failed\n");
1682  MmUnlockPages(master_mdl);
1683  IoFreeMdl(master_mdl);
1685  goto exit;
1686  }
1687  }
1688  }
1689 
1690  stripeoff = ExAllocatePoolWithTag(NonPagedPool, sizeof(uint32_t) * ci->num_stripes, ALLOC_TAG);
1691  if (!stripeoff) {
1692  ERR("out of memory\n");
1693  MmUnlockPages(master_mdl);
1694  IoFreeMdl(master_mdl);
1696  goto exit;
1697  }
1698 
1699  RtlZeroMemory(stripeoff, sizeof(uint32_t) * ci->num_stripes);
1700 
1701  pos = 0;
1702  stripe = startoffstripe;
1703  while (pos < length) {
1704  PFN_NUMBER* stripe_pfns = (PFN_NUMBER*)(context.stripes[stripe].mdl + 1);
1705 
1706  if (pos == 0) {
1707  uint32_t readlen = (uint32_t)min(context.stripes[stripe].stripeend - context.stripes[stripe].stripestart, ci->stripe_length - (context.stripes[stripe].stripestart % ci->stripe_length));
1708 
1709  RtlCopyMemory(stripe_pfns, pfns, readlen * sizeof(PFN_NUMBER) >> PAGE_SHIFT);
1710 
1711  stripeoff[stripe] += readlen;
1712  pos += readlen;
1713  } else if (length - pos < ci->stripe_length) {
1714  RtlCopyMemory(&stripe_pfns[stripeoff[stripe] >> PAGE_SHIFT], &pfns[pos >> PAGE_SHIFT], (length - pos) * sizeof(PFN_NUMBER) >> PAGE_SHIFT);
1715 
1716  pos = length;
1717  } else {
1718  RtlCopyMemory(&stripe_pfns[stripeoff[stripe] >> PAGE_SHIFT], &pfns[pos >> PAGE_SHIFT], (ULONG)(ci->stripe_length * sizeof(PFN_NUMBER) >> PAGE_SHIFT));
1719 
1720  stripeoff[stripe] += (uint32_t)ci->stripe_length;
1721  pos += (uint32_t)ci->stripe_length;
1722  }
1723 
1724  stripe = (stripe + 1) % ci->num_stripes;
1725  }
1726 
1727  MmUnlockPages(master_mdl);
1728  IoFreeMdl(master_mdl);
1729 
1730  ExFreePool(stripeoff);
1731  } else if (type == BLOCK_FLAG_RAID10) {
1732  uint64_t startoff, endoff;
1733  uint16_t endoffstripe, j, stripe;
1734  ULONG orig_ls;
1735  PMDL master_mdl;
1736  PFN_NUMBER* pfns;
1737  uint32_t* stripeoff, pos;
1738  read_data_stripe** stripes;
1739 
1740  if (c)
1741  orig_ls = c->last_stripe;
1742  else
1743  orig_ls = 0;
1744 
1745  get_raid0_offset(addr - offset, ci->stripe_length, ci->num_stripes / ci->sub_stripes, &startoff, &startoffstripe);
1746  get_raid0_offset(addr + length - offset - 1, ci->stripe_length, ci->num_stripes / ci->sub_stripes, &endoff, &endoffstripe);
1747 
1748  if ((ci->num_stripes % ci->sub_stripes) != 0) {
1749  ERR("chunk %I64x: num_stripes %x was not a multiple of sub_stripes %x!\n", offset, ci->num_stripes, ci->sub_stripes);
1751  goto exit;
1752  }
1753 
1754  if (file_read) {
1756 
1757  if (!context.va) {
1758  ERR("out of memory\n");
1760  goto exit;
1761  }
1762  } else
1763  context.va = buf;
1764 
1765  context.firstoff = (uint16_t)((startoff % ci->stripe_length) >> Vcb->sector_shift);
1766  context.startoffstripe = startoffstripe;
1767  context.sectors_per_stripe = (uint16_t)(ci->stripe_length >> Vcb->sector_shift);
1768 
1769  startoffstripe *= ci->sub_stripes;
1770  endoffstripe *= ci->sub_stripes;
1771 
1772  if (c)
1773  c->last_stripe = (orig_ls + 1) % ci->sub_stripes;
1774 
1775  master_mdl = IoAllocateMdl(context.va, length, false, false, NULL);
1776  if (!master_mdl) {
1777  ERR("out of memory\n");
1779  goto exit;
1780  }
1781 
1783 
1784  _SEH2_TRY {
1788  } _SEH2_END;
1789 
1790  if (!NT_SUCCESS(Status)) {
1791  ERR("MmProbeAndLockPages threw exception %08lx\n", Status);
1792  IoFreeMdl(master_mdl);
1793  goto exit;
1794  }
1795 
1796  pfns = (PFN_NUMBER*)(master_mdl + 1);
1797 
1799  if (!stripes) {
1800  ERR("out of memory\n");
1801  MmUnlockPages(master_mdl);
1802  IoFreeMdl(master_mdl);
1804  goto exit;
1805  }
1806 
1807  RtlZeroMemory(stripes, sizeof(read_data_stripe*) * ci->num_stripes / ci->sub_stripes);
1808 
1809  for (i = 0; i < ci->num_stripes; i += ci->sub_stripes) {
1810  uint64_t sstart, send;
1811  bool stripeset = false;
1812 
1813  if (startoffstripe > i)
1814  sstart = startoff - (startoff % ci->stripe_length) + ci->stripe_length;
1815  else if (startoffstripe == i)
1816  sstart = startoff;
1817  else
1818  sstart = startoff - (startoff % ci->stripe_length);
1819 
1820  if (endoffstripe > i)
1821  send = endoff - (endoff % ci->stripe_length) + ci->stripe_length;
1822  else if (endoffstripe == i)
1823  send = endoff + 1;
1824  else
1825  send = endoff - (endoff % ci->stripe_length);
1826 
1827  for (j = 0; j < ci->sub_stripes; j++) {
1828  if (j == orig_ls && devices[i+j] && devices[i+j]->devobj) {
1829  context.stripes[i+j].stripestart = sstart;
1830  context.stripes[i+j].stripeend = send;
1831  stripes[i / ci->sub_stripes] = &context.stripes[i+j];
1832 
1833  if (sstart != send) {
1834  context.stripes[i+j].mdl = IoAllocateMdl(context.va, (ULONG)(send - sstart), false, false, NULL);
1835 
1836  if (!context.stripes[i+j].mdl) {
1837  ERR("IoAllocateMdl failed\n");
1838  MmUnlockPages(master_mdl);
1839  IoFreeMdl(master_mdl);
1841  goto exit;
1842  }
1843  }
1844 
1845  stripeset = true;
1846  } else
1847  context.stripes[i+j].status = ReadDataStatus_Skip;
1848  }
1849 
1850  if (!stripeset) {
1851  for (j = 0; j < ci->sub_stripes; j++) {
1852  if (devices[i+j] && devices[i+j]->devobj) {
1853  context.stripes[i+j].stripestart = sstart;
1854  context.stripes[i+j].stripeend = send;
1855  context.stripes[i+j].status = ReadDataStatus_Pending;
1856  stripes[i / ci->sub_stripes] = &context.stripes[i+j];
1857 
1858  if (sstart != send) {
1859  context.stripes[i+j].mdl = IoAllocateMdl(context.va, (ULONG)(send - sstart), false, false, NULL);
1860 
1861  if (!context.stripes[i+j].mdl) {
1862  ERR("IoAllocateMdl failed\n");
1863  MmUnlockPages(master_mdl);
1864  IoFreeMdl(master_mdl);
1866  goto exit;
1867  }
1868  }
1869 
1870  stripeset = true;
1871  break;
1872  }
1873  }
1874 
1875  if (!stripeset) {
1876  ERR("could not find stripe to read\n");
1878  goto exit;
1879  }
1880  }
1881  }
1882 
1883  stripeoff = ExAllocatePoolWithTag(NonPagedPool, sizeof(uint32_t) * ci->num_stripes / ci->sub_stripes, ALLOC_TAG);
1884  if (!stripeoff) {
1885  ERR("out of memory\n");
1886  MmUnlockPages(master_mdl);
1887  IoFreeMdl(master_mdl);
1889  goto exit;
1890  }
1891 
1892  RtlZeroMemory(stripeoff, sizeof(uint32_t) * ci->num_stripes / ci->sub_stripes);
1893 
1894  pos = 0;
1895  stripe = startoffstripe / ci->sub_stripes;
1896  while (pos < length) {
1897  PFN_NUMBER* stripe_pfns = (PFN_NUMBER*)(stripes[stripe]->mdl + 1);
1898 
1899  if (pos == 0) {
1900  uint32_t readlen = (uint32_t)min(stripes[stripe]->stripeend - stripes[stripe]->stripestart,
1901  ci->stripe_length - (stripes[stripe]->stripestart % ci->stripe_length));
1902 
1903  RtlCopyMemory(stripe_pfns, pfns, readlen * sizeof(PFN_NUMBER) >> PAGE_SHIFT);
1904 
1905  stripeoff[stripe] += readlen;
1906  pos += readlen;
1907  } else if (length - pos < ci->stripe_length) {
1908  RtlCopyMemory(&stripe_pfns[stripeoff[stripe] >> PAGE_SHIFT], &pfns[pos >> PAGE_SHIFT], (length - pos) * sizeof(PFN_NUMBER) >> PAGE_SHIFT);
1909 
1910  pos = length;
1911  } else {
1912  RtlCopyMemory(&stripe_pfns[stripeoff[stripe] >> PAGE_SHIFT], &pfns[pos >> PAGE_SHIFT], (ULONG)(ci->stripe_length * sizeof(PFN_NUMBER) >> PAGE_SHIFT));
1913 
1914  stripeoff[stripe] += (ULONG)ci->stripe_length;
1915  pos += (ULONG)ci->stripe_length;
1916  }
1917 
1918  stripe = (stripe + 1) % (ci->num_stripes / ci->sub_stripes);
1919  }
1920 
1921  MmUnlockPages(master_mdl);
1922  IoFreeMdl(master_mdl);
1923 
1924  ExFreePool(stripeoff);
1925  ExFreePool(stripes);
1926  } else if (type == BLOCK_FLAG_DUPLICATE) {
1927  uint64_t orig_ls;
1928 
1929  if (c)
1930  orig_ls = i = c->last_stripe;
1931  else
1932  orig_ls = i = 0;
1933 
1934  while (!devices[i] || !devices[i]->devobj) {
1935  i = (i + 1) % ci->num_stripes;
1936 
1937  if (i == orig_ls) {
1938  ERR("no devices available to service request\n");
1940  goto exit;
1941  }
1942  }
1943 
1944  if (c)
1945  c->last_stripe = (i + 1) % ci->num_stripes;
1946 
1947  context.stripes[i].stripestart = addr - offset;
1948  context.stripes[i].stripeend = context.stripes[i].stripestart + length;
1949 
1950  if (file_read) {
1952 
1953  if (!context.va) {
1954  ERR("out of memory\n");
1956  goto exit;
1957  }
1958 
1959  context.stripes[i].mdl = IoAllocateMdl(context.va, length, false, false, NULL);
1960  if (!context.stripes[i].mdl) {
1961  ERR("IoAllocateMdl failed\n");
1963  goto exit;
1964  }
1965 
1966  MmBuildMdlForNonPagedPool(context.stripes[i].mdl);
1967  } else {
1968  context.stripes[i].mdl = IoAllocateMdl(buf, length, false, false, NULL);
1969 
1970  if (!context.stripes[i].mdl) {
1971  ERR("IoAllocateMdl failed\n");
1973  goto exit;
1974  }
1975 
1977 
1978  _SEH2_TRY {
1982  } _SEH2_END;
1983 
1984  if (!NT_SUCCESS(Status)) {
1985  ERR("MmProbeAndLockPages threw exception %08lx\n", Status);
1986  goto exit;
1987  }
1988  }
1989  } else if (type == BLOCK_FLAG_RAID5) {
1990  uint64_t startoff, endoff;
1991  uint16_t endoffstripe, parity;
1992  uint32_t *stripeoff, pos;
1993  PMDL master_mdl;
1994  PFN_NUMBER *pfns, dummy = 0;
1995  bool need_dummy = false;
1996 
1997  get_raid0_offset(addr - offset, ci->stripe_length, ci->num_stripes - 1, &startoff, &startoffstripe);
1998  get_raid0_offset(addr + length - offset - 1, ci->stripe_length, ci->num_stripes - 1, &endoff, &endoffstripe);
1999 
2000  if (file_read) {
2002 
2003  if (!context.va) {
2004  ERR("out of memory\n");
2006  goto exit;
2007  }
2008  } else
2009  context.va = buf;
2010 
2011  master_mdl = IoAllocateMdl(context.va, length, false, false, NULL);
2012  if (!master_mdl) {
2013  ERR("out of memory\n");
2015  goto exit;
2016  }
2017 
2019 
2020  _SEH2_TRY {
2024  } _SEH2_END;
2025 
2026  if (!NT_SUCCESS(Status)) {
2027  ERR("MmProbeAndLockPages threw exception %08lx\n", Status);
2028  IoFreeMdl(master_mdl);
2029  goto exit;
2030  }
2031 
2032  pfns = (PFN_NUMBER*)(master_mdl + 1);
2033 
2034  pos = 0;
2035  while (pos < length) {
2036  parity = (((addr - offset + pos) / ((ci->num_stripes - 1) * ci->stripe_length)) + ci->num_stripes - 1) % ci->num_stripes;
2037 
2038  if (pos == 0) {
2039  uint16_t stripe = (parity + startoffstripe + 1) % ci->num_stripes;
2040  ULONG skip, readlen;
2041 
2042  i = startoffstripe;
2043  while (stripe != parity) {
2044  if (i == startoffstripe) {
2045  readlen = min(length, (ULONG)(ci->stripe_length - (startoff % ci->stripe_length)));
2046 
2047  context.stripes[stripe].stripestart = startoff;
2048  context.stripes[stripe].stripeend = startoff + readlen;
2049 
2050  pos += readlen;
2051 
2052  if (pos == length)
2053  break;
2054  } else {
2055  readlen = min(length - pos, (ULONG)ci->stripe_length);
2056 
2057  context.stripes[stripe].stripestart = startoff - (startoff % ci->stripe_length);
2058  context.stripes[stripe].stripeend = context.stripes[stripe].stripestart + readlen;
2059 
2060  pos += readlen;
2061 
2062  if (pos == length)
2063  break;
2064  }
2065 
2066  i++;
2067  stripe = (stripe + 1) % ci->num_stripes;
2068  }
2069 
2070  if (pos == length)
2071  break;
2072 
2073  for (i = 0; i < startoffstripe; i++) {
2074  uint16_t stripe2 = (parity + i + 1) % ci->num_stripes;
2075 
2076  context.stripes[stripe2].stripestart = context.stripes[stripe2].stripeend = startoff - (startoff % ci->stripe_length) + ci->stripe_length;
2077  }
2078 
2079  context.stripes[parity].stripestart = context.stripes[parity].stripeend = startoff - (startoff % ci->stripe_length) + ci->stripe_length;
2080 
2081  if (length - pos > ci->num_stripes * (ci->num_stripes - 1) * ci->stripe_length) {
2082  skip = (ULONG)(((length - pos) / (ci->num_stripes * (ci->num_stripes - 1) * ci->stripe_length)) - 1);
2083 
2084  for (i = 0; i < ci->num_stripes; i++) {
2085  context.stripes[i].stripeend += skip * ci->num_stripes * ci->stripe_length;
2086  }
2087 
2088  pos += (uint32_t)(skip * (ci->num_stripes - 1) * ci->num_stripes * ci->stripe_length);
2089  need_dummy = true;
2090  }
2091  } else if (length - pos >= ci->stripe_length * (ci->num_stripes - 1)) {
2092  for (i = 0; i < ci->num_stripes; i++) {
2093  context.stripes[i].stripeend += ci->stripe_length;
2094  }
2095 
2096  pos += (uint32_t)(ci->stripe_length * (ci->num_stripes - 1));
2097  need_dummy = true;
2098  } else {
2099  uint16_t stripe = (parity + 1) % ci->num_stripes;
2100 
2101  i = 0;
2102  while (stripe != parity) {
2103  if (endoffstripe == i) {
2104  context.stripes[stripe].stripeend = endoff + 1;
2105  break;
2106  } else if (endoffstripe > i)
2107  context.stripes[stripe].stripeend = endoff - (endoff % ci->stripe_length) + ci->stripe_length;
2108 
2109  i++;
2110  stripe = (stripe + 1) % ci->num_stripes;
2111  }
2112 
2113  break;
2114  }
2115  }
2116 
2117  for (i = 0; i < ci->num_stripes; i++) {
2118  if (context.stripes[i].stripestart != context.stripes[i].stripeend) {
2119  context.stripes[i].mdl = IoAllocateMdl(context.va, (ULONG)(context.stripes[i].stripeend - context.stripes[i].stripestart),
2120  false, false, NULL);
2121 
2122  if (!context.stripes[i].mdl) {
2123  ERR("IoAllocateMdl failed\n");
2124  MmUnlockPages(master_mdl);
2125  IoFreeMdl(master_mdl);
2127  goto exit;
2128  }
2129  }
2130  }
2131 
2132  if (need_dummy) {
2134  if (!dummypage) {
2135  ERR("out of memory\n");
2136  MmUnlockPages(master_mdl);
2137  IoFreeMdl(master_mdl);
2139  goto exit;
2140  }
2141 
2142  dummy_mdl = IoAllocateMdl(dummypage, PAGE_SIZE, false, false, NULL);
2143  if (!dummy_mdl) {
2144  ERR("IoAllocateMdl failed\n");
2145  MmUnlockPages(master_mdl);
2146  IoFreeMdl(master_mdl);
2148  goto exit;
2149  }
2150 
2151  MmBuildMdlForNonPagedPool(dummy_mdl);
2152 
2153  dummy = *(PFN_NUMBER*)(dummy_mdl + 1);
2154  }
2155 
2156  stripeoff = ExAllocatePoolWithTag(NonPagedPool, sizeof(uint32_t) * ci->num_stripes, ALLOC_TAG);
2157  if (!stripeoff) {
2158  ERR("out of memory\n");
2159  MmUnlockPages(master_mdl);
2160  IoFreeMdl(master_mdl);
2162  goto exit;
2163  }
2164 
2165  RtlZeroMemory(stripeoff, sizeof(uint32_t) * ci->num_stripes);
2166 
2167  pos = 0;
2168 
2169  while (pos < length) {
2170  PFN_NUMBER* stripe_pfns;
2171 
2172  parity = (((addr - offset + pos) / ((ci->num_stripes - 1) * ci->stripe_length)) + ci->num_stripes - 1) % ci->num_stripes;
2173 
2174  if (pos == 0) {
2175  uint16_t stripe = (parity + startoffstripe + 1) % ci->num_stripes;
2176  uint32_t readlen = min(length - pos, (uint32_t)min(context.stripes[stripe].stripeend - context.stripes[stripe].stripestart,
2177  ci->stripe_length - (context.stripes[stripe].stripestart % ci->stripe_length)));
2178 
2179  stripe_pfns = (PFN_NUMBER*)(context.stripes[stripe].mdl + 1);
2180 
2181  RtlCopyMemory(stripe_pfns, pfns, readlen * sizeof(PFN_NUMBER) >> PAGE_SHIFT);
2182 
2183  stripeoff[stripe] = readlen;
2184  pos += readlen;
2185 
2186  stripe = (stripe + 1) % ci->num_stripes;
2187 
2188  while (stripe != parity) {
2189  stripe_pfns = (PFN_NUMBER*)(context.stripes[stripe].mdl + 1);
2190  readlen = min(length - pos, (uint32_t)min(context.stripes[stripe].stripeend - context.stripes[stripe].stripestart, ci->stripe_length));
2191 
2192  if (readlen == 0)
2193  break;
2194 
2195  RtlCopyMemory(stripe_pfns, &pfns[pos >> PAGE_SHIFT], readlen * sizeof(PFN_NUMBER) >> PAGE_SHIFT);
2196 
2197  stripeoff[stripe] = readlen;
2198  pos += readlen;
2199 
2200  stripe = (stripe + 1) % ci->num_stripes;
2201  }
2202  } else if (length - pos >= ci->stripe_length * (ci->num_stripes - 1)) {
2203  uint16_t stripe = (parity + 1) % ci->num_stripes;
2204  ULONG k;
2205 
2206  while (stripe != parity) {
2207  stripe_pfns = (PFN_NUMBER*)(context.stripes[stripe].mdl + 1);
2208 
2209  RtlCopyMemory(&stripe_pfns[stripeoff[stripe] >> PAGE_SHIFT], &pfns[pos >> PAGE_SHIFT], (ULONG)(ci->stripe_length * sizeof(PFN_NUMBER) >> PAGE_SHIFT));
2210 
2211  stripeoff[stripe] += (uint32_t)ci->stripe_length;
2212  pos += (uint32_t)ci->stripe_length;
2213 
2214  stripe = (stripe + 1) % ci->num_stripes;
2215  }
2216 
2217  stripe_pfns = (PFN_NUMBER*)(context.stripes[parity].mdl + 1);
2218 
2219  for (k = 0; k < ci->stripe_length >> PAGE_SHIFT; k++) {
2220  stripe_pfns[stripeoff[parity] >> PAGE_SHIFT] = dummy;
2221  stripeoff[parity] += PAGE_SIZE;
2222  }
2223  } else {
2224  uint16_t stripe = (parity + 1) % ci->num_stripes;
2225  uint32_t readlen;
2226 
2227  while (pos < length) {
2228  stripe_pfns = (PFN_NUMBER*)(context.stripes[stripe].mdl + 1);
2229  readlen = min(length - pos, (ULONG)min(context.stripes[stripe].stripeend - context.stripes[stripe].stripestart, ci->stripe_length));
2230 
2231  if (readlen == 0)
2232  break;
2233 
2234  RtlCopyMemory(&stripe_pfns[stripeoff[stripe] >> PAGE_SHIFT], &pfns[pos >> PAGE_SHIFT], readlen * sizeof(PFN_NUMBER) >> PAGE_SHIFT);
2235 
2236  stripeoff[stripe] += readlen;
2237  pos += readlen;
2238 
2239  stripe = (stripe + 1) % ci->num_stripes;
2240  }
2241  }
2242  }
2243 
2244  MmUnlockPages(master_mdl);
2245  IoFreeMdl(master_mdl);
2246 
2247  ExFreePool(stripeoff);
2248  } else if (type == BLOCK_FLAG_RAID6) {
2249  uint64_t startoff, endoff;
2250  uint16_t endoffstripe, parity1;
2251  uint32_t *stripeoff, pos;
2252  PMDL master_mdl;
2253  PFN_NUMBER *pfns, dummy = 0;
2254  bool need_dummy = false;
2255 
2256  get_raid0_offset(addr - offset, ci->stripe_length, ci->num_stripes - 2, &startoff, &startoffstripe);
2257  get_raid0_offset(addr + length - offset - 1, ci->stripe_length, ci->num_stripes - 2, &endoff, &endoffstripe);
2258 
2259  if (file_read) {
2261 
2262  if (!context.va) {
2263  ERR("out of memory\n");
2265  goto exit;
2266  }
2267  } else
2268  context.va = buf;
2269 
2270  master_mdl = IoAllocateMdl(context.va, length, false, false, NULL);
2271  if (!master_mdl) {
2272  ERR("out of memory\n");
2274  goto exit;
2275  }
2276 
2278 
2279  _SEH2_TRY {
2283  } _SEH2_END;
2284 
2285  if (!NT_SUCCESS(Status)) {
2286  ERR("MmProbeAndLockPages threw exception %08lx\n", Status);
2287  IoFreeMdl(master_mdl);
2288  goto exit;
2289  }
2290 
2291  pfns = (PFN_NUMBER*)(master_mdl + 1);
2292 
2293  pos = 0;
2294  while (pos < length) {
2295  parity1 = (((addr - offset + pos) / ((ci->num_stripes - 2) * ci->stripe_length)) + ci->num_stripes - 2) % ci->num_stripes;
2296 
2297  if (pos == 0) {
2298  uint16_t stripe = (parity1 + startoffstripe + 2) % ci->num_stripes, parity2;
2299  ULONG skip, readlen;
2300 
2301  i = startoffstripe;
2302  while (stripe != parity1) {
2303  if (i == startoffstripe) {
2304  readlen = (ULONG)min(length, ci->stripe_length - (startoff % ci->stripe_length));
2305 
2306  context.stripes[stripe].stripestart = startoff;
2307  context.stripes[stripe].stripeend = startoff + readlen;
2308 
2309  pos += readlen;
2310 
2311  if (pos == length)
2312  break;
2313  } else {
2314  readlen = min(length - pos, (ULONG)ci->stripe_length);
2315 
2316  context.stripes[stripe].stripestart = startoff - (startoff % ci->stripe_length);
2317  context.stripes[stripe].stripeend = context.stripes[stripe].stripestart + readlen;
2318 
2319  pos += readlen;
2320 
2321  if (pos == length)
2322  break;
2323  }
2324 
2325  i++;
2326  stripe = (stripe + 1) % ci->num_stripes;
2327  }
2328 
2329  if (pos == length)
2330  break;
2331 
2332  for (i = 0; i < startoffstripe; i++) {
2333  uint16_t stripe2 = (parity1 + i + 2) % ci->num_stripes;
2334 
2335  context.stripes[stripe2].stripestart = context.stripes[stripe2].stripeend = startoff - (startoff % ci->stripe_length) + ci->stripe_length;
2336  }
2337 
2338  context.stripes[parity1].stripestart = context.stripes[parity1].stripeend = startoff - (startoff % ci->stripe_length) + ci->stripe_length;
2339 
2340  parity2 = (parity1 + 1) % ci->num_stripes;
2341  context.stripes[parity2].stripestart = context.stripes[parity2].stripeend = startoff - (startoff % ci->stripe_length) + ci->stripe_length;
2342 
2343  if (length - pos > ci->num_stripes * (ci->num_stripes - 2) * ci->stripe_length) {
2344  skip = (ULONG)(((length - pos) / (ci->num_stripes * (ci->num_stripes - 2) * ci->stripe_length)) - 1);
2345 
2346  for (i = 0; i < ci->num_stripes; i++) {
2347  context.stripes[i].stripeend += skip * ci->num_stripes * ci->stripe_length;
2348  }
2349 
2350  pos += (uint32_t)(skip * (ci->num_stripes - 2) * ci->num_stripes * ci->stripe_length);
2351  need_dummy = true;
2352  }
2353  } else if (length - pos >= ci->stripe_length * (ci->num_stripes - 2)) {
2354  for (i = 0; i < ci->num_stripes; i++) {
2355  context.stripes[i].stripeend += ci->stripe_length;
2356  }
2357 
2358  pos += (uint32_t)(ci->stripe_length * (ci->num_stripes - 2));
2359  need_dummy = true;
2360  } else {
2361  uint16_t stripe = (parity1 + 2) % ci->num_stripes;
2362 
2363  i = 0;
2364  while (stripe != parity1) {
2365  if (endoffstripe == i) {
2366  context.stripes[stripe].stripeend = endoff + 1;
2367  break;
2368  } else if (endoffstripe > i)
2369  context.stripes[stripe].stripeend = endoff - (endoff % ci->stripe_length) + ci->stripe_length;
2370 
2371  i++;
2372  stripe = (stripe + 1) % ci->num_stripes;
2373  }
2374 
2375  break;
2376  }
2377  }
2378 
2379  for (i = 0; i < ci->num_stripes; i++) {
2380  if (context.stripes[i].stripestart != context.stripes[i].stripeend) {
2381  context.stripes[i].mdl = IoAllocateMdl(context.va, (ULONG)(context.stripes[i].stripeend - context.stripes[i].stripestart), false, false, NULL);
2382 
2383  if (!context.stripes[i].mdl) {
2384  ERR("IoAllocateMdl failed\n");
2385  MmUnlockPages(master_mdl);
2386  IoFreeMdl(master_mdl);
2388  goto exit;
2389  }
2390  }
2391  }
2392 
2393  if (need_dummy) {
2395  if (!dummypage) {
2396  ERR("out of memory\n");
2397  MmUnlockPages(master_mdl);
2398  IoFreeMdl(master_mdl);
2400  goto exit;
2401  }
2402 
2403  dummy_mdl = IoAllocateMdl(dummypage, PAGE_SIZE, false, false, NULL);
2404  if (!dummy_mdl) {
2405  ERR("IoAllocateMdl failed\n");
2406  MmUnlockPages(master_mdl);
2407  IoFreeMdl(master_mdl);
2409  goto exit;
2410  }
2411 
2412  MmBuildMdlForNonPagedPool(dummy_mdl);
2413 
2414  dummy = *(PFN_NUMBER*)(dummy_mdl + 1);
2415  }
2416 
2417  stripeoff = ExAllocatePoolWithTag(NonPagedPool, sizeof(uint32_t) * ci->num_stripes, ALLOC_TAG);
2418  if (!stripeoff) {
2419  ERR("out of memory\n");
2420  MmUnlockPages(master_mdl);
2421  IoFreeMdl(master_mdl);
2423  goto exit;
2424  }
2425 
2426  RtlZeroMemory(stripeoff, sizeof(uint32_t) * ci->num_stripes);
2427 
2428  pos = 0;
2429 
2430  while (pos < length) {
2431  PFN_NUMBER* stripe_pfns;
2432 
2433  parity1 = (((addr - offset + pos) / ((ci->num_stripes - 2) * ci->stripe_length)) + ci->num_stripes - 2) % ci->num_stripes;
2434 
2435  if (pos == 0) {
2436  uint16_t stripe = (parity1 + startoffstripe + 2) % ci->num_stripes;
2437  uint32_t readlen = min(length - pos, (uint32_t)min(context.stripes[stripe].stripeend - context.stripes[stripe].stripestart,
2438  ci->stripe_length - (context.stripes[stripe].stripestart % ci->stripe_length)));
2439 
2440  stripe_pfns = (PFN_NUMBER*)(context.stripes[stripe].mdl + 1);
2441 
2442  RtlCopyMemory(stripe_pfns, pfns, readlen * sizeof(PFN_NUMBER) >> PAGE_SHIFT);
2443 
2444  stripeoff[stripe] = readlen;
2445  pos += readlen;
2446 
2447  stripe = (stripe + 1) % ci->num_stripes;
2448 
2449  while (stripe != parity1) {
2450  stripe_pfns = (PFN_NUMBER*)(context.stripes[stripe].mdl + 1);
2451  readlen = (uint32_t)min(length - pos, min(context.stripes[stripe].stripeend - context.stripes[stripe].stripestart, ci->stripe_length));
2452 
2453  if (readlen == 0)
2454  break;
2455 
2456  RtlCopyMemory(stripe_pfns, &pfns[pos >> PAGE_SHIFT], readlen * sizeof(PFN_NUMBER) >> PAGE_SHIFT);
2457 
2458  stripeoff[stripe] = readlen;
2459  pos += readlen;
2460 
2461  stripe = (stripe + 1) % ci->num_stripes;
2462  }
2463  } else if (length - pos >= ci->stripe_length * (ci->num_stripes - 2)) {
2464  uint16_t stripe = (parity1 + 2) % ci->num_stripes;
2465  uint16_t parity2 = (parity1 + 1) % ci->num_stripes;
2466  ULONG k;
2467 
2468  while (stripe != parity1) {
2469  stripe_pfns = (PFN_NUMBER*)(context.stripes[stripe].mdl + 1);
2470 
2471  RtlCopyMemory(&stripe_pfns[stripeoff[stripe] >> PAGE_SHIFT], &pfns[pos >> PAGE_SHIFT], (ULONG)(ci->stripe_length * sizeof(PFN_NUMBER) >> PAGE_SHIFT));
2472 
2473  stripeoff[stripe] += (uint32_t)ci->stripe_length;
2474  pos += (uint32_t)ci->stripe_length;
2475 
2476  stripe = (stripe + 1) % ci->num_stripes;
2477  }
2478 
2479  stripe_pfns = (PFN_NUMBER*)(context.stripes[parity1].mdl + 1);
2480 
2481  for (k = 0; k < ci->stripe_length >> PAGE_SHIFT; k++) {
2482  stripe_pfns[stripeoff[parity1] >> PAGE_SHIFT] = dummy;
2483  stripeoff[parity1] += PAGE_SIZE;
2484  }
2485 
2486  stripe_pfns = (PFN_NUMBER*)(context.stripes[parity2].mdl + 1);
2487 
2488  for (k = 0; k < ci->stripe_length >> PAGE_SHIFT; k++) {
2489  stripe_pfns[stripeoff[parity2] >> PAGE_SHIFT] = dummy;
2490  stripeoff[parity2] += PAGE_SIZE;
2491  }
2492  } else {
2493  uint16_t stripe = (parity1 + 2) % ci->num_stripes;
2494  uint32_t readlen;
2495 
2496  while (pos < length) {
2497  stripe_pfns = (PFN_NUMBER*)(context.stripes[stripe].mdl + 1);
2498  readlen = (uint32_t)min(length - pos, min(context.stripes[stripe].stripeend - context.stripes[stripe].stripestart, ci->stripe_length));
2499 
2500  if (readlen == 0)
2501  break;
2502 
2503  RtlCopyMemory(&stripe_pfns[stripeoff[stripe] >> PAGE_SHIFT], &pfns[pos >> PAGE_SHIFT], readlen * sizeof(PFN_NUMBER) >> PAGE_SHIFT);
2504 
2505  stripeoff[stripe] += readlen;
2506  pos += readlen;
2507 
2508  stripe = (stripe + 1) % ci->num_stripes;
2509  }
2510  }
2511  }
2512 
2513  MmUnlockPages(master_mdl);
2514  IoFreeMdl(master_mdl);
2515 
2516  ExFreePool(stripeoff);
2517  }
2518 
2519  context.address = addr;
2520 
2521  for (i = 0; i < ci->num_stripes; i++) {
2522  if (!devices[i] || !devices[i]->devobj || context.stripes[i].stripestart == context.stripes[i].stripeend) {
2523  context.stripes[i].status = ReadDataStatus_MissingDevice;
2524  context.stripes_left--;
2525 
2526  if (!devices[i] || !devices[i]->devobj)
2527  missing_devices++;
2528  }
2529  }
2530 
2531  if (missing_devices > allowed_missing) {
2532  ERR("not enough devices to service request (%u missing)\n", missing_devices);
2534  goto exit;
2535  }
2536 
2537  for (i = 0; i < ci->num_stripes; i++) {
2539 
2540  if (devices[i] && devices[i]->devobj && context.stripes[i].stripestart != context.stripes[i].stripeend && context.stripes[i].status != ReadDataStatus_Skip) {
2541  context.stripes[i].context = (struct read_data_context*)&context;
2542 
2543  if (type == BLOCK_FLAG_RAID10) {
2544  context.stripes[i].stripenum = i / ci->sub_stripes;
2545  }
2546 
2547  if (!Irp) {
2548  context.stripes[i].Irp = IoAllocateIrp(devices[i]->devobj->StackSize, false);
2549 
2550  if (!context.stripes[i].Irp) {
2551  ERR("IoAllocateIrp failed\n");
2553  goto exit;
2554  }
2555  } else {
2556  context.stripes[i].Irp = IoMakeAssociatedIrp(Irp, devices[i]->devobj->StackSize);
2557 
2558  if (!context.stripes[i].Irp) {
2559  ERR("IoMakeAssociatedIrp failed\n");
2561  goto exit;
2562  }
2563  }
2564 
2565  IrpSp = IoGetNextIrpStackLocation(context.stripes[i].Irp);
2568  IrpSp->FileObject = devices[i]->fileobj;
2569 
2570  if (devices[i]->devobj->Flags & DO_BUFFERED_IO) {
2571  context.stripes[i].Irp->AssociatedIrp.SystemBuffer = ExAllocatePoolWithTag(NonPagedPool, (ULONG)(context.stripes[i].stripeend - context.stripes[i].stripestart), ALLOC_TAG);
2572  if (!context.stripes[i].Irp->AssociatedIrp.SystemBuffer) {
2573  ERR("out of memory\n");
2575  goto exit;
2576  }
2577 
2579 
2580  context.stripes[i].Irp->UserBuffer = MmGetSystemAddressForMdlSafe(context.stripes[i].mdl, priority);
2581  } else if (devices[i]->devobj->Flags & DO_DIRECT_IO)
2582  context.stripes[i].Irp->MdlAddress = context.stripes[i].mdl;
2583  else
2584  context.stripes[i].Irp->UserBuffer = MmGetSystemAddressForMdlSafe(context.stripes[i].mdl, priority);
2585 
2586  IrpSp->Parameters.Read.Length = (ULONG)(context.stripes[i].stripeend - context.stripes[i].stripestart);
2587  IrpSp->Parameters.Read.ByteOffset.QuadPart = context.stripes[i].stripestart + cis[i].offset;
2588 
2589  total_reading += IrpSp->Parameters.Read.Length;
2590 
2591  context.stripes[i].Irp->UserIosb = &context.stripes[i].iosb;
2592 
2593  IoSetCompletionRoutine(context.stripes[i].Irp, read_data_completion, &context.stripes[i], true, true, true);
2594 
2595  context.stripes[i].status = ReadDataStatus_Pending;
2596  }
2597  }
2598 
2599  need_to_wait = false;
2600  for (i = 0; i < ci->num_stripes; i++) {
2601  if (context.stripes[i].status != ReadDataStatus_MissingDevice && context.stripes[i].status != ReadDataStatus_Skip) {
2602  IoCallDriver(devices[i]->devobj, context.stripes[i].Irp);
2603  need_to_wait = true;
2604  }
2605  }
2606 
2607  if (need_to_wait)
2609 
2610  if (diskacc)
2611  fFsRtlUpdateDiskCounters(total_reading, 0);
2612 
2613  // check if any of the devices return a "user-induced" error
2614 
2615  for (i = 0; i < ci->num_stripes; i++) {
2616  if (context.stripes[i].status == ReadDataStatus_Error && IoIsErrorUserInduced(context.stripes[i].iosb.Status)) {
2617  Status = context.stripes[i].iosb.Status;
2618  goto exit;
2619  }
2620  }
2621 
2622  if (type == BLOCK_FLAG_RAID0) {
2623  Status = read_data_raid0(Vcb, file_read ? context.va : buf, addr, length, &context, ci, devices, generation, offset);
2624  if (!NT_SUCCESS(Status)) {
2625  ERR("read_data_raid0 returned %08lx\n", Status);
2626 
2627  if (file_read)
2628  ExFreePool(context.va);
2629 
2630  goto exit;
2631  }
2632 
2633  if (file_read) {
2635  ExFreePool(context.va);
2636  }
2637  } else if (type == BLOCK_FLAG_RAID10) {
2638  Status = read_data_raid10(Vcb, file_read ? context.va : buf, addr, length, &context, ci, devices, generation, offset);
2639 
2640  if (!NT_SUCCESS(Status)) {
2641  ERR("read_data_raid10 returned %08lx\n", Status);
2642 
2643  if (file_read)
2644  ExFreePool(context.va);
2645 
2646  goto exit;
2647  }
2648 
2649  if (file_read) {
2651  ExFreePool(context.va);
2652  }
2653  } else if (type == BLOCK_FLAG_DUPLICATE) {
2654  Status = read_data_dup(Vcb, file_read ? context.va : buf, addr, &context, ci, devices, generation);
2655  if (!NT_SUCCESS(Status)) {
2656  ERR("read_data_dup returned %08lx\n", Status);
2657 
2658  if (file_read)
2659  ExFreePool(context.va);
2660 
2661  goto exit;
2662  }
2663 
2664  if (file_read) {
2666  ExFreePool(context.va);
2667  }
2668  } else if (type == BLOCK_FLAG_RAID5) {
2669  Status = read_data_raid5(Vcb, file_read ? context.va : buf, addr, length, &context, ci, devices, offset, generation, c, missing_devices > 0 ? true : false);
2670  if (!NT_SUCCESS(Status)) {
2671  ERR("read_data_raid5 returned %08lx\n", Status);
2672 
2673  if (file_read)
2674  ExFreePool(context.va);
2675 
2676  goto exit;
2677  }
2678 
2679  if (file_read) {
2681  ExFreePool(context.va);
2682  }
2683  } else if (type == BLOCK_FLAG_RAID6) {
2684  Status = read_data_raid6(Vcb, file_read ? context.va : buf, addr, length, &context, ci, devices, offset, generation, c, missing_devices > 0 ? true : false);
2685  if (!NT_SUCCESS(Status)) {
2686  ERR("read_data_raid6 returned %08lx\n", Status);
2687 
2688  if (file_read)
2689  ExFreePool(context.va);
2690 
2691  goto exit;
2692  }
2693 
2694  if (file_read) {
2696  ExFreePool(context.va);
2697  }
2698  }
2699 
2700 exit:
2701  if (c && (type == BLOCK_FLAG_RAID5 || type == BLOCK_FLAG_RAID6))
2702  chunk_unlock_range(Vcb, c, lockaddr, locklen);
2703 
2704  if (dummy_mdl)
2705  IoFreeMdl(dummy_mdl);
2706 
2707  if (dummypage)
2708  ExFreePool(dummypage);
2709 
2710  for (i = 0; i < ci->num_stripes; i++) {
2711  if (context.stripes[i].mdl) {
2712  if (context.stripes[i].mdl->MdlFlags & MDL_PAGES_LOCKED)
2713  MmUnlockPages(context.stripes[i].mdl);
2714 
2715  IoFreeMdl(context.stripes[i].mdl);
2716  }
2717 
2718  if (context.stripes[i].Irp)
2719  IoFreeIrp(context.stripes[i].Irp);
2720  }
2721 
2722  ExFreePool(context.stripes);
2723 
2724  if (!Vcb->log_to_phys_loaded)
2726 
2727  return Status;
2728 }
while(CdLookupNextInitialFileDirent(IrpContext, Fcb, FileContext))
uint64_t obj_id
Definition: btrfs.h:144
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
uint8_t obj_type
Definition: btrfs.h:145
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
uint16_t sub_stripes
Definition: btrfs.h:348
Definition: http.c:7251
const char * devices
Definition: diskspace.c:793
VOID NTAPI MmBuildMdlForNonPagedPool(IN PMDL Mdl)
Definition: mdlsup.c:424
#define IoIsErrorUserInduced(Status)
Definition: iofuncs.h:2817
#define TYPE_CHUNK_ITEM
Definition: btrfs.h:48
LONG NTSTATUS
Definition: precomp.h:26
Definition: write.c:113
uint64_t stripe_length
Definition: btrfs.h:342
VOID NTAPI MmUnlockPages(IN PMDL Mdl)
Definition: mdlsup.c:1435
unsigned short int uint16_t
Definition: acefiex.h:54
#define uint16_t
Definition: nsiface.idl:60
if(dx==0 &&dy==0)
Definition: linetemp.h:174
#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:146
_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:989
#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:87
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
uint64_t offset
Definition: btrfs.h:353
uint64_t size
Definition: btrfs.h:340
ULONG PFN_NUMBER
Definition: ke.h:9
_In_ PIRP Irp
Definition: csq.h:116
Definition: devices.h:37
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
void chunk_unlock_range(_In_ device_extension *Vcb, _In_ chunk *c, _In_ uint64_t start, _In_ uint64_t length)
Definition: btrfs.c:5860
#define BLOCK_FLAG_RAID1C3
Definition: btrfs.h:87
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
WDF_INTERRUPT_PRIORITY priority
#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
Status
Definition: gdiplustypes.h:24
#define BLOCK_FLAG_RAID0
Definition: shellext.h:78
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define MDL_PAGES_LOCKED
Definition: mmtypes.h:19
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
GLintptr offset
Definition: glext.h:5920
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
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:5813
#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:3268
_In_opt_ PVOID _In_ ULONG _In_ PVOID context
Definition: wdfdriver.h:113
VOID NTAPI IoFreeMdl(PMDL Mdl)
Definition: iomdl.c:146
#define BLOCK_FLAG_RAID1C4
Definition: btrfs.h:88
#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:996
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:2695
BYTE uint8_t
Definition: msvideo1.c:66
MDL * mdl
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
PFILE_OBJECT FileObject
Definition: iotypes.h:3169
_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:931
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
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:651
unsigned char dummy
Definition: maze.c:118
_In_ uint64_t _In_ uint64_t _In_ uint64_t generation
Definition: btrfs.c:2964
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4137
tFsRtlUpdateDiskCounters fFsRtlUpdateDiskCounters
Definition: btrfs.c:93
#define min(a, b)
Definition: monoChain.cc:55
Definition: list.h:27
#define NULL
Definition: types.h:112
NTSTATUS bool void get_raid56_lock_range(chunk *c, uint64_t address, uint64_t length, uint64_t *lockaddr, uint64_t *locklen) __attribute__((nonnull(1
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
Definition: ffs.h:52
#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:467
uint16_t num_stripes
Definition: btrfs.h:347
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
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:397
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:40
#define BLOCK_FLAG_DUPLICATE
Definition: shellext.h:80
#define STATUS_SUCCESS
Definition: shellext.h:65
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:165
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:3128
uint64_t type
Definition: btrfs.h:343
#define uint32_t
Definition: nsiface.idl:61
void * data
Definition: btrfs_drv.h:615
int k
Definition: mpi.c:3369
#define IRP_MN_NORMAL
Definition: iotypes.h:4417
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
NTSTATUS NTSTATUS NTSTATUS NTSTATUS NTSTATUS chunk * get_chunk_from_address(device_extension *Vcb, uint64_t address) __attribute__((nonnull(1)))
bool diskacc
Definition: btrfs.c:100
#define BLOCK_FLAG_RAID1
Definition: shellext.h:79
#define STATUS_DEVICE_NOT_READY
Definition: shellext.h:70

◆ 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  bool checksum_error = false;
239  uint16_t j, stripe = 0;
241  CHUNK_ITEM_STRIPE* cis = (CHUNK_ITEM_STRIPE*)&ci[1];
242 
243  for (j = 0; j < ci->num_stripes; j++) {
244  if (context->stripes[j].status == ReadDataStatus_Error) {
245  WARN("stripe %u returned error %08lx\n", j, context->stripes[j].iosb.Status);
247  return context->stripes[j].iosb.Status;
248  } else if (context->stripes[j].status == ReadDataStatus_Success) {
249  stripe = j;
250  break;
251  }
252  }
253 
254  if (context->stripes[stripe].status != ReadDataStatus_Success)
255  return STATUS_INTERNAL_ERROR;
256 
257  if (context->tree) {
258  tree_header* th = (tree_header*)buf;
259 
260  if (th->address != context->address || !check_tree_checksum(Vcb, th)) {
261  checksum_error = true;
263  } else if (generation != 0 && th->generation != generation) {
264  checksum_error = true;
266  }
267  } else if (context->csum) {
268  Status = check_csum(Vcb, buf, (ULONG)context->stripes[stripe].Irp->IoStatus.Information / context->sector_size, context->csum);
269 
270  if (Status == STATUS_CRC_ERROR) {
271  checksum_error = true;
273  } else if (!NT_SUCCESS(Status)) {
274  ERR("check_csum returned %08lx\n", Status);
275  return Status;
276  }
277  }
278 
279  if (!checksum_error)
280  return STATUS_SUCCESS;
281 
282  if (ci->num_stripes == 1)
283  return STATUS_CRC_ERROR;
284 
285  if (context->tree) {
286  tree_header* t2;
287  bool recovered = false;
288 
289  t2 = ExAllocatePoolWithTag(NonPagedPool, Vcb->superblock.node_size, ALLOC_TAG);
290  if (!t2) {
291  ERR("out of memory\n");
293  }
294 
295  for (j = 0; j < ci->num_stripes; j++) {
296  if (j != stripe && devices[j] && devices[j]->devobj) {
297  Status = sync_read_phys(devices[j]->devobj, devices[j]->fileobj, cis[j].offset + context->stripes[stripe].stripestart,
298  Vcb->superblock.node_size, (uint8_t*)t2, false);
299  if (!NT_SUCCESS(Status)) {
300  WARN("sync_read_phys returned %08lx\n", Status);
302  } else {
303  bool checksum_error = !check_tree_checksum(Vcb, t2);
304 
305  if (t2->address == addr && !checksum_error && (generation == 0 || t2->generation == generation)) {
306  RtlCopyMemory(buf, t2, Vcb->superblock.node_size);
307  ERR("recovering from checksum error at %I64x, device %I64x\n", addr, devices[stripe]->devitem.dev_id);
308  recovered = true;
309 
310  if (!Vcb->readonly && !devices[stripe]->readonly) { // write good data over bad
311  Status = write_data_phys(devices[stripe]->devobj, devices[stripe]->fileobj, cis[stripe].offset + context->stripes[stripe].stripestart,
312  t2, Vcb->superblock.node_size);
313  if (!NT_SUCCESS(Status)) {
314  WARN("write_data_phys returned %08lx\n", Status);
316  }
317  }
318 
319  break;
320  } else if (t2->address != addr || checksum_error)
322  else
324  }
325  }
326  }
327 
328  if (!recovered) {
329  ERR("unrecoverable checksum error at %I64x\n", addr);
330  ExFreePool(t2);
331  return STATUS_CRC_ERROR;
332  }
333 
334  ExFreePool(t2);
335  } else {
336  ULONG sectors = (ULONG)context->stripes[stripe].Irp->IoStatus.Information >> Vcb->sector_shift;
337  uint8_t* sector;
338  void* ptr = context->csum;
339 
340  sector = ExAllocatePoolWithTag(NonPagedPool, Vcb->superblock.sector_size, ALLOC_TAG);
341  if (!sector) {
342  ERR("out of memory\n");
344  }
345 
346  for (ULONG i = 0; i < sectors; i++) {
347  if (!check_sector_csum(Vcb, buf + (i << Vcb->sector_shift), ptr)) {
348  bool recovered = false;
349 
350  for (j = 0; j < ci->num_stripes; j++) {
351  if (j != stripe && devices[j] && devices[j]->devobj) {
352  Status = sync_read_phys(devices[j]->devobj, devices[j]->fileobj,
353  cis[j].offset + context->stripes[stripe].stripestart + ((uint64_t)i << Vcb->sector_shift),
354  Vcb->superblock.sector_size, sector, false);
355  if (!NT_SUCCESS(Status)) {
356  WARN("sync_read_phys returned %08lx\n", Status);
358  } else {
359  if (check_sector_csum(Vcb, sector, ptr)) {
360  RtlCopyMemory(buf + (i << Vcb->sector_shift), sector, Vcb->superblock.sector_size);
361  ERR("recovering from checksum error at %I64x, device %I64x\n", addr + ((uint64_t)i << Vcb->sector_shift), devices[stripe]->devitem.dev_id);
362  recovered = true;
363 
364  if (!Vcb->readonly && !devices[stripe]->readonly) { // write good data over bad
365  Status = write_data_phys(devices[stripe]->devobj, devices[stripe]->fileobj,
366  cis[stripe].offset + context->stripes[stripe].stripestart + ((uint64_t)i << Vcb->sector_shift),
367  sector, Vcb->superblock.sector_size);
368  if (!NT_SUCCESS(Status)) {
369  WARN("write_data_phys returned %08lx\n", Status);
371  }
372  }
373 
374  break;
375  } else
377  }
378  }
379  }
380 
381  if (!recovered) {
382  ERR("unrecoverable checksum error at %I64x\n", addr + ((uint64_t)i << Vcb->sector_shift));
384  return STATUS_CRC_ERROR;
385  }
386  }
387 
388  ptr = (uint8_t*)ptr + Vcb->csum_size;
389  }
390 
392  }
393 
394  return STATUS_SUCCESS;
395 }
uint32_t sector
Definition: isohybrid.c:61
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
Definition: http.c:7251
const char * devices
Definition: diskspace.c:793
#define WARN(fmt,...)
Definition: debug.h:112
LONG NTSTATUS
Definition: precomp.h:26
Definition: write.c:113
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:87
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
uint64_t address
Definition: btrfs.h:156
static PVOID ptr
Definition: dispmode.c:27
uint64_t generation
Definition: btrfs.h:159
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:542
Status
Definition: gdiplustypes.h:24
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:64
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define BTRFS_DEV_STAT_GENERATION_ERRORS
Definition: btrfs.h:543
GLintptr offset
Definition: glext.h:5920
#define Vcb
Definition: cdprocs.h:1415
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
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:2701
#define BTRFS_DEV_STAT_READ_ERRORS
Definition: btrfs.h:540
#define ERR(fmt,...)
Definition: debug.h:110
UINT64 uint64_t
Definition: types.h:77
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
void log_device_error(_In_ device_extension *Vcb, _Inout_ device *dev, _In_ int error)
Definition: btrfs.c:5883
_In_ uint64_t _In_ uint64_t _In_ uint64_t generation
Definition: btrfs.c:2964
__u8 sectors[2]
Definition: mkdosfs.c:366
#define BTRFS_DEV_STAT_WRITE_ERRORS
Definition: btrfs.h:539
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:347
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define STATUS_SUCCESS
Definition: shellext.h:65
#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 397 of file read.c.

398  {
399  for (uint16_t i = 0; i < ci->num_stripes; i++) {
400  if (context->stripes[i].status == ReadDataStatus_Error) {
401  WARN("stripe %u returned error %08lx\n", i, context->stripes[i].iosb.Status);
403  return context->stripes[i].iosb.Status;
404  }
405  }
406 
407  if (context->tree) { // shouldn't happen, as trees shouldn't cross stripe boundaries
408  tree_header* th = (tree_header*)buf;
409  bool checksum_error = !check_tree_checksum(Vcb, th);
410 
411  if (checksum_error || addr != th->address || (generation != 0 && generation != th->generation)) {
412  uint64_t off;
414 
416 
417  ERR("unrecoverable checksum error at %I64x, device %I64x\n", addr, devices[stripe]->devitem.dev_id);
418 
419  if (checksum_error) {
421  return STATUS_CRC_ERROR;
422  } else if (addr != th->address) {
423  WARN("address of tree was %I64x, not %I64x as expected\n", th->address, addr);
425  return STATUS_CRC_ERROR;
426  } else if (generation != 0 && generation != th->generation) {
427  WARN("generation of tree was %I64x, not %I64x as expected\n", th->generation, generation);
429  return STATUS_CRC_ERROR;
430  }
431  }
432  } else if (context->csum) {
434 
435  Status = check_csum(Vcb, buf, length >> Vcb->sector_shift, context->csum);
436 
437  if (Status == STATUS_CRC_ERROR) {
438  void* ptr = context->csum;
439 
440  for (uint32_t i = 0; i < length >> Vcb->sector_shift; i++) {
441  if (!check_sector_csum(Vcb, buf + (i << Vcb->sector_shift), ptr)) {
442  uint64_t off;
444 
445  get_raid0_offset(addr - offset + ((uint64_t)i << Vcb->sector_shift), ci->stripe_length, ci->num_stripes, &off, &stripe);
446 
447  ERR("unrecoverable checksum error at %I64x, device %I64x\n", addr, devices[stripe]->devitem.dev_id);
448 
450 
451  return Status;
452  }
453 
454  ptr = (uint8_t*)ptr + Vcb->csum_size;
455  }
456 
457  return Status;
458  } else if (!NT_SUCCESS(Status)) {
459  ERR("check_csum returned %08lx\n", Status);
460  return Status;
461  }
462  }
463 
464  return STATUS_SUCCESS;
465 }
Definition: http.c:7251
const char * devices
Definition: diskspace.c:793
#define WARN(fmt,...)
Definition: debug.h:112
LONG NTSTATUS
Definition: precomp.h:26
Definition: write.c:113
uint64_t stripe_length
Definition: btrfs.h:342
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:989
bool check_sector_csum(device_extension *Vcb, void *buf, void *csum)
Definition: read.c:202
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
uint64_t address
Definition: btrfs.h:156
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
static PVOID ptr
Definition: dispmode.c:27
uint64_t generation
Definition: btrfs.h:159
#define BTRFS_DEV_STAT_CORRUPTION_ERRORS
Definition: btrfs.h:542
Status
Definition: gdiplustypes.h:24
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define BTRFS_DEV_STAT_GENERATION_ERRORS
Definition: btrfs.h:543
GLintptr offset
Definition: glext.h:5920
#define Vcb
Definition: cdprocs.h:1415
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:540
#define ERR(fmt,...)
Definition: debug.h:110
UINT64 uint64_t
Definition: types.h:77
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
void log_device_error(_In_ device_extension *Vcb, _Inout_ device *dev, _In_ int error)
Definition: btrfs.c:5883
_In_ uint64_t _In_ uint64_t _In_ uint64_t generation
Definition: btrfs.c:2964
UINT32 uint32_t
Definition: types.h:75
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:347
#define STATUS_SUCCESS
Definition: shellext.h:65
bool check_tree_checksum(device_extension *Vcb, tree_header *th)
Definition: read.c:128

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 467 of file read.c.

468  {
469  uint16_t stripe = 0;
471  bool checksum_error = false;
472  CHUNK_ITEM_STRIPE* cis = (CHUNK_ITEM_STRIPE*)&ci[1];
473 
474  for (uint16_t j = 0; j < ci->num_stripes; j++) {
475  if (context->stripes[j].status == ReadDataStatus_Error) {
476  WARN("stripe %u returned error %08lx\n", j, context->stripes[j].iosb.Status);
478  return context->stripes[j].iosb.Status;
479  } else if (context->stripes[j].status == ReadDataStatus_Success)
480  stripe = j;
481  }
482 
483  if (context->tree) {
484  tree_header* th = (tree_header*)buf;
485 
486  if (!check_tree_checksum(Vcb, th)) {
487  checksum_error = true;
489  } else if (addr != th->address) {
490  WARN("address of tree was %I64x, not %I64x as expected\n", th->address, addr);
491  checksum_error = true;
493  } else if (generation != 0 && generation != th->generation) {
494  WARN("generation of tree was %I64x, not %I64x as expected\n", th->generation, generation);
495  checksum_error = true;
497  }
498  } else if (context->csum) {
499  Status = check_csum(Vcb, buf, length >> Vcb->sector_shift, context->csum);
500 
501  if (Status == STATUS_CRC_ERROR)
502  checksum_error = true;
503  else if (!NT_SUCCESS(Status)) {
504  ERR("check_csum returned %08lx\n", Status);
505  return Status;
506  }
507  }
508 
509  if (!checksum_error)
510  return STATUS_SUCCESS;
511 
512  if (context->tree) {
513  tree_header* t2;
514  uint64_t off;
515  uint16_t badsubstripe = 0;
516  bool recovered = false;
517 
518  t2 = ExAllocatePoolWithTag(NonPagedPool, Vcb->superblock.node_size, ALLOC_TAG);
519  if (!t2) {
520  ERR("out of memory\n");
522  }
523 
525 
526  stripe *= ci->sub_stripes;
527 
528  for (uint16_t j = 0; j < ci->sub_stripes; j++) {
529  if (context->stripes[stripe + j].status == ReadDataStatus_Success) {
530  badsubstripe = j;
531  break;
532  }
533  }
534 
535  for (uint16_t j = 0; j < ci->sub_stripes; j++) {
536  if (context->stripes[stripe + j].status != ReadDataStatus_Success && devices[stripe + j] && devices[stripe + j]->devobj) {
537  Status = sync_read_phys(devices[stripe + j]->devobj, devices[stripe + j]->fileobj, cis[stripe + j].offset + off,
538  Vcb->superblock.node_size, (uint8_t*)t2, false);
539  if (!NT_SUCCESS(Status)) {
540  WARN("sync_read_phys returned %08lx\n", Status);
542  } else {
543  bool checksum_error = !check_tree_checksum(Vcb, t2);
544 
545  if (t2->address == addr && !checksum_error && (generation == 0 || t2->generation == generation)) {
546  RtlCopyMemory(buf, t2, Vcb->superblock.node_size);
547  ERR("recovering from checksum error at %I64x, device %I64x\n", addr, devices[stripe + j]->devitem.dev_id);
548  recovered = true;
549 
550  if (!Vcb->readonly && !devices[stripe + badsubstripe]->readonly && devices[stripe + badsubstripe]->devobj) { // write good data over bad
551  Status = write_data_phys(devices[stripe + badsubstripe]->devobj, devices[stripe + badsubstripe]->fileobj,
552  cis[stripe + badsubstripe].offset + off, t2, Vcb->superblock.node_size);
553  if (!NT_SUCCESS(Status)) {
554  WARN("write_data_phys returned %08lx\n", Status);
556  }
557  }
558 
559  break;
560  } else if (t2->address != addr || checksum_error)
562  else
564  }
565  }
566  }
567 
568  if (!recovered) {
569  ERR("unrecoverable checksum error at %I64x\n", addr);
570  ExFreePool(t2);
571  return STATUS_CRC_ERROR;
572  }
573 
574  ExFreePool(t2);
575  } else {
576  ULONG sectors = length >> Vcb->sector_shift;
577  uint8_t* sector;
578  void* ptr = context->csum;
579 
580  sector = ExAllocatePoolWithTag(NonPagedPool, Vcb->superblock.sector_size, ALLOC_TAG);
581  if (!sector) {
582  ERR("out of memory\n");
584  }
585 
586  for (ULONG i = 0; i < sectors; i++) {
587  if (!check_sector_csum(Vcb, buf + (i << Vcb->sector_shift), ptr)) {
588  uint64_t off;
589  uint16_t stripe2, badsubstripe = 0;
590  bool recovered = false;
591 
592  get_raid0_offset(addr - offset + ((uint64_t)i << Vcb->sector_shift), ci->stripe_length,
593  ci->num_stripes / ci->sub_stripes, &off, &stripe2);
594 
595  stripe2 *= ci->sub_stripes;
596 
597  for (uint16_t j = 0; j < ci->sub_stripes; j++) {
598  if (context->stripes[stripe2 + j].status == ReadDataStatus_Success) {
599  badsubstripe = j;
600  break;
601  }
602  }
603 
605 
606  for (uint16_t j = 0; j < ci->sub_stripes; j++) {
607  if (context->stripes[stripe2 + j].status != ReadDataStatus_Success && devices[stripe2 + j] && devices[stripe2 + j]->devobj) {
608  Status = sync_read_phys(devices[stripe2 + j]->devobj, devices[stripe2 + j]->fileobj, cis[stripe2 + j].offset + off,
609  Vcb->superblock.sector_size, sector, false);
610  if (!NT_SUCCESS(Status)) {
611  WARN("sync_read_phys returned %08lx\n", Status);
613  } else {
614  if (check_sector_csum(Vcb, sector, ptr)) {
615  RtlCopyMemory(buf + (i << Vcb->sector_shift), sector, Vcb->superblock.sector_size);
616  ERR("recovering from checksum error at %I64x, device %I64x\n", addr + ((uint64_t)i << Vcb->sector_shift), devices[stripe2 + j]->devitem.dev_id);
617  recovered = true;
618 
619  if (!Vcb->readonly && !devices[stripe2 + badsubstripe]->readonly && devices[stripe2 + badsubstripe]->devobj) { // write good data over bad
620  Status = write_data_phys(devices[stripe2 + badsubstripe]->devobj, devices[stripe2 + badsubstripe]->fileobj,
621  cis[stripe2 + badsubstripe].offset + off, sector, Vcb->superblock.sector_size);
622  if (!NT_SUCCESS(Status)) {
623  WARN("write_data_phys returned %08lx\n", Status);
624  log_device_error(Vcb, devices[stripe2 + badsubstripe], BTRFS_DEV_STAT_READ_ERRORS);
625  }
626  }
627 
628  break;
629  } else
631  }
632  }
633  }
634 
635  if (!recovered) {
636  ERR("unrecoverable checksum error at %I64x\n", addr + ((uint64_t)i << Vcb->sector_shift));
638  return STATUS_CRC_ERROR;
639  }
640  }
641 
642  ptr = (uint8_t*)ptr + Vcb->csum_size;
643  }
644 
646  }
647 
648  return STATUS_SUCCESS;
649 }
uint32_t sector
Definition: isohybrid.c:61
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
uint16_t sub_stripes
Definition: btrfs.h:348
Definition: http.c:7251
const char * devices
Definition: diskspace.c:793
#define WARN(fmt,...)
Definition: debug.h:112
LONG NTSTATUS
Definition: precomp.h:26
Definition: write.c:113
uint64_t stripe_length
Definition: btrfs.h:342
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:989
bool check_sector_csum(device_extension *Vcb, void *buf, void *csum)
Definition: read.c:202
#define ALLOC_TAG
Definition: btrfs_drv.h:87
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
uint64_t address
Definition: btrfs.h:156
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
static PVOID ptr
Definition: dispmode.c:27
uint64_t generation
Definition: btrfs.h:159
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:542
Status
Definition: gdiplustypes.h:24
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:64
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define BTRFS_DEV_STAT_GENERATION_ERRORS
Definition: btrfs.h:543
GLintptr offset
Definition: glext.h:5920
#define Vcb
Definition: cdprocs.h:1415
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
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:2701
#define BTRFS_DEV_STAT_READ_ERRORS
Definition: btrfs.h:540
#define ERR(fmt,...)
Definition: debug.h:110
UINT64 uint64_t
Definition: types.h:77
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
void log_device_error(_In_ device_extension *Vcb, _Inout_ device *dev, _In_ int error)
Definition: btrfs.c:5883
_In_ uint64_t _In_ uint64_t _In_ uint64_t generation
Definition: btrfs.c:2964
__u8 sectors[2]
Definition: mkdosfs.c:366
#define BTRFS_DEV_STAT_WRITE_ERRORS
Definition: btrfs.h:539
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:347
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define STATUS_SUCCESS
Definition: shellext.h:65
#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_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 651 of file read.c.

652  {
654  bool checksum_error = false;
655  CHUNK_ITEM_STRIPE* cis = (CHUNK_ITEM_STRIPE*)&ci[1];
656  uint16_t j, stripe = 0;
657  bool no_success = true;
658 
659  for (j = 0; j < ci->num_stripes; j++) {
660  if (context->stripes[j].status == ReadDataStatus_Error) {
661  WARN("stripe %u returned error %08lx\n", j, context->stripes[j].iosb.Status);
663  return context->stripes[j].iosb.Status;
664  } else if (context->stripes[j].status == ReadDataStatus_Success) {
665  stripe = j;
666  no_success = false;
667  }
668  }
669 
670  if (c) { // check partial stripes
671  LIST_ENTRY* le;
672  uint64_t ps_length = (ci->num_stripes - 1) * ci->stripe_length;
673 
674  ExAcquireResourceSharedLite(&c->partial_stripes_lock, true);
675 
676  le = c->partial_stripes.Flink;
677  while (le != &c->partial_stripes) {
679 
680  if (ps->address + ps_length > addr && ps->address < addr + length) {
681  ULONG runlength, index;
682 
683  runlength = RtlFindFirstRunClear(&ps->bmp, &index);
684 
685  while (runlength != 0) {
686  if (index >= ps->bmplen)
687  break;
688 
689  if (index + runlength >= ps->bmplen) {
690  runlength = ps->bmplen - index;
691 
692  if (runlength == 0)
693  break;
694  }
695 
696  uint64_t runstart = ps->address + (index << Vcb->sector_shift);
697  uint64_t runend = runstart + (runlength << Vcb->sector_shift);
698  uint64_t start = max(runstart, addr);
699  uint64_t end = min(runend, addr + length);
700 
701  if (end > start)
702  RtlCopyMemory(buf + start - addr, &ps->data[start - ps->address], (ULONG)(end - start));
703 
704  runlength = RtlFindNextForwardRunClear(&ps->bmp, index + runlength, &index);
705  }
706  } else if (ps->address >= addr + length)
707  break;
708 
709  le = le->Flink;
710  }
711 
712  ExReleaseResourceLite(&c->partial_stripes_lock);
713  }
714 
715  if (context->tree) {
716  tree_header* th = (tree_header*)buf;
717 
718  if (addr != th->address || !check_tree_checksum(Vcb, th)) {
719  checksum_error = true;
720  if (!no_success && !degraded)
722  } else if (generation != 0 && generation != th->generation) {
723  checksum_error = true;
724  if (!no_success && !degraded)
726  }
727  } else if (context->csum) {
728  Status = check_csum(Vcb, buf, length >> Vcb->sector_shift, context->csum);
729 
730  if (Status == STATUS_CRC_ERROR) {
731  if (!degraded)
732  WARN("checksum error\n");
733  checksum_error = true;
734  } else if (!NT_SUCCESS(Status)) {
735  ERR("check_csum returned %08lx\n", Status);
736  return Status;
737  }
738  } else if (degraded)
739  checksum_error = true;
740 
741  if (!checksum_error)
742  return STATUS_SUCCESS;
743 
744  if (context->tree) {
745  uint16_t parity;
746  uint64_t off;
747  bool recovered = false, first = true, failed = false;
748  uint8_t* t2;
749 
750  t2 = ExAllocatePoolWithTag(NonPagedPool, Vcb->superblock.node_size * 2, ALLOC_TAG);
751  if (!t2) {
752  ERR("out of memory\n");
754  }
755 
756  get_raid0_offset(addr - offset, ci->stripe_length, ci->num_stripes - 1, &off, &stripe);
757 
758  parity = (((addr - offset) / ((ci->num_stripes - 1) * ci->stripe_length)) + ci->num_stripes - 1) % ci->num_stripes;
759 
760  stripe = (parity + stripe + 1) % ci->num_stripes;
761 
762  for (j = 0; j < ci->num_stripes; j++) {
763  if (j != stripe) {
764  if (devices[j] && devices[j]->devobj) {
765  if (first) {
766  Status = sync_read_phys(devices[j]->devobj, devices[j]->fileobj, cis[j].offset + off, Vcb->superblock.node_size, t2, false);
767  if (!NT_SUCCESS(Status)) {
768  ERR("sync_read_phys returned %08lx\n", Status);
770  failed = true;
771  break;
772  }
773 
774  first = false;
775  } else {
776  Status = sync_read_phys(devices[j]->devobj, devices[j]->fileobj, cis[j].offset + off, Vcb->superblock.node_size, t2 + Vcb->superblock.node_size, false);
777  if (!NT_SUCCESS(Status)) {
778  ERR("sync_read_phys returned %08lx\n", Status);
780  failed = true;
781  break;
782  }
783 
784  do_xor(t2, t2 + Vcb->superblock.node_size, Vcb->superblock.node_size);
785  }
786  } else {
787  failed = true;
788  break;
789  }
790  }
791  }
792 
793  if (!failed) {
794  tree_header* t3 = (tree_header*)t2;
795 
796  if (t3->address == addr && check_tree_checksum(Vcb, t3) && (generation == 0 || t3->generation == generation)) {
797  RtlCopyMemory(buf, t2, Vcb->superblock.node_size);
798 
799  if (!degraded)
800  ERR("recovering from checksum error at %I64x, device %I64x\n", addr, devices[stripe]->devitem.dev_id);
801 
802  recovered = true;
803 
804  if (!Vcb->readonly && devices[stripe] && !devices[stripe]->readonly && devices[stripe]->devobj) { // write good data over bad
805  Status = write_data_phys(devices[stripe]->devobj, devices[stripe]->fileobj, cis[stripe].offset + off, t2, Vcb->superblock.node_size);
806  if (!NT_SUCCESS(Status)) {
807  WARN("write_data_phys returned %08lx\n", Status);
809  }
810  }
811  }
812  }
813 
814  if (!recovered) {
815  ERR("unrecoverable checksum error at %I64x\n", addr);
816  ExFreePool(t2);
817  return STATUS_CRC_ERROR;
818  }
819 
820  ExFreePool(t2);
821  } else {
822  ULONG sectors = length >> Vcb->sector_shift;
823  uint8_t* sector;
824  void* ptr = context->csum;
825 
826  sector = ExAllocatePoolWithTag(NonPagedPool, Vcb->superblock.sector_size * 2, ALLOC_TAG);
827  if (!sector) {
828  ERR("out of memory\n");
830  }
831 
832  for (ULONG i = 0; i < sectors; i++) {
833  uint16_t parity;
834  uint64_t off;
835 
836  get_raid0_offset(addr - offset + ((uint64_t)i << Vcb->sector_shift), ci->stripe_length,
837  ci->num_stripes - 1, &off, &stripe);
838 
839  parity = (((addr - offset + ((uint64_t)i << Vcb->sector_shift)) / ((ci->num_stripes - 1) * ci->stripe_length)) + ci->num_stripes - 1) % ci->num_stripes;
840 
841  stripe = (parity + stripe + 1) % ci->num_stripes;
842 
843  if (!devices[stripe] || !devices[stripe]->devobj || (ptr && !check_sector_csum(Vcb, buf + (i << Vcb->sector_shift), ptr))) {
844  bool recovered = false, first = true, failed = false;
845 
846  if (devices[stripe] && devices[stripe]->devobj)
848 
849  for (j = 0; j < ci->num_stripes; j++) {
850  if (j != stripe) {
851  if (devices[j] && devices[j]->devobj) {
852  if (first) {
853  Status = sync_read_phys(devices[j]->devobj, devices[j]->fileobj, cis[j].offset + off, Vcb->superblock.sector_size, sector, false);
854  if (!NT_SUCCESS(Status)) {
855  ERR("sync_read_phys returned %08lx\n", Status);
856  failed = true;
858  break;
859  }
860 
861  first = false;
862  } else {
863  Status = sync_read_phys(devices[j]->devobj, devices[j]->fileobj, cis[j].offset + off, Vcb->superblock.sector_size,
864  sector + Vcb->superblock.sector_size, false);
865  if (!NT_SUCCESS(Status)) {
866  ERR("sync_read_phys returned %08lx\n", Status);
867  failed = true;
869  break;
870  }
871 
872  do_xor(sector, sector + Vcb->superblock.sector_size, Vcb->superblock.sector_size);
873  }
874  } else {
875  failed = true;
876  break;
877  }
878  }
879  }
880 
881  if (!failed) {
882  if (!ptr || check_sector_csum(Vcb, sector, ptr)) {
883  RtlCopyMemory(buf + (i << Vcb->sector_shift), sector, Vcb->superblock.sector_size);
884 
885  if (!degraded)
886  ERR("recovering from checksum error at %I64x, device %I64x\n", addr + ((uint64_t)i << Vcb->sector_shift), devices[stripe]->devitem.dev_id);
887 
888  recovered = true;
889 
890  if (!Vcb->readonly && devices[stripe] && !devices[stripe]->readonly && devices[stripe]->devobj) { // write good data over bad
891  Status = write_data_phys(devices[stripe]->devobj, devices[stripe]->fileobj, cis[stripe].offset + off,
892  sector, Vcb->superblock.sector_size);
893  if (!NT_SUCCESS(Status)) {
894  WARN("write_data_phys returned %08lx\n", Status);
896  }
897  }
898  }
899  }
900 
901  if (!recovered) {
902  ERR("unrecoverable checksum error at %I64x\n", addr + ((uint64_t)i << Vcb->sector_shift));
904  return STATUS_CRC_ERROR;
905  }
906  }
907 
908  if (ptr)
909  ptr = (uint8_t*)ptr + Vcb->csum_size;
910  }
911 
913  }
914 
915  return STATUS_SUCCESS;
916 }
uint32_t sector
Definition: isohybrid.c:61
#define max(a, b)
Definition: svc.c:63
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
Definition: http.c:7251
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
Definition: write.c:113
uint64_t address
Definition: btrfs_drv.h:546
uint64_t stripe_length
Definition: btrfs.h:342
RTL_BITMAP bmp
Definition: btrfs_drv.h:549
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:989
bool check_sector_csum(device_extension *Vcb, void *buf, void *csum)
Definition: read.c:202
#define ALLOC_TAG
Definition: btrfs_drv.h:87
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
uint64_t address
Definition: btrfs.h:156
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
static PVOID ptr
Definition: dispmode.c:27
uint64_t generation
Definition: btrfs.h:159
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:542
Status
Definition: gdiplustypes.h:24
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:64
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define BTRFS_DEV_STAT_GENERATION_ERRORS
Definition: btrfs.h:543
GLintptr offset
Definition: glext.h:5920
#define Vcb
Definition: cdprocs.h:1415
const GLubyte * c
Definition: glext.h:8905
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
GLuint GLuint end
Definition: gl.h:1545
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
GLenum const GLvoid * addr
Definition: glext.h:9621
#define index(s, c)
Definition: various.h:29
uint8_t data[1]
Definition: btrfs_drv.h:551
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:2701
#define uint64_t
Definition: nsiface.idl:62
#define BTRFS_DEV_STAT_READ_ERRORS
Definition: btrfs.h:540
#define ERR(fmt,...)
Definition: debug.h:110
UINT64 uint64_t
Definition: types.h:77
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