ReactOS  0.4.15-dev-318-g99b52df
scrub.c File Reference
#include "btrfs_drv.h"
Include dependency graph for scrub.c:

Go to the source code of this file.

Classes

struct  scrub_context_stripe
 
struct  _scrub_context
 
struct  path_part
 
struct  scrub_context_raid56_stripe
 
struct  scrub_context_raid56
 

Macros

#define SCRUB_UNIT   0x100000
 

Typedefs

typedef struct _scrub_context scrub_context
 

Functions

static void log_file_checksum_error (device_extension *Vcb, uint64_t addr, uint64_t devid, uint64_t subvol, uint64_t inode, uint64_t offset)
 
static void log_file_checksum_error_shared (device_extension *Vcb, uint64_t treeaddr, uint64_t addr, uint64_t devid, uint64_t extent)
 
static void log_tree_checksum_error (device_extension *Vcb, uint64_t addr, uint64_t devid, uint64_t root, uint8_t level, KEY *firstitem)
 
static void log_tree_checksum_error_shared (device_extension *Vcb, uint64_t offset, uint64_t address, uint64_t devid)
 
static void log_unrecoverable_error (device_extension *Vcb, uint64_t address, uint64_t devid)
 
static void log_error (device_extension *Vcb, uint64_t addr, uint64_t devid, bool metadata, bool recoverable, bool parity)
 
 _Function_class_ (IO_COMPLETION_ROUTINE)
 
static NTSTATUS scrub_extent_dup (device_extension *Vcb, chunk *c, uint64_t offset, void *csum, scrub_context *context)
 
static NTSTATUS scrub_extent_raid0 (device_extension *Vcb, chunk *c, uint64_t offset, uint32_t length, uint16_t startoffstripe, void *csum, scrub_context *context)
 
static NTSTATUS scrub_extent_raid10 (device_extension *Vcb, chunk *c, uint64_t offset, uint32_t length, uint16_t startoffstripe, void *csum, scrub_context *context)
 
static NTSTATUS scrub_extent (device_extension *Vcb, chunk *c, ULONG type, uint64_t offset, uint32_t size, void *csum)
 
static NTSTATUS scrub_data_extent (device_extension *Vcb, chunk *c, uint64_t offset, ULONG type, void *csum, RTL_BITMAP *bmp, ULONG bmplen)
 
static void scrub_raid5_stripe (device_extension *Vcb, chunk *c, scrub_context_raid56 *context, uint64_t stripe_start, uint64_t bit_start, uint64_t num, uint16_t missing_devices)
 
static void scrub_raid6_stripe (device_extension *Vcb, chunk *c, scrub_context_raid56 *context, uint64_t stripe_start, uint64_t bit_start, uint64_t num, uint16_t missing_devices)
 
static NTSTATUS scrub_chunk_raid56_stripe_run (device_extension *Vcb, chunk *c, uint64_t stripe_start, uint64_t stripe_end)
 
static NTSTATUS scrub_chunk_raid56 (device_extension *Vcb, chunk *c, uint64_t *offset, bool *changed)
 
static NTSTATUS scrub_chunk (device_extension *Vcb, chunk *c, uint64_t *offset, bool *changed)
 
 _Function_class_ (KSTART_ROUTINE)
 
NTSTATUS start_scrub (device_extension *Vcb, KPROCESSOR_MODE processor_mode)
 
NTSTATUS query_scrub (device_extension *Vcb, KPROCESSOR_MODE processor_mode, void *data, ULONG length)
 
NTSTATUS pause_scrub (device_extension *Vcb, KPROCESSOR_MODE processor_mode)
 
NTSTATUS resume_scrub (device_extension *Vcb, KPROCESSOR_MODE processor_mode)
 
NTSTATUS stop_scrub (device_extension *Vcb, KPROCESSOR_MODE processor_mode)
 

Macro Definition Documentation

◆ SCRUB_UNIT

#define SCRUB_UNIT   0x100000

Definition at line 20 of file scrub.c.

Typedef Documentation

◆ scrub_context

Function Documentation

◆ _Function_class_() [1/2]

_Function_class_ ( IO_COMPLETION_ROUTINE  )

Definition at line 651 of file scrub.c.

652  {
653  scrub_context_stripe* stripe = conptr;
655  ULONG left = InterlockedDecrement(&context->stripes_left);
656 
658 
659  stripe->iosb = Irp->IoStatus;
660 
661  if (left == 0)
662  KeSetEvent(&context->Event, 0, false);
663 
665 }
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:68
Definition: http.c:7094
_In_ PIRP Irp
Definition: csq.h:116
Definition: write.c:111
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
#define UNUSED(x)
Definition: btrfs_drv.h:86
GLint left
Definition: glext.h:7726
#define InterlockedDecrement
Definition: armddk.h:52
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1560
unsigned int ULONG
Definition: retypes.h:1

◆ _Function_class_() [2/2]

_Function_class_ ( KSTART_ROUTINE  )

Definition at line 3139 of file scrub.c.

3140  {
3142  LIST_ENTRY chunks, *le;
3143  NTSTATUS Status;
3145 
3146  KeInitializeEvent(&Vcb->scrub.finished, NotificationEvent, false);
3147 
3148  InitializeListHead(&chunks);
3149 
3150  ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
3151 
3152  if (Vcb->need_write && !Vcb->readonly)
3153  Status = do_write(Vcb, NULL);
3154  else
3156 
3157  free_trees(Vcb);
3158 
3159  if (!NT_SUCCESS(Status)) {
3160  ExReleaseResourceLite(&Vcb->tree_lock);
3161  ERR("do_write returned %08lx\n", Status);
3162  Vcb->scrub.error = Status;
3163  goto end;
3164  }
3165 
3166  ExConvertExclusiveToSharedLite(&Vcb->tree_lock);
3167 
3168  ExAcquireResourceExclusiveLite(&Vcb->scrub.stats_lock, true);
3169 
3170  KeQuerySystemTime(&Vcb->scrub.start_time);
3171  Vcb->scrub.finish_time.QuadPart = 0;
3172  Vcb->scrub.resume_time.QuadPart = Vcb->scrub.start_time.QuadPart;
3173  Vcb->scrub.duration.QuadPart = 0;
3174  Vcb->scrub.total_chunks = 0;
3175  Vcb->scrub.chunks_left = 0;
3176  Vcb->scrub.data_scrubbed = 0;
3177  Vcb->scrub.num_errors = 0;
3178 
3179  while (!IsListEmpty(&Vcb->scrub.errors)) {
3181  ExFreePool(err);
3182  }
3183 
3184  ExAcquireResourceSharedLite(&Vcb->chunk_lock, true);
3185 
3186  le = Vcb->chunks.Flink;
3187  while (le != &Vcb->chunks) {
3189 
3191 
3192  if (!c->readonly) {
3193  InsertTailList(&chunks, &c->list_entry_balance);
3194  Vcb->scrub.total_chunks++;
3195  Vcb->scrub.chunks_left++;
3196  }
3197 
3199 
3200  le = le->Flink;
3201  }
3202 
3203  ExReleaseResourceLite(&Vcb->chunk_lock);
3204 
3205  ExReleaseResource(&Vcb->scrub.stats_lock);
3206 
3207  ExReleaseResourceLite(&Vcb->tree_lock);
3208 
3209  while (!IsListEmpty(&chunks)) {
3210  chunk* c = CONTAINING_RECORD(RemoveHeadList(&chunks), chunk, list_entry_balance);
3211  uint64_t offset = c->offset;
3212  bool changed;
3213 
3214  c->reloc = true;
3215 
3216  KeWaitForSingleObject(&Vcb->scrub.event, Executive, KernelMode, false, NULL);
3217 
3218  if (!Vcb->scrub.stopping) {
3219  do {
3220  changed = false;
3221 
3222  Status = scrub_chunk(Vcb, c, &offset, &changed);
3223  if (!NT_SUCCESS(Status)) {
3224  ERR("scrub_chunk returned %08lx\n", Status);
3225  Vcb->scrub.stopping = true;
3226  Vcb->scrub.error = Status;
3227  break;
3228  }
3229 
3230  if (offset == c->offset + c->chunk_item->size || Vcb->scrub.stopping)
3231  break;
3232 
3233  KeWaitForSingleObject(&Vcb->scrub.event, Executive, KernelMode, false, NULL);
3234  } while (changed);
3235  }
3236 
3237  ExAcquireResourceExclusiveLite(&Vcb->scrub.stats_lock, true);
3238 
3239  if (!Vcb->scrub.stopping)
3240  Vcb->scrub.chunks_left--;
3241 
3242  if (IsListEmpty(&chunks))
3243  KeQuerySystemTime(&Vcb->scrub.finish_time);
3244 
3245  ExReleaseResource(&Vcb->scrub.stats_lock);
3246 
3247  c->reloc = false;
3248  c->list_entry_balance.Flink = NULL;
3249  }
3250 
3252  Vcb->scrub.duration.QuadPart += time.QuadPart - Vcb->scrub.resume_time.QuadPart;
3253 
3254 end:
3255  ZwClose(Vcb->scrub.thread);
3256  Vcb->scrub.thread = NULL;
3257 
3258  KeSetEvent(&Vcb->scrub.finished, 0, false);
3259 }
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
Definition: http.c:7094
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
NTSTATUS do_write(device_extension *Vcb, PIRP Irp)
Definition: flushthread.c:7789
VOID NTAPI ExConvertExclusiveToSharedLite(IN PERESOURCE Resource)
Definition: resource.c:1402
LONG NTSTATUS
Definition: precomp.h:26
GLintptr offset
Definition: glext.h:5920
release_chunk_lock(c, Vcb)
GLuint GLuint end
Definition: gl.h:1545
__u16 time
Definition: mkdosfs.c:366
#define InsertTailList(ListHead, Entry)
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
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
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
smooth NULL
Definition: ftsmooth.c:416
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
void free_trees(device_extension *Vcb)
Definition: treefuncs.c:794
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
struct _LIST_ENTRY * Flink
Definition: typedefs.h:120
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1425
const GLubyte * c
Definition: glext.h:8905
#define ExReleaseResource(R)
Definition: exfuncs.h:257
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
Definition: typedefs.h:118
#define err(...)
Status
Definition: gdiplustypes.h:24
static NTSTATUS scrub_chunk(device_extension *Vcb, chunk *c, uint64_t *offset, bool *changed)
Definition: scrub.c:2924
#define ERR(fmt,...)
Definition: debug.h:110
UINT64 uint64_t
Definition: types.h:77
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define acquire_chunk_lock(c, Vcb)
Definition: btrfs_drv.h:1137
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
Definition: list.h:27
BOOLEAN NTAPI ExAcquireResourceSharedLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:885
return STATUS_SUCCESS
Definition: btrfs.c:3014
#define ExFreePool(addr)
Definition: env_spec_w32.h:352

◆ log_error()

static void log_error ( device_extension Vcb,
uint64_t  addr,
uint64_t  devid,
bool  metadata,
bool  recoverable,
bool  parity 
)
static

Definition at line 605 of file scrub.c.

605  {
606  if (recoverable) {
607  scrub_error* err;
608 
609  if (parity) {
610  ERR("recovering from parity error at %I64x on device %I64x\n", addr, devid);
611  } else {
612  if (metadata)
613  ERR("recovering from metadata checksum error at %I64x on device %I64x\n", addr, devid);
614  else
615  ERR("recovering from data checksum error at %I64x on device %I64x\n", addr, devid);
616  }
617 
619  if (!err) {
620  ERR("out of memory\n");
621  return;
622  }
623 
624  err->address = addr;
625  err->device = devid;
626  err->recovered = true;
627  err->is_metadata = metadata;
628  err->parity = parity;
629 
630  if (metadata)
631  RtlZeroMemory(&err->metadata, sizeof(err->metadata));
632  else
633  RtlZeroMemory(&err->data, sizeof(err->data));
634 
635  ExAcquireResourceExclusiveLite(&Vcb->scrub.stats_lock, true);
636 
637  Vcb->scrub.num_errors++;
638  InsertTailList(&Vcb->scrub.errors, &err->list_entry);
639 
640  ExReleaseResourceLite(&Vcb->scrub.stats_lock);
641  } else {
642  if (metadata)
643  ERR("unrecoverable metadata checksum error at %I64x\n", addr);
644  else
645  ERR("unrecoverable data checksum error at %I64x\n", addr);
646 
648  }
649 }
#define InsertTailList(ListHead, Entry)
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
#define ALLOC_TAG
Definition: btrfs_drv.h:91
#define Vcb
Definition: cdprocs.h:1425
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
GLenum const GLvoid * addr
Definition: glext.h:9621
#define err(...)
#define ERR(fmt,...)
Definition: debug.h:110
static void log_unrecoverable_error(device_extension *Vcb, uint64_t address, uint64_t devid)
Definition: scrub.c:442
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261

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

◆ log_file_checksum_error()

static void log_file_checksum_error ( device_extension Vcb,
uint64_t  addr,
uint64_t  devid,
uint64_t  subvol,
uint64_t  inode,
uint64_t  offset 
)
static

Definition at line 47 of file scrub.c.

47  {
48  LIST_ENTRY *le, parts;
49  root* r = NULL;
50  KEY searchkey;
52  uint64_t dir;
53  bool orig_subvol = true, not_in_tree = false;
57  ULONG utf16len;
58 
59  le = Vcb->roots.Flink;
60  while (le != &Vcb->roots) {
62 
63  if (r2->id == subvol) {
64  r = r2;
65  break;
66  }
67 
68  le = le->Flink;
69  }
70 
71  if (!r) {
72  ERR("could not find subvol %I64x\n", subvol);
73  return;
74  }
75 
77 
78  dir = inode;
79 
80  while (true) {
81  if (dir == r->root_item.objid) {
82  if (r == Vcb->root_fileref->fcb->subvol)
83  break;
84 
85  searchkey.obj_id = r->id;
86  searchkey.obj_type = TYPE_ROOT_BACKREF;
87  searchkey.offset = 0xffffffffffffffff;
88 
89  Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, false, NULL);
90  if (!NT_SUCCESS(Status)) {
91  ERR("find_item returned %08lx\n", Status);
92  goto end;
93  }
94 
95  if (tp.item->key.obj_id == searchkey.obj_id && tp.item->key.obj_type == searchkey.obj_type) {
96  ROOT_REF* rr = (ROOT_REF*)tp.item->data;
97  path_part* pp;
98 
99  if (tp.item->size < sizeof(ROOT_REF)) {
100  ERR("(%I64x,%x,%I64x) was %u bytes, expected at least %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, sizeof(ROOT_REF));
101  goto end;
102  }
103 
104  if (tp.item->size < offsetof(ROOT_REF, name[0]) + rr->n) {
105  ERR("(%I64x,%x,%I64x) was %u bytes, expected at least %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset,
106  tp.item->size, offsetof(ROOT_REF, name[0]) + rr->n);
107  goto end;
108  }
109 
111  if (!pp) {
112  ERR("out of memory\n");
113  goto end;
114  }
115 
116  pp->name.Buffer = rr->name;
117  pp->name.Length = pp->name.MaximumLength = rr->n;
118  pp->orig_subvol = false;
119 
120  InsertTailList(&parts, &pp->list_entry);
121 
122  r = NULL;
123 
124  le = Vcb->roots.Flink;
125  while (le != &Vcb->roots) {
127 
128  if (r2->id == tp.item->key.offset) {
129  r = r2;
130  break;
131  }
132 
133  le = le->Flink;
134  }
135 
136  if (!r) {
137  ERR("could not find subvol %I64x\n", tp.item->key.offset);
138  goto end;
139  }
140 
141  dir = rr->dir;
142  orig_subvol = false;
143  } else {
144  not_in_tree = true;
145  break;
146  }
147  } else {
148  searchkey.obj_id = dir;
149  searchkey.obj_type = TYPE_INODE_EXTREF;
150  searchkey.offset = 0xffffffffffffffff;
151 
152  Status = find_item(Vcb, r, &tp, &searchkey, false, NULL);
153  if (!NT_SUCCESS(Status)) {
154  ERR("find_item returned %08lx\n", Status);
155  goto end;
156  }
157 
158  if (tp.item->key.obj_id == searchkey.obj_id && tp.item->key.obj_type == TYPE_INODE_REF) {
159  INODE_REF* ir = (INODE_REF*)tp.item->data;
160  path_part* pp;
161 
162  if (tp.item->size < sizeof(INODE_REF)) {
163  ERR("(%I64x,%x,%I64x) was %u bytes, expected at least %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, sizeof(INODE_REF));
164  goto end;
165  }
166 
167  if (tp.item->size < offsetof(INODE_REF, name[0]) + ir->n) {
168  ERR("(%I64x,%x,%I64x) was %u bytes, expected at least %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset,
169  tp.item->size, offsetof(INODE_REF, name[0]) + ir->n);
170  goto end;
171  }
172 
174  if (!pp) {
175  ERR("out of memory\n");
176  goto end;
177  }
178 
179  pp->name.Buffer = ir->name;
180  pp->name.Length = pp->name.MaximumLength = ir->n;
181  pp->orig_subvol = orig_subvol;
182 
183  InsertTailList(&parts, &pp->list_entry);
184 
185  if (dir == tp.item->key.offset)
186  break;
187 
188  dir = tp.item->key.offset;
189  } else if (tp.item->key.obj_id == searchkey.obj_id && tp.item->key.obj_type == TYPE_INODE_EXTREF) {
191  path_part* pp;
192 
193  if (tp.item->size < sizeof(INODE_EXTREF)) {
194  ERR("(%I64x,%x,%I64x) was %u bytes, expected at least %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset,
195  tp.item->size, sizeof(INODE_EXTREF));
196  goto end;
197  }
198 
199  if (tp.item->size < offsetof(INODE_EXTREF, name[0]) + ier->n) {
200  ERR("(%I64x,%x,%I64x) was %u bytes, expected at least %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset,
201  tp.item->size, offsetof(INODE_EXTREF, name[0]) + ier->n);
202  goto end;
203  }
204 
206  if (!pp) {
207  ERR("out of memory\n");
208  goto end;
209  }
210 
211  pp->name.Buffer = ier->name;
212  pp->name.Length = pp->name.MaximumLength = ier->n;
213  pp->orig_subvol = orig_subvol;
214 
215  InsertTailList(&parts, &pp->list_entry);
216 
217  if (dir == ier->dir)
218  break;
219 
220  dir = ier->dir;
221  } else {
222  ERR("could not find INODE_REF for inode %I64x in subvol %I64x\n", dir, r->id);
223  goto end;
224  }
225  }
226  }
227 
228  fn.MaximumLength = 0;
229 
230  if (not_in_tree) {
231  le = parts.Blink;
232  while (le != &parts) {
234  LIST_ENTRY* le2 = le->Blink;
235 
236  if (pp->orig_subvol)
237  break;
238 
240  ExFreePool(pp);
241 
242  le = le2;
243  }
244  }
245 
246  le = parts.Flink;
247  while (le != &parts) {
249 
250  fn.MaximumLength += pp->name.Length + 1;
251 
252  le = le->Flink;
253  }
254 
255  fn.Buffer = ExAllocatePoolWithTag(PagedPool, fn.MaximumLength, ALLOC_TAG);
256  if (!fn.Buffer) {
257  ERR("out of memory\n");
258  goto end;
259  }
260 
261  fn.Length = 0;
262 
263  le = parts.Blink;
264  while (le != &parts) {
266 
267  fn.Buffer[fn.Length] = '\\';
268  fn.Length++;
269 
270  RtlCopyMemory(&fn.Buffer[fn.Length], pp->name.Buffer, pp->name.Length);
271  fn.Length += pp->name.Length;
272 
273  le = le->Blink;
274  }
275 
276  if (not_in_tree)
277  ERR("subvol %I64x, %.*s, offset %I64x\n", subvol, fn.Length, fn.Buffer, offset);
278  else
279  ERR("%.*s, offset %I64x\n", fn.Length, fn.Buffer, offset);
280 
281  Status = utf8_to_utf16(NULL, 0, &utf16len, fn.Buffer, fn.Length);
282  if (!NT_SUCCESS(Status)) {
283  ERR("utf8_to_utf16 1 returned %08lx\n", Status);
284  ExFreePool(fn.Buffer);
285  goto end;
286  }
287 
289  if (!err) {
290  ERR("out of memory\n");
291  ExFreePool(fn.Buffer);
292  goto end;
293  }
294 
295  err->address = addr;
296  err->device = devid;
297  err->recovered = false;
298  err->is_metadata = false;
299  err->parity = false;
300 
301  err->data.subvol = not_in_tree ? subvol : 0;
302  err->data.offset = offset;
303  err->data.filename_length = (uint16_t)utf16len;
304 
305  Status = utf8_to_utf16(err->data.filename, utf16len, &utf16len, fn.Buffer, fn.Length);
306  if (!NT_SUCCESS(Status)) {
307  ERR("utf8_to_utf16 2 returned %08lx\n", Status);
308  ExFreePool(fn.Buffer);
309  ExFreePool(err);
310  goto end;
311  }
312 
313  ExAcquireResourceExclusiveLite(&Vcb->scrub.stats_lock, true);
314 
315  Vcb->scrub.num_errors++;
316  InsertTailList(&Vcb->scrub.errors, &err->list_entry);
317 
318  ExReleaseResourceLite(&Vcb->scrub.stats_lock);
319 
320  ExFreePool(fn.Buffer);
321 
322 end:
323  while (!IsListEmpty(&parts)) {
325 
326  ExFreePool(pp);
327  }
328 }
uint64_t obj_id
Definition: btrfs.h:137
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
uint8_t obj_type
Definition: btrfs.h:138
uint16_t n
Definition: btrfs.h:371
char name[1]
Definition: btrfs.h:453
static GLenum _GLUfuncptr fn
Definition: wgl_font.c:159
static const D3D_BLOB_PART parts[]
Definition: blob.c:76
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
struct _LIST_ENTRY * Blink
Definition: typedefs.h:121
FORCEINLINE PLIST_ENTRY RemoveTailList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:154
LONG NTSTATUS
Definition: precomp.h:26
GLintptr offset
Definition: glext.h:5920
uint16_t size
Definition: btrfs_drv.h:430
WCHAR filename[1]
Definition: btrfs_drv.h:734
GLuint GLuint end
Definition: gl.h:1545
#define uint16_t
Definition: nsiface.idl:60
#define InsertTailList(ListHead, Entry)
uint16_t n
Definition: btrfs.h:452
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
uint64_t offset
Definition: btrfs.h:139
uint8_t * data
Definition: btrfs_drv.h:431
uint64_t dir
Definition: btrfs.h:450
Definition: fs.h:78
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
#define ALLOC_TAG
Definition: btrfs_drv.h:91
#define pp
Definition: hlsl.yy.c:1208
char name[1]
Definition: btrfs.h:365
smooth NULL
Definition: ftsmooth.c:416
#define offsetof(TYPE, MEMBER)
#define TYPE_INODE_REF
Definition: btrfs.h:20
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
unsigned int dir
Definition: maze.c:112
uint16_t n
Definition: btrfs.h:364
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
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2930
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
struct _LIST_ENTRY * Flink
Definition: typedefs.h:120
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1425
static DNS_RECORDW r2
Definition: record.c:38
wstring utf8_to_utf16(const string_view &utf8)
Definition: main.cpp:736
char * name
Definition: compiler.c:66
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
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
tree_data * item
Definition: btrfs_drv.h:518
GLenum const GLvoid * addr
Definition: glext.h:9621
#define TYPE_INODE_EXTREF
Definition: btrfs.h:21
Definition: typedefs.h:118
#define err(...)
uint64_t dir
Definition: btrfs.h:369
Status
Definition: gdiplustypes.h:24
char name[1]
Definition: btrfs.h:372
#define ERR(fmt,...)
Definition: debug.h:110
Definition: btrfs.h:136
UINT64 uint64_t
Definition: types.h:77
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
Definition: list.h:27
#define TYPE_ROOT_BACKREF
Definition: btrfs.h:29
Definition: name.c:38
unsigned int ULONG
Definition: retypes.h:1
#define ExFreePool(addr)
Definition: env_spec_w32.h:352

Referenced by log_file_checksum_error_shared(), and log_unrecoverable_error().

◆ log_file_checksum_error_shared()

static void log_file_checksum_error_shared ( device_extension Vcb,
uint64_t  treeaddr,
uint64_t  addr,
uint64_t  devid,
uint64_t  extent 
)
static

Definition at line 330 of file scrub.c.

330  {
331  tree_header* tree;
333  leaf_node* ln;
334  ULONG i;
335 
336  tree = ExAllocatePoolWithTag(PagedPool, Vcb->superblock.node_size, ALLOC_TAG);
337  if (!tree) {
338  ERR("out of memory\n");
339  return;
340  }
341 
342  Status = read_data(Vcb, treeaddr, Vcb->superblock.node_size, NULL, true, (uint8_t*)tree, NULL, NULL, NULL, 0, false, NormalPagePriority);
343  if (!NT_SUCCESS(Status)) {
344  ERR("read_data returned %08lx\n", Status);
345  goto end;
346  }
347 
348  if (tree->level != 0) {
349  ERR("tree level was %x, expected 0\n", tree->level);
350  goto end;
351  }
352 
353  ln = (leaf_node*)&tree[1];
354 
355  for (i = 0; i < tree->num_items; i++) {
356  if (ln[i].key.obj_type == TYPE_EXTENT_DATA && ln[i].size >= sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2)) {
357  EXTENT_DATA* ed = (EXTENT_DATA*)((uint8_t*)tree + sizeof(tree_header) + ln[i].offset);
359 
360  if (ed->type == EXTENT_TYPE_REGULAR && ed2->size != 0 && ed2->address == addr)
361  log_file_checksum_error(Vcb, addr, devid, tree->tree_id, ln[i].key.obj_id, ln[i].key.offset + addr - extent);
362  }
363  }
364 
365 end:
366  ExFreePool(tree);
367 }
uint8_t type
Definition: btrfs.h:351
EXTENT_DATA2 * ed2
Definition: write.c:2805
struct _tree tree
LONG NTSTATUS
Definition: precomp.h:26
GLintptr offset
Definition: glext.h:5920
GLuint GLuint end
Definition: gl.h:1545
#define ALLOC_TAG
Definition: btrfs_drv.h:91
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
uint64_t address
Definition: btrfs.h:356
smooth NULL
Definition: ftsmooth.c:416
uint64_t size
Definition: btrfs.h:357
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1425
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
GLenum const GLvoid * addr
Definition: glext.h:9621
BYTE uint8_t
Definition: msvideo1.c:66
#define EXTENT_TYPE_REGULAR
Definition: btrfs.h:71
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:110
uint8_t data[1]
Definition: btrfs.h:352
static void log_file_checksum_error(device_extension *Vcb, uint64_t addr, uint64_t devid, uint64_t subvol, uint64_t inode, uint64_t offset)
Definition: scrub.c:47
static BOOL read_data(struct request *request, void *buffer, DWORD size, DWORD *read, BOOL async)
Definition: request.c:2018
unsigned int ULONG
Definition: retypes.h:1
#define TYPE_EXTENT_DATA
Definition: btrfs.h:26
EXTENT_DATA * ed
Definition: write.c:2804
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
Definition: path.c:41

Referenced by log_unrecoverable_error().

◆ log_tree_checksum_error()

static void log_tree_checksum_error ( device_extension Vcb,
uint64_t  addr,
uint64_t  devid,
uint64_t  root,
uint8_t  level,
KEY firstitem 
)
static

Definition at line 369 of file scrub.c.

369  {
370  scrub_error* err;
371 
373  if (!err) {
374  ERR("out of memory\n");
375  return;
376  }
377 
378  err->address = addr;
379  err->device = devid;
380  err->recovered = false;
381  err->is_metadata = true;
382  err->parity = false;
383 
384  err->metadata.root = root;
385  err->metadata.level = level;
386 
387  if (firstitem) {
388  ERR("root %I64x, level %u, first item (%I64x,%x,%I64x)\n", root, level, firstitem->obj_id,
389  firstitem->obj_type, firstitem->offset);
390 
391  err->metadata.firstitem = *firstitem;
392  } else {
393  ERR("root %I64x, level %u\n", root, level);
394 
395  RtlZeroMemory(&err->metadata.firstitem, sizeof(KEY));
396  }
397 
398  ExAcquireResourceExclusiveLite(&Vcb->scrub.stats_lock, true);
399 
400  Vcb->scrub.num_errors++;
401  InsertTailList(&Vcb->scrub.errors, &err->list_entry);
402 
403  ExReleaseResourceLite(&Vcb->scrub.stats_lock);
404 }
uint64_t obj_id
Definition: btrfs.h:137
GLint level
Definition: gl.h:1546
uint8_t obj_type
Definition: btrfs.h:138
struct _root root
#define InsertTailList(ListHead, Entry)
uint64_t offset
Definition: btrfs.h:139
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
#define ALLOC_TAG
Definition: btrfs_drv.h:91
#define Vcb
Definition: cdprocs.h:1425
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
GLenum const GLvoid * addr
Definition: glext.h:9621
#define err(...)
#define ERR(fmt,...)
Definition: debug.h:110
Definition: btrfs.h:136
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261

Referenced by log_tree_checksum_error_shared(), and log_unrecoverable_error().

◆ log_tree_checksum_error_shared()

static void log_tree_checksum_error_shared ( device_extension Vcb,
uint64_t  offset,
uint64_t  address,
uint64_t  devid 
)
static

Definition at line 406 of file scrub.c.

406  {
407  tree_header* tree;
409  internal_node* in;
410  ULONG i;
411 
412  tree = ExAllocatePoolWithTag(PagedPool, Vcb->superblock.node_size, ALLOC_TAG);
413  if (!tree) {
414  ERR("out of memory\n");
415  return;
416  }
417 
418  Status = read_data(Vcb, offset, Vcb->superblock.node_size, NULL, true, (uint8_t*)tree, NULL, NULL, NULL, 0, false, NormalPagePriority);
419  if (!NT_SUCCESS(Status)) {
420  ERR("read_data returned %08lx\n", Status);
421  goto end;
422  }
423 
424  if (tree->level == 0) {
425  ERR("tree level was 0\n");
426  goto end;
427  }
428 
429  in = (internal_node*)&tree[1];
430 
431  for (i = 0; i < tree->num_items; i++) {
432  if (in[i].address == address) {
433  log_tree_checksum_error(Vcb, address, devid, tree->tree_id, tree->level - 1, &in[i].key);
434  break;
435  }
436  }
437 
438 end:
439  ExFreePool(tree);
440 }
struct _tree tree
LONG NTSTATUS
Definition: precomp.h:26
GLintptr offset
Definition: glext.h:5920
GLuint GLuint end
Definition: gl.h:1545
#define ALLOC_TAG
Definition: btrfs_drv.h:91
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
smooth NULL
Definition: ftsmooth.c:416
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1425
GLuint address
Definition: glext.h:9393
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
BYTE uint8_t
Definition: msvideo1.c:66
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:110
GLuint in
Definition: glext.h:9616
static BOOL read_data(struct request *request, void *buffer, DWORD size, DWORD *read, BOOL async)
Definition: request.c:2018
unsigned int ULONG
Definition: retypes.h:1
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
static void log_tree_checksum_error(device_extension *Vcb, uint64_t addr, uint64_t devid, uint64_t root, uint8_t level, KEY *firstitem)
Definition: scrub.c:369

Referenced by log_unrecoverable_error().

◆ log_unrecoverable_error()

static void log_unrecoverable_error ( device_extension Vcb,
uint64_t  address,
uint64_t  devid 
)
static

Definition at line 442 of file scrub.c.

442  {
443  KEY searchkey;
446  EXTENT_ITEM* ei;
447  EXTENT_ITEM2* ei2 = NULL;
448  uint8_t* ptr;
449  ULONG len;
450  uint64_t rc;
451 
452  // FIXME - still log even if rest of this function fails
453 
454  searchkey.obj_id = address;
455  searchkey.obj_type = TYPE_METADATA_ITEM;
456  searchkey.offset = 0xffffffffffffffff;
457 
458  Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, false, NULL);
459  if (!NT_SUCCESS(Status)) {
460  ERR("find_item returned %08lx\n", Status);
461  return;
462  }
463 
465  tp.item->key.obj_id >= address + Vcb->superblock.sector_size ||
467  (tp.item->key.obj_type == TYPE_METADATA_ITEM && tp.item->key.obj_id + Vcb->superblock.node_size <= address)
468  )
469  return;
470 
471  if (tp.item->size < sizeof(EXTENT_ITEM)) {
472  ERR("(%I64x,%x,%I64x) was %u bytes, expected at least %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, sizeof(EXTENT_ITEM));
473  return;
474  }
475 
476  ei = (EXTENT_ITEM*)tp.item->data;
477  ptr = (uint8_t*)&ei[1];
478  len = tp.item->size - sizeof(EXTENT_ITEM);
479 
481  if (tp.item->size < sizeof(EXTENT_ITEM) + sizeof(EXTENT_ITEM2)) {
482  ERR("(%I64x,%x,%I64x) was %u bytes, expected at least %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset,
483  tp.item->size, sizeof(EXTENT_ITEM) + sizeof(EXTENT_ITEM2));
484  return;
485  }
486 
487  ei2 = (EXTENT_ITEM2*)ptr;
488 
489  ptr += sizeof(EXTENT_ITEM2);
490  len -= sizeof(EXTENT_ITEM2);
491  }
492 
493  rc = 0;
494 
495  while (len > 0) {
496  uint8_t type = *ptr;
497 
498  ptr++;
499  len--;
500 
501  if (type == TYPE_TREE_BLOCK_REF) {
502  TREE_BLOCK_REF* tbr;
503 
504  if (len < sizeof(TREE_BLOCK_REF)) {
505  ERR("TREE_BLOCK_REF takes up %Iu bytes, but only %lu remaining\n", sizeof(TREE_BLOCK_REF), len);
506  break;
507  }
508 
509  tbr = (TREE_BLOCK_REF*)ptr;
510 
511  log_tree_checksum_error(Vcb, address, devid, tbr->offset, ei2 ? ei2->level : (uint8_t)tp.item->key.offset, ei2 ? &ei2->firstitem : NULL);
512 
513  rc++;
514 
515  ptr += sizeof(TREE_BLOCK_REF);
516  len -= sizeof(TREE_BLOCK_REF);
517  } else if (type == TYPE_EXTENT_DATA_REF) {
518  EXTENT_DATA_REF* edr;
519 
520  if (len < sizeof(EXTENT_DATA_REF)) {
521  ERR("EXTENT_DATA_REF takes up %Iu bytes, but only %lu remaining\n", sizeof(EXTENT_DATA_REF), len);
522  break;
523  }
524 
525  edr = (EXTENT_DATA_REF*)ptr;
526 
527  log_file_checksum_error(Vcb, address, devid, edr->root, edr->objid, edr->offset + address - tp.item->key.obj_id);
528 
529  rc += edr->count;
530 
531  ptr += sizeof(EXTENT_DATA_REF);
532  len -= sizeof(EXTENT_DATA_REF);
533  } else if (type == TYPE_SHARED_BLOCK_REF) {
534  SHARED_BLOCK_REF* sbr;
535 
536  if (len < sizeof(SHARED_BLOCK_REF)) {
537  ERR("SHARED_BLOCK_REF takes up %Iu bytes, but only %lu remaining\n", sizeof(SHARED_BLOCK_REF), len);
538  break;
539  }
540 
541  sbr = (SHARED_BLOCK_REF*)ptr;
542 
544 
545  rc++;
546 
547  ptr += sizeof(SHARED_BLOCK_REF);
548  len -= sizeof(SHARED_BLOCK_REF);
549  } else if (type == TYPE_SHARED_DATA_REF) {
550  SHARED_DATA_REF* sdr;
551 
552  if (len < sizeof(SHARED_DATA_REF)) {
553  ERR("SHARED_DATA_REF takes up %Iu bytes, but only %lu remaining\n", sizeof(SHARED_DATA_REF), len);
554  break;
555  }
556 
557  sdr = (SHARED_DATA_REF*)ptr;
558 
560 
561  rc += sdr->count;
562 
563  ptr += sizeof(SHARED_DATA_REF);
564  len -= sizeof(SHARED_DATA_REF);
565  } else {
566  ERR("unknown extent type %x\n", type);
567  break;
568  }
569  }
570 
571  if (rc < ei->refcount) {
572  do {
573  traverse_ptr next_tp;
574 
575  if (find_next_item(Vcb, &tp, &next_tp, false, NULL))
576  tp = next_tp;
577  else
578  break;
579 
580  if (tp.item->key.obj_id == address) {
582  log_tree_checksum_error(Vcb, address, devid, tp.item->key.offset, ei2 ? ei2->level : (uint8_t)tp.item->key.offset, ei2 ? &ei2->firstitem : NULL);
583  else if (tp.item->key.obj_type == TYPE_EXTENT_DATA_REF) {
584  EXTENT_DATA_REF* edr;
585 
586  if (tp.item->size < sizeof(EXTENT_DATA_REF)) {
587  ERR("(%I64x,%x,%I64x) was %u bytes, expected %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset,
588  tp.item->size, sizeof(EXTENT_DATA_REF));
589  break;
590  }
591 
592  edr = (EXTENT_DATA_REF*)tp.item->data;
593 
594  log_file_checksum_error(Vcb, address, devid, edr->root, edr->objid, edr->offset + address - tp.item->key.obj_id);
595  } else if (tp.item->key.obj_type == TYPE_SHARED_BLOCK_REF)
597  else if (tp.item->key.obj_type == TYPE_SHARED_DATA_REF)
599  } else
600  break;
601  } while (true);
602  }
603 }
uint64_t obj_id
Definition: btrfs.h:137
uint8_t obj_type
Definition: btrfs.h:138
uint64_t offset
Definition: btrfs.h:407
LONG NTSTATUS
Definition: precomp.h:26
uint64_t objid
Definition: btrfs.h:406
uint16_t size
Definition: btrfs_drv.h:430
#define TYPE_TREE_BLOCK_REF
Definition: btrfs.h:33
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
#define TYPE_METADATA_ITEM
Definition: btrfs.h:32
uint64_t offset
Definition: btrfs.h:139
uint8_t * data
Definition: btrfs_drv.h:431
static PVOID ptr
Definition: dispmode.c:27
uint32_t count
Definition: btrfs.h:408
static void log_file_checksum_error_shared(device_extension *Vcb, uint64_t treeaddr, uint64_t addr, uint64_t devid, uint64_t extent)
Definition: scrub.c:330
smooth NULL
Definition: ftsmooth.c:416
#define TYPE_EXTENT_ITEM
Definition: btrfs.h:31
static void log_tree_checksum_error_shared(device_extension *Vcb, uint64_t offset, uint64_t address, uint64_t devid)
Definition: scrub.c:406
uint64_t root
Definition: btrfs.h:405
uint64_t offset
Definition: btrfs.h:401
#define TYPE_EXTENT_DATA_REF
Definition: btrfs.h:34
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2930
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
#define TYPE_SHARED_DATA_REF
Definition: btrfs.h:37
bool find_next_item(_Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, const traverse_ptr *tp, traverse_ptr *next_tp, bool ignore, PIRP Irp)
Definition: treefuncs.c:593
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1425
KEY firstitem
Definition: btrfs.h:386
GLuint address
Definition: glext.h:9393
#define TYPE_SHARED_BLOCK_REF
Definition: btrfs.h:36
tree_data * item
Definition: btrfs_drv.h:518
uint64_t offset
Definition: btrfs.h:425
uint32_t count
Definition: btrfs.h:430
uint8_t level
Definition: btrfs.h:387
GLenum GLsizei len
Definition: glext.h:6722
BYTE uint8_t
Definition: msvideo1.c:66
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:110
Definition: btrfs.h:136
UINT64 uint64_t
Definition: types.h:77
#define EXTENT_ITEM_TREE_BLOCK
Definition: btrfs.h:376
static void log_file_checksum_error(device_extension *Vcb, uint64_t addr, uint64_t devid, uint64_t subvol, uint64_t inode, uint64_t offset)
Definition: scrub.c:47
unsigned int ULONG
Definition: retypes.h:1
uint64_t flags
Definition: btrfs.h:382
uint64_t offset
Definition: btrfs.h:429
static void log_tree_checksum_error(device_extension *Vcb, uint64_t addr, uint64_t devid, uint64_t root, uint8_t level, KEY *firstitem)
Definition: scrub.c:369

Referenced by log_error().

◆ pause_scrub()

NTSTATUS pause_scrub ( device_extension Vcb,
KPROCESSOR_MODE  processor_mode 
)

Definition at line 3402 of file scrub.c.

3402  {
3404 
3405  if (!SeSinglePrivilegeCheck(RtlConvertLongToLuid(SE_MANAGE_VOLUME_PRIVILEGE), processor_mode))
3407 
3408  if (!Vcb->scrub.thread)
3409  return STATUS_DEVICE_NOT_READY;
3410 
3411  if (Vcb->scrub.paused)
3412  return STATUS_DEVICE_NOT_READY;
3413 
3414  Vcb->scrub.paused = true;
3415  KeClearEvent(&Vcb->scrub.event);
3416 
3418  Vcb->scrub.duration.QuadPart += time.QuadPart - Vcb->scrub.resume_time.QuadPart;
3419 
3420  return STATUS_SUCCESS;
3421 }
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
#define STATUS_PRIVILEGE_NOT_HELD
Definition: DriverTester.h:9
BOOLEAN NTAPI SeSinglePrivilegeCheck(IN LUID PrivilegeValue, IN KPROCESSOR_MODE PreviousMode)
Definition: priv.c:524
__u16 time
Definition: mkdosfs.c:366
#define Vcb
Definition: cdprocs.h:1425
#define SE_MANAGE_VOLUME_PRIVILEGE
Definition: security.c:682
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
return STATUS_SUCCESS
Definition: btrfs.c:3014
#define STATUS_DEVICE_NOT_READY
Definition: shellext.h:70

Referenced by fsctl_request().

◆ query_scrub()

NTSTATUS query_scrub ( device_extension Vcb,
KPROCESSOR_MODE  processor_mode,
void data,
ULONG  length 
)

Definition at line 3302 of file scrub.c.

3302  {
3304  ULONG len;
3305  NTSTATUS Status;
3306  LIST_ENTRY* le;
3307  btrfs_scrub_error* bse = NULL;
3308 
3309  if (!SeSinglePrivilegeCheck(RtlConvertLongToLuid(SE_MANAGE_VOLUME_PRIVILEGE), processor_mode))
3311 
3312  if (length < offsetof(btrfs_query_scrub, errors))
3313  return STATUS_BUFFER_TOO_SMALL;
3314 
3315  ExAcquireResourceSharedLite(&Vcb->scrub.stats_lock, true);
3316 
3317  if (Vcb->scrub.thread && Vcb->scrub.chunks_left > 0)
3318  bqs->status = Vcb->scrub.paused ? BTRFS_SCRUB_PAUSED : BTRFS_SCRUB_RUNNING;
3319  else
3320  bqs->status = BTRFS_SCRUB_STOPPED;
3321 
3322  bqs->start_time.QuadPart = Vcb->scrub.start_time.QuadPart;
3323  bqs->finish_time.QuadPart = Vcb->scrub.finish_time.QuadPart;
3324  bqs->chunks_left = Vcb->scrub.chunks_left;
3325  bqs->total_chunks = Vcb->scrub.total_chunks;
3326  bqs->data_scrubbed = Vcb->scrub.data_scrubbed;
3327 
3328  bqs->duration = Vcb->scrub.duration.QuadPart;
3329 
3330  if (bqs->status == BTRFS_SCRUB_RUNNING) {
3332 
3334  bqs->duration += time.QuadPart - Vcb->scrub.resume_time.QuadPart;
3335  }
3336 
3337  bqs->error = Vcb->scrub.error;
3338 
3339  bqs->num_errors = Vcb->scrub.num_errors;
3340 
3341  len = length - offsetof(btrfs_query_scrub, errors);
3342 
3343  le = Vcb->scrub.errors.Flink;
3344  while (le != &Vcb->scrub.errors) {
3346  ULONG errlen;
3347 
3348  if (err->is_metadata)
3349  errlen = offsetof(btrfs_scrub_error, metadata.firstitem) + sizeof(KEY);
3350  else
3351  errlen = offsetof(btrfs_scrub_error, data.filename) + err->data.filename_length;
3352 
3353  if (len < errlen) {
3355  goto end;
3356  }
3357 
3358  if (!bse)
3359  bse = &bqs->errors;
3360  else {
3361  ULONG lastlen;
3362 
3363  if (bse->is_metadata)
3364  lastlen = offsetof(btrfs_scrub_error, metadata.firstitem) + sizeof(KEY);
3365  else
3366  lastlen = offsetof(btrfs_scrub_error, data.filename) + bse->data.filename_length;
3367 
3368  bse->next_entry = lastlen;
3369  bse = (btrfs_scrub_error*)(((uint8_t*)bse) + lastlen);
3370  }
3371 
3372  bse->next_entry = 0;
3373  bse->address = err->address;
3374  bse->device = err->device;
3375  bse->recovered = err->recovered;
3376  bse->is_metadata = err->is_metadata;
3377  bse->parity = err->parity;
3378 
3379  if (err->is_metadata) {
3380  bse->metadata.root = err->metadata.root;
3381  bse->metadata.level = err->metadata.level;
3382  bse->metadata.firstitem = err->metadata.firstitem;
3383  } else {
3384  bse->data.subvol = err->data.subvol;
3385  bse->data.offset = err->data.offset;
3386  bse->data.filename_length = err->data.filename_length;
3387  RtlCopyMemory(bse->data.filename, err->data.filename, err->data.filename_length);
3388  }
3389 
3390  len -= errlen;
3391  le = le->Flink;
3392  }
3393 
3395 
3396 end:
3397  ExReleaseResourceLite(&Vcb->scrub.stats_lock);
3398 
3399  return Status;
3400 }
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
btrfs_scrub_error errors
Definition: btrfsioctl.h:232
uint32_t next_entry
Definition: btrfsioctl.h:199
#define STATUS_PRIVILEGE_NOT_HELD
Definition: DriverTester.h:9
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define BTRFS_SCRUB_STOPPED
Definition: btrfsioctl.h:194
LARGE_INTEGER start_time
Definition: btrfsioctl.h:224
#define BTRFS_SCRUB_PAUSED
Definition: btrfsioctl.h:196
uint64_t data_scrubbed
Definition: btrfsioctl.h:228
uint64_t total_chunks
Definition: btrfsioctl.h:227
uint32_t num_errors
Definition: btrfsioctl.h:231
LONG NTSTATUS
Definition: precomp.h:26
BOOLEAN NTAPI SeSinglePrivilegeCheck(IN LUID PrivilegeValue, IN KPROCESSOR_MODE PreviousMode)
Definition: priv.c:524
#define BTRFS_SCRUB_RUNNING
Definition: btrfsioctl.h:195
GLuint GLuint end
Definition: gl.h:1545
__u16 time
Definition: mkdosfs.c:366
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
uint64_t address
Definition: btrfsioctl.h:200
smooth NULL
Definition: ftsmooth.c:416
#define offsetof(TYPE, MEMBER)
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
struct _LIST_ENTRY * Flink
Definition: typedefs.h:120
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
uint64_t duration
Definition: btrfsioctl.h:229
#define Vcb
Definition: cdprocs.h:1425
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLenum GLsizei len
Definition: glext.h:6722
Definition: typedefs.h:118
#define err(...)
BYTE uint8_t
Definition: msvideo1.c:66
Status
Definition: gdiplustypes.h:24
struct btrfs_scrub_error::@642::@645 metadata
#define SE_MANAGE_VOLUME_PRIVILEGE
Definition: security.c:682
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
#define KEY
Definition: profile.c:30
WCHAR filename[1]
Definition: btrfsioctl.h:211
LARGE_INTEGER finish_time
Definition: btrfsioctl.h:225
Definition: list.h:27
BOOLEAN NTAPI ExAcquireResourceSharedLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:885
unsigned int ULONG
Definition: retypes.h:1
uint64_t chunks_left
Definition: btrfsioctl.h:226
struct btrfs_scrub_error::@642::@644 data
return STATUS_SUCCESS
Definition: btrfs.c:3014
LONGLONG QuadPart
Definition: typedefs.h:113

Referenced by fsctl_request().

◆ resume_scrub()

NTSTATUS resume_scrub ( device_extension Vcb,
KPROCESSOR_MODE  processor_mode 
)

Definition at line 3423 of file scrub.c.

3423  {
3424  if (!SeSinglePrivilegeCheck(RtlConvertLongToLuid(SE_MANAGE_VOLUME_PRIVILEGE), processor_mode))
3426 
3427  if (!Vcb->scrub.thread)
3428  return STATUS_DEVICE_NOT_READY;
3429 
3430  if (!Vcb->scrub.paused)
3431  return STATUS_DEVICE_NOT_READY;
3432 
3433  Vcb->scrub.paused = false;
3434  KeSetEvent(&Vcb->scrub.event, 0, false);
3435 
3436  KeQuerySystemTime(&Vcb->scrub.resume_time);
3437 
3438  return STATUS_SUCCESS;
3439 }
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
#define STATUS_PRIVILEGE_NOT_HELD
Definition: DriverTester.h:9
BOOLEAN NTAPI SeSinglePrivilegeCheck(IN LUID PrivilegeValue, IN KPROCESSOR_MODE PreviousMode)
Definition: priv.c:524
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
#define Vcb
Definition: cdprocs.h:1425
#define SE_MANAGE_VOLUME_PRIVILEGE
Definition: security.c:682
return STATUS_SUCCESS
Definition: btrfs.c:3014
#define STATUS_DEVICE_NOT_READY
Definition: shellext.h:70

Referenced by fsctl_request().

◆ scrub_chunk()

static NTSTATUS scrub_chunk ( device_extension Vcb,
chunk c,
uint64_t offset,
bool changed 
)
static

Definition at line 2924 of file scrub.c.

2924  {
2925  NTSTATUS Status;
2926  KEY searchkey;
2927  traverse_ptr tp;
2928  bool b = false, tree_run = false;
2929  ULONG type, num_extents = 0;
2930  uint64_t total_data = 0, tree_run_start, tree_run_end;
2931 
2932  TRACE("chunk %I64x\n", c->offset);
2933 
2934  ExAcquireResourceSharedLite(&Vcb->tree_lock, true);
2935 
2936  if (c->chunk_item->type & BLOCK_FLAG_DUPLICATE)
2938  else if (c->chunk_item->type & BLOCK_FLAG_RAID0)
2940  else if (c->chunk_item->type & BLOCK_FLAG_RAID1)
2942  else if (c->chunk_item->type & BLOCK_FLAG_RAID10)
2944  else if (c->chunk_item->type & BLOCK_FLAG_RAID5) {
2945  Status = scrub_chunk_raid56(Vcb, c, offset, changed);
2946  goto end;
2947  } else if (c->chunk_item->type & BLOCK_FLAG_RAID6) {
2948  Status = scrub_chunk_raid56(Vcb, c, offset, changed);
2949  goto end;
2950  } else if (c->chunk_item->type & BLOCK_FLAG_RAID1C3)
2952  else if (c->chunk_item->type & BLOCK_FLAG_RAID1C4)
2954  else // SINGLE
2956 
2957  searchkey.obj_id = *offset;
2958  searchkey.obj_type = TYPE_METADATA_ITEM;
2959  searchkey.offset = 0xffffffffffffffff;
2960 
2961  Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, false, NULL);
2962  if (!NT_SUCCESS(Status)) {
2963  ERR("error - find_item returned %08lx\n", Status);
2964  goto end;
2965  }
2966 
2967  do {
2968  traverse_ptr next_tp;
2969 
2970  if (tp.item->key.obj_id >= c->offset + c->chunk_item->size)
2971  break;
2972 
2974  uint64_t size = tp.item->key.obj_type == TYPE_METADATA_ITEM ? Vcb->superblock.node_size : tp.item->key.offset;
2975  bool is_tree;
2976  void* csum = NULL;
2977  RTL_BITMAP bmp;
2978  ULONG* bmparr = NULL, bmplen;
2979 
2980  TRACE("%I64x\n", tp.item->key.obj_id);
2981 
2982  is_tree = false;
2983 
2985  is_tree = true;
2986  else {
2987  EXTENT_ITEM* ei = (EXTENT_ITEM*)tp.item->data;
2988 
2989  if (tp.item->size < sizeof(EXTENT_ITEM)) {
2990  ERR("(%I64x,%x,%I64x) was %u bytes, expected at least %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, sizeof(EXTENT_ITEM));
2992  goto end;
2993  }
2994 
2995  if (ei->flags & EXTENT_ITEM_TREE_BLOCK)
2996  is_tree = true;
2997  }
2998 
3000  ERR("extent %I64x has size less than sector_size (%I64x < %x)\n", tp.item->key.obj_id, size, Vcb->superblock.sector_size);
3002  goto end;
3003  }
3004 
3005  // load csum
3006  if (!is_tree) {
3007  traverse_ptr tp2;
3008 
3009  csum = ExAllocatePoolWithTag(PagedPool, (ULONG)(Vcb->csum_size * size / Vcb->superblock.sector_size), ALLOC_TAG);
3010  if (!csum) {
3011  ERR("out of memory\n");
3013  goto end;
3014  }
3015 
3016  bmplen = (ULONG)(size / Vcb->superblock.sector_size);
3017 
3018  bmparr = ExAllocatePoolWithTag(PagedPool, (ULONG)(sector_align((bmplen >> 3) + 1, sizeof(ULONG))), ALLOC_TAG);
3019  if (!bmparr) {
3020  ERR("out of memory\n");
3021  ExFreePool(csum);
3023  goto end;
3024  }
3025 
3026  RtlInitializeBitMap(&bmp, bmparr, bmplen);
3027  RtlSetAllBits(&bmp); // 1 = no csum, 0 = csum
3028 
3029  searchkey.obj_id = EXTENT_CSUM_ID;
3030  searchkey.obj_type = TYPE_EXTENT_CSUM;
3031  searchkey.offset = tp.item->key.obj_id;
3032 
3033  Status = find_item(Vcb, Vcb->checksum_root, &tp2, &searchkey, false, NULL);
3034  if (!NT_SUCCESS(Status) && Status != STATUS_NOT_FOUND) {
3035  ERR("find_item returned %08lx\n", Status);
3036  ExFreePool(csum);
3037  ExFreePool(bmparr);
3038  goto end;
3039  }
3040 
3041  if (Status != STATUS_NOT_FOUND) {
3042  do {
3043  traverse_ptr next_tp2;
3044 
3045  if (tp2.item->key.obj_type == TYPE_EXTENT_CSUM) {
3046  if (tp2.item->key.offset >= tp.item->key.obj_id + size)
3047  break;
3048  else if (tp2.item->size >= Vcb->csum_size && tp2.item->key.offset + (tp2.item->size * Vcb->superblock.sector_size / Vcb->csum_size) >= tp.item->key.obj_id) {
3049  uint64_t cs = max(tp.item->key.obj_id, tp2.item->key.offset);
3050  uint64_t ce = min(tp.item->key.obj_id + size, tp2.item->key.offset + (tp2.item->size * Vcb->superblock.sector_size / Vcb->csum_size));
3051 
3052  RtlCopyMemory((uint8_t*)csum + ((cs - tp.item->key.obj_id) * Vcb->csum_size / Vcb->superblock.sector_size),
3053  tp2.item->data + ((cs - tp2.item->key.offset) * Vcb->csum_size / Vcb->superblock.sector_size),
3054  (ULONG)((ce - cs) * Vcb->csum_size / Vcb->superblock.sector_size));
3055 
3056  RtlClearBits(&bmp, (ULONG)((cs - tp.item->key.obj_id) / Vcb->superblock.sector_size), (ULONG)((ce - cs) / Vcb->superblock.sector_size));
3057 
3058  if (ce == tp.item->key.obj_id + size)
3059  break;
3060  }
3061  }
3062 
3063  if (find_next_item(Vcb, &tp2, &next_tp2, false, NULL))
3064  tp2 = next_tp2;
3065  else
3066  break;
3067  } while (true);
3068  }
3069  }
3070 
3071  if (tree_run) {
3072  if (!is_tree || tp.item->key.obj_id > tree_run_end) {
3073  Status = scrub_extent(Vcb, c, type, tree_run_start, (uint32_t)(tree_run_end - tree_run_start), NULL);
3074  if (!NT_SUCCESS(Status)) {
3075  ERR("scrub_extent returned %08lx\n", Status);
3076  goto end;
3077  }
3078 
3079  if (!is_tree)
3080  tree_run = false;
3081  else {
3082  tree_run_start = tp.item->key.obj_id;
3083  tree_run_end = tp.item->key.obj_id + Vcb->superblock.node_size;
3084  }
3085  } else
3086  tree_run_end = tp.item->key.obj_id + Vcb->superblock.node_size;
3087  } else if (is_tree) {
3088  tree_run = true;
3089  tree_run_start = tp.item->key.obj_id;
3090  tree_run_end = tp.item->key.obj_id + Vcb->superblock.node_size;
3091  }
3092 
3093  if (!is_tree) {
3094  Status = scrub_data_extent(Vcb, c, tp.item->key.obj_id, type, csum, &bmp, bmplen);
3095  if (!NT_SUCCESS(Status)) {
3096  ERR("scrub_data_extent returned %08lx\n", Status);
3097  ExFreePool(csum);
3098  ExFreePool(bmparr);
3099  goto end;
3100  }
3101 
3102  ExFreePool(csum);
3103  ExFreePool(bmparr);
3104  }
3105 
3106  *offset = tp.item->key.obj_id + size;
3107  *changed = true;
3108 
3109  total_data += size;
3110  num_extents++;
3111 
3112  // only do so much at a time
3113  if (num_extents >= 64 || total_data >= 0x8000000) // 128 MB
3114  break;
3115  }
3116 
3117  b = find_next_item(Vcb, &tp, &next_tp, false, NULL);
3118 
3119  if (b)
3120  tp = next_tp;
3121  } while (b);
3122 
3123  if (tree_run) {
3124  Status = scrub_extent(Vcb, c, type, tree_run_start, (uint32_t)(tree_run_end - tree_run_start), NULL);
3125  if (!NT_SUCCESS(Status)) {
3126  ERR("scrub_extent returned %08lx\n", Status);
3127  goto end;
3128  }
3129  }
3130 
3132 
3133 end:
3134  ExReleaseResourceLite(&Vcb->tree_lock);
3135 
3136  return Status;
3137 }
uint64_t obj_id
Definition: btrfs.h:137
#define max(a, b)
Definition: svc.c:63
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
uint8_t obj_type
Definition: btrfs.h:138
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
NTSYSAPI void WINAPI RtlInitializeBitMap(PRTL_BITMAP, PULONG, ULONG)
LONG NTSTATUS
Definition: precomp.h:26
GLintptr offset
Definition: glext.h:5920
uint16_t size
Definition: btrfs_drv.h:430
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLuint GLuint end
Definition: gl.h:1545
#define TYPE_METADATA_ITEM
Definition: btrfs.h:32
uint64_t offset
Definition: btrfs.h:139
uint8_t * data
Definition: btrfs_drv.h:431
static NTSTATUS scrub_chunk_raid56(device_extension *Vcb, chunk *c, uint64_t *offset, bool *changed)
Definition: scrub.c:2837
#define TYPE_EXTENT_CSUM
Definition: btrfs.h:27
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:451
#define ALLOC_TAG
Definition: btrfs_drv.h:91
uint32_t cs
Definition: isohybrid.c:75
static NTSTATUS scrub_extent(device_extension *Vcb, chunk *c, ULONG type, uint64_t offset, uint32_t size, void *csum)
Definition: scrub.c:1377
NTSYSAPI void WINAPI RtlSetAllBits(PRTL_BITMAP)
#define BLOCK_FLAG_RAID1C3
Definition: btrfs.h:83
smooth NULL
Definition: ftsmooth.c:416
#define TYPE_EXTENT_ITEM
Definition: btrfs.h:31
#define BLOCK_FLAG_RAID10
Definition: shellext.h:81
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2930
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
#define BLOCK_FLAG_RAID0
Definition: shellext.h:78
#define STATUS_NOT_FOUND
Definition: shellext.h:72
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
#define TRACE(s)
Definition: solgame.cpp:4
GLsizeiptr size
Definition: glext.h:5919
bool find_next_item(_Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, const traverse_ptr *tp, traverse_ptr *next_tp, bool ignore, PIRP Irp)
Definition: treefuncs.c:593
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1425
const GLubyte * c
Definition: glext.h:8905
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
#define BLOCK_FLAG_RAID6
Definition: shellext.h:83
BITMAP bmp
Definition: alphablend.c:62
#define BLOCK_FLAG_RAID1C4
Definition: btrfs.h:84
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
tree_data * item
Definition: btrfs_drv.h:518
BYTE uint8_t
Definition: msvideo1.c:66
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:110
NTSYSAPI void WINAPI RtlClearBits(PRTL_BITMAP, ULONG, ULONG)
Definition: btrfs.h:136
#define EXTENT_CSUM_ID
Definition: btrfs.h:87
UINT64 uint64_t
Definition: types.h:77
#define EXTENT_ITEM_TREE_BLOCK
Definition: btrfs.h:376
#define min(a, b)
Definition: monoChain.cc:55
UINT32 uint32_t
Definition: types.h:75
BOOLEAN NTAPI ExAcquireResourceSharedLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:885
Definition: fs.h:216
unsigned int ULONG
Definition: retypes.h:1
#define BLOCK_FLAG_DUPLICATE
Definition: shellext.h:80
uint64_t flags
Definition: btrfs.h:382
#define BLOCK_FLAG_RAID5
Definition: shellext.h:82
uint32_t sector_size
Definition: btrfs.h:231
return STATUS_SUCCESS
Definition: btrfs.c:3014
static uint64_t __inline sector_align(uint64_t n, uint64_t a)
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
static NTSTATUS scrub_data_extent(device_extension *Vcb, chunk *c, uint64_t offset, ULONG type, void *csum, RTL_BITMAP *bmp, ULONG bmplen)
Definition: scrub.c:1627
#define BLOCK_FLAG_RAID1
Definition: shellext.h:79

Referenced by _Function_class_().

◆ scrub_chunk_raid56()

static NTSTATUS scrub_chunk_raid56 ( device_extension Vcb,
chunk c,
uint64_t offset,
bool changed 
)
static

Definition at line 2837 of file scrub.c.

2837  {
2838  NTSTATUS Status;
2839  KEY searchkey;
2840  traverse_ptr tp;
2841  bool b;
2842  uint64_t full_stripe_len, stripe, stripe_start, stripe_end, total_data = 0;
2843  ULONG num_extents = 0, num_parity_stripes = c->chunk_item->type & BLOCK_FLAG_RAID6 ? 2 : 1;
2844 
2845  full_stripe_len = (c->chunk_item->num_stripes - num_parity_stripes) * c->chunk_item->stripe_length;
2846  stripe = (*offset - c->offset) / full_stripe_len;
2847 
2848  *offset = c->offset + (stripe * full_stripe_len);
2849 
2850  searchkey.obj_id = *offset;
2851  searchkey.obj_type = TYPE_METADATA_ITEM;
2852  searchkey.offset = 0xffffffffffffffff;
2853 
2854  Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, false, NULL);
2855  if (!NT_SUCCESS(Status)) {
2856  ERR("find_item returned %08lx\n", Status);
2857  return Status;
2858  }
2859 
2860  *changed = false;
2861 
2862  do {
2863  traverse_ptr next_tp;
2864 
2865  if (tp.item->key.obj_id >= c->offset + c->chunk_item->size)
2866  break;
2867 
2869  uint64_t size = tp.item->key.obj_type == TYPE_METADATA_ITEM ? Vcb->superblock.node_size : tp.item->key.offset;
2870 
2871  TRACE("%I64x\n", tp.item->key.obj_id);
2872 
2874  ERR("extent %I64x has size less than sector_size (%I64x < %x)\n", tp.item->key.obj_id, size, Vcb->superblock.sector_size);
2875  return STATUS_INTERNAL_ERROR;
2876  }
2877 
2878  stripe = (tp.item->key.obj_id - c->offset) / full_stripe_len;
2879 
2880  if (*changed) {
2881  if (stripe > stripe_end + 1) {
2882  Status = scrub_chunk_raid56_stripe_run(Vcb, c, stripe_start, stripe_end);
2883  if (!NT_SUCCESS(Status)) {
2884  ERR("scrub_chunk_raid56_stripe_run returned %08lx\n", Status);
2885  return Status;
2886  }
2887 
2888  stripe_start = stripe;
2889  }
2890  } else
2891  stripe_start = stripe;
2892 
2893  stripe_end = (tp.item->key.obj_id + size - 1 - c->offset) / full_stripe_len;
2894 
2895  *changed = true;
2896 
2897  total_data += size;
2898  num_extents++;
2899 
2900  // only do so much at a time
2901  if (num_extents >= 64 || total_data >= 0x8000000) // 128 MB
2902  break;
2903  }
2904 
2905  b = find_next_item(Vcb, &tp, &next_tp, false, NULL);
2906 
2907  if (b)
2908  tp = next_tp;
2909  } while (b);
2910 
2911  if (*changed) {
2912  Status = scrub_chunk_raid56_stripe_run(Vcb, c, stripe_start, stripe_end);
2913  if (!NT_SUCCESS(Status)) {
2914  ERR("scrub_chunk_raid56_stripe_run returned %08lx\n", Status);
2915  return Status;
2916  }
2917 
2918  *offset = c->offset + ((stripe_end + 1) * full_stripe_len);
2919  }
2920 
2921  return STATUS_SUCCESS;
2922 }
uint64_t obj_id
Definition: btrfs.h:137
uint8_t obj_type
Definition: btrfs.h:138
LONG NTSTATUS
Definition: precomp.h:26
GLintptr offset
Definition: glext.h:5920
Definition: write.c:111
#define TYPE_METADATA_ITEM
Definition: btrfs.h:32
uint64_t offset
Definition: btrfs.h:139
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:451
smooth NULL
Definition: ftsmooth.c:416
#define TYPE_EXTENT_ITEM
Definition: btrfs.h:31
#define b
Definition: ke_i.h:79
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2930
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
#define TRACE(s)
Definition: solgame.cpp:4
GLsizeiptr size
Definition: glext.h:5919
bool find_next_item(_Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, const traverse_ptr *tp, traverse_ptr *next_tp, bool ignore, PIRP Irp)
Definition: treefuncs.c:593
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1425
const GLubyte * c
Definition: glext.h:8905
#define BLOCK_FLAG_RAID6
Definition: shellext.h:83
tree_data * item
Definition: btrfs_drv.h:518
static NTSTATUS scrub_chunk_raid56_stripe_run(device_extension *Vcb, chunk *c, uint64_t stripe_start, uint64_t stripe_end)
Definition: scrub.c:2426
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:110
Definition: btrfs.h:136
UINT64 uint64_t
Definition: types.h:77
unsigned int ULONG
Definition: retypes.h:1
uint32_t sector_size
Definition: btrfs.h:231
return STATUS_SUCCESS
Definition: btrfs.c:3014

Referenced by scrub_chunk().

◆ scrub_chunk_raid56_stripe_run()

static NTSTATUS scrub_chunk_raid56_stripe_run ( device_extension Vcb,
chunk c,
uint64_t  stripe_start,
uint64_t  stripe_end 
)
static

Definition at line 2426 of file scrub.c.

2426  {
2427  NTSTATUS Status;
2428  KEY searchkey;
2429  traverse_ptr tp;
2430  bool b;
2431  uint64_t run_start, run_end, full_stripe_len, stripe;
2432  uint32_t max_read, num_sectors;
2433  ULONG arrlen, *allocarr, *csumarr = NULL, *treearr, num_parity_stripes = c->chunk_item->type & BLOCK_FLAG_RAID6 ? 2 : 1;
2435  uint16_t i;
2436  CHUNK_ITEM_STRIPE* cis = (CHUNK_ITEM_STRIPE*)&c->chunk_item[1];
2437 
2438  TRACE("(%p, %p, %I64x, %I64x)\n", Vcb, c, stripe_start, stripe_end);
2439 
2440  full_stripe_len = (c->chunk_item->num_stripes - num_parity_stripes) * c->chunk_item->stripe_length;
2441  run_start = c->offset + (stripe_start * full_stripe_len);
2442  run_end = c->offset + ((stripe_end + 1) * full_stripe_len);
2443 
2444  searchkey.obj_id = run_start;
2445  searchkey.obj_type = TYPE_METADATA_ITEM;
2446  searchkey.offset = 0xffffffffffffffff;
2447 
2448  Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, false, NULL);
2449  if (!NT_SUCCESS(Status)) {
2450  ERR("find_item returned %08lx\n", Status);
2451  return Status;
2452  }
2453 
2454  num_sectors = (uint32_t)((stripe_end - stripe_start + 1) * full_stripe_len / Vcb->superblock.sector_size);
2455  arrlen = (ULONG)sector_align((num_sectors / 8) + 1, sizeof(ULONG));
2456 
2457  allocarr = ExAllocatePoolWithTag(PagedPool, arrlen, ALLOC_TAG);
2458  if (!allocarr) {
2459  ERR("out of memory\n");
2461  }
2462 
2463  treearr = ExAllocatePoolWithTag(PagedPool, arrlen, ALLOC_TAG);
2464  if (!treearr) {
2465  ERR("out of memory\n");
2466  ExFreePool(allocarr);
2468  }
2469 
2470  RtlInitializeBitMap(&context.alloc, allocarr, num_sectors);
2471  RtlClearAllBits(&context.alloc);
2472 
2473  RtlInitializeBitMap(&context.is_tree, treearr, num_sectors);
2474  RtlClearAllBits(&context.is_tree);
2475 
2476  context.parity_scratch = ExAllocatePoolWithTag(PagedPool, (ULONG)c->chunk_item->stripe_length, ALLOC_TAG);
2477  if (!context.parity_scratch) {
2478  ERR("out of memory\n");
2479  ExFreePool(allocarr);
2480  ExFreePool(treearr);
2482  }
2483 
2484  if (c->chunk_item->type & BLOCK_FLAG_DATA) {
2485  csumarr = ExAllocatePoolWithTag(PagedPool, arrlen, ALLOC_TAG);
2486  if (!csumarr) {
2487  ERR("out of memory\n");
2488  ExFreePool(allocarr);
2489  ExFreePool(treearr);
2490  ExFreePool(context.parity_scratch);
2492  }
2493 
2494  RtlInitializeBitMap(&context.has_csum, csumarr, num_sectors);
2495  RtlClearAllBits(&context.has_csum);
2496 
2497  context.csum = ExAllocatePoolWithTag(PagedPool, num_sectors * Vcb->csum_size, ALLOC_TAG);
2498  if (!context.csum) {
2499  ERR("out of memory\n");
2500  ExFreePool(allocarr);
2501  ExFreePool(treearr);
2502  ExFreePool(context.parity_scratch);
2503  ExFreePool(csumarr);
2505  }
2506  }
2507 
2508  if (c->chunk_item->type & BLOCK_FLAG_RAID6) {
2509  context.parity_scratch2 = ExAllocatePoolWithTag(PagedPool, (ULONG)c->chunk_item->stripe_length, ALLOC_TAG);
2510  if (!context.parity_scratch2) {
2511  ERR("out of memory\n");
2512  ExFreePool(allocarr);
2513  ExFreePool(treearr);
2514  ExFreePool(context.parity_scratch);
2515 
2516  if (c->chunk_item->type & BLOCK_FLAG_DATA) {
2517  ExFreePool(csumarr);
2518  ExFreePool(context.csum);
2519  }
2520 
2522  }
2523  }
2524 
2525  do {
2526  traverse_ptr next_tp;
2527 
2528  if (tp.item->key.obj_id >= run_end)
2529  break;
2530 
2532  uint64_t size = tp.item->key.obj_type == TYPE_METADATA_ITEM ? Vcb->superblock.node_size : tp.item->key.offset;
2533 
2534  if (tp.item->key.obj_id + size > run_start) {
2535  uint64_t extent_start = max(run_start, tp.item->key.obj_id);
2536  uint64_t extent_end = min(tp.item->key.obj_id + size, run_end);
2537  bool extent_is_tree = false;
2538 
2539  RtlSetBits(&context.alloc, (ULONG)((extent_start - run_start) / Vcb->superblock.sector_size), (ULONG)((extent_end - extent_start) / Vcb->superblock.sector_size));
2540 
2542  extent_is_tree = true;
2543  else {
2544  EXTENT_ITEM* ei = (EXTENT_ITEM*)tp.item->data;
2545 
2546  if (tp.item->size < sizeof(EXTENT_ITEM)) {
2547  ERR("(%I64x,%x,%I64x) was %u bytes, expected at least %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, sizeof(EXTENT_ITEM));
2549  goto end;
2550  }
2551 
2552  if (ei->flags & EXTENT_ITEM_TREE_BLOCK)
2553  extent_is_tree = true;
2554  }
2555 
2556  if (extent_is_tree)
2557  RtlSetBits(&context.is_tree, (ULONG)((extent_start - run_start) / Vcb->superblock.sector_size), (ULONG)((extent_end - extent_start) / Vcb->superblock.sector_size));
2558  else if (c->chunk_item->type & BLOCK_FLAG_DATA) {
2559  traverse_ptr tp2;
2560  bool b2;
2561 
2562  searchkey.obj_id = EXTENT_CSUM_ID;
2563  searchkey.obj_type = TYPE_EXTENT_CSUM;
2564  searchkey.offset = extent_start;
2565 
2566  Status = find_item(Vcb, Vcb->checksum_root, &tp2, &searchkey, false, NULL);
2567  if (!NT_SUCCESS(Status) && Status != STATUS_NOT_FOUND) {
2568  ERR("find_item returned %08lx\n", Status);
2569  goto end;
2570  }
2571 
2572  do {
2573  traverse_ptr next_tp2;
2574 
2575  if (tp2.item->key.offset >= extent_end)
2576  break;
2577 
2578  if (tp2.item->key.offset >= extent_start) {
2579  uint64_t csum_start = max(extent_start, tp2.item->key.offset);
2580  uint64_t csum_end = min(extent_end, tp2.item->key.offset + (tp2.item->size * Vcb->superblock.sector_size / Vcb->csum_size));
2581 
2582  RtlSetBits(&context.has_csum, (ULONG)((csum_start - run_start) / Vcb->superblock.sector_size), (ULONG)((csum_end - csum_start) / Vcb->superblock.sector_size));
2583 
2584  RtlCopyMemory((uint8_t*)context.csum + ((csum_start - run_start) * Vcb->csum_size / Vcb->superblock.sector_size),
2585  tp2.item->data + ((csum_start - tp2.item->key.offset) * Vcb->csum_size / Vcb->superblock.sector_size),
2586  (ULONG)((csum_end - csum_start) * Vcb->csum_size / Vcb->superblock.sector_size));
2587  }
2588 
2589  b2 = find_next_item(Vcb, &tp2, &next_tp2, false, NULL);
2590 
2591  if (b2)
2592  tp2 = next_tp2;
2593  } while (b2);
2594  }
2595  }
2596  }
2597 
2598  b = find_next_item(Vcb, &tp, &next_tp, false, NULL);
2599 
2600  if (b)
2601  tp = next_tp;
2602  } while (b);
2603 
2604  context.stripes = ExAllocatePoolWithTag(PagedPool, sizeof(scrub_context_raid56_stripe) * c->chunk_item->num_stripes, ALLOC_TAG);
2605  if (!context.stripes) {
2606  ERR("out of memory\n");
2608  goto end;
2609  }
2610 
2611  max_read = (uint32_t)min(1048576 / c->chunk_item->stripe_length, stripe_end - stripe_start + 1); // only process 1 MB of data at a time
2612 
2613  for (i = 0; i < c->chunk_item->num_stripes; i++) {
2614  context.stripes[i].buf = ExAllocatePoolWithTag(PagedPool, (ULONG)(max_read * c->chunk_item->stripe_length), ALLOC_TAG);
2615  if (!context.stripes[i].buf) {
2616  uint64_t j;
2617 
2618  ERR("out of memory\n");
2619 
2620  for (j = 0; j < i; j++) {
2621  ExFreePool(context.stripes[j].buf);
2622  }
2623  ExFreePool(context.stripes);
2624 
2626  goto end;
2627  }
2628 
2629  context.stripes[i].errorarr = ExAllocatePoolWithTag(PagedPool, (ULONG)sector_align(((c->chunk_item->stripe_length / Vcb->superblock.sector_size) / 8) + 1, sizeof(ULONG)), ALLOC_TAG);
2630  if (!context.stripes[i].errorarr) {
2631  uint64_t j;
2632 
2633  ERR("out of memory\n");
2634 
2635  ExFreePool(context.stripes[i].buf);
2636 
2637  for (j = 0; j < i; j++) {
2638  ExFreePool(context.stripes[j].buf);
2639  }
2640  ExFreePool(context.stripes);
2641 
2643  goto end;
2644  }
2645 
2646  RtlInitializeBitMap(&context.stripes[i].error, context.stripes[i].errorarr, (ULONG)(c->chunk_item->stripe_length / Vcb->superblock.sector_size));
2647 
2648  context.stripes[i].context = &context;
2649  context.stripes[i].rewrite = false;
2650  }
2651 
2652  stripe = stripe_start;
2653 
2655 
2656  chunk_lock_range(Vcb, c, run_start, run_end - run_start);
2657 
2658  do {
2659  ULONG read_stripes;
2660  uint16_t missing_devices = 0;
2661  bool need_wait = false;
2662 
2663  if (max_read < stripe_end + 1 - stripe)
2664  read_stripes = max_read;
2665  else
2666  read_stripes = (ULONG)(stripe_end + 1 - stripe);
2667 
2668  context.stripes_left = c->chunk_item->num_stripes;
2669 
2670  // read megabyte by megabyte
2671  for (i = 0; i < c->chunk_item->num_stripes; i++) {
2672  if (c->devices[i]->devobj) {
2674 
2675  context.stripes[i].Irp = IoAllocateIrp(c->devices[i]->devobj->StackSize, false);
2676 
2677  if (!context.stripes[i].Irp) {
2678  ERR("IoAllocateIrp failed\n");
2680  goto end3;
2681  }
2682 
2683  context.stripes[i].Irp->MdlAddress = NULL;
2684 
2685  IrpSp = IoGetNextIrpStackLocation(context.stripes[i].Irp);
2687  IrpSp->FileObject = c->devices[i]->fileobj;
2688 
2689  if (c->devices[i]->devobj->Flags & DO_BUFFERED_IO) {
2690  context.stripes[i].Irp->AssociatedIrp.SystemBuffer = ExAllocatePoolWithTag(NonPagedPool, (ULONG)(read_stripes * c->chunk_item->stripe_length), ALLOC_TAG);
2691  if (!context.stripes[i].Irp->AssociatedIrp.SystemBuffer) {
2692  ERR("out of memory\n");
2694  goto end3;
2695  }
2696 
2698 
2699  context.stripes[i].Irp->UserBuffer = context.stripes[i].buf;
2700  } else if (c->devices[i]->devobj->Flags & DO_DIRECT_IO) {
2701  context.stripes[i].Irp->MdlAddress = IoAllocateMdl(context.stripes[i].buf, (ULONG)(read_stripes * c->chunk_item->stripe_length), false, false, NULL);
2702  if (!context.stripes[i].Irp->MdlAddress) {
2703  ERR("IoAllocateMdl failed\n");
2705  goto end3;
2706  }
2707 
2709 
2710  _SEH2_TRY {
2711  MmProbeAndLockPages(context.stripes[i].Irp->MdlAddress, KernelMode, IoWriteAccess);
2714  } _SEH2_END;
2715 
2716  if (!NT_SUCCESS(Status)) {
2717  ERR("MmProbeAndLockPages threw exception %08lx\n", Status);
2718  IoFreeMdl(context.stripes[i].Irp->MdlAddress);
2719  goto end3;
2720  }
2721  } else
2722  context.stripes[i].Irp->UserBuffer = context.stripes[i].buf;
2723 
2724  context.stripes[i].offset = stripe * c->chunk_item->stripe_length;
2725 
2726  IrpSp->Parameters.Read.Length = (ULONG)(read_stripes * c->chunk_item->stripe_length);
2727  IrpSp->Parameters.Read.ByteOffset.QuadPart = cis[i].offset + context.stripes[i].offset;
2728 
2729  context.stripes[i].Irp->UserIosb = &context.stripes[i].iosb;
2730  context.stripes[i].missing = false;
2731 
2732  IoSetCompletionRoutine(context.stripes[i].Irp, scrub_read_completion_raid56, &context.stripes[i], true, true, true);
2733 
2734  Vcb->scrub.data_scrubbed += read_stripes * c->chunk_item->stripe_length;
2735  need_wait = true;
2736  } else {
2737  context.stripes[i].Irp = NULL;
2738  context.stripes[i].missing = true;
2739  missing_devices++;
2740  InterlockedDecrement(&context.stripes_left);
2741  }
2742  }
2743 
2744  if (c->chunk_item->type & BLOCK_FLAG_RAID5 && missing_devices > 1) {
2745  ERR("too many missing devices (%u, maximum 1)\n", missing_devices);
2747  goto end3;
2748  } else if (c->chunk_item->type & BLOCK_FLAG_RAID6 && missing_devices > 2) {
2749  ERR("too many missing devices (%u, maximum 2)\n", missing_devices);
2751  goto end3;
2752  }
2753 
2754  if (need_wait) {
2756 
2757  for (i = 0; i < c->chunk_item->num_stripes; i++) {
2758  if (c->devices[i]->devobj)
2759  IoCallDriver(c->devices[i]->devobj, context.stripes[i].Irp);
2760  }
2761 
2763  }
2764 
2765  // return an error if any of the stripes returned an error
2766  for (i = 0; i < c->chunk_item->num_stripes; i++) {
2767  if (!context.stripes[i].missing && !NT_SUCCESS(context.stripes[i].iosb.Status)) {
2768  Status = context.stripes[i].iosb.Status;
2770  goto end3;
2771  }
2772  }
2773 
2774  if (c->chunk_item->type & BLOCK_FLAG_RAID6) {
2775  for (i = 0; i < read_stripes; i++) {
2776  scrub_raid6_stripe(Vcb, c, &context, stripe_start, stripe, i, missing_devices);
2777  }
2778  } else {
2779  for (i = 0; i < read_stripes; i++) {
2780  scrub_raid5_stripe(Vcb, c, &context, stripe_start, stripe, i, missing_devices);
2781  }
2782  }
2783  stripe += read_stripes;
2784 
2785 end3:
2786  for (i = 0; i < c->chunk_item->num_stripes; i++) {
2787  if (context.stripes[i].Irp) {
2788  if (c->devices[i]->devobj->Flags & DO_DIRECT_IO && context.stripes[i].Irp->MdlAddress) {
2789  MmUnlockPages(context.stripes[i].Irp->MdlAddress);
2790  IoFreeMdl(context.stripes[i].Irp->MdlAddress);
2791  }
2792  IoFreeIrp(context.stripes[i].Irp);
2793  context.stripes[i].Irp = NULL;
2794 
2795  if (context.stripes[i].rewrite) {
2796  Status = write_data_phys(c->devices[i]->devobj, c->devices[i]->fileobj, cis[i].offset + context.stripes[i].offset,
2797  context.stripes[i].buf, (uint32_t)(read_stripes * c->chunk_item->stripe_length));
2798 
2799  if (!NT_SUCCESS(Status)) {
2800  ERR("write_data_phys returned %08lx\n", Status);
2802  goto end2;
2803  }
2804  }
2805  }
2806  }
2807 
2808  if (!NT_SUCCESS(Status))
2809  break;
2810  } while (stripe < stripe_end);
2811 
2812 end2:
2813  chunk_unlock_range(Vcb, c, run_start, run_end - run_start);
2814 
2815  for (i = 0; i < c->chunk_item->num_stripes; i++) {
2816  ExFreePool(context.stripes[i].buf);
2817  ExFreePool(context.stripes[i].errorarr);
2818  }
2819  ExFreePool(context.stripes);
2820 
2821 end:
2822  ExFreePool(treearr);
2823  ExFreePool(allocarr);
2824  ExFreePool(context.parity_scratch);
2825 
2826  if (c->chunk_item->type & BLOCK_FLAG_RAID6)
2827  ExFreePool(context.parity_scratch2);
2828 
2829  if (c->chunk_item->type & BLOCK_FLAG_DATA) {
2830  ExFreePool(csumarr);
2831  ExFreePool(context.csum);
2832  }
2833 
2834  return Status;
2835 }
uint64_t obj_id
Definition: btrfs.h:137
#define max(a, b)
Definition: svc.c:63
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
uint8_t obj_type
Definition: btrfs.h:138
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
Definition: http.c:7094
NTSYSAPI void WINAPI RtlInitializeBitMap(PRTL_BITMAP, PULONG, ULONG)
LONG NTSTATUS
Definition: precomp.h:26
uint16_t size
Definition: btrfs_drv.h:430
Definition: write.c:111
VOID NTAPI MmUnlockPages(IN PMDL Mdl)
Definition: mdlsup.c:1439
GLuint GLuint end
Definition: gl.h:1545
unsigned short int uint16_t
Definition: acefiex.h:54
#define TYPE_METADATA_ITEM
Definition: btrfs.h:32
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
uint64_t offset
Definition: btrfs.h:139
uint8_t * data
Definition: btrfs_drv.h:431
#define DO_DIRECT_IO
Definition: env_spec_w32.h:396
_SEH2_TRY
Definition: create.c:4250
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:498
#define TYPE_EXTENT_CSUM
Definition: btrfs.h:27
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:451
#define ALLOC_TAG
Definition: btrfs_drv.h:91
uint64_t offset
Definition: btrfs.h:341
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 chunk_unlock_range(_In_ device_extension *Vcb, _In_ chunk *c, _In_ uint64_t start, _In_ uint64_t length)
Definition: btrfs.c:5794
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
smooth NULL
Definition: ftsmooth.c:416
#define TYPE_EXTENT_ITEM
Definition: btrfs.h:31
#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
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2930
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
#define STATUS_NOT_FOUND
Definition: shellext.h:72
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
#define TRACE(s)
Definition: solgame.cpp:4
GLsizeiptr size
Definition: glext.h:5919
NTSTATUS write_data_phys(_In_ PDEVICE_OBJECT device, _In_ PFILE_OBJECT fileobj, _In_ uint64_t address, _In_reads_bytes_(length) void *data, _In_ uint32_t length)
Definition: flushthread.c:65
bool find_next_item(_Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, const traverse_ptr *tp, traverse_ptr *next_tp, bool ignore, PIRP Irp)
Definition: treefuncs.c:593
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define DO_BUFFERED_IO
Definition: env_spec_w32.h:394
#define Vcb
Definition: cdprocs.h:1425
const GLubyte * c
Definition: glext.h:8905
static void scrub_raid5_stripe(device_extension *Vcb, chunk *c, scrub_context_raid56 *context, uint64_t stripe_start, uint64_t bit_start, uint64_t num, uint16_t missing_devices)
Definition: scrub.c:1708
void chunk_lock_range(_In_ device_extension *Vcb, _In_ chunk *c, _In_ uint64_t start, _In_ uint64_t length)
Definition: btrfs.c:5747
#define BLOCK_FLAG_RAID6
Definition: shellext.h:83
VOID NTAPI IoFreeMdl(PMDL Mdl)
Definition: iomdl.c:146
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
tree_data * item
Definition: btrfs_drv.h:518
#define InterlockedDecrement
Definition: armddk.h:52
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2647
BYTE uint8_t
Definition: msvideo1.c:66
#define BTRFS_DEV_STAT_READ_ERRORS
Definition: btrfs.h:528
Status
Definition: gdiplustypes.h:24
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
Definition: btrfs.h:136
PFILE_OBJECT FileObject
Definition: iotypes.h:2813
_SEH2_END
Definition: create.c:4424
#define EXTENT_CSUM_ID
Definition: btrfs.h:87
UINT64 uint64_t
Definition: types.h:77
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define IRP_INPUT_OPERATION
#define IRP_BUFFERED_IO
VOID NTAPI MmProbeAndLockPages(IN PMDL Mdl, IN KPROCESSOR_MODE AccessMode, IN LOCK_OPERATION Operation)
Definition: mdlsup.c:935
void log_device_error(_In_ device_extension *Vcb, _Inout_ device *dev, _In_ int error)
Definition: btrfs.c:5817
#define EXTENT_ITEM_TREE_BLOCK
Definition: btrfs.h:376
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4157
NTSYSAPI void WINAPI RtlSetBits(PRTL_BITMAP, ULONG, ULONG)
#define min(a, b)
Definition: monoChain.cc:55
static void scrub_raid6_stripe(device_extension *Vcb, chunk *c, scrub_context_raid56 *context, uint64_t stripe_start, uint64_t bit_start, uint64_t num, uint16_t missing_devices)
Definition: scrub.c:1897
NTSTATUS NTAPI IoCallDriver(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: irp.c:1218
UINT32 uint32_t
Definition: types.h:75
NTSYSAPI void WINAPI RtlClearAllBits(PRTL_BITMAP)
#define STATUS_UNEXPECTED_IO_ERROR
Definition: ntstatus.h:455
#define BLOCK_FLAG_DATA
Definition: shellext.h:75
#define IRP_MJ_READ
Definition: rdpdr.c:46
#define IRP_DEALLOCATE_BUFFER
VOID NTAPI IoFreeIrp(IN PIRP Irp)
Definition: irp.c:1666
#define BTRFS_DEV_STAT_WRITE_ERRORS
Definition: btrfs.h:527
unsigned int ULONG
Definition: retypes.h:1
static CRYPT_DATA_BLOB b2[]
Definition: msg.c:582
PIRP NTAPI IoAllocateIrp(IN CCHAR StackSize, IN BOOLEAN ChargeQuota)
Definition: irp.c:615
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
uint64_t flags
Definition: btrfs.h:382
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
#define BLOCK_FLAG_RAID5
Definition: shellext.h:82
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:2772
#define uint32_t
Definition: nsiface.idl:61
return STATUS_SUCCESS
Definition: btrfs.c:3014
static uint64_t __inline sector_align(uint64_t n, uint64_t a)
#define ExFreePool(addr)
Definition: env_spec_w32.h:352

Referenced by scrub_chunk_raid56().

◆ scrub_data_extent()

static NTSTATUS scrub_data_extent ( device_extension Vcb,
chunk c,
uint64_t  offset,
ULONG  type,
void csum,
RTL_BITMAP bmp,
ULONG  bmplen 
)
static

Definition at line 1627 of file scrub.c.

1627  {
1628  NTSTATUS Status;
1629  ULONG runlength, index;
1630 
1631  runlength = RtlFindFirstRunClear(bmp, &index);
1632 
1633  while (runlength != 0) {
1634  if (index >= bmplen)
1635  break;
1636 
1637  if (index + runlength >= bmplen) {
1638  runlength = bmplen - index;
1639 
1640  if (runlength == 0)
1641  break;
1642  }
1643 
1644  do {
1645  ULONG rl;
1646 
1647  if (runlength * Vcb->superblock.sector_size > SCRUB_UNIT)
1648  rl = SCRUB_UNIT / Vcb->superblock.sector_size;
1649  else
1650  rl = runlength;
1651 
1652  Status = scrub_extent(Vcb, c, type, offset + UInt32x32To64(index, Vcb->superblock.sector_size),
1653  rl * Vcb->superblock.sector_size, (uint8_t*)csum + (index * Vcb->csum_size));
1654  if (!NT_SUCCESS(Status)) {
1655  ERR("scrub_data_extent_dup returned %08lx\n", Status);
1656  return Status;
1657  }
1658 
1659  runlength -= rl;
1660  index += rl;
1661  } while (runlength > 0);
1662 
1663  runlength = RtlFindNextForwardRunClear(bmp, index, &index);
1664  }
1665 
1666  return STATUS_SUCCESS;
1667 }
LONG NTSTATUS
Definition: precomp.h:26
GLintptr offset
Definition: glext.h:5920
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
static NTSTATUS scrub_extent(device_extension *Vcb, chunk *c, ULONG type, uint64_t offset, uint32_t size, void *csum)
Definition: scrub.c:1377
GLuint index
Definition: glext.h:6031
#define SCRUB_UNIT
Definition: scrub.c:20
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1425
const GLubyte * c
Definition: glext.h:8905
BITMAP bmp
Definition: alphablend.c:62
#define index(s, c)
Definition: various.h:29
BYTE uint8_t
Definition: msvideo1.c:66
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:110
NTSYSAPI ULONG NTAPI RtlFindFirstRunClear(_In_ PRTL_BITMAP BitMapHeader, _Out_ PULONG StartingIndex)
NTSYSAPI ULONG WINAPI RtlFindNextForwardRunClear(PCRTL_BITMAP, ULONG, PULONG)
Definition: fs.h:216
unsigned int ULONG
Definition: retypes.h:1
return STATUS_SUCCESS
Definition: btrfs.c:3014
#define UInt32x32To64(a, b)
Definition: intsafe.h:258

Referenced by scrub_chunk().

◆ scrub_extent()

static NTSTATUS scrub_extent ( device_extension Vcb,
chunk c,
ULONG  type,
uint64_t  offset,
uint32_t  size,
void csum 
)
static

Definition at line 1377 of file scrub.c.

1377  {
1378  ULONG i;
1380  CHUNK_ITEM_STRIPE* cis;
1381  NTSTATUS Status;
1382  uint16_t startoffstripe, num_missing, allowed_missing;
1383 
1384  TRACE("(%p, %p, %lx, %I64x, %x, %p)\n", Vcb, c, type, offset, size, csum);
1385 
1386  context.stripes = ExAllocatePoolWithTag(NonPagedPool, sizeof(scrub_context_stripe) * c->chunk_item->num_stripes, ALLOC_TAG);
1387  if (!context.stripes) {
1388  ERR("out of memory\n");
1390  goto end;
1391  }
1392 
1393  RtlZeroMemory(context.stripes, sizeof(scrub_context_stripe) * c->chunk_item->num_stripes);
1394 
1395  context.stripes_left = 0;
1396 
1397  cis = (CHUNK_ITEM_STRIPE*)&c->chunk_item[1];
1398 
1399  if (type == BLOCK_FLAG_RAID0) {
1400  uint64_t startoff, endoff;
1401  uint16_t endoffstripe;
1402 
1403  get_raid0_offset(offset - c->offset, c->chunk_item->stripe_length, c->chunk_item->num_stripes, &startoff, &startoffstripe);
1404  get_raid0_offset(offset + size - c->offset - 1, c->chunk_item->stripe_length, c->chunk_item->num_stripes, &endoff, &endoffstripe);
1405 
1406  for (i = 0; i < c->chunk_item->num_stripes; i++) {
1407  if (startoffstripe > i)
1408  context.stripes[i].start = startoff - (startoff % c->chunk_item->stripe_length) + c->chunk_item->stripe_length;
1409  else if (startoffstripe == i)
1410  context.stripes[i].start = startoff;
1411  else
1412  context.stripes[i].start = startoff - (startoff % c->chunk_item->stripe_length);
1413 
1414  if (endoffstripe > i)
1415  context.stripes[i].length = (uint32_t)(endoff - (endoff % c->chunk_item->stripe_length) + c->chunk_item->stripe_length - context.stripes[i].start);
1416  else if (endoffstripe == i)
1417  context.stripes[i].length = (uint32_t)(endoff + 1 - context.stripes[i].start);
1418  else
1419  context.stripes[i].length = (uint32_t)(endoff - (endoff % c->chunk_item->stripe_length) - context.stripes[i].start);
1420  }
1421 
1422  allowed_missing = 0;
1423  } else if (type == BLOCK_FLAG_RAID10) {
1424  uint64_t startoff, endoff;
1425  uint16_t endoffstripe, j, sub_stripes = max(c->chunk_item->sub_stripes, 1);
1426 
1427  get_raid0_offset(offset - c->offset, c->chunk_item->stripe_length, c->chunk_item->num_stripes / sub_stripes, &startoff, &startoffstripe);
1428  get_raid0_offset(offset + size - c->offset - 1, c->chunk_item->stripe_length, c->chunk_item->num_stripes / sub_stripes, &endoff, &endoffstripe);
1429 
1430  if ((c->chunk_item->num_stripes % sub_stripes) != 0) {
1431  ERR("chunk %I64x: num_stripes %x was not a multiple of sub_stripes %x!\n", c->offset, c->chunk_item->num_stripes, sub_stripes);
1433  goto end;
1434  }
1435 
1436  startoffstripe *= sub_stripes;
1437  endoffstripe *= sub_stripes;
1438 
1439  for (i = 0; i < c->chunk_item->num_stripes; i += sub_stripes) {
1440  if (startoffstripe > i)
1441  context.stripes[i].start = startoff - (startoff % c->chunk_item->stripe_length) + c->chunk_item->stripe_length;
1442  else if (startoffstripe == i)
1443  context.stripes[i].start = startoff;
1444  else
1445  context.stripes[i].start = startoff - (startoff % c->chunk_item->stripe_length);
1446 
1447  if (endoffstripe > i)
1448  context.stripes[i].length = (uint32_t)(endoff - (endoff % c->chunk_item->stripe_length) + c->chunk_item->stripe_length - context.stripes[i].start);
1449  else if (endoffstripe == i)
1450  context.stripes[i].length = (uint32_t)(endoff + 1 - context.stripes[i].start);
1451  else
1452  context.stripes[i].length = (uint32_t)(endoff - (endoff % c->chunk_item->stripe_length) - context.stripes[i].start);
1453 
1454  for (j = 1; j < sub_stripes; j++) {
1455  context.stripes[i+j].start = context.stripes[i].start;
1456  context.stripes[i+j].length = context.stripes[i].length;
1457  }
1458  }
1459 
1460  startoffstripe /= sub_stripes;
1461  allowed_missing = 1;
1462  } else
1463  allowed_missing = c->chunk_item->num_stripes - 1;
1464 
1465  num_missing = 0;
1466 
1467  for (i = 0; i < c->chunk_item->num_stripes; i++) {
1469 
1470  context.stripes[i].context = (struct _scrub_context*)&context;
1471 
1472  if (type == BLOCK_FLAG_DUPLICATE) {
1473  context.stripes[i].start = offset - c->offset;
1474  context.stripes[i].length = size;
1475  } else if (type != BLOCK_FLAG_RAID0 && type != BLOCK_FLAG_RAID10) {
1476  ERR("unexpected chunk type %lx\n", type);
1478  goto end;
1479  }
1480 
1481  if (!c->devices[i]->devobj) {
1482  num_missing++;
1483 
1484  if (num_missing > allowed_missing) {
1485  ERR("too many missing devices (at least %u, maximum allowed %u)\n", num_missing, allowed_missing);
1487  goto end;
1488  }
1489  } else if (context.stripes[i].length > 0) {
1490  context.stripes[i].buf = ExAllocatePoolWithTag(NonPagedPool, context.stripes[i].length, ALLOC_TAG);
1491 
1492  if (!context.stripes[i].buf) {
1493  ERR("out of memory\n");
1495  goto end;
1496  }
1497 
1498  context.stripes[i].Irp = IoAllocateIrp(c->devices[i]->devobj->StackSize, false);
1499 
1500  if (!context.stripes[i].Irp) {
1501  ERR("IoAllocateIrp failed\n");
1503  goto end;
1504  }
1505 
1506  IrpSp = IoGetNextIrpStackLocation(context.stripes[i].Irp);
1508  IrpSp->FileObject = c->devices[i]->fileobj;
1509 
1510  if (c->devices[i]->devobj->Flags & DO_BUFFERED_IO) {
1511  context.stripes[i].Irp->AssociatedIrp.SystemBuffer = ExAllocatePoolWithTag(NonPagedPool, context.stripes[i].length, ALLOC_TAG);
1512  if (!context.stripes[i].Irp->AssociatedIrp.SystemBuffer) {
1513  ERR("out of memory\n");
1515  goto end;
1516  }
1517 
1519 
1520  context.stripes[i].Irp->UserBuffer = context.stripes[i].buf;
1521  } else if (c->devices[i]->devobj->Flags & DO_DIRECT_IO) {
1522  context.stripes[i].Irp->MdlAddress = IoAllocateMdl(context.stripes[i].buf, context.stripes[i].length, false, false, NULL);
1523  if (!context.stripes[i].Irp->MdlAddress) {
1524  ERR("IoAllocateMdl failed\n");
1526  goto end;
1527  }
1528 
1530 
1531  _SEH2_TRY {
1532  MmProbeAndLockPages(context.stripes[i].Irp->MdlAddress, KernelMode, IoWriteAccess);
1535  } _SEH2_END;
1536 
1537  if (!NT_SUCCESS(Status)) {
1538  ERR("MmProbeAndLockPages threw exception %08lx\n", Status);
1539  IoFreeMdl(context.stripes[i].Irp->MdlAddress);
1540  context.stripes[i].Irp->MdlAddress = NULL;
1541  goto end;
1542  }
1543  } else
1544  context.stripes[i].Irp->UserBuffer = context.stripes[i].buf;
1545 
1546  IrpSp->Parameters.Read.Length = context.stripes[i].length;
1547  IrpSp->Parameters.Read.ByteOffset.QuadPart = context.stripes[i].start + cis[i].offset;
1548 
1549  context.stripes[i].Irp->UserIosb = &context.stripes[i].iosb;
1550 
1551  IoSetCompletionRoutine(context.stripes[i].Irp, scrub_read_completion, &context.stripes[i], true, true, true);
1552 
1553  context.stripes_left++;
1554 
1555  Vcb->scrub.data_scrubbed += context.stripes[i].length;
1556  }
1557  }
1558 
1559  if (context.stripes_left == 0) {
1560  ERR("error - not reading any stripes\n");
1562  goto end;
1563  }
1564 
1566 
1567  for (i = 0; i < c->chunk_item->num_stripes; i++) {
1568  if (c->devices[i]->devobj && context.stripes[i].length > 0)
1569  IoCallDriver(c->devices[i]->devobj, context.stripes[i].Irp);
1570  }
1571 
1573 
1574  // return an error if any of the stripes returned an error
1575  for (i = 0; i < c->chunk_item->num_stripes; i++) {
1576  if (!NT_SUCCESS(context.stripes[i].iosb.Status)) {
1577  Status = context.stripes[i].iosb.Status;
1579  goto end;
1580  }
1581  }
1582 
1583  if (type == BLOCK_FLAG_DUPLICATE) {
1585  if (!NT_SUCCESS(Status)) {
1586  ERR("scrub_extent_dup returned %08lx\n", Status);
1587  goto end;
1588  }
1589  } else if (type == BLOCK_FLAG_RAID0) {
1590  Status = scrub_extent_raid0(Vcb, c, offset, size, startoffstripe, csum, &context);
1591  if (!NT_SUCCESS(Status)) {
1592  ERR("scrub_extent_raid0 returned %08lx\n", Status);
1593  goto end;
1594  }
1595  } else if (type == BLOCK_FLAG_RAID10) {
1596  Status = scrub_extent_raid10(Vcb, c, offset, size, startoffstripe, csum, &context);
1597  if (!NT_SUCCESS(Status)) {
1598  ERR("scrub_extent_raid10 returned %08lx\n", Status);
1599  goto end;
1600  }
1601  }
1602 
1603 end:
1604  if (context.stripes) {
1605  for (i = 0; i < c->chunk_item->num_stripes; i++) {
1606  if (context.stripes[i].Irp) {
1607  if (c->devices[i]->devobj->Flags & DO_DIRECT_IO && context.stripes[i].Irp->MdlAddress) {
1608  MmUnlockPages(context.stripes[i].Irp->MdlAddress);
1609  IoFreeMdl(context.stripes[i].Irp->MdlAddress);
1610  }
1611  IoFreeIrp(context.stripes[i].Irp);
1612  }
1613 
1614  if (context.stripes[i].buf)
1615  ExFreePool(context.stripes[i].buf);
1616 
1617  if (context.stripes[i].bad_csums)
1618  ExFreePool(context.stripes[i].bad_csums);
1619  }
1620 
1621  ExFreePool(context.stripes);
1622  }
1623 
1624  return Status;
1625 }
#define max(a, b)
Definition: svc.c:63
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
Definition: http.c:7094
uint16_t startoffstripe
Definition: read.c:53
LONG NTSTATUS
Definition: precomp.h:26
GLintptr offset
Definition: glext.h:5920
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
VOID NTAPI MmUnlockPages(IN PMDL Mdl)
Definition: mdlsup.c:1439
static NTSTATUS scrub_extent_raid0(device_extension *Vcb, chunk *c, uint64_t offset, uint32_t length, uint16_t startoffstripe, void *csum, scrub_context *context)
Definition: scrub.c:940
GLuint GLuint end
Definition: gl.h:1545
unsigned short int uint16_t
Definition: acefiex.h:54
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
_Post_satisfies_ static stripe __inline void get_raid0_offset(_In_ uint64_t off, _In_ uint64_t stripe_length, _In_ uint16_t num_stripes, _Out_ uint64_t *stripeoff, _Out_ uint16_t *stripe)
Definition: btrfs_drv.h:1005
#define DO_DIRECT_IO
Definition: env_spec_w32.h:396
_SEH2_TRY
Definition: create.c:4250
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:498
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:451
#define ALLOC_TAG
Definition: btrfs_drv.h:91
uint64_t offset
Definition: btrfs.h:341
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
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
smooth NULL
Definition: ftsmooth.c:416
#define BLOCK_FLAG_RAID10
Definition: shellext.h:81
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define BLOCK_FLAG_RAID0
Definition: shellext.h:78
#define TRACE(s)
Definition: solgame.cpp:4
GLsizeiptr size
Definition: glext.h:5919
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define DO_BUFFERED_IO
Definition: env_spec_w32.h:394
#define Vcb
Definition: cdprocs.h:1425
const GLubyte * c
Definition: glext.h:8905
VOID NTAPI IoFreeMdl(PMDL Mdl)
Definition: iomdl.c:146
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
static NTSTATUS scrub_extent_raid10(device_extension *Vcb, chunk *c, uint64_t offset, uint32_t length, uint16_t startoffstripe, void *csum, scrub_context *context)
Definition: scrub.c:998
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2647
#define BTRFS_DEV_STAT_READ_ERRORS
Definition: btrfs.h:528
Status
Definition: gdiplustypes.h:24
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:2813
_SEH2_END
Definition: create.c:4424
UINT64 uint64_t
Definition: types.h:77
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define IRP_INPUT_OPERATION
#define IRP_BUFFERED_IO
VOID NTAPI MmProbeAndLockPages(IN PMDL Mdl, IN KPROCESSOR_MODE AccessMode, IN LOCK_OPERATION Operation)
Definition: mdlsup.c:935
void log_device_error(_In_ device_extension *Vcb, _Inout_ device *dev, _In_ int error)
Definition: btrfs.c:5817
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4157
NTSTATUS NTAPI IoCallDriver(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: irp.c:1218
#define IRP_MJ_READ
Definition: rdpdr.c:46
Definition: fs.h:216
#define IRP_DEALLOCATE_BUFFER
VOID NTAPI IoFreeIrp(IN PIRP Irp)
Definition: irp.c:1666
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
static NTSTATUS scrub_extent_dup(device_extension *Vcb, chunk *c, uint64_t offset, void *csum, scrub_context *context)
Definition: scrub.c:667
PIRP NTAPI IoAllocateIrp(IN CCHAR StackSize, IN BOOLEAN ChargeQuota)
Definition: irp.c:615
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define BLOCK_FLAG_DUPLICATE
Definition: shellext.h:80
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:2772
#define uint32_t
Definition: nsiface.idl:61
return STATUS_SUCCESS
Definition: btrfs.c:3014
#define ExFreePool(addr)
Definition: env_spec_w32.h:352

Referenced by scrub_chunk(), and scrub_data_extent().

◆ scrub_extent_dup()

static NTSTATUS scrub_extent_dup ( device_extension Vcb,
chunk c,
uint64_t  offset,
void csum,
scrub_context context 
)
static

Definition at line 667 of file scrub.c.

667  {
669  bool csum_error = false;
670  ULONG i;
671  CHUNK_ITEM_STRIPE* cis = (CHUNK_ITEM_STRIPE*)&c->chunk_item[1];
672  uint16_t present_devices = 0;
673 
674  if (csum) {
675  ULONG good_stripe = 0xffffffff;
676 
677  for (i = 0; i < c->chunk_item->num_stripes; i++) {
678  if (c->devices[i]->devobj) {
679  present_devices++;
680 
681  // if first stripe is okay, we only need to check that the others are identical to it
682  if (good_stripe != 0xffffffff) {
683  if (RtlCompareMemory(context->stripes[i].buf, context->stripes[good_stripe].buf,
684  context->stripes[good_stripe].length) != context->stripes[i].length) {
685  context->stripes[i].csum_error = true;
686  csum_error = true;
688  }
689  } else {
690  Status = check_csum(Vcb, context->stripes[i].buf, context->stripes[i].length / Vcb->superblock.sector_size, csum);
691  if (Status == STATUS_CRC_ERROR) {
692  context->stripes[i].csum_error = true;
693  csum_error = true;
695  } else if (!NT_SUCCESS(Status)) {
696  ERR("check_csum returned %08lx\n", Status);
697  return Status;
698  } else
699  good_stripe = i;
700  }
701  }
702  }
703  } else {
704  ULONG good_stripe = 0xffffffff;
705 
706  for (i = 0; i < c->chunk_item->num_stripes; i++) {
707  ULONG j;
708 
709  if (c->devices[i]->devobj) {
710  // if first stripe is okay, we only need to check that the others are identical to it
711  if (good_stripe != 0xffffffff) {
712  if (RtlCompareMemory(context->stripes[i].buf, context->stripes[good_stripe].buf,
713  context->stripes[good_stripe].length) != context->stripes[i].length) {
714  context->stripes[i].csum_error = true;
715  csum_error = true;
717  }
718  } else {
719  for (j = 0; j < context->stripes[i].length / Vcb->superblock.node_size; j++) {
720  tree_header* th = (tree_header*)&context->stripes[i].buf[j * Vcb->superblock.node_size];
721 
722  if (!check_tree_checksum(Vcb, th) || th->address != offset + UInt32x32To64(j, Vcb->superblock.node_size)) {
723  context->stripes[i].csum_error = true;
724  csum_error = true;
726  }
727  }
728 
729  if (!context->stripes[i].csum_error)
730  good_stripe = i;
731  }
732  }
733  }
734  }
735 
736  if (!csum_error)
737  return STATUS_SUCCESS;
738 
739  // handle checksum error
740 
741  for (i = 0; i < c->chunk_item->num_stripes; i++) {
742  if (context->stripes[i].csum_error) {
743  if (csum) {
744  context->stripes[i].bad_csums = ExAllocatePoolWithTag(PagedPool, context->stripes[i].length * Vcb->csum_size / Vcb->superblock.sector_size, ALLOC_TAG);
745  if (!context->stripes[i].bad_csums) {
746  ERR("out of memory\n");
748  }
749 
750  do_calc_job(Vcb, context->stripes[i].buf, context->stripes[i].length / Vcb->superblock.sector_size, context->stripes[i].bad_csums);
751  } else {
752  ULONG j;
753 
754  context->stripes[i].bad_csums = ExAllocatePoolWithTag(PagedPool, context->stripes[i].length * Vcb->csum_size / Vcb->superblock.node_size, ALLOC_TAG);
755  if (!context->stripes[i].bad_csums) {
756  ERR("out of memory\n");
758  }
759 
760  for (j = 0; j < context->stripes[i].length / Vcb->superblock.node_size; j++) {
761  tree_header* th = (tree_header*)&context->stripes[i].buf[j * Vcb->superblock.node_size];
762 
763  get_tree_checksum(Vcb, th, (uint8_t*)context->stripes[i].bad_csums + (Vcb->csum_size * j));
764  }
765  }
766  }
767  }
768 
769  if (present_devices > 1) {
770  ULONG good_stripe = 0xffffffff;
771 
772  for (i = 0; i < c->chunk_item->num_stripes; i++) {
773  if (c->devices[i]->devobj && !context->stripes[i].csum_error) {
774  good_stripe = i;
775  break;
776  }
777  }
778 
779  if (good_stripe != 0xffffffff) {
780  // log
781 
782  for (i = 0; i < c->chunk_item->num_stripes; i++) {
783  if (context->stripes[i].csum_error) {
784  ULONG j;
785 
786  if (csum) {
787  for (j = 0; j < context->stripes[i].length / Vcb->superblock.sector_size; j++) {
788  if (RtlCompareMemory((uint8_t*)context->stripes[i].bad_csums + (j * Vcb->csum_size), (uint8_t*)csum + (j + Vcb->csum_size), Vcb->csum_size) != Vcb->csum_size) {
789  uint64_t addr = offset + UInt32x32To64(j, Vcb->superblock.sector_size);
790 
791  log_error(Vcb, addr, c->devices[i]->devitem.dev_id, false, true, false);
793  }
794  }
795  } else {
796  for (j = 0; j < context->stripes[i].length / Vcb->superblock.node_size; j++) {
797  tree_header* th = (tree_header*)&context->stripes[i].buf[j * Vcb->superblock.node_size];
798  uint64_t addr = offset + UInt32x32To64(j, Vcb->superblock.node_size);
799 
800  if (RtlCompareMemory((uint8_t*)context->stripes[i].bad_csums + (j * Vcb->csum_size), th, Vcb->csum_size) != Vcb->csum_size || th->address != addr) {
801  log_error(Vcb, addr, c->devices[i]->devitem.dev_id, true, true, false);
803  }
804  }
805  }
806  }
807  }
808 
809  // write good data over bad
810 
811  for (i = 0; i < c->chunk_item->num_stripes; i++) {
812  if (context->stripes[i].csum_error && !c->devices[i]->readonly) {
813  Status = write_data_phys(c->devices[i]->devobj, c->devices[i]->fileobj, cis[i].offset + offset - c->offset,
814  context->stripes[good_stripe].buf, context->stripes[i].length);
815 
816  if (!NT_SUCCESS(Status)) {
817  ERR("write_data_phys returned %08lx\n", Status);
819  return Status;
820  }
821  }
822  }
823 
824  return STATUS_SUCCESS;
825  }
826 
827  // if csum errors on all stripes, check sector by sector
828 
829  for (i = 0; i < c->chunk_item->num_stripes; i++) {
830  ULONG j;
831 
832  if (c->devices[i]->devobj) {
833  if (csum) {
834  for (j = 0; j < context->stripes[i].length / Vcb->superblock.sector_size; j++) {
835  if (RtlCompareMemory((uint8_t*)context->stripes[i].bad_csums + (j * Vcb->csum_size), (uint8_t*)csum + (j * Vcb->csum_size), Vcb->csum_size) != Vcb->csum_size) {
836  ULONG k;
837  uint64_t addr = offset + UInt32x32To64(j, Vcb->superblock.sector_size);
838  bool recovered = false;
839 
840  for (k = 0; k < c->chunk_item->num_stripes; k++) {
841  if (i != k && c->devices[k]->devobj &&
842  RtlCompareMemory((uint8_t*)context->stripes[k].bad_csums + (j * Vcb->csum_size),
843  (uint8_t*)csum + (j * Vcb->csum_size), Vcb->csum_size) == Vcb->csum_size) {
844  log_error(Vcb, addr, c->devices[i]->devitem.dev_id, false, true, false);
846 
847  RtlCopyMemory(context->stripes[i].buf + (j * Vcb->superblock.sector_size),
848  context->stripes[k].buf + (j * Vcb->superblock.sector_size), Vcb->superblock.sector_size);
849 
850  recovered = true;
851  break;
852  }
853  }
854 
855  if (!recovered) {
856  log_error(Vcb, addr, c->devices[i]->devitem.dev_id, false, false, false);
858  }
859  }
860  }
861  } else {
862  for (j = 0; j < context->stripes[i].length / Vcb->superblock.node_size; j++) {
863  tree_header* th = (tree_header*)&context->stripes[i].buf[j * Vcb->superblock.node_size];
864  uint64_t addr = offset + UInt32x32To64(j, Vcb->superblock.node_size);
865 
866  if (RtlCompareMemory((uint8_t*)context->stripes[i].bad_csums + (j * Vcb->csum_size), th, Vcb->csum_size) != Vcb->csum_size || th->address != addr) {
867  ULONG k;
868  bool recovered = false;
869 
870  for (k = 0; k < c->chunk_item->num_stripes; k++) {
871  if (i != k && c->devices[k]->devobj) {
872  tree_header* th2 = (tree_header*)&context->stripes[k].buf[j * Vcb->superblock.node_size];
873 
874  if (RtlCompareMemory((uint8_t*)context->stripes[k].bad_csums + (j * Vcb->csum_size), th2, Vcb->csum_size) == Vcb->csum_size && th2->address == addr) {
875  log_error(Vcb, addr, c->devices[i]->devitem.dev_id, true, true, false);
877 
878  RtlCopyMemory(th, th2, Vcb->superblock.node_size);
879 
880  recovered = true;
881  break;
882  }
883  }
884  }
885 
886  if (!recovered) {
887  log_error(Vcb, addr, c->devices[i]->devitem.dev_id, true, false, false);
889  }
890  }
891  }
892  }
893  }
894  }
895 
896  // write good data over bad
897 
898  for (i = 0; i < c->chunk_item->num_stripes; i++) {
899  if (c->devices[i]->devobj && !c->devices[i]->readonly) {
900  Status = write_data_phys(c->devices[i]->devobj, c->devices[i]->fileobj, cis[i].offset + offset - c->offset,
901  context->stripes[i].buf, context->stripes[i].length);
902  if (!NT_SUCCESS(Status)) {
903  ERR("write_data_phys returned %08lx\n", Status);
905  return Status;
906  }
907  }
908  }
909 
910  return STATUS_SUCCESS;
911  }
912 
913  for (i = 0; i < c->chunk_item->num_stripes; i++) {
914  if (c->devices[i]->devobj) {
915  ULONG j;
916 
917  if (csum) {
918  for (j = 0; j < context->stripes[i].length / Vcb->superblock.sector_size; j++) {
919  if (RtlCompareMemory((uint8_t*)context->stripes[i].bad_csums + (j * Vcb->csum_size), (uint8_t*)csum + (j + Vcb->csum_size), Vcb->csum_size) != Vcb->csum_size) {
920  uint64_t addr = offset + UInt32x32To64(j, Vcb->superblock.sector_size);
921 
922  log_error(Vcb, addr, c->devices[i]->devitem.dev_id, false, false, false);
923  }
924  }
925  } else {
926  for (j = 0; j < context->stripes[i].length / Vcb->superblock.node_size; j++) {
927  tree_header* th = (tree_header*)&context->stripes[i].buf[j * Vcb->superblock.node_size];
928  uint64_t addr = offset + UInt32x32To64(j, Vcb->superblock.node_size);
929 
930  if (RtlCompareMemory((uint8_t*)context->stripes[i].bad_csums + (j * Vcb->csum_size), th, Vcb->csum_size) != Vcb->csum_size || th->address != addr)
931  log_error(Vcb, addr, c->devices[i]->devitem.dev_id, true, false, false);
932  }
933  }
934  }
935  }
936 
937  return STATUS_SUCCESS;
938 }
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
Definition: http.c:7094
LONG NTSTATUS
Definition: precomp.h:26
GLintptr offset
Definition: glext.h:5920
unsigned short int uint16_t
Definition: acefiex.h:54
#define ALLOC_TAG
Definition: btrfs_drv.h:91
void do_calc_job(device_extension *Vcb, uint8_t *data, uint32_t sectors, void *csum)
Definition: calcthread.c:141
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
uint64_t address
Definition: btrfs.h:149
static void log_error(device_extension *Vcb, uint64_t addr, uint64_t devid, bool metadata, bool recoverable, bool parity)
Definition: scrub.c:605
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define BTRFS_DEV_STAT_CORRUPTION_ERRORS
Definition: btrfs.h:530
NTSTATUS write_data_phys(_In_ PDEVICE_OBJECT device, _In_ PFILE_OBJECT fileobj, _In_ uint64_t address, _In_reads_bytes_(length) void *data, _In_ uint32_t length)
Definition: flushthread.c:65
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1425
const GLubyte * c
Definition: glext.h:8905
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
GLenum const GLvoid * addr
Definition: glext.h:9621
bool check_tree_checksum(device_extension *Vcb, tree_header *th)
Definition: read.c:128
#define STATUS_CRC_ERROR
Definition: udferr_usr.h:153
BYTE uint8_t
Definition: msvideo1.c:66
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:110
void get_tree_checksum(device_extension *Vcb, tree_header *th, void *csum)
Definition: read.c:108
UINT64 uint64_t
Definition: types.h:77
void log_device_error(_In_ device_extension *Vcb, _Inout_ device *dev, _In_ int error)
Definition: btrfs.c:5817
static bool check_csum(btrfs_send_command *cmd, uint8_t *data)
Definition: recv.cpp:1257
Definition: fs.h:216
#define BTRFS_DEV_STAT_WRITE_ERRORS
Definition: btrfs.h:527
unsigned int ULONG
Definition: retypes.h:1
return STATUS_SUCCESS
Definition: btrfs.c:3014
#define UInt32x32To64(a, b)
Definition: intsafe.h:258
int k
Definition: mpi.c:3369
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465

Referenced by scrub_extent().

◆ scrub_extent_raid0()

static NTSTATUS scrub_extent_raid0 ( device_extension Vcb,
chunk c,
uint64_t  offset,
uint32_t  length,
uint16_t  startoffstripe,
void csum,
scrub_context context 
)
static

Definition at line 940 of file scrub.c.

940  {
941  ULONG j;
943  uint32_t pos, *stripeoff;
944 
945  pos = 0;
946  stripeoff = ExAllocatePoolWithTag(NonPagedPool, sizeof(uint32_t) * c->chunk_item->num_stripes, ALLOC_TAG);
947  if (!stripeoff) {
948  ERR("out of memory\n");
950  }
951 
952  RtlZeroMemory(stripeoff, sizeof(uint32_t) * c->chunk_item->num_stripes);
953 
954  stripe = startoffstripe;
955  while (pos < length) {
956  uint32_t readlen;
957 
958  if (pos == 0)
959  readlen = (uint32_t)min(context->stripes[stripe].length, c->chunk_item->stripe_length - (context->stripes[stripe].start % c->chunk_item->stripe_length));
960  else
961  readlen = min(length - pos, (uint32_t)c->chunk_item->stripe_length);
962 
963  if (csum) {
964  for (j = 0; j < readlen; j += Vcb->superblock.sector_size) {
965  if (!check_sector_csum(Vcb, context->stripes[stripe].buf + stripeoff[stripe], (uint8_t*)csum + (pos * Vcb->csum_size / Vcb->superblock.sector_size))) {
966  uint64_t addr = offset + pos;
967 
968  log_error(Vcb, addr, c->devices[stripe]->devitem.dev_id, false, false, false);
970  }
971 
972  pos += Vcb->superblock.sector_size;
973  stripeoff[stripe] += Vcb->superblock.sector_size;
974  }
975  } else {
976  for (j = 0; j < readlen; j += Vcb->superblock.node_size) {
977  tree_header* th = (tree_header*)(context->stripes[stripe].buf + stripeoff[stripe]);
978  uint64_t addr = offset + pos;
979 
980  if (!check_tree_checksum(Vcb, th) || th->address != addr) {
981  log_error(Vcb, addr, c->devices[stripe]->devitem.dev_id, true, false, false);
983  }
984 
985  pos += Vcb->superblock.node_size;
986  stripeoff[stripe] += Vcb->superblock.node_size;
987  }
988  }
989 
990  stripe = (stripe + 1) % c->chunk_item->num_stripes;
991  }
992 
993  ExFreePool(stripeoff);
994 
995  return STATUS_SUCCESS;
996 }
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
Definition: http.c:7094
GLintptr offset
Definition: glext.h:5920
Definition: write.c:111
unsigned short int uint16_t
Definition: acefiex.h:54
bool check_sector_csum(device_extension *Vcb, void *buf, void *csum)
Definition: read.c:202
#define ALLOC_TAG
Definition: btrfs_drv.h:91
uint64_t address
Definition: btrfs.h:149
static void log_error(device_extension *Vcb, uint64_t addr, uint64_t devid, bool metadata, bool recoverable, bool parity)
Definition: scrub.c:605
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define BTRFS_DEV_STAT_CORRUPTION_ERRORS
Definition: btrfs.h:530
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
#define Vcb
Definition: cdprocs.h:1425
const GLubyte * c
Definition: glext.h:8905
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
GLenum const GLvoid * addr
Definition: glext.h:9621
bool check_tree_checksum(device_extension *Vcb, tree_header *th)
Definition: read.c:128
BYTE uint8_t
Definition: msvideo1.c:66
#define ERR(fmt,...)
Definition: debug.h:110
UINT64 uint64_t
Definition: types.h:77
void log_device_error(_In_ device_extension *Vcb, _Inout_ device *dev, _In_ int error)
Definition: btrfs.c:5817
#define min(a, b)
Definition: monoChain.cc:55
UINT32 uint32_t
Definition: types.h:75
Definition: fs.h:216
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
#define uint32_t
Definition: nsiface.idl:61
return STATUS_SUCCESS
Definition: btrfs.c:3014
#define ExFreePool(addr)
Definition: env_spec_w32.h:352

Referenced by scrub_extent().

◆ scrub_extent_raid10()

static NTSTATUS scrub_extent_raid10 ( device_extension Vcb,
chunk c,
uint64_t  offset,
uint32_t  length,
uint16_t  startoffstripe,
void csum,
scrub_context context 
)
static

Definition at line 998 of file scrub.c.

998  {
999  ULONG j;
1000  uint16_t stripe, sub_stripes = max(c->chunk_item->sub_stripes, 1);
1001  uint32_t pos, *stripeoff;
1002  bool csum_error = false;
1003  NTSTATUS Status;
1004 
1005  pos = 0;
1006  stripeoff = ExAllocatePoolWithTag(NonPagedPool, sizeof(uint32_t) * c->chunk_item->num_stripes / sub_stripes, ALLOC_TAG);
1007  if (!stripeoff) {
1008  ERR("out of memory\n");
1010  }
1011 
1012  RtlZeroMemory(stripeoff, sizeof(uint32_t) * c->chunk_item->num_stripes / sub_stripes);
1013 
1014  stripe = startoffstripe;
1015  while (pos < length) {
1016  uint32_t readlen;
1017 
1018  if (pos == 0)
1019  readlen = (uint32_t)min(context->stripes[stripe * sub_stripes].length,
1020  c->chunk_item->stripe_length - (context->stripes[stripe * sub_stripes].start % c->chunk_item->stripe_length));
1021  else
1022  readlen = min(length - pos, (uint32_t)c->chunk_item->stripe_length);
1023 
1024  if (csum) {
1025  ULONG good_stripe = 0xffffffff;
1026  uint16_t k;
1027 
1028  for (k = 0; k < sub_stripes; k++) {
1029  if (c->devices[(stripe * sub_stripes) + k]->devobj) {
1030  // if first stripe is okay, we only need to check that the others are identical to it
1031  if (good_stripe != 0xffffffff) {
1032  if (RtlCompareMemory(context->stripes[(stripe * sub_stripes) + k].buf + stripeoff[stripe],
1033  context->stripes[(stripe * sub_stripes) + good_stripe].buf + stripeoff[stripe],
1034  readlen) != readlen) {
1035  context->stripes[(stripe * sub_stripes) + k].csum_error = true;
1036  csum_error = true;
1037  log_device_error(Vcb, c->devices[(stripe * sub_stripes) + k], BTRFS_DEV_STAT_CORRUPTION_ERRORS);
1038  }
1039  } else {
1040  for (j = 0; j < readlen; j += Vcb->superblock.sector_size) {
1041  if (!check_sector_csum(Vcb, context->stripes[(stripe * sub_stripes) + k].buf + stripeoff[stripe] + j,
1042  (uint8_t*)csum + ((pos + j) * Vcb->csum_size / Vcb->superblock.sector_size))) {
1043  csum_error = true;
1044  context->stripes[(stripe * sub_stripes) + k].csum_error = true;
1045  log_device_error(Vcb, c->devices[(stripe * sub_stripes) + k], BTRFS_DEV_STAT_CORRUPTION_ERRORS);
1046  break;
1047  }
1048  }
1049 
1050  if (!context->stripes[(stripe * sub_stripes) + k].csum_error)
1051  good_stripe = k;
1052  }
1053  }
1054  }
1055 
1056  pos += readlen;
1057  stripeoff[stripe] += readlen;
1058  } else {
1059  ULONG good_stripe = 0xffffffff;
1060  uint16_t k;
1061 
1062  for (k = 0; k < sub_stripes; k++) {
1063  if (c->devices[(stripe * sub_stripes) + k]->devobj) {
1064  // if first stripe is okay, we only need to check that the others are identical to it
1065  if (good_stripe != 0xffffffff) {
1066  if (RtlCompareMemory(context->stripes[(stripe * sub_stripes) + k].buf + stripeoff[stripe],
1067  context->stripes[(stripe * sub_stripes) + good_stripe].buf + stripeoff[stripe],
1068  readlen) != readlen) {