ReactOS  0.4.15-dev-1070-ge1a01de
balance.c File Reference
#include "btrfs_drv.h"
#include "btrfsioctl.h"
#include "crc32c.h"
#include <ntddstor.h>
Include dependency graph for balance.c:

Go to the source code of this file.

Classes

struct  metadata_reloc
 
struct  metadata_reloc_ref
 
struct  data_reloc
 
struct  data_reloc_ref
 

Macros

#define DEVICE_DSM_FLAG_TRIM_NOT_FS_ALLOCATED   0x80000000
 
#define BALANCE_UNIT   0x100000
 

Functions

static NTSTATUS add_metadata_reloc (_Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, LIST_ENTRY *items, traverse_ptr *tp, bool skinny, metadata_reloc **mr2, chunk *c, LIST_ENTRY *rollback)
 
static NTSTATUS add_metadata_reloc_parent (_Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, LIST_ENTRY *items, uint64_t address, metadata_reloc **mr2, LIST_ENTRY *rollback)
 
static void sort_metadata_reloc_refs (metadata_reloc *mr)
 
static NTSTATUS add_metadata_reloc_extent_item (_Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, metadata_reloc *mr)
 
static NTSTATUS write_metadata_items (_Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, LIST_ENTRY *items, LIST_ENTRY *data_items, chunk *c, LIST_ENTRY *rollback)
 
static NTSTATUS balance_metadata_chunk (device_extension *Vcb, chunk *c, bool *changed)
 
static NTSTATUS data_reloc_add_tree_edr (_Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, LIST_ENTRY *metadata_items, data_reloc *dr, EXTENT_DATA_REF *edr, LIST_ENTRY *rollback)
 
static NTSTATUS add_data_reloc (_Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, LIST_ENTRY *items, LIST_ENTRY *metadata_items, traverse_ptr *tp, chunk *c, LIST_ENTRY *rollback)
 
static void sort_data_reloc_refs (data_reloc *dr)
 
static NTSTATUS add_data_reloc_extent_item (_Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, data_reloc *dr)
 
static NTSTATUS balance_data_chunk (device_extension *Vcb, chunk *c, bool *changed)
 
static __inline uint64_t get_chunk_dup_type (chunk *c)
 
static bool should_balance_chunk (device_extension *Vcb, uint8_t sort, chunk *c)
 
static void copy_balance_args (btrfs_balance_opts *opts, BALANCE_ARGS *args)
 
static NTSTATUS add_balance_item (device_extension *Vcb)
 
static NTSTATUS remove_balance_item (device_extension *Vcb)
 
static void load_balance_args (btrfs_balance_opts *opts, BALANCE_ARGS *args)
 
static NTSTATUS remove_superblocks (device *dev)
 
static NTSTATUS finish_removing_device (_Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, device *dev)
 
static void trim_unalloc_space (_Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, device *dev)
 
static NTSTATUS try_consolidation (device_extension *Vcb, uint64_t flags, chunk **newchunk)
 
static NTSTATUS regenerate_space_list (device_extension *Vcb, device *dev)
 
 _Function_class_ (KSTART_ROUTINE)
 
NTSTATUS start_balance (device_extension *Vcb, void *data, ULONG length, KPROCESSOR_MODE processor_mode)
 
NTSTATUS look_for_balance_item (_Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb)
 
NTSTATUS query_balance (device_extension *Vcb, void *data, ULONG length)
 
NTSTATUS pause_balance (device_extension *Vcb, KPROCESSOR_MODE processor_mode)
 
NTSTATUS resume_balance (device_extension *Vcb, KPROCESSOR_MODE processor_mode)
 
NTSTATUS stop_balance (device_extension *Vcb, KPROCESSOR_MODE processor_mode)
 
NTSTATUS remove_device (device_extension *Vcb, void *data, ULONG length, KPROCESSOR_MODE processor_mode)
 

Macro Definition Documentation

◆ BALANCE_UNIT

#define BALANCE_UNIT   0x100000

Definition at line 75 of file balance.c.

◆ DEVICE_DSM_FLAG_TRIM_NOT_FS_ALLOCATED

#define DEVICE_DSM_FLAG_TRIM_NOT_FS_ALLOCATED   0x80000000

Definition at line 72 of file balance.c.

Function Documentation

◆ _Function_class_()

_Function_class_ ( KSTART_ROUTINE  )

Definition at line 3051 of file balance.c.

3052  {
3054  LIST_ENTRY chunks;
3055  LIST_ENTRY* le;
3056  uint64_t num_chunks[3], okay_metadata_chunks = 0, okay_data_chunks = 0, okay_system_chunks = 0;
3057  uint64_t old_data_flags = 0, old_metadata_flags = 0, old_system_flags = 0;
3058  NTSTATUS Status;
3059 
3060  Vcb->balance.balance_num++;
3061 
3062  Vcb->balance.stopping = false;
3063  KeInitializeEvent(&Vcb->balance.finished, NotificationEvent, false);
3064 
3065  if (Vcb->balance.opts[BALANCE_OPTS_DATA].flags & BTRFS_BALANCE_OPTS_ENABLED && Vcb->balance.opts[BALANCE_OPTS_DATA].flags & BTRFS_BALANCE_OPTS_CONVERT) {
3066  old_data_flags = Vcb->data_flags;
3067  Vcb->data_flags = BLOCK_FLAG_DATA | (Vcb->balance.opts[BALANCE_OPTS_DATA].convert == BLOCK_FLAG_SINGLE ? 0 : Vcb->balance.opts[BALANCE_OPTS_DATA].convert);
3068 
3070  }
3071 
3072  if (Vcb->balance.opts[BALANCE_OPTS_METADATA].flags & BTRFS_BALANCE_OPTS_ENABLED && Vcb->balance.opts[BALANCE_OPTS_METADATA].flags & BTRFS_BALANCE_OPTS_CONVERT) {
3073  old_metadata_flags = Vcb->metadata_flags;
3074  Vcb->metadata_flags = BLOCK_FLAG_METADATA | (Vcb->balance.opts[BALANCE_OPTS_METADATA].convert == BLOCK_FLAG_SINGLE ? 0 : Vcb->balance.opts[BALANCE_OPTS_METADATA].convert);
3075  }
3076 
3077  if (Vcb->balance.opts[BALANCE_OPTS_SYSTEM].flags & BTRFS_BALANCE_OPTS_ENABLED && Vcb->balance.opts[BALANCE_OPTS_SYSTEM].flags & BTRFS_BALANCE_OPTS_CONVERT) {
3078  old_system_flags = Vcb->system_flags;
3079  Vcb->system_flags = BLOCK_FLAG_SYSTEM | (Vcb->balance.opts[BALANCE_OPTS_SYSTEM].convert == BLOCK_FLAG_SINGLE ? 0 : Vcb->balance.opts[BALANCE_OPTS_SYSTEM].convert);
3080  }
3081 
3082  if (Vcb->superblock.incompat_flags & BTRFS_INCOMPAT_FLAGS_MIXED_GROUPS) {
3083  if (Vcb->balance.opts[BALANCE_OPTS_DATA].flags & BTRFS_BALANCE_OPTS_ENABLED)
3084  RtlCopyMemory(&Vcb->balance.opts[BALANCE_OPTS_METADATA], &Vcb->balance.opts[BALANCE_OPTS_DATA], sizeof(btrfs_balance_opts));
3085  else if (Vcb->balance.opts[BALANCE_OPTS_METADATA].flags & BTRFS_BALANCE_OPTS_ENABLED)
3086  RtlCopyMemory(&Vcb->balance.opts[BALANCE_OPTS_DATA], &Vcb->balance.opts[BALANCE_OPTS_METADATA], sizeof(btrfs_balance_opts));
3087  }
3088 
3089  num_chunks[0] = num_chunks[1] = num_chunks[2] = 0;
3090  Vcb->balance.total_chunks = Vcb->balance.chunks_left = 0;
3091 
3092  InitializeListHead(&chunks);
3093 
3094  // FIXME - what are we supposed to do with limit_start?
3095 
3096  if (!Vcb->readonly) {
3097  if (!Vcb->balance.removing && !Vcb->balance.shrinking) {
3099  if (!NT_SUCCESS(Status)) {
3100  ERR("add_balance_item returned %08lx\n", Status);
3101  Vcb->balance.status = Status;
3102  goto end;
3103  }
3104  } else {
3105  if (Vcb->need_write) {
3106  Status = do_write(Vcb, NULL);
3107 
3108  free_trees(Vcb);
3109 
3110  if (!NT_SUCCESS(Status)) {
3111  ERR("do_write returned %08lx\n", Status);
3112  Vcb->balance.status = Status;
3113  goto end;
3114  }
3115  }
3116  }
3117  }
3118 
3119  KeWaitForSingleObject(&Vcb->balance.event, Executive, KernelMode, false, NULL);
3120 
3121  if (Vcb->balance.stopping)
3122  goto end;
3123 
3124  ExAcquireResourceSharedLite(&Vcb->chunk_lock, true);
3125 
3126  le = Vcb->chunks.Flink;
3127  while (le != &Vcb->chunks) {
3129  uint8_t sort;
3130 
3132 
3133  if (c->chunk_item->type & BLOCK_FLAG_DATA)
3135  else if (c->chunk_item->type & BLOCK_FLAG_METADATA)
3137  else if (c->chunk_item->type & BLOCK_FLAG_SYSTEM)
3139  else {
3140  ERR("unexpected chunk type %I64x\n", c->chunk_item->type);
3142  break;
3143  }
3144 
3145  if ((!(Vcb->balance.opts[sort].flags & BTRFS_BALANCE_OPTS_LIMIT) || num_chunks[sort] < Vcb->balance.opts[sort].limit_end) &&
3147  InsertTailList(&chunks, &c->list_entry_balance);
3148 
3149  num_chunks[sort]++;
3150  Vcb->balance.total_chunks++;
3151  Vcb->balance.chunks_left++;
3152  } else if (sort == BALANCE_OPTS_METADATA)
3153  okay_metadata_chunks++;
3154  else if (sort == BALANCE_OPTS_DATA)
3155  okay_data_chunks++;
3156  else if (sort == BALANCE_OPTS_SYSTEM)
3157  okay_system_chunks++;
3158 
3159  if (!c->cache_loaded) {
3161 
3162  if (!NT_SUCCESS(Status)) {
3163  ERR("load_cache_chunk returned %08lx\n", Status);
3164  Vcb->balance.status = Status;
3166  ExReleaseResourceLite(&Vcb->chunk_lock);
3167  goto end;
3168  }
3169  }
3170 
3172 
3173  le = le->Flink;
3174  }
3175 
3176  ExReleaseResourceLite(&Vcb->chunk_lock);
3177 
3178  // If we're doing a full balance, try and allocate a new chunk now, before we mess things up
3179  if (okay_metadata_chunks == 0 || okay_data_chunks == 0 || okay_system_chunks == 0) {
3180  bool consolidated = false;
3181  chunk* c;
3182 
3183  if (okay_metadata_chunks == 0) {
3184  ExAcquireResourceExclusiveLite(&Vcb->chunk_lock, true);
3185 
3186  Status = alloc_chunk(Vcb, Vcb->metadata_flags, &c, true);
3187  if (NT_SUCCESS(Status))
3188  c->balance_num = Vcb->balance.balance_num;
3189  else if (Status != STATUS_DISK_FULL || consolidated) {
3190  ERR("alloc_chunk returned %08lx\n", Status);
3191  ExReleaseResourceLite(&Vcb->chunk_lock);
3192  Vcb->balance.status = Status;
3193  goto end;
3194  }
3195 
3196  ExReleaseResourceLite(&Vcb->chunk_lock);
3197 
3198  if (Status == STATUS_DISK_FULL) {
3199  Status = try_consolidation(Vcb, Vcb->metadata_flags, &c);
3200  if (!NT_SUCCESS(Status)) {
3201  ERR("try_consolidation returned %08lx\n", Status);
3202  Vcb->balance.status = Status;
3203  goto end;
3204  } else
3205  c->balance_num = Vcb->balance.balance_num;
3206 
3207  consolidated = true;
3208 
3209  if (Vcb->balance.stopping)
3210  goto end;
3211  }
3212  }
3213 
3214  if (okay_data_chunks == 0) {
3215  ExAcquireResourceExclusiveLite(&Vcb->chunk_lock, true);
3216 
3217  Status = alloc_chunk(Vcb, Vcb->data_flags, &c, true);
3218  if (NT_SUCCESS(Status))
3219  c->balance_num = Vcb->balance.balance_num;
3220  else if (Status != STATUS_DISK_FULL || consolidated) {
3221  ERR("alloc_chunk returned %08lx\n", Status);
3222  ExReleaseResourceLite(&Vcb->chunk_lock);
3223  Vcb->balance.status = Status;
3224  goto end;
3225  }
3226 
3227  ExReleaseResourceLite(&Vcb->chunk_lock);
3228 
3229  if (Status == STATUS_DISK_FULL) {
3230  Status = try_consolidation(Vcb, Vcb->data_flags, &c);
3231  if (!NT_SUCCESS(Status)) {
3232  ERR("try_consolidation returned %08lx\n", Status);
3233  Vcb->balance.status = Status;
3234  goto end;
3235  } else
3236  c->balance_num = Vcb->balance.balance_num;
3237 
3238  consolidated = true;
3239 
3240  if (Vcb->balance.stopping)
3241  goto end;
3242  }
3243  }
3244 
3245  if (okay_system_chunks == 0) {
3246  ExAcquireResourceExclusiveLite(&Vcb->chunk_lock, true);
3247 
3248  Status = alloc_chunk(Vcb, Vcb->system_flags, &c, true);
3249  if (NT_SUCCESS(Status))
3250  c->balance_num = Vcb->balance.balance_num;
3251  else if (Status != STATUS_DISK_FULL || consolidated) {
3252  ERR("alloc_chunk returned %08lx\n", Status);
3253  ExReleaseResourceLite(&Vcb->chunk_lock);
3254  Vcb->balance.status = Status;
3255  goto end;
3256  }
3257 
3258  ExReleaseResourceLite(&Vcb->chunk_lock);
3259 
3260  if (Status == STATUS_DISK_FULL) {
3261  Status = try_consolidation(Vcb, Vcb->system_flags, &c);
3262  if (!NT_SUCCESS(Status)) {
3263  ERR("try_consolidation returned %08lx\n", Status);
3264  Vcb->balance.status = Status;
3265  goto end;
3266  } else
3267  c->balance_num = Vcb->balance.balance_num;
3268 
3269  consolidated = true;
3270 
3271  if (Vcb->balance.stopping)
3272  goto end;
3273  }
3274  }
3275  }
3276 
3277  ExAcquireResourceSharedLite(&Vcb->chunk_lock, true);
3278 
3279  le = chunks.Flink;
3280  while (le != &chunks) {
3281  chunk* c = CONTAINING_RECORD(le, chunk, list_entry_balance);
3282 
3283  c->reloc = true;
3284 
3285  le = le->Flink;
3286  }
3287 
3288  ExReleaseResourceLite(&Vcb->chunk_lock);
3289 
3290  // do data chunks before metadata
3291  le = chunks.Flink;
3292  while (le != &chunks) {
3293  chunk* c = CONTAINING_RECORD(le, chunk, list_entry_balance);
3294  LIST_ENTRY* le2 = le->Flink;
3295 
3296  if (c->chunk_item->type & BLOCK_FLAG_DATA) {
3297  bool changed;
3298 
3299  do {
3300  changed = false;
3301 
3302  Status = balance_data_chunk(Vcb, c, &changed);
3303  if (!NT_SUCCESS(Status)) {
3304  ERR("balance_data_chunk returned %08lx\n", Status);
3305  Vcb->balance.status = Status;
3306  goto end;
3307  }
3308 
3309  KeWaitForSingleObject(&Vcb->balance.event, Executive, KernelMode, false, NULL);
3310 
3311  if (Vcb->readonly)
3312  Vcb->balance.stopping = true;
3313 
3314  if (Vcb->balance.stopping)
3315  break;
3316  } while (changed);
3317 
3318  c->changed = true;
3319  c->space_changed = true;
3320  }
3321 
3322  if (Vcb->balance.stopping)
3323  goto end;
3324 
3325  if (c->chunk_item->type & BLOCK_FLAG_DATA &&
3326  (!(Vcb->balance.opts[BALANCE_OPTS_METADATA].flags & BTRFS_BALANCE_OPTS_ENABLED) || !(c->chunk_item->type & BLOCK_FLAG_METADATA))) {
3327  RemoveEntryList(&c->list_entry_balance);
3328  c->list_entry_balance.Flink = NULL;
3329 
3330  Vcb->balance.chunks_left--;
3331  }
3332 
3333  le = le2;
3334  }
3335 
3336  // do metadata chunks
3337  while (!IsListEmpty(&chunks)) {
3338  chunk* c;
3339  bool changed;
3340 
3341  le = RemoveHeadList(&chunks);
3342  c = CONTAINING_RECORD(le, chunk, list_entry_balance);
3343 
3344  if (c->chunk_item->type & BLOCK_FLAG_METADATA || c->chunk_item->type & BLOCK_FLAG_SYSTEM) {
3345  do {
3346  Status = balance_metadata_chunk(Vcb, c, &changed);
3347  if (!NT_SUCCESS(Status)) {
3348  ERR("balance_metadata_chunk returned %08lx\n", Status);
3349  Vcb->balance.status = Status;
3350  goto end;
3351  }
3352 
3353  KeWaitForSingleObject(&Vcb->balance.event, Executive, KernelMode, false, NULL);
3354 
3355  if (Vcb->readonly)
3356  Vcb->balance.stopping = true;
3357 
3358  if (Vcb->balance.stopping)
3359  break;
3360  } while (changed);
3361 
3362  c->changed = true;
3363  c->space_changed = true;
3364  }
3365 
3366  if (Vcb->balance.stopping)
3367  break;
3368 
3369  c->list_entry_balance.Flink = NULL;
3370 
3371  Vcb->balance.chunks_left--;
3372  }
3373 
3374 end:
3375  if (!Vcb->readonly) {
3376  if (Vcb->balance.stopping || !NT_SUCCESS(Vcb->balance.status)) {
3377  le = chunks.Flink;
3378  while (le != &chunks) {
3379  chunk* c = CONTAINING_RECORD(le, chunk, list_entry_balance);
3380  c->reloc = false;
3381 
3382  le = le->Flink;
3383  c->list_entry_balance.Flink = NULL;
3384  }
3385 
3386  if (old_data_flags != 0)
3387  Vcb->data_flags = old_data_flags;
3388 
3389  if (old_metadata_flags != 0)
3390  Vcb->metadata_flags = old_metadata_flags;
3391 
3392  if (old_system_flags != 0)
3393  Vcb->system_flags = old_system_flags;
3394  }
3395 
3396  if (Vcb->balance.removing) {
3397  device* dev = NULL;
3398 
3399  ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
3400 
3401  le = Vcb->devices.Flink;
3402  while (le != &Vcb->devices) {
3403  device* dev2 = CONTAINING_RECORD(le, device, list_entry);
3404 
3405  if (dev2->devitem.dev_id == Vcb->balance.opts[0].devid) {
3406  dev = dev2;
3407  break;
3408  }
3409 
3410  le = le->Flink;
3411  }
3412 
3413  if (dev) {
3414  if (Vcb->balance.chunks_left == 0) {
3416 
3417  if (!NT_SUCCESS(Status)) {
3418  ERR("finish_removing_device returned %08lx\n", Status);
3419  dev->reloc = false;
3420  }
3421  } else
3422  dev->reloc = false;
3423  }
3424 
3425  ExReleaseResourceLite(&Vcb->tree_lock);
3426  } else if (Vcb->balance.shrinking) {
3427  device* dev = NULL;
3428 
3429  ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
3430 
3431  le = Vcb->devices.Flink;
3432  while (le != &Vcb->devices) {
3433  device* dev2 = CONTAINING_RECORD(le, device, list_entry);
3434 
3435  if (dev2->devitem.dev_id == Vcb->balance.opts[0].devid) {
3436  dev = dev2;
3437  break;
3438  }
3439 
3440  le = le->Flink;
3441  }
3442 
3443  if (!dev) {
3444  ERR("could not find device %I64x\n", Vcb->balance.opts[0].devid);
3445  Vcb->balance.status = STATUS_INTERNAL_ERROR;
3446  }
3447 
3448  if (Vcb->balance.stopping || !NT_SUCCESS(Vcb->balance.status)) {
3449  if (dev) {
3451  if (!NT_SUCCESS(Status))
3452  WARN("regenerate_space_list returned %08lx\n", Status);
3453  }
3454  } else {
3455  uint64_t old_size;
3456 
3457  old_size = dev->devitem.num_bytes;
3458  dev->devitem.num_bytes = Vcb->balance.opts[0].drange_start;
3459 
3461  if (!NT_SUCCESS(Status)) {
3462  ERR("update_dev_item returned %08lx\n", Status);
3463  dev->devitem.num_bytes = old_size;
3464  Vcb->balance.status = Status;
3465 
3467  if (!NT_SUCCESS(Status))
3468  WARN("regenerate_space_list returned %08lx\n", Status);
3469  } else {
3470  Vcb->superblock.total_bytes -= old_size - dev->devitem.num_bytes;
3471 
3472  Status = do_write(Vcb, NULL);
3473  if (!NT_SUCCESS(Status))
3474  ERR("do_write returned %08lx\n", Status);
3475 
3476  free_trees(Vcb);
3477  }
3478  }
3479 
3480  ExReleaseResourceLite(&Vcb->tree_lock);
3481 
3482  if (!Vcb->balance.stopping && NT_SUCCESS(Vcb->balance.status))
3484  } else {
3486  if (!NT_SUCCESS(Status)) {
3487  ERR("remove_balance_item returned %08lx\n", Status);
3488  goto end;
3489  }
3490  }
3491 
3492  if (Vcb->trim && !Vcb->options.no_trim) {
3493  ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
3494 
3495  le = Vcb->devices.Flink;
3496  while (le != &Vcb->devices) {
3497  device* dev2 = CONTAINING_RECORD(le, device, list_entry);
3498 
3499  if (dev2->devobj && !dev2->readonly && dev2->trim)
3500  trim_unalloc_space(Vcb, dev2);
3501 
3502  le = le->Flink;
3503  }
3504 
3505  ExReleaseResourceLite(&Vcb->tree_lock);
3506  }
3507  }
3508 
3509  ZwClose(Vcb->balance.thread);
3510  Vcb->balance.thread = NULL;
3511 
3512  KeSetEvent(&Vcb->balance.finished, 0, false);
3513 }
static bool should_balance_chunk(device_extension *Vcb, uint8_t sort, chunk *c)
Definition: balance.c:2229
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define BALANCE_OPTS_SYSTEM
Definition: btrfs_drv.h:703
Definition: http.c:7094
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
_STLP_MOVE_TO_STD_NAMESPACE void sort(_RandomAccessIter __first, _RandomAccessIter __last)
Definition: _algo.c:993
NTSTATUS do_write(device_extension *Vcb, PIRP Irp)
Definition: flushthread.c:7789
PDEVICE_OBJECT devobj
Definition: btrfs_drv.h:534
#define WARN(fmt,...)
Definition: debug.h:112
LONG NTSTATUS
Definition: precomp.h:26
release_chunk_lock(c, Vcb)
bool readonly
Definition: btrfs_drv.h:539
GLuint GLuint end
Definition: gl.h:1545
#define InsertTailList(ListHead, Entry)
static NTSTATUS balance_metadata_chunk(device_extension *Vcb, chunk *c, bool *changed)
Definition: balance.c:1104
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
#define BLOCK_FLAG_SINGLE
Definition: btrfsioctl.h:140
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
static NTSTATUS try_consolidation(device_extension *Vcb, uint64_t flags, chunk **newchunk)
Definition: balance.c:2906
#define BTRFS_BALANCE_OPTS_CONVERT
Definition: btrfsioctl.h:137
Definition: devices.h:37
#define BTRFS_INCOMPAT_FLAGS_MIXED_GROUPS
Definition: btrfs.h:110
#define BLOCK_FLAG_SYSTEM
Definition: shellext.h:76
bool trim
Definition: btrfs_drv.h:541
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
#define FSRTL_VOLUME_CHANGE_SIZE
Definition: fsrtltypes.h:101
static NTSTATUS add_balance_item(device_extension *Vcb)
Definition: balance.c:2382
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
static NTSTATUS regenerate_space_list(device_extension *Vcb, device *dev)
Definition: balance.c:3001
NTSTATUS NTAPI FsRtlNotifyVolumeEvent(IN PFILE_OBJECT FileObject, IN ULONG EventCode)
Definition: pnp.c:38
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1415
#define BTRFS_BALANCE_OPTS_LIMIT
Definition: btrfsioctl.h:134
const GLubyte * c
Definition: glext.h:8905
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
NTSTATUS update_dev_item(device_extension *Vcb, device *device, PIRP Irp)
Definition: flushthread.c:4099
#define BTRFS_BALANCE_OPTS_ENABLED
Definition: btrfsioctl.h:129
Status
Definition: gdiplustypes.h:24
#define BLOCK_FLAG_METADATA
Definition: shellext.h:77
uint64_t dev_id
Definition: btrfs.h:171
Definition: typedefs.h:119
BYTE uint8_t
Definition: msvideo1.c:66
NTSTATUS load_cache_chunk(device_extension *Vcb, chunk *c, PIRP Irp)
Definition: free-space.c:980
#define ERR(fmt,...)
Definition: debug.h:110
static NTSTATUS remove_balance_item(device_extension *Vcb)
Definition: balance.c:2455
static NTSTATUS balance_data_chunk(device_extension *Vcb, chunk *c, bool *changed)
Definition: balance.c:1675
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
DEV_ITEM devitem
Definition: btrfs_drv.h:536
BOOLEAN NTAPI ExAcquireResourceSharedLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:885
#define BLOCK_FLAG_DATA
Definition: shellext.h:75
static NTSTATUS finish_removing_device(_Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, device *dev)
Definition: balance.c:2590
#define STATUS_DISK_FULL
Definition: udferr_usr.h:155
static void trim_unalloc_space(_Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, device *dev)
Definition: balance.c:2806
#define c
Definition: ke_i.h:80
#define BALANCE_OPTS_METADATA
Definition: btrfs_drv.h:702
NTSTATUS alloc_chunk(device_extension *Vcb, uint64_t flags, chunk **pc, bool full_size)
Definition: write.c:361
#define BALANCE_OPTS_DATA
Definition: btrfs_drv.h:701

◆ add_balance_item()

static NTSTATUS add_balance_item ( device_extension Vcb)
static

Definition at line 2382 of file balance.c.

2382  {
2383  KEY searchkey;
2384  traverse_ptr tp;
2385  NTSTATUS Status;
2386  BALANCE_ITEM* bi;
2387 
2388  searchkey.obj_id = BALANCE_ITEM_ID;
2389  searchkey.obj_type = TYPE_TEMP_ITEM;
2390  searchkey.offset = 0;
2391 
2392  ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
2393 
2394  Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, false, NULL);
2395  if (!NT_SUCCESS(Status)) {
2396  ERR("find_item returned %08lx\n", Status);
2397  goto end;
2398  }
2399 
2400  if (!keycmp(tp.item->key, searchkey)) {
2402  if (!NT_SUCCESS(Status)) {
2403  ERR("delete_tree_item returned %08lx\n", Status);
2404  goto end;
2405  }
2406  }
2407 
2409  if (!bi) {
2410  ERR("out of memory\n");
2412  goto end;
2413  }
2414 
2415  RtlZeroMemory(bi, sizeof(BALANCE_ITEM));
2416 
2417  if (Vcb->balance.opts[BALANCE_OPTS_DATA].flags & BTRFS_BALANCE_OPTS_ENABLED) {
2418  bi->flags |= BALANCE_FLAGS_DATA;
2419  copy_balance_args(&Vcb->balance.opts[BALANCE_OPTS_DATA], &bi->data);
2420  }
2421 
2422  if (Vcb->balance.opts[BALANCE_OPTS_METADATA].flags & BTRFS_BALANCE_OPTS_ENABLED) {
2424  copy_balance_args(&Vcb->balance.opts[BALANCE_OPTS_METADATA], &bi->metadata);
2425  }
2426 
2427  if (Vcb->balance.opts[BALANCE_OPTS_SYSTEM].flags & BTRFS_BALANCE_OPTS_ENABLED) {
2428  bi->flags |= BALANCE_FLAGS_SYSTEM;
2429  copy_balance_args(&Vcb->balance.opts[BALANCE_OPTS_SYSTEM], &bi->system);
2430  }
2431 
2432  Status = insert_tree_item(Vcb, Vcb->root_root, BALANCE_ITEM_ID, TYPE_TEMP_ITEM, 0, bi, sizeof(BALANCE_ITEM), NULL, NULL);
2433  if (!NT_SUCCESS(Status)) {
2434  ERR("insert_tree_item returned %08lx\n", Status);
2435  ExFreePool(bi);
2436  goto end;
2437  }
2438 
2440 
2441 end:
2442  if (NT_SUCCESS(Status)) {
2443  Status = do_write(Vcb, NULL);
2444  if (!NT_SUCCESS(Status))
2445  ERR("do_write returned %08lx\n", Status);
2446  }
2447 
2448  free_trees(Vcb);
2449 
2450  ExReleaseResourceLite(&Vcb->tree_lock);
2451 
2452  return Status;
2453 }
#define BALANCE_ITEM_ID
Definition: btrfs.h:88
uint64_t obj_id
Definition: btrfs.h:137
uint8_t obj_type
Definition: btrfs.h:138
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define BALANCE_OPTS_SYSTEM
Definition: btrfs_drv.h:703
NTSTATUS do_write(device_extension *Vcb, PIRP Irp)
Definition: flushthread.c:7789
#define keycmp(key1, key2)
Definition: btrfs_drv.h:1024
LONG NTSTATUS
Definition: precomp.h:26
uint64_t flags
Definition: btrfs.h:513
GLuint GLuint end
Definition: gl.h:1545
BALANCE_ARGS data
Definition: btrfs.h:514
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
smooth NULL
Definition: ftsmooth.c:416
void free_trees(device_extension *Vcb)
Definition: treefuncs.c:794
#define TYPE_TEMP_ITEM
Definition: btrfs.h:45
_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 NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1415
static void copy_balance_args(btrfs_balance_opts *opts, BALANCE_ARGS *args)
Definition: balance.c:2322
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
NTSTATUS insert_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _In_ uint64_t obj_id, _In_ uint8_t obj_type, _In_ uint64_t offset, _In_reads_bytes_opt_(size) _When_(return >=0, __drv_aliasesMem) void *data, _In_ uint16_t size, _Out_opt_ traverse_ptr *ptp, _In_opt_ PIRP Irp)
Definition: treefuncs.c:858
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
tree_data * item
Definition: btrfs_drv.h:518
#define BTRFS_BALANCE_OPTS_ENABLED
Definition: btrfsioctl.h:129
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:110
Definition: btrfs.h:136
#define BALANCE_FLAGS_SYSTEM
Definition: btrfs.h:465
BALANCE_ARGS metadata
Definition: btrfs.h:515
#define BALANCE_FLAGS_DATA
Definition: btrfs.h:464
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
BALANCE_ARGS system
Definition: btrfs.h:516
#define BALANCE_OPTS_METADATA
Definition: btrfs_drv.h:702
return STATUS_SUCCESS
Definition: btrfs.c:3014
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
NTSTATUS delete_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _Inout_ traverse_ptr *tp)
Definition: treefuncs.c:990
#define BALANCE_FLAGS_METADATA
Definition: btrfs.h:466
#define BALANCE_OPTS_DATA
Definition: btrfs_drv.h:701

Referenced by _Function_class_().

◆ add_data_reloc()

static NTSTATUS add_data_reloc ( _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension Vcb,
LIST_ENTRY items,
LIST_ENTRY metadata_items,
traverse_ptr tp,
chunk c,
LIST_ENTRY rollback 
)
static

Definition at line 1320 of file balance.c.

1321  {
1322  NTSTATUS Status;
1323  data_reloc* dr;
1324  EXTENT_ITEM* ei;
1325  uint16_t len;
1326  uint64_t inline_rc;
1327  uint8_t* ptr;
1328 
1330  if (!dr) {
1331  ERR("out of memory\n");
1333  }
1334 
1335  dr->address = tp->item->key.obj_id;
1336  dr->size = tp->item->key.offset;
1337  dr->ei = (EXTENT_ITEM*)tp->item->data;
1338  InitializeListHead(&dr->refs);
1339 
1341  if (!NT_SUCCESS(Status)) {
1342  ERR("delete_tree_item returned %08lx\n", Status);
1343  return Status;
1344  }
1345 
1346  if (!c)
1348 
1349  if (c) {
1351 
1352  c->used -= tp->item->key.offset;
1353 
1355 
1357  }
1358 
1359  ei = (EXTENT_ITEM*)tp->item->data;
1360  inline_rc = 0;
1361 
1362  len = tp->item->size - sizeof(EXTENT_ITEM);
1363  ptr = (uint8_t*)tp->item->data + sizeof(EXTENT_ITEM);
1364 
1365  while (len > 0) {
1366  uint8_t secttype = *ptr;
1367  uint16_t sectlen = secttype == TYPE_EXTENT_DATA_REF ? sizeof(EXTENT_DATA_REF) : (secttype == TYPE_SHARED_DATA_REF ? sizeof(SHARED_DATA_REF) : 0);
1368 
1369  len--;
1370 
1371  if (sectlen > len) {
1372  ERR("(%I64x,%x,%I64x): %x bytes left, expecting at least %x\n", tp->item->key.obj_id, tp->item->key.obj_type, tp->item->key.offset, len, sectlen);
1373  return STATUS_INTERNAL_ERROR;
1374  }
1375 
1376  if (sectlen == 0) {
1377  ERR("(%I64x,%x,%I64x): unrecognized extent type %x\n", tp->item->key.obj_id, tp->item->key.obj_type, tp->item->key.offset, secttype);
1378  return STATUS_INTERNAL_ERROR;
1379  }
1380 
1381  if (secttype == TYPE_EXTENT_DATA_REF) {
1382  EXTENT_DATA_REF* edr = (EXTENT_DATA_REF*)(ptr + sizeof(uint8_t));
1383 
1384  inline_rc += edr->count;
1385 
1386  Status = data_reloc_add_tree_edr(Vcb, metadata_items, dr, edr, rollback);
1387  if (!NT_SUCCESS(Status)) {
1388  ERR("data_reloc_add_tree_edr returned %08lx\n", Status);
1389  return Status;
1390  }
1391  } else if (secttype == TYPE_SHARED_DATA_REF) {
1392  metadata_reloc* mr;
1394 
1396  if (!ref) {
1397  ERR("out of memory\n");
1399  }
1400 
1401  ref->type = TYPE_SHARED_DATA_REF;
1402  RtlCopyMemory(&ref->sdr, ptr + sizeof(uint8_t), sizeof(SHARED_DATA_REF));
1403  inline_rc += ref->sdr.count;
1404 
1405  Status = add_metadata_reloc_parent(Vcb, metadata_items, ref->sdr.offset, &mr, rollback);
1406  if (!NT_SUCCESS(Status)) {
1407  ERR("add_metadata_reloc_parent returned %08lx\n", Status);
1408  ExFreePool(ref);
1409  return Status;
1410  }
1411 
1412  ref->parent = mr;
1413 
1414  InsertTailList(&dr->refs, &ref->list_entry);
1415  } else {
1416  ERR("unexpected tree type %x\n", secttype);
1417  return STATUS_INTERNAL_ERROR;
1418  }
1419 
1420 
1421  len -= sectlen;
1422  ptr += sizeof(uint8_t) + sectlen;
1423  }
1424 
1425  if (inline_rc < ei->refcount) { // look for non-inline entries
1426  traverse_ptr tp2 = *tp, next_tp;
1427 
1428  while (find_next_item(Vcb, &tp2, &next_tp, false, NULL)) {
1429  tp2 = next_tp;
1430 
1431  if (tp2.item->key.obj_id == tp->item->key.obj_id) {
1432  if (tp2.item->key.obj_type == TYPE_EXTENT_DATA_REF && tp2.item->size >= sizeof(EXTENT_DATA_REF)) {
1433  Status = data_reloc_add_tree_edr(Vcb, metadata_items, dr, (EXTENT_DATA_REF*)tp2.item->data, rollback);
1434  if (!NT_SUCCESS(Status)) {
1435  ERR("data_reloc_add_tree_edr returned %08lx\n", Status);
1436  return Status;
1437  }
1438 
1439  Status = delete_tree_item(Vcb, &tp2);
1440  if (!NT_SUCCESS(Status)) {
1441  ERR("delete_tree_item returned %08lx\n", Status);
1442  return Status;
1443  }
1444  } else if (tp2.item->key.obj_type == TYPE_SHARED_DATA_REF && tp2.item->size >= sizeof(uint32_t)) {
1445  metadata_reloc* mr;
1447 
1449  if (!ref) {
1450  ERR("out of memory\n");
1452  }
1453 
1454  ref->type = TYPE_SHARED_DATA_REF;
1455  ref->sdr.offset = tp2.item->key.offset;
1456  ref->sdr.count = *((uint32_t*)tp2.item->data);
1457 
1458  Status = add_metadata_reloc_parent(Vcb, metadata_items, ref->sdr.offset, &mr, rollback);
1459  if (!NT_SUCCESS(Status)) {
1460  ERR("add_metadata_reloc_parent returned %08lx\n", Status);
1461  ExFreePool(ref);
1462  return Status;
1463  }
1464 
1465  ref->parent = mr;
1466  InsertTailList(&dr->refs, &ref->list_entry);
1467 
1468  Status = delete_tree_item(Vcb, &tp2);
1469  if (!NT_SUCCESS(Status)) {
1470  ERR("delete_tree_item returned %08lx\n", Status);
1471  return Status;
1472  }
1473  }
1474  } else
1475  break;
1476  }
1477  }
1478 
1480 
1481  return STATUS_SUCCESS;
1482 }
LIST_ENTRY list_entry
Definition: balance.c:55
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
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
LONG NTSTATUS
Definition: precomp.h:26
uint16_t size
Definition: btrfs_drv.h:430
release_chunk_lock(c, Vcb)
static NTSTATUS data_reloc_add_tree_edr(_Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, LIST_ENTRY *metadata_items, data_reloc *dr, EXTENT_DATA_REF *edr, LIST_ENTRY *rollback)
Definition: balance.c:1221
unsigned short int uint16_t
Definition: acefiex.h:54
#define InsertTailList(ListHead, Entry)
LIST_ENTRY list_entry
Definition: send.c:49
Definition: send.c:48
uint64_t offset
Definition: btrfs.h:139
uint8_t * data
Definition: btrfs_drv.h:431
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
#define ALLOC_TAG
Definition: btrfs_drv.h:91
void space_list_add(chunk *c, uint64_t address, uint64_t length, LIST_ENTRY *rollback)
Definition: free-space.c:1959
GLenum GLint ref
Definition: glext.h:6028
static PVOID ptr
Definition: dispmode.c:27
LIST_ENTRY refs
Definition: balance.c:54
uint32_t count
Definition: btrfs.h:408
smooth NULL
Definition: ftsmooth.c:416
#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
#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:1415
const GLubyte * c
Definition: glext.h:8905
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
tree_data * item
Definition: btrfs_drv.h:518
Status
Definition: gdiplustypes.h:24
GLenum GLsizei len
Definition: glext.h:6722
static NTSTATUS add_metadata_reloc_parent(_Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, LIST_ENTRY *items, uint64_t address, metadata_reloc **mr2, LIST_ENTRY *rollback)
Definition: balance.c:230
BYTE uint8_t
Definition: msvideo1.c:66
#define ERR(fmt,...)
Definition: debug.h:110
chunk * get_chunk_from_address(device_extension *Vcb, uint64_t address)
Definition: write.c:89
UINT64 uint64_t
Definition: types.h:77
#define uint8_t
Definition: nsiface.idl:59
#define acquire_chunk_lock(c, Vcb)
Definition: btrfs_drv.h:1137
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY * rollback
Definition: btrfs_drv.h:1357
UINT32 uint32_t
Definition: types.h:75
EXTENT_ITEM * ei
Definition: balance.c:53
static TCHAR * items[]
Definition: page1.c:45
return STATUS_SUCCESS
Definition: btrfs.c:3014
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
NTSTATUS delete_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _Inout_ traverse_ptr *tp)
Definition: treefuncs.c:990
uint64_t size
Definition: balance.c:50
uint64_t address
Definition: balance.c:49

Referenced by balance_data_chunk().

◆ add_data_reloc_extent_item()

static NTSTATUS add_data_reloc_extent_item ( _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension Vcb,
data_reloc dr 
)
static

Definition at line 1545 of file balance.c.

1545  {
1546  NTSTATUS Status;
1547  LIST_ENTRY* le;
1548  uint64_t rc = 0;
1549  uint16_t inline_len;
1550  bool all_inline = true;
1551  data_reloc_ref* first_noninline = NULL;
1552  EXTENT_ITEM* ei;
1553  uint8_t* ptr;
1554 
1555  inline_len = sizeof(EXTENT_ITEM);
1556 
1558 
1559  le = dr->refs.Flink;
1560  while (le != &dr->refs) {
1562  uint16_t extlen = 0;
1563 
1564  if (ref->type == TYPE_EXTENT_DATA_REF) {
1565  extlen += sizeof(EXTENT_DATA_REF);
1566  rc += ref->edr.count;
1567  } else if (ref->type == TYPE_SHARED_DATA_REF) {
1568  extlen += sizeof(SHARED_DATA_REF);
1569  rc++;
1570  }
1571 
1572  if (all_inline) {
1573  if ((ULONG)(inline_len + 1 + extlen) > (Vcb->superblock.node_size >> 2)) {
1574  all_inline = false;
1575  first_noninline = ref;
1576  } else
1577  inline_len += extlen + 1;
1578  }
1579 
1580  le = le->Flink;
1581  }
1582 
1583  ei = ExAllocatePoolWithTag(PagedPool, inline_len, ALLOC_TAG);
1584  if (!ei) {
1585  ERR("out of memory\n");
1587  }
1588 
1589  ei->refcount = rc;
1590  ei->generation = dr->ei->generation;
1591  ei->flags = dr->ei->flags;
1592  ptr = (uint8_t*)&ei[1];
1593 
1594  le = dr->refs.Flink;
1595  while (le != &dr->refs) {
1597 
1598  if (ref == first_noninline)
1599  break;
1600 
1601  *ptr = ref->type;
1602  ptr++;
1603 
1604  if (ref->type == TYPE_EXTENT_DATA_REF) {
1606 
1607  RtlCopyMemory(edr, &ref->edr, sizeof(EXTENT_DATA_REF));
1608 
1609  ptr += sizeof(EXTENT_DATA_REF);
1610  } else if (ref->type == TYPE_SHARED_DATA_REF) {
1612 
1613  sdr->offset = ref->parent->new_address;
1614  sdr->count = ref->sdr.count;
1615 
1616  ptr += sizeof(SHARED_DATA_REF);
1617  }
1618 
1619  le = le->Flink;
1620  }
1621 
1622  Status = insert_tree_item(Vcb, Vcb->extent_root, dr->new_address, TYPE_EXTENT_ITEM, dr->size, ei, inline_len, NULL, NULL);
1623  if (!NT_SUCCESS(Status)) {
1624  ERR("insert_tree_item returned %08lx\n", Status);
1625  return Status;
1626  }
1627 
1628  if (!all_inline) {
1629  le = &first_noninline->list_entry;
1630 
1631  while (le != &dr->refs) {
1633 
1634  if (ref->type == TYPE_EXTENT_DATA_REF) {
1635  EXTENT_DATA_REF* edr;
1636 
1638  if (!edr) {
1639  ERR("out of memory\n");
1641  }
1642 
1643  RtlCopyMemory(edr, &ref->edr, sizeof(EXTENT_DATA_REF));
1644 
1645  Status = insert_tree_item(Vcb, Vcb->extent_root, dr->new_address, TYPE_EXTENT_DATA_REF, ref->hash, edr, sizeof(EXTENT_DATA_REF), NULL, NULL);
1646  if (!NT_SUCCESS(Status)) {
1647  ERR("insert_tree_item returned %08lx\n", Status);
1648  return Status;
1649  }
1650  } else if (ref->type == TYPE_SHARED_DATA_REF) {
1651  uint32_t* sdr;
1652 
1654  if (!sdr) {
1655  ERR("out of memory\n");
1657  }
1658 
1659  *sdr = ref->sdr.count;
1660 
1661  Status = insert_tree_item(Vcb, Vcb->extent_root, dr->new_address, TYPE_SHARED_DATA_REF, ref->parent->new_address, sdr, sizeof(uint32_t), NULL, NULL);
1662  if (!NT_SUCCESS(Status)) {
1663  ERR("insert_tree_item returned %08lx\n", Status);
1664  return Status;
1665  }
1666  }
1667 
1668  le = le->Flink;
1669  }
1670  }
1671 
1672  return STATUS_SUCCESS;
1673 }
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
LONG NTSTATUS
Definition: precomp.h:26
unsigned short int uint16_t
Definition: acefiex.h:54
Definition: send.c:48
static void sort_data_reloc_refs(data_reloc *dr)
Definition: balance.c:1484
#define ALLOC_TAG
Definition: btrfs_drv.h:91
uint64_t refcount
Definition: btrfs.h:380
uint64_t new_address
Definition: balance.c:51
GLenum GLint ref
Definition: glext.h:6028
static PVOID ptr
Definition: dispmode.c:27
LIST_ENTRY refs
Definition: balance.c:54
smooth NULL
Definition: ftsmooth.c:416
#define TYPE_EXTENT_ITEM
Definition: btrfs.h:31
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
#define TYPE_EXTENT_DATA_REF
Definition: btrfs.h:34
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define TYPE_SHARED_DATA_REF
Definition: btrfs.h:37
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1415
NTSTATUS insert_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _In_ uint64_t obj_id, _In_ uint8_t obj_type, _In_ uint64_t offset, _In_reads_bytes_opt_(size) _When_(return >=0, __drv_aliasesMem) void *data, _In_ uint16_t size, _Out_opt_ traverse_ptr *ptp, _In_opt_ PIRP Irp)
Definition: treefuncs.c:858
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
LIST_ENTRY list_entry
Definition: balance.c:68
uint32_t count
Definition: btrfs.h:430
Status
Definition: gdiplustypes.h:24
Definition: typedefs.h:119
BYTE uint8_t
Definition: msvideo1.c:66
uint64_t generation
Definition: btrfs.h:381
#define ERR(fmt,...)
Definition: debug.h:110
UINT64 uint64_t
Definition: types.h:77
Definition: list.h:27
UINT32 uint32_t
Definition: types.h:75
unsigned int ULONG
Definition: retypes.h:1
EXTENT_ITEM * ei
Definition: balance.c:53
uint64_t flags
Definition: btrfs.h:382
return STATUS_SUCCESS
Definition: btrfs.c:3014
uint64_t offset
Definition: btrfs.h:429
uint64_t size
Definition: balance.c:50

Referenced by balance_data_chunk().

◆ add_metadata_reloc()

static NTSTATUS add_metadata_reloc ( _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension Vcb,
LIST_ENTRY items,
traverse_ptr tp,
bool  skinny,
metadata_reloc **  mr2,
chunk c,
LIST_ENTRY rollback 
)
static

Definition at line 77 of file balance.c.

78  {
80  metadata_reloc* mr;
81  EXTENT_ITEM* ei;
82  uint16_t len;
83  uint64_t inline_rc;
84  uint8_t* ptr;
85 
87  if (!mr) {
88  ERR("out of memory\n");
90  }
91 
92  mr->address = tp->item->key.obj_id;
93  mr->data = NULL;
94  mr->ei = (EXTENT_ITEM*)tp->item->data;
95  mr->system = false;
97 
99  if (!NT_SUCCESS(Status)) {
100  ERR("delete_tree_item returned %08lx\n", Status);
101  ExFreePool(mr);
102  return Status;
103  }
104 
105  if (!c)
107 
108  if (c) {
110 
111  c->used -= Vcb->superblock.node_size;
112 
113  space_list_add(c, tp->item->key.obj_id, Vcb->superblock.node_size, rollback);
114 
116  }
117 
118  ei = (EXTENT_ITEM*)tp->item->data;
119  inline_rc = 0;
120 
121  len = tp->item->size - sizeof(EXTENT_ITEM);
122  ptr = (uint8_t*)tp->item->data + sizeof(EXTENT_ITEM);
123  if (!skinny) {
124  len -= sizeof(EXTENT_ITEM2);
125  ptr += sizeof(EXTENT_ITEM2);
126  }
127 
128  while (len > 0) {
129  uint8_t secttype = *ptr;
130  uint16_t sectlen = secttype == TYPE_TREE_BLOCK_REF ? sizeof(TREE_BLOCK_REF) : (secttype == TYPE_SHARED_BLOCK_REF ? sizeof(SHARED_BLOCK_REF) : 0);
132 
133  len--;
134 
135  if (sectlen > len) {
136  ERR("(%I64x,%x,%I64x): %x bytes left, expecting at least %x\n", tp->item->key.obj_id, tp->item->key.obj_type, tp->item->key.offset, len, sectlen);
137  return STATUS_INTERNAL_ERROR;
138  }
139 
140  if (sectlen == 0) {
141  ERR("(%I64x,%x,%I64x): unrecognized extent type %x\n", tp->item->key.obj_id, tp->item->key.obj_type, tp->item->key.offset, secttype);
142  return STATUS_INTERNAL_ERROR;
143  }
144 
146  if (!ref) {
147  ERR("out of memory\n");
149  }
150 
151  if (secttype == TYPE_TREE_BLOCK_REF) {
152  ref->type = TYPE_TREE_BLOCK_REF;
153  RtlCopyMemory(&ref->tbr, ptr + sizeof(uint8_t), sizeof(TREE_BLOCK_REF));
154  inline_rc++;
155  } else if (secttype == TYPE_SHARED_BLOCK_REF) {
156  ref->type = TYPE_SHARED_BLOCK_REF;
157  RtlCopyMemory(&ref->sbr, ptr + sizeof(uint8_t), sizeof(SHARED_BLOCK_REF));
158  inline_rc++;
159  } else {
160  ERR("unexpected tree type %x\n", secttype);
161  ExFreePool(ref);
162  return STATUS_INTERNAL_ERROR;
163  }
164 
165  ref->parent = NULL;
166  ref->top = false;
168 
169  len -= sectlen;
170  ptr += sizeof(uint8_t) + sectlen;
171  }
172 
173  if (inline_rc < ei->refcount) { // look for non-inline entries
174  traverse_ptr tp2 = *tp, next_tp;
175 
176  while (find_next_item(Vcb, &tp2, &next_tp, false, NULL)) {
177  tp2 = next_tp;
178 
179  if (tp2.item->key.obj_id == tp->item->key.obj_id) {
180  if (tp2.item->key.obj_type == TYPE_TREE_BLOCK_REF) {
182  if (!ref) {
183  ERR("out of memory\n");
185  }
186 
187  ref->type = TYPE_TREE_BLOCK_REF;
188  ref->tbr.offset = tp2.item->key.offset;
189  ref->parent = NULL;
190  ref->top = false;
192 
193  Status = delete_tree_item(Vcb, &tp2);
194  if (!NT_SUCCESS(Status)) {
195  ERR("delete_tree_item returned %08lx\n", Status);
196  return Status;
197  }
198  } else if (tp2.item->key.obj_type == TYPE_SHARED_BLOCK_REF) {
200  if (!ref) {
201  ERR("out of memory\n");
203  }
204 
205  ref->type = TYPE_SHARED_BLOCK_REF;
206  ref->sbr.offset = tp2.item->key.offset;
207  ref->parent = NULL;
208  ref->top = false;
210 
211  Status = delete_tree_item(Vcb, &tp2);
212  if (!NT_SUCCESS(Status)) {
213  ERR("delete_tree_item returned %08lx\n", Status);
214  return Status;
215  }
216  }
217  } else
218  break;
219  }
220  }
221 
223 
224  if (mr2)
225  *mr2 = mr;
226 
227  return STATUS_SUCCESS;
228 }
uint64_t obj_id
Definition: btrfs.h:137
LIST_ENTRY list_entry
Definition: balance.c:31
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
LONG NTSTATUS
Definition: precomp.h:26
uint16_t size
Definition: btrfs_drv.h:430
#define TYPE_TREE_BLOCK_REF
Definition: btrfs.h:33
release_chunk_lock(c, Vcb)
unsigned short int uint16_t
Definition: acefiex.h:54
tree_header * data
Definition: balance.c:26
#define InsertTailList(ListHead, Entry)
LIST_ENTRY list_entry
Definition: send.c:49
Definition: send.c:48
uint64_t offset
Definition: btrfs.h:139
uint8_t * data
Definition: btrfs_drv.h:431
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
#define ALLOC_TAG
Definition: btrfs_drv.h:91
void space_list_add(chunk *c, uint64_t address, uint64_t length, LIST_ENTRY *rollback)
Definition: free-space.c:1959
GLenum GLint ref
Definition: glext.h:6028
static PVOID ptr
Definition: dispmode.c:27
smooth NULL
Definition: ftsmooth.c:416
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2930
EXTENT_ITEM * ei
Definition: balance.c:27
bool system
Definition: balance.c:29
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:1415
const GLubyte * c
Definition: glext.h:8905
#define TYPE_SHARED_BLOCK_REF
Definition: btrfs.h:36
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
tree_data * item
Definition: btrfs_drv.h:518
Status
Definition: gdiplustypes.h:24
GLenum GLsizei len
Definition: glext.h:6722
BYTE uint8_t
Definition: msvideo1.c:66
#define ERR(fmt,...)
Definition: debug.h:110
chunk * get_chunk_from_address(device_extension *Vcb, uint64_t address)
Definition: write.c:89
UINT64 uint64_t
Definition: types.h:77
#define uint8_t
Definition: nsiface.idl:59
#define acquire_chunk_lock(c, Vcb)
Definition: btrfs_drv.h:1137
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
uint64_t address
Definition: balance.c:24
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY * rollback
Definition: btrfs_drv.h:1357
static TCHAR * items[]
Definition: page1.c:45
return STATUS_SUCCESS
Definition: btrfs.c:3014
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
NTSTATUS delete_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _Inout_ traverse_ptr *tp)
Definition: treefuncs.c:990
LIST_ENTRY refs
Definition: balance.c:30

Referenced by add_metadata_reloc_parent(), and balance_metadata_chunk().

◆ add_metadata_reloc_extent_item()

static NTSTATUS add_metadata_reloc_extent_item ( _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension Vcb,
metadata_reloc mr 
)
static

Definition at line 326 of file balance.c.

326  {
328  LIST_ENTRY* le;
329  uint64_t rc = 0;
330  uint16_t inline_len;
331  bool all_inline = true;
332  metadata_reloc_ref* first_noninline = NULL;
333  EXTENT_ITEM* ei;
334  uint8_t* ptr;
335 
336  inline_len = sizeof(EXTENT_ITEM);
337  if (!(Vcb->superblock.incompat_flags & BTRFS_INCOMPAT_FLAGS_SKINNY_METADATA))
338  inline_len += sizeof(EXTENT_ITEM2);
339 
341 
342  le = mr->refs.Flink;
343  while (le != &mr->refs) {
345  uint16_t extlen = 0;
346 
347  rc++;
348 
349  if (ref->type == TYPE_TREE_BLOCK_REF)
350  extlen += sizeof(TREE_BLOCK_REF);
351  else if (ref->type == TYPE_SHARED_BLOCK_REF)
352  extlen += sizeof(SHARED_BLOCK_REF);
353 
354  if (all_inline) {
355  if ((ULONG)(inline_len + 1 + extlen) > (Vcb->superblock.node_size >> 2)) {
356  all_inline = false;
357  first_noninline = ref;
358  } else
359  inline_len += extlen + 1;
360  }
361 
362  le = le->Flink;
363  }
364 
365  ei = ExAllocatePoolWithTag(PagedPool, inline_len, ALLOC_TAG);
366  if (!ei) {
367  ERR("out of memory\n");
369  }
370 
371  ei->refcount = rc;
372  ei->generation = mr->ei->generation;
373  ei->flags = mr->ei->flags;
374  ptr = (uint8_t*)&ei[1];
375 
376  if (!(Vcb->superblock.incompat_flags & BTRFS_INCOMPAT_FLAGS_SKINNY_METADATA)) {
377  EXTENT_ITEM2* ei2 = (EXTENT_ITEM2*)ptr;
378 
379  ei2->firstitem = *(KEY*)&mr->data[1];
380  ei2->level = mr->data->level;
381 
382  ptr += sizeof(EXTENT_ITEM2);
383  }
384 
385  le = mr->refs.Flink;
386  while (le != &mr->refs) {
388 
389  if (ref == first_noninline)
390  break;
391 
392  *ptr = ref->type;
393  ptr++;
394 
395  if (ref->type == TYPE_TREE_BLOCK_REF) {
397 
398  tbr->offset = ref->tbr.offset;
399 
400  ptr += sizeof(TREE_BLOCK_REF);
401  } else if (ref->type == TYPE_SHARED_BLOCK_REF) {
403 
404  sbr->offset = ref->parent->new_address;
405 
406  ptr += sizeof(SHARED_BLOCK_REF);
407  }
408 
409  le = le->Flink;
410  }
411 
412  if (Vcb->superblock.incompat_flags & BTRFS_INCOMPAT_FLAGS_SKINNY_METADATA)
413  Status = insert_tree_item(Vcb, Vcb->extent_root, mr->new_address, TYPE_METADATA_ITEM, mr->data->level, ei, inline_len, NULL, NULL);
414  else
415  Status = insert_tree_item(Vcb, Vcb->extent_root, mr->new_address, TYPE_EXTENT_ITEM, Vcb->superblock.node_size, ei, inline_len, NULL, NULL);
416 
417  if (!NT_SUCCESS(Status)) {
418  ERR("insert_tree_item returned %08lx\n", Status);
419  ExFreePool(ei);
420  return Status;
421  }
422 
423  if (!all_inline) {
424  le = &first_noninline->list_entry;
425 
426  while (le != &mr->refs) {
428 
429  if (ref->type == TYPE_TREE_BLOCK_REF) {
430  Status = insert_tree_item(Vcb, Vcb->extent_root, mr->new_address, TYPE_TREE_BLOCK_REF, ref->tbr.offset, NULL, 0, NULL, NULL);
431  if (!NT_SUCCESS(Status)) {
432  ERR("insert_tree_item returned %08lx\n", Status);
433  return Status;
434  }
435  } else if (ref->type == TYPE_SHARED_BLOCK_REF) {
436  Status = insert_tree_item(Vcb, Vcb->extent_root, mr->new_address, TYPE_SHARED_BLOCK_REF, ref->parent->new_address, NULL, 0, NULL, NULL);
437  if (!NT_SUCCESS(Status)) {
438  ERR("insert_tree_item returned %08lx\n", Status);
439  return Status;
440  }
441  }
442 
443  le = le->Flink;
444  }
445  }
446 
448  if (mr->data->level > 0) {
449  uint16_t i;
450  internal_node* in = (internal_node*)&mr->data[1];
451 
452  for (i = 0; i < mr->data->num_items; i++) {
454 
455  if (sbrrc > 0) {
456  SHARED_BLOCK_REF sbr;
457 
458  sbr.offset = mr->new_address;
459 
460  Status = increase_extent_refcount(Vcb, in[i].address, Vcb->superblock.node_size, TYPE_SHARED_BLOCK_REF, &sbr, NULL, 0, NULL);
461  if (!NT_SUCCESS(Status)) {
462  ERR("increase_extent_refcount returned %08lx\n", Status);
463  return Status;
464  }
465 
466  sbr.offset = mr->address;
467 
468  Status = decrease_extent_refcount(Vcb, in[i].address, Vcb->superblock.node_size, TYPE_SHARED_BLOCK_REF, &sbr, NULL, 0,
469  sbr.offset, false, NULL);
470  if (!NT_SUCCESS(Status)) {
471  ERR("decrease_extent_refcount returned %08lx\n", Status);
472  return Status;
473  }
474  }
475  }
476  } else {
477  uint16_t i;
478  leaf_node* ln = (leaf_node*)&mr->data[1];
479 
480  for (i = 0; i < mr->data->num_items; i++) {
481  if (ln[i].key.obj_type == TYPE_EXTENT_DATA && ln[i].size >= sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2)) {
482  EXTENT_DATA* ed = (EXTENT_DATA*)((uint8_t*)mr->data + sizeof(tree_header) + ln[i].offset);
483 
486 
487  if (ed2->size > 0) { // not sparse
489 
490  if (sdrrc > 0) {
491  SHARED_DATA_REF sdr;
492  chunk* c;
493 
494  sdr.offset = mr->new_address;
495  sdr.count = sdrrc;
496 
498  if (!NT_SUCCESS(Status)) {
499  ERR("increase_extent_refcount returned %08lx\n", Status);
500  return Status;
501  }
502 
503  sdr.offset = mr->address;
504 
506  sdr.offset, false, NULL);
507  if (!NT_SUCCESS(Status)) {
508  ERR("decrease_extent_refcount returned %08lx\n", Status);
509  return Status;
510  }
511 
513 
514  if (c) {
515  // check changed_extents
516 
517  ExAcquireResourceExclusiveLite(&c->changed_extents_lock, true);
518 
519  le = c->changed_extents.Flink;
520 
521  while (le != &c->changed_extents) {
523 
524  if (ce->address == ed2->address) {
525  LIST_ENTRY* le2;
526 
527  le2 = ce->refs.Flink;
528  while (le2 != &ce->refs) {
530 
531  if (cer->type == TYPE_SHARED_DATA_REF && cer->sdr.offset == mr->address) {
532  cer->sdr.offset = mr->new_address;
533  break;
534  }
535 
536  le2 = le2->Flink;
537  }
538 
539  le2 = ce->old_refs.Flink;
540  while (le2 != &ce->old_refs) {
542 
543  if (cer->type == TYPE_SHARED_DATA_REF && cer->sdr.offset == mr->address) {
544  cer->sdr.offset = mr->new_address;
545  break;
546  }
547 
548  le2 = le2->Flink;
549  }
550 
551  break;
552  }
553 
554  le = le->Flink;
555  }
556 
557  ExReleaseResourceLite(&c->changed_extents_lock);
558  }
559  }
560  }
561  }
562  }
563  }
564  }
565  }
566 
567  return STATUS_SUCCESS;
568 }
SHARED_DATA_REF sdr
Definition: btrfs_drv.h:623
uint64_t new_address
Definition: balance.c:25
uint8_t type
Definition: btrfs.h:351
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
EXTENT_DATA2 * ed2
Definition: write.c:2805
NTSTATUS decrease_extent_refcount(device_extension *Vcb, uint64_t address, uint64_t size, uint8_t type, void *data, KEY *firstitem, uint8_t level, uint64_t parent, bool superseded, PIRP Irp)
Definition: extent-tree.c:903
LONG NTSTATUS
Definition: precomp.h:26
uint64_t flags
Definition: btrfs.h:150
GLintptr offset
Definition: glext.h:5920
#define TYPE_TREE_BLOCK_REF
Definition: btrfs.h:33
NTSTATUS increase_extent_refcount(device_extension *Vcb, uint64_t address, uint64_t size, uint8_t type, void *data, KEY *firstitem, uint8_t level, PIRP Irp)
Definition: extent-tree.c:454
#define BTRFS_INCOMPAT_FLAGS_SKINNY_METADATA
Definition: btrfs.h:116
unsigned short int uint16_t
Definition: acefiex.h:54
tree_header * data
Definition: balance.c:26
#define TYPE_METADATA_ITEM
Definition: btrfs.h:32
#define HEADER_FLAG_SHARED_BACKREF
Definition: btrfs.h:143
LIST_ENTRY old_refs
Definition: btrfs_drv.h:614
#define HEADER_FLAG_MIXED_BACKREF
Definition: btrfs.h:144
Definition: send.c:48
LIST_ENTRY list_entry
Definition: balance.c:45
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
#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 refcount
Definition: btrfs.h:380
uint64_t address
Definition: btrfs.h:356
GLenum GLint ref
Definition: glext.h:6028
static PVOID ptr
Definition: dispmode.c:27
smooth NULL
Definition: ftsmooth.c:416
#define TYPE_EXTENT_ITEM
Definition: btrfs.h:31
uint64_t size
Definition: btrfs.h:357
uint64_t offset
Definition: btrfs.h:401
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:121
#define TYPE_SHARED_DATA_REF
Definition: btrfs.h:37
EXTENT_ITEM * ei
Definition: balance.c:27
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1415
const GLubyte * c
Definition: glext.h:8905
KEY firstitem
Definition: btrfs.h:386
uint8_t level
Definition: btrfs.h:155
#define for
Definition: utility.h:88
GLuint address
Definition: glext.h:9393
uint64_t find_extent_shared_tree_refcount(device_extension *Vcb, uint64_t address, uint64_t parent, PIRP Irp)
Definition: extent-tree.c:2119
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
static void sort_metadata_reloc_refs(metadata_reloc *mr)
Definition: balance.c:284
NTSTATUS insert_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _In_ uint64_t obj_id, _In_ uint8_t obj_type, _In_ uint64_t offset, _In_reads_bytes_opt_(size) _When_(return >=0, __drv_aliasesMem) void *data, _In_ uint16_t size, _Out_opt_ traverse_ptr *ptp, _In_opt_ PIRP Irp)
Definition: treefuncs.c:858
#define TYPE_SHARED_BLOCK_REF
Definition: btrfs.h:36
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
uint64_t offset
Definition: btrfs.h:425
uint32_t count
Definition: btrfs.h:430
Status
Definition: gdiplustypes.h:24
uint8_t level
Definition: btrfs.h:387
Definition: typedefs.h:119
#define EXTENT_TYPE_PREALLOC
Definition: btrfs.h:72
BYTE uint8_t
Definition: msvideo1.c:66
uint64_t generation
Definition: btrfs.h:381
#define EXTENT_TYPE_REGULAR
Definition: btrfs.h:71
#define ERR(fmt,...)
Definition: debug.h:110
uint8_t data[1]
Definition: btrfs.h:352
Definition: btrfs.h:136
chunk * get_chunk_from_address(device_extension *Vcb, uint64_t address)
Definition: write.c:89
UINT64 uint64_t
Definition: types.h:77
GLuint in
Definition: glext.h:9616
uint32_t find_extent_shared_data_refcount(device_extension *Vcb, uint64_t address, uint64_t parent, PIRP Irp)
Definition: extent-tree.c:2220
uint64_t address
Definition: balance.c:24
LIST_ENTRY refs
Definition: btrfs_drv.h:613
Definition: list.h:27
UINT32 uint32_t
Definition: types.h:75
uint64_t address
Definition: btrfs_drv.h:606
#define c
Definition: ke_i.h:80
unsigned int ULONG
Definition: retypes.h:1
uint32_t num_items
Definition: btrfs.h:154
#define EXTENT_ITEM_SHARED_BACKREFS
Definition: btrfs.h:377
uint64_t flags
Definition: btrfs.h:382
#define TYPE_EXTENT_DATA
Definition: btrfs.h:26
return STATUS_SUCCESS
Definition: btrfs.c:3014
uint64_t offset
Definition: btrfs.h:429
EXTENT_DATA * ed
Definition: write.c:2804
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
Definition: path.c:41
LIST_ENTRY refs
Definition: balance.c:30

Referenced by write_metadata_items().

◆ add_metadata_reloc_parent()

static NTSTATUS add_metadata_reloc_parent ( _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension Vcb,
LIST_ENTRY items,
uint64_t  address,
metadata_reloc **  mr2,
LIST_ENTRY rollback 
)
static

Definition at line 230 of file balance.c.

231  {
232  LIST_ENTRY* le;
233  KEY searchkey;
235  bool skinny = false;
237 
238  le = items->Flink;
239  while (le != items) {
241 
242  if (mr->address == address) {
243  *mr2 = mr;
244  return STATUS_SUCCESS;
245  }
246 
247  le = le->Flink;
248  }
249 
250  searchkey.obj_id = address;
251  searchkey.obj_type = TYPE_METADATA_ITEM;
252  searchkey.offset = 0xffffffffffffffff;
253 
254  Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, false, NULL);
255  if (!NT_SUCCESS(Status)) {
256  ERR("find_item returned %08lx\n", Status);
257  return Status;
258  }
259 
261  skinny = true;
262  else if (tp.item->key.obj_id == address && tp.item->key.obj_type == TYPE_EXTENT_ITEM && tp.item->key.offset == Vcb->superblock.node_size &&
263  tp.item->size >= sizeof(EXTENT_ITEM)) {
265 
266  if (!(ei->flags & EXTENT_ITEM_TREE_BLOCK)) {
267  ERR("EXTENT_ITEM for %I64x found, but tree flag not set\n", address);
268  return STATUS_INTERNAL_ERROR;
269  }
270  } else {
271  ERR("could not find valid EXTENT_ITEM for address %I64x\n", address);
272  return STATUS_INTERNAL_ERROR;
273  }
274 
275  Status = add_metadata_reloc(Vcb, items, &tp, skinny, mr2, NULL, rollback);
276  if (!NT_SUCCESS(Status)) {
277  ERR("add_metadata_reloc returned %08lx\n", Status);
278  return Status;
279  }
280 
281  return STATUS_SUCCESS;
282 }
uint64_t obj_id
Definition: btrfs.h:137
uint8_t obj_type
Definition: btrfs.h:138
static NTSTATUS add_metadata_reloc(_Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, LIST_ENTRY *items, traverse_ptr *tp, bool skinny, metadata_reloc **mr2, chunk *c, LIST_ENTRY *rollback)
Definition: balance.c:77
LONG NTSTATUS
Definition: precomp.h:26
uint16_t size
Definition: btrfs_drv.h:430
#define TYPE_METADATA_ITEM
Definition: btrfs.h:32
uint64_t offset
Definition: btrfs.h:139
uint8_t * data
Definition: btrfs_drv.h:431
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
smooth NULL
Definition: ftsmooth.c:416
#define TYPE_EXTENT_ITEM
Definition: btrfs.h:31
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:121
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1415
GLuint address
Definition: glext.h:9393
tree_data * item
Definition: btrfs_drv.h:518
Status
Definition: gdiplustypes.h:24
Definition: typedefs.h:119
#define ERR(fmt,...)
Definition: debug.h:110
Definition: btrfs.h:136
#define EXTENT_ITEM_TREE_BLOCK
Definition: btrfs.h:376
uint64_t address
Definition: balance.c:24
Definition: list.h:27
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY * rollback
Definition: btrfs_drv.h:1357
uint64_t flags
Definition: btrfs.h:382
static TCHAR * items[]
Definition: page1.c:45
return STATUS_SUCCESS
Definition: btrfs.c:3014

Referenced by add_data_reloc(), data_reloc_add_tree_edr(), and write_metadata_items().

◆ balance_data_chunk()

static NTSTATUS balance_data_chunk ( device_extension Vcb,
chunk c,
bool changed 
)
static

Definition at line 1675 of file balance.c.

1675  {
1676  KEY searchkey;
1677  traverse_ptr tp;
1678  NTSTATUS Status;
1679  bool b;
1680  LIST_ENTRY items, metadata_items, rollback, *le;
1681  uint64_t loaded = 0, num_loaded = 0;
1682  chunk* newchunk = NULL;
1683  uint8_t* data = NULL;
1684 
1685  TRACE("chunk %I64x\n", c->offset);
1686 
1689  InitializeListHead(&metadata_items);
1690 
1691  ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
1692 
1693  searchkey.obj_id = c->offset;
1694  searchkey.obj_type = TYPE_EXTENT_ITEM;
1695  searchkey.offset = 0xffffffffffffffff;
1696 
1697  Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, false, NULL);
1698  if (!NT_SUCCESS(Status)) {
1699  ERR("find_item returned %08lx\n", Status);
1700  goto end;
1701  }
1702 
1703  do {
1704  traverse_ptr next_tp;
1705 
1706  if (tp.item->key.obj_id >= c->offset + c->chunk_item->size)
1707  break;
1708 
1709  if (tp.item->key.obj_id >= c->offset && tp.item->key.obj_type == TYPE_EXTENT_ITEM) {
1710  bool tree = false;
1711 
1712  if (tp.item->key.obj_type == TYPE_EXTENT_ITEM && tp.item->size >= sizeof(EXTENT_ITEM)) {
1713  EXTENT_ITEM* ei = (EXTENT_ITEM*)tp.item->data;
1714 
1716  tree = true;
1717  }
1718 
1719  if (!tree) {
1720  Status = add_data_reloc(Vcb, &items, &metadata_items, &tp, c, &rollback);
1721 
1722  if (!NT_SUCCESS(Status)) {
1723  ERR("add_data_reloc returned %08lx\n", Status);
1724  goto end;
1725  }
1726 
1727  loaded += tp.item->key.offset;
1728  num_loaded++;
1729 
1730  if (loaded >= 0x1000000 || num_loaded >= 100) // only do so much at a time, so we don't block too obnoxiously
1731  break;
1732  }
1733  }
1734 
1735  b = find_next_item(Vcb, &tp, &next_tp, false, NULL);
1736 
1737  if (b)
1738  tp = next_tp;
1739  } while (b);
1740 
1741  if (IsListEmpty(&items)) {
1742  *changed = false;
1744  goto end;
1745  } else
1746  *changed = true;
1747 
1749  if (!data) {
1750  ERR("out of memory\n");
1752  goto end;
1753  }
1754 
1755  le = items.Flink;
1756  while (le != &items) {
1758  bool done = false;
1759  LIST_ENTRY* le2;
1760  void* csum;
1761  RTL_BITMAP bmp;
1762  ULONG* bmparr;
1763  ULONG bmplen, runlength, index, lastoff;
1764 
1765  if (newchunk) {
1766  acquire_chunk_lock(newchunk, Vcb);
1767 
1768  if (find_data_address_in_chunk(Vcb, newchunk, dr->size, &dr->new_address)) {
1769  newchunk->used += dr->size;
1770  space_list_subtract(newchunk, false, dr->new_address, dr->size, &rollback);
1771  done = true;
1772  }
1773 
1774  release_chunk_lock(newchunk, Vcb);
1775  }
1776 
1777  if (!done) {
1778  ExAcquireResourceExclusiveLite(&Vcb->chunk_lock, true);
1779 
1780  le2 = Vcb->chunks.Flink;
1781  while (le2 != &Vcb->chunks) {
1782  chunk* c2 = CONTAINING_RECORD(le2, chunk, list_entry);
1783 
1784  if (!c2->readonly && !c2->reloc && c2 != newchunk && c2->chunk_item->type == Vcb->data_flags) {
1785  acquire_chunk_lock(c2, Vcb);
1786 
1787  if ((c2->chunk_item->size - c2->used) >= dr->size) {
1788  if (find_data_address_in_chunk(Vcb, c2, dr->size, &dr->new_address)) {
1789  c2->used += dr->size;
1790  space_list_subtract(c2, false, dr->new_address, dr->size, &rollback);
1791  release_chunk_lock(c2, Vcb);
1792  newchunk = c2;
1793  done = true;
1794  break;
1795  }
1796  }
1797 
1798  release_chunk_lock(c2, Vcb);
1799  }
1800 
1801  le2 = le2->Flink;
1802  }
1803 
1804  // allocate new chunk if necessary
1805  if (!done) {
1806  Status = alloc_chunk(Vcb, Vcb->data_flags, &newchunk, false);
1807 
1808  if (!NT_SUCCESS(Status)) {
1809  ERR("alloc_chunk returned %08lx\n", Status);
1810  ExReleaseResourceLite(&Vcb->chunk_lock);
1811  goto end;
1812  }
1813 
1814  acquire_chunk_lock(newchunk, Vcb);
1815 
1816  newchunk->balance_num = Vcb->balance.balance_num;
1817 
1818  if (!find_data_address_in_chunk(Vcb, newchunk, dr->size, &dr->new_address)) {
1819  release_chunk_lock(newchunk, Vcb);
1820  ExReleaseResourceLite(&Vcb->chunk_lock);
1821  ERR("could not find address in new chunk\n");
1823  goto end;
1824  } else {
1825  newchunk->used += dr->size;
1826  space_list_subtract(newchunk, false, dr->new_address, dr->size, &rollback);
1827  }
1828 
1829  release_chunk_lock(newchunk, Vcb);
1830  }
1831 
1832  ExReleaseResourceLite(&Vcb->chunk_lock);
1833  }
1834 
1835  dr->newchunk = newchunk;
1836 
1837  bmplen = (ULONG)(dr->size / Vcb->superblock.sector_size);
1838 
1839  bmparr = ExAllocatePoolWithTag(PagedPool, (ULONG)sector_align(bmplen + 1, sizeof(ULONG)), ALLOC_TAG);
1840  if (!bmparr) {
1841  ERR("out of memory\n");
1843  goto end;
1844  }
1845 
1846  csum = ExAllocatePoolWithTag(PagedPool, (ULONG)(dr->size * Vcb->csum_size / Vcb->superblock.sector_size), ALLOC_TAG);
1847  if (!csum) {
1848  ERR("out of memory\n");
1849  ExFreePool(bmparr);
1851  goto end;
1852  }
1853 
1854  RtlInitializeBitMap(&bmp, bmparr, bmplen);
1855  RtlSetAllBits(&bmp); // 1 = no csum, 0 = csum
1856 
1857  searchkey.obj_id = EXTENT_CSUM_ID;
1858  searchkey.obj_type = TYPE_EXTENT_CSUM;
1859  searchkey.offset = dr->address;
1860 
1861  Status = find_item(Vcb, Vcb->checksum_root, &tp, &searchkey, false, NULL);
1862  if (!NT_SUCCESS(Status) && Status != STATUS_NOT_FOUND) {
1863  ERR("find_item returned %08lx\n", Status);
1864  ExFreePool(csum);
1865  ExFreePool(bmparr);
1866  goto end;
1867  }
1868 
1869  if (Status != STATUS_NOT_FOUND) {
1870  do {
1871  traverse_ptr next_tp;
1872 
1873  if (tp.item->key.obj_type == TYPE_EXTENT_CSUM) {
1874  if (tp.item->key.offset >= dr->address + dr->size)
1875  break;
1876  else if (tp.item->size >= Vcb->csum_size && tp.item->key.offset + (tp.item->size * Vcb->superblock.sector_size / Vcb->csum_size) >= dr->address) {
1877  uint64_t cs = max(dr->address, tp.item->key.offset);
1878  uint64_t ce = min(dr->address + dr->size, tp.item->key.offset + (tp.item->size * Vcb->superblock.sector_size / Vcb->csum_size));
1879 
1880  RtlCopyMemory((uint8_t*)csum + ((cs - dr->address) * Vcb->csum_size / Vcb->superblock.sector_size),
1881  tp.item->data + ((cs - tp.item->key.offset) * Vcb->csum_size / Vcb->superblock.sector_size),
1882  (ULONG)((ce - cs) * Vcb->csum_size / Vcb->superblock.sector_size));
1883 
1884  RtlClearBits(&bmp, (ULONG)((cs - dr->address) / Vcb->superblock.sector_size), (ULONG)((ce - cs) / Vcb->superblock.sector_size));
1885 
1886  if (ce == dr->address + dr->size)
1887  break;
1888  }
1889  }
1890 
1891  if (find_next_item(Vcb, &tp, &next_tp, false, NULL))
1892  tp = next_tp;
1893  else
1894  break;
1895  } while (true);
1896  }
1897 
1898  lastoff = 0;
1899  runlength = RtlFindFirstRunClear(&bmp, &index);
1900 
1901  while (runlength != 0) {
1902  if (index >= bmplen)
1903  break;
1904 
1905  if (index + runlength >= bmplen) {
1906  runlength = bmplen - index;
1907 
1908  if (runlength == 0)
1909  break;
1910  }
1911 
1912  if (index > lastoff) {
1913  ULONG off = lastoff;
1914  ULONG size = index - lastoff;
1915 
1916  // handle no csum run
1917  do {
1918  ULONG rl;
1919 
1920  if (size * Vcb->superblock.sector_size > BALANCE_UNIT)
1921  rl = BALANCE_UNIT / Vcb->superblock.sector_size;
1922  else
1923  rl = size;
1924 
1925  Status = read_data(Vcb, dr->address + (off * Vcb->superblock.sector_size), rl * Vcb->superblock.sector_size, NULL, false, data,
1926  c, NULL, NULL, 0, false, NormalPagePriority);
1927  if (!NT_SUCCESS(Status)) {
1928  ERR("read_data returned %08lx\n", Status);
1929  ExFreePool(csum);
1930  ExFreePool(bmparr);
1931  goto end;
1932  }
1933 
1934  Status = write_data_complete(Vcb, dr->new_address + (off * Vcb->superblock.sector_size), data, rl * Vcb->superblock.sector_size,
1935  NULL, newchunk, false, 0, NormalPagePriority);
1936  if (!NT_SUCCESS(Status)) {
1937  ERR("write_data_complete returned %08lx\n", Status);
1938  ExFreePool(csum);
1939  ExFreePool(bmparr);
1940  goto end;
1941  }
1942 
1943  size -= rl;
1944  off += rl;
1945  } while (size > 0);
1946  }
1947 
1948  add_checksum_entry(Vcb, dr->new_address + (index * Vcb->superblock.sector_size), runlength, (uint8_t*)csum + (index * Vcb->csum_size), NULL);
1949  add_checksum_entry(Vcb, dr->address + (index * Vcb->superblock.sector_size), runlength, NULL, NULL);
1950 
1951  // handle csum run
1952  do {
1953  ULONG rl;
1954 
1955  if (runlength * Vcb->superblock.sector_size > BALANCE_UNIT)
1956  rl = BALANCE_UNIT / Vcb->superblock.sector_size;
1957  else
1958  rl = runlength;
1959 
1960  Status = read_data(Vcb, dr->address + (index * Vcb->superblock.sector_size), rl * Vcb->superblock.sector_size,
1961  (uint8_t*)csum + (index * Vcb->csum_size), false, data, c, NULL, NULL, 0, false, NormalPagePriority);
1962  if (!NT_SUCCESS(Status)) {
1963  ERR("read_data returned %08lx\n", Status);
1964  ExFreePool(csum);
1965  ExFreePool(bmparr);
1966  goto end;
1967  }
1968 
1969  Status = write_data_complete(Vcb, dr->new_address + (index * Vcb->superblock.sector_size), data, rl * Vcb->superblock.sector_size,
1970  NULL, newchunk, false, 0, NormalPagePriority);
1971  if (!NT_SUCCESS(Status)) {
1972  ERR("write_data_complete returned %08lx\n", Status);
1973  ExFreePool(csum);
1974  ExFreePool(bmparr);
1975  goto end;
1976  }
1977 
1978  runlength -= rl;
1979  index += rl;
1980  } while (runlength > 0);
1981 
1982  lastoff = index;
1983  runlength = RtlFindNextForwardRunClear(&bmp, index, &index);
1984  }
1985 
1986  ExFreePool(csum);
1987  ExFreePool(bmparr);
1988 
1989  // handle final nocsum run
1990  if (lastoff < dr->size / Vcb->superblock.sector_size) {
1991  ULONG off = lastoff;
1992  ULONG size = (ULONG)((dr->size / Vcb->superblock.sector_size) - lastoff);
1993 
1994  do {
1995  ULONG rl;
1996 
1997  if (size * Vcb->superblock.sector_size > BALANCE_UNIT)
1998  rl = BALANCE_UNIT / Vcb->superblock.sector_size;
1999  else
2000  rl = size;
2001 
2002  Status = read_data(Vcb, dr->address + (off * Vcb->superblock.sector_size), rl * Vcb->superblock.sector_size, NULL, false, data,
2003  c, NULL, NULL, 0, false, NormalPagePriority);
2004  if (!NT_SUCCESS(Status)) {
2005  ERR("read_data returned %08lx\n", Status);
2006  goto end;
2007  }
2008 
2009  Status = write_data_complete(Vcb, dr->new_address + (off * Vcb->superblock.sector_size), data, rl * Vcb->superblock.sector_size,
2010  NULL, newchunk, false, 0, NormalPagePriority);
2011  if (!NT_SUCCESS(Status)) {
2012  ERR("write_data_complete returned %08lx\n", Status);
2013  goto end;
2014  }
2015 
2016  size -= rl;
2017  off += rl;
2018  } while (size > 0);
2019  }
2020 
2021  le = le->Flink;
2022  }
2023 
2024  ExFreePool(data);
2025  data = NULL;
2026 
2027  Status = write_metadata_items(Vcb, &metadata_items, &items, NULL, &rollback);
2028  if (!NT_SUCCESS(Status)) {
2029  ERR("write_metadata_items returned %08lx\n", Status);
2030  goto end;
2031  }
2032 
2033  le = items.Flink;
2034  while (le != &items) {
2036 
2038  if (!NT_SUCCESS(Status)) {
2039  ERR("add_data_reloc_extent_item returned %08lx\n", Status);
2040  goto end;
2041  }
2042 
2043  le = le->Flink;
2044  }
2045 
2046  le = c->changed_extents.Flink;
2047  while (le != &c->changed_extents) {
2048  LIST_ENTRY *le2, *le3;
2050 
2051  le3 = le->Flink;
2052 
2053  le2 = items.Flink;
2054  while (le2 != &items) {
2056 
2057  if (ce->address == dr->address) {
2058  ce->address = dr->new_address;
2061  break;
2062  }
2063 
2064  le2 = le2->Flink;
2065  }
2066 
2067  le = le3;
2068  }
2069 
2071 
2072  Vcb->need_write = true;
2073 
2074 end:
2075  if (NT_SUCCESS(Status)) {
2076  // update extents in cache inodes before we flush
2077  le = Vcb->chunks.Flink;
2078  while (le != &Vcb->chunks) {
2080 
2081  if (c2->cache) {
2082  LIST_ENTRY* le2;
2083 
2084  ExAcquireResourceExclusiveLite(c2->cache->Header.Resource, true);
2085 
2086  le2 = c2->cache->extents.Flink;
2087  while (le2 != &c2->cache->extents) {
2089 
2090  if (!ext->ignore) {
2091  if (ext->extent_data.type == EXTENT_TYPE_REGULAR || ext->extent_data.type == EXTENT_TYPE_PREALLOC) {
2092  EXTENT_DATA2* ed2 = (EXTENT_DATA2*)ext->extent_data.data;
2093 
2094  if (ed2->size > 0 && ed2->address >= c->offset && ed2->address < c->offset + c->chunk_item->size) {
2095  LIST_ENTRY* le3 = items.Flink;
2096  while (le3 != &items) {
2098 
2099  if (ed2->address == dr->address) {
2100  ed2->address = dr->new_address;
2101  break;
2102  }
2103 
2104  le3 = le3->Flink;
2105  }
2106  }
2107  }
2108  }
2109 
2110  le2 = le2->Flink;
2111  }
2112 
2113  ExReleaseResourceLite(c2->cache->Header.Resource);
2114  }
2115 
2116  le = le->Flink;
2117  }
2118 
2119  Status = do_write(Vcb, NULL);
2120  if (!NT_SUCCESS(Status))
2121  ERR("do_write returned %08lx\n", Status);
2122  }
2123 
2124  if (NT_SUCCESS(Status)) {
2126 
2127  // update open FCBs
2128  // FIXME - speed this up(?)
2129 
2130  le = Vcb->all_fcbs.Flink;
2131  while (le != &Vcb->all_fcbs) {
2132  struct _fcb* fcb = CONTAINING_RECORD(le, struct _fcb, list_entry_all);
2133  LIST_ENTRY* le2;
2134 
2135  ExAcquireResourceExclusiveLite(fcb->Header.Resource, true);
2136 
2137  le2 = fcb->extents.Flink;
2138  while (le2 != &fcb->extents) {
2140 
2141  if (!ext->ignore) {
2142  if (ext->extent_data.type == EXTENT_TYPE_REGULAR || ext->extent_data.type == EXTENT_TYPE_PREALLOC) {
2143  EXTENT_DATA2* ed2 = (EXTENT_DATA2*)ext->extent_data.data;
2144 
2145  if (ed2->size > 0 && ed2->address >= c->offset && ed2->address < c->offset + c->chunk_item->size) {
2146  LIST_ENTRY* le3 = items.Flink;
2147  while (le3 != &items) {
2149 
2150  if (ed2->address == dr->address) {
2151  ed2->address = dr->new_address;
2152  break;
2153  }
2154 
2155  le3 = le3->Flink;
2156  }
2157  }
2158  }
2159  }
2160 
2161  le2 = le2->Flink;
2162  }
2163 
2164  ExReleaseResourceLite(fcb->Header.Resource);
2165 
2166  le = le->Flink;
2167  }
2168  } else
2170 
2171  free_trees(Vcb);
2172 
2173  ExReleaseResourceLite(&Vcb->tree_lock);
2174 
2175  if (data)
2176  ExFreePool(data);
2177 
2178  while (!IsListEmpty(&items)) {
2180 
2181  while (!IsListEmpty(&dr->refs)) {
2183 
2184  ExFreePool(ref);
2185  }
2186 
2187  ExFreePool(dr);
2188  }
2189 
2190  while (!IsListEmpty(&metadata_items)) {
2192 
2193  while (!IsListEmpty(&mr->refs)) {
2195 
2196  ExFreePool(ref);
2197  }
2198 
2199  if (mr->data)
2200  ExFreePool(mr->data);
2201 
2202  ExFreePool(mr);
2203  }
2204 
2205  return Status;
2206 }
uint64_t obj_id
Definition: btrfs.h:137
void do_rollback(device_extension *Vcb, LIST_ENTRY *rollback)
Definition: treefuncs.c:1050
void clear_rollback(LIST_ENTRY *rollback)
Definition: treefuncs.c:1029
#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
LIST_ENTRY list_entry
Definition: btrfs_drv.h:615
void space_list_subtract(chunk *c, bool deleting, uint64_t address, uint64_t length, LIST_ENTRY *rollback)
Definition: free-space.c:2047
EXTENT_DATA2 * ed2
Definition: write.c:2805
NTSTATUS write_data_complete(device_extension *Vcb, uint64_t address, void *data, uint32_t length, PIRP Irp, chunk *c, bool file_write, uint64_t irp_offset, ULONG priority)
Definition: write.c:2182
NTSTATUS do_write(device_extension *Vcb, PIRP Irp)
Definition: flushthread.c:7789
NTSYSAPI void WINAPI RtlInitializeBitMap(PRTL_BITMAP, PULONG, ULONG)
LONG NTSTATUS
Definition: precomp.h:26
uint16_t size
Definition: btrfs_drv.h:430
release_chunk_lock(c, Vcb)
uint64_t used
Definition: btrfs_drv.h:574
GLuint GLuint end
Definition: gl.h:1545
bool readonly
Definition: btrfs_drv.h:589
tree_header * data
Definition: balance.c:26
#define InsertTailList(ListHead, Entry)
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
Definition: send.c:48
uint64_t offset
Definition: btrfs.h:139
uint8_t * data
Definition: btrfs_drv.h:431
LIST_ENTRY list_entry_all
Definition: btrfs_drv.h:348
#define TYPE_EXTENT_CSUM
Definition: btrfs.h:27
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
#define ALLOC_TAG
Definition: btrfs_drv.h:91
uint64_t size
Definition: btrfs.h:328
uint32_t cs
Definition: isohybrid.c:75
uint64_t address
Definition: btrfs.h:356
uint64_t new_address
Definition: balance.c:51
NTSYSAPI void WINAPI RtlSetAllBits(PRTL_BITMAP)
LIST_ENTRY refs
Definition: balance.c:54
chunk * newchunk
Definition: balance.c:52
smooth NULL
Definition: ftsmooth.c:416
char ext[3]
Definition: mkdosfs.c:358
#define TYPE_EXTENT_ITEM
Definition: btrfs.h:31
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
uint64_t size
Definition: btrfs.h:357
bool reloc
Definition: btrfs_drv.h:590
GLuint index
Definition: glext.h:6031
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
#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
FSRTL_ADVANCED_FCB_HEADER Header
Definition: btrfs_drv.h:294
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#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:1415
static NTSTATUS add_data_reloc_extent_item(_Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, data_reloc *dr)
Definition: balance.c:1545
const GLubyte * c
Definition: glext.h:8905
LIST_ENTRY extents
Definition: btrfs_drv.h:311
static NTSTATUS add_data_reloc(_Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, LIST_ENTRY *items, LIST_ENTRY *metadata_items, traverse_ptr *tp, chunk *c, LIST_ENTRY *rollback)
Definition: balance.c:1320
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
BOOL loaded
Definition: xmlview.c:54
BITMAP bmp
Definition: alphablend.c:62
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
tree_data * item
Definition: btrfs_drv.h:518
Status
Definition: gdiplustypes.h:24
#define index(s, c)
Definition: various.h:29
LIST_ENTRY changed_extents
Definition: btrfs_drv.h:582
void add_checksum_entry(device_extension *Vcb, uint64_t address, ULONG length, void *csum, PIRP Irp)
Definition: flushthread.c:2595
Definition: typedefs.h:119
#define EXTENT_TYPE_PREALLOC
Definition: btrfs.h:72
BYTE uint8_t
Definition: msvideo1.c:66
#define BALANCE_UNIT
Definition: balance.c:75
#define EXTENT_TYPE_REGULAR
Definition: btrfs.h:71
#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 acquire_chunk_lock(c, Vcb)
Definition: btrfs_drv.h:1137
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
NTSYSAPI ULONG NTAPI RtlFindFirstRunClear(_In_ PRTL_BITMAP BitMapHeader, _Out_ PULONG StartingIndex)
#define min(a, b)
Definition: monoChain.cc:55
Definition: list.h:27
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY * rollback
Definition: btrfs_drv.h:1357
uint64_t address
Definition: btrfs_drv.h:606
CHUNK_ITEM * chunk_item
Definition: btrfs_drv.h:571
NTSYSAPI ULONG WINAPI RtlFindNextForwardRunClear(PCRTL_BITMAP, ULONG, PULONG)
Definition: fs.h:216
bool find_data_address_in_chunk(device_extension *Vcb, chunk *c, uint64_t length, uint64_t *address)
ULONG balance_num
Definition: btrfs_drv.h:599
#define STATUS_DISK_FULL
Definition: udferr_usr.h:155
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
static NTSTATUS write_metadata_items(_Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, LIST_ENTRY *items, LIST_ENTRY *data_items, chunk *c, LIST_ENTRY *rollback)
Definition: balance.c:570
uint64_t flags
Definition: btrfs.h:382
NTSTATUS alloc_chunk(device_extension *Vcb, uint64_t flags, chunk **pc, bool full_size)
Definition: write.c:361
uint64_t type
Definition: btrfs.h:331
static TCHAR * items[]
Definition: page1.c:45
return STATUS_SUCCESS
Definition: btrfs.c:3014
fcb * cache
Definition: btrfs_drv.h:577
static uint64_t __inline sector_align(uint64_t n, uint64_t a)
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
void * csum
Definition: write.c:2807
uint64_t size
Definition: balance.c:50
off
Definition: i386-dis.c:3909
LIST_ENTRY refs
Definition: balance.c:30
uint64_t address
Definition: balance.c:49

Referenced by _Function_class_(), and try_consolidation().

◆ balance_metadata_chunk()

static NTSTATUS balance_metadata_chunk ( device_extension Vcb,
chunk c,
bool changed 
)
static

Definition at line 1104 of file balance.c.

1104  {
1105  KEY searchkey;
1106  traverse_ptr tp;
1107  NTSTATUS Status;
1108  bool b;
1110  uint32_t loaded = 0;
1111 
1112  TRACE("chunk %I64x\n", c->offset);
1113 
1116 
1117  ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
1118 
1119  searchkey.obj_id = c->offset;
1120  searchkey.obj_type = TYPE_METADATA_ITEM;
1121  searchkey.offset = 0xffffffffffffffff;
1122 
1123  Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, false, NULL);
1124  if (!NT_SUCCESS(Status)) {
1125  ERR("find_item returned %08lx\n", Status);
1126  goto end;
1127  }
1128 
1129  do {
1130  traverse_ptr next_tp;
1131 
1132  if (tp.item->key.obj_id >= c->offset + c->chunk_item->size)
1133  break;
1134 
1135  if (tp.item->key.obj_id >= c->offset && (tp.item->key.obj_type == TYPE_EXTENT_ITEM || tp.item->key.obj_type == TYPE_METADATA_ITEM)) {
1136  bool tree = false, skinny = false;
1137 
1138  if (tp.item->key.obj_type == TYPE_METADATA_ITEM && tp.item->size >= sizeof(EXTENT_ITEM)) {
1139  tree = true;
1140  skinny = true;
1141  } else if (tp.item->key.obj_type == TYPE_EXTENT_ITEM && tp.item->key.offset == Vcb->superblock.node_size &&
1142  tp.item->size >= sizeof(EXTENT_ITEM)) {
1143  EXTENT_ITEM* ei = (EXTENT_ITEM*)tp.item->data;
1144 
1146  tree = true;
1147  }
1148 
1149  if (tree) {
1150  Status = add_metadata_reloc(Vcb, &items, &tp, skinny, NULL, c, &rollback);
1151 
1152  if (!NT_SUCCESS(Status)) {
1153  ERR("add_metadata_reloc returned %08lx\n", Status);
1154  goto end;
1155  }
1156 
1157  loaded++;
1158 
1159  if (loaded >= 64) // only do 64 at a time
1160  break;
1161  }
1162  }
1163 
1164  b = find_next_item(Vcb, &tp, &next_tp, false, NULL);
1165 
1166  if (b)
1167  tp = next_tp;
1168  } while (b);
1169 
1170  if (IsListEmpty(&items)) {
1171  *changed = false;
1173  goto end;
1174  } else
1175  *changed = true;
1176 
1178  if (!NT_SUCCESS(Status)) {
1179  ERR("write_metadata_items returned %08lx\n", Status);
1180  goto end;
1181  }
1182 
1184 
1185  Vcb->need_write = true;
1186 
1187 end:
1188  if (NT_SUCCESS(Status)) {
1189  Status = do_write(Vcb, NULL);
1190  if (!NT_SUCCESS(Status))
1191  ERR("do_write returned %08lx\n", Status);
1192  }
1193 
1194  if (NT_SUCCESS(Status))
1196  else
1198 
1199  free_trees(Vcb);
1200 
1201  ExReleaseResourceLite(&Vcb->tree_lock);
1202 
1203  while (!IsListEmpty(&items)) {
1205 
1206  while (!IsListEmpty(&mr->refs)) {
1208 
1209  ExFreePool(ref);
1210  }
1211 
1212  if (mr->data)
1213  ExFreePool(mr->data);
1214 
1215  ExFreePool(mr);
1216  }
1217 
1218  return Status;
1219 }
uint64_t obj_id
Definition: btrfs.h:137
void do_rollback(device_extension *Vcb, LIST_ENTRY *rollback)
Definition: treefuncs.c:1050
void clear_rollback(LIST_ENTRY *rollback)
Definition: treefuncs.c:1029
uint8_t obj_type
Definition: btrfs.h:138
static NTSTATUS add_metadata_reloc(_Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, LIST_ENTRY *items, traverse_ptr *tp, bool skinny, metadata_reloc **mr2, chunk *c, LIST_ENTRY *rollback)
Definition: balance.c:77
NTSTATUS do_write(device_extension *Vcb, PIRP Irp)
Definition: flushthread.c:7789
LONG NTSTATUS
Definition: precomp.h:26
uint16_t size
Definition: btrfs_drv.h:430
GLuint GLuint end
Definition: gl.h:1545
tree_header * data
Definition: balance.c:26
#define TYPE_METADATA_ITEM
Definition: btrfs.h:32
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
Definition: send.c:48
uint64_t offset
Definition: btrfs.h:139
uint8_t * data
Definition: btrfs_drv.h:431
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
smooth NULL
Definition: ftsmooth.c:416
#define TYPE_EXTENT_ITEM
Definition: btrfs.h:31
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
#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
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:1415
const GLubyte * c
Definition: glext.h:8905
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
BOOL loaded
Definition: xmlview.c:54
tree_data * item
Definition: btrfs_drv.h:518
Status
Definition: gdiplustypes.h:24
Definition: typedefs.h:119
#define ERR(fmt,...)
Definition: debug.h:110
Definition: btrfs.h:136
#define EXTENT_ITEM_TREE_BLOCK
Definition: btrfs.h:376
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
Definition: list.h:27
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY * rollback
Definition: btrfs_drv.h:1357
UINT32 uint32_t
Definition: types.h:75
static NTSTATUS write_metadata_items(_Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, LIST_ENTRY *items, LIST_ENTRY *data_items, chunk *c, LIST_ENTRY *rollback)
Definition: balance.c:570
uint64_t flags
Definition: btrfs.h:382
static TCHAR * items[]
Definition: page1.c:45
return STATUS_SUCCESS
Definition: btrfs.c:3014
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
LIST_ENTRY refs
Definition: balance.c:30

Referenced by _Function_class_().

◆ copy_balance_args()

static void copy_balance_args ( btrfs_balance_opts opts,
BALANCE_ARGS args 
)
static

Definition at line 2322 of file balance.c.

2322  {
2323  if (opts->flags & BTRFS_BALANCE_OPTS_PROFILES) {
2324  args->profiles = opts->profiles;
2326  }
2327 
2328  if (opts->flags & BTRFS_BALANCE_OPTS_USAGE) {
2329  if (args->usage_start == 0) {
2331  args->usage_start = opts->usage_start;
2332  args->usage_end = opts->usage_end;
2333  } else {
2334  args->flags |= BALANCE_ARGS_FLAGS_USAGE;
2335  args->usage = opts->usage_end;
2336  }
2337  }
2338 
2339  if (opts->flags & BTRFS_BALANCE_OPTS_DEVID) {
2340  args->devid = opts->devid;
2341  args->flags |= BALANCE_ARGS_FLAGS_DEVID;
2342  }
2343 
2344  if (opts->flags & BTRFS_BALANCE_OPTS_DRANGE) {
2345  args->drange_start = opts->drange_start;
2346  args->drange_end = opts->drange_end;
2347  args->flags |= BALANCE_ARGS_FLAGS_DRANGE;
2348  }
2349 
2350  if (opts->flags & BTRFS_BALANCE_OPTS_VRANGE) {
2351  args->vrange_start = opts->vrange_start;
2352  args->vrange_end = opts->vrange_end;
2353  args->flags |= BALANCE_ARGS_FLAGS_VRANGE;
2354  }
2355 
2356  if (opts->flags & BTRFS_BALANCE_OPTS_CONVERT) {
2357  args->convert = opts->convert;
2358  args->flags |= BALANCE_ARGS_FLAGS_CONVERT;
2359 
2360  if (opts->flags & BTRFS_BALANCE_OPTS_SOFT)
2361  args->flags |= BALANCE_ARGS_FLAGS_SOFT;
2362  }
2363 
2364  if (opts->flags & BTRFS_BALANCE_OPTS_LIMIT) {
2365  if (args->limit_start == 0) {
2367  args->limit_start = (uint32_t)opts->limit_start;
2368  args->limit_end = (uint32_t)opts->limit_end;
2369  } else {
2370  args->flags |= BALANCE_ARGS_FLAGS_LIMIT;
2371  args->limit = opts->limit_end;
2372  }
2373  }
2374 
2375  if (opts->flags & BTRFS_BALANCE_OPTS_STRIPES) {
2376  args->stripes_start = opts->stripes_start;
2377  args->stripes_end = opts->stripes_end;
2379  }
2380 }
#define BALANCE_ARGS_FLAGS_DRANGE
Definition: btrfs.h:471
#define BALANCE_ARGS_FLAGS_LIMIT_RANGE
Definition: btrfs.h:474
#define BTRFS_BALANCE_OPTS_PROFILES
Definition: btrfsioctl.h:130
#define BALANCE_ARGS_FLAGS_VRANGE
Definition: btrfs.h:472
#define BALANCE_ARGS_FLAGS_STRIPES_RANGE
Definition: btrfs.h:475
#define BALANCE_ARGS_FLAGS_PROFILES
Definition: btrfs.h:468
#define BALANCE_ARGS_FLAGS_LIMIT
Definition: btrfs.h:473
uint16_t stripes_end
Definition: btrfsioctl.h:153
#define BTRFS_BALANCE_OPTS_VRANGE
Definition: btrfsioctl.h:133
Definition: match.c:390
#define BALANCE_ARGS_FLAGS_USAGE_RANGE
Definition: btrfs.h:478
uint64_t limit_start
Definition: btrfsioctl.h:150
#define BALANCE_ARGS_FLAGS_SOFT
Definition: btrfs.h:477
#define BTRFS_BALANCE_OPTS_USAGE
Definition: btrfsioctl.h:136
uint64_t vrange_start
Definition: btrfsioctl.h:148
#define BTRFS_BALANCE_OPTS_CONVERT
Definition: btrfsioctl.h:137
#define BTRFS_BALANCE_OPTS_SOFT
Definition: btrfsioctl.h:138
uint64_t limit_end
Definition: btrfsioctl.h:151
#define BALANCE_ARGS_FLAGS_CONVERT
Definition: btrfs.h:476
uint64_t drange_end
Definition: btrfsioctl.h:147
#define BTRFS_BALANCE_OPTS_LIMIT
Definition: btrfsioctl.h:134
#define BTRFS_BALANCE_OPTS_DRANGE
Definition: btrfsioctl.h:132
uint16_t stripes_start
Definition: btrfsioctl.h:152
#define BALANCE_ARGS_FLAGS_USAGE
Definition: btrfs.h:469
uint64_t vrange_end
Definition: btrfsioctl.h:149
uint64_t drange_start
Definition: btrfsioctl.h:146
#define BALANCE_ARGS_FLAGS_DEVID
Definition: btrfs.h:470
UINT32 uint32_t
Definition: types.h:75
#define BTRFS_BALANCE_OPTS_DEVID
Definition: btrfsioctl.h:131
#define uint32_t
Definition: nsiface.idl:61
#define BTRFS_BALANCE_OPTS_STRIPES
Definition: btrfsioctl.h:135

Referenced by add_balance_item().

◆ data_reloc_add_tree_edr()

static NTSTATUS data_reloc_add_tree_edr ( _Requires_lock_held_(_Curr_->tree_lock) device_extension Vcb,
LIST_ENTRY metadata_items,
data_reloc dr,
EXTENT_DATA_REF edr,
LIST_ENTRY rollback 
)
static

Definition at line 1221 of file balance.c.

1222  {
1223  NTSTATUS Status;
1224  LIST_ENTRY* le;
1225  KEY searchkey;
1226  traverse_ptr tp;
1227  root* r = NULL;
1228  metadata_reloc* mr;
1229  uint64_t last_tree = 0;
1231 
1232  le = Vcb->roots.Flink;
1233  while (le != &Vcb->roots) {
1235 
1236  if (r2->id == edr->root) {
1237  r = r2;
1238  break;
1239  }
1240 
1241  le = le->Flink;
1242  }
1243 
1244  if (!r) {
1245  ERR("could not find subvol %I64x\n", edr->root);
1246  return STATUS_INTERNAL_ERROR;
1247  }
1248 
1249  searchkey.obj_id = edr->objid;
1250  searchkey.obj_type = TYPE_EXTENT_DATA;
1251  searchkey.offset = 0;
1252 
1253  Status = find_item(Vcb, r, &tp, &searchkey, false, NULL);
1254  if (!NT_SUCCESS(Status)) {
1255  ERR("find_item returned %08lx\n", Status);
1256  return Status;
1257  }
1258 
1259  if (tp.item->key.obj_id < searchkey.obj_id || (tp.item->key.obj_id == searchkey.obj_id && tp.item->key.obj_type < searchkey.obj_type)) {
1260  traverse_ptr tp2;
1261 
1262  if (find_next_item(Vcb, &tp, &tp2, false, NULL))
1263  tp = tp2;
1264  else {
1265  ERR("could not find EXTENT_DATA for inode %I64x in root %I64x\n", searchkey.obj_id, r->id);
1266  return STATUS_INTERNAL_ERROR;
1267  }
1268  }
1269 
1270  ref = NULL;
1271 
1272  while (tp.item->key.obj_id == searchkey.obj_id && tp.item->key.obj_type == searchkey.obj_type) {
1273  traverse_ptr tp2;
1274 
1275  if (tp.item->size >= sizeof(EXTENT_DATA)) {
1277 
1280 
1281  if (ed2->address == dr->address && ed2->size == dr->size && tp.item->key.offset - ed2->offset == edr->offset) {
1282  if (ref && last_tree == tp.tree->header.address)
1283  ref->edr.count++;
1284  else {
1286  if (!ref) {
1287  ERR("out of memory\n");
1289  }
1290 
1291  ref->type = TYPE_EXTENT_DATA_REF;
1292  RtlCopyMemory(&ref->edr, edr, sizeof(EXTENT_DATA_REF));
1293  ref->edr.count = 1;
1294 
1295  Status = add_metadata_reloc_parent(Vcb, metadata_items, tp.tree->header.address, &mr, rollback);
1296  if (!NT_SUCCESS(Status)) {
1297  ERR("add_metadata_reloc_parent returned %08lx\n", Status);
1298  ExFreePool(ref);
1299  return Status;
1300  }
1301 
1302  last_tree = tp.tree->header.address;
1303  ref->parent = mr;
1304 
1305  InsertTailList(&dr->refs, &ref->list_entry);
1306  }
1307  }
1308  }
1309  }
1310 
1311  if (find_next_item(Vcb, &tp, &tp2, false, NULL))
1312  tp = tp2;
1313  else
1314  break;
1315  }
1316 
1317  return STATUS_SUCCESS;
1318 }
uint64_t obj_id
Definition: btrfs.h:137
uint8_t type
Definition: btrfs.h:351
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
EXTENT_DATA2 * ed2
Definition: write.c:2805
uint64_t offset
Definition: btrfs.h:407
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
LONG NTSTATUS
Definition: precomp.h:26
uint64_t objid
Definition: btrfs.h:406
uint16_t size
Definition: btrfs_drv.h:430
#define InsertTailList(ListHead, Entry)
LIST_ENTRY list_entry
Definition: send.c:49
Definition: send.c:48
uint64_t offset
Definition: btrfs.h:139
uint8_t * data
Definition: btrfs_drv.h:431
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
#define ALLOC_TAG
Definition: btrfs_drv.h:91
uint64_t address
Definition: btrfs.h:149
tree * tree
Definition: btrfs_drv.h:517
uint64_t address
Definition: btrfs.h:356
GLenum GLint ref
Definition: glext.h:6028
LIST_ENTRY refs
Definition: balance.c:54
smooth NULL
Definition: ftsmooth.c:416
#define offsetof(TYPE, MEMBER)
uint64_t size
Definition: btrfs.h:357
uint64_t root
Definition: btrfs.h:405
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
#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
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
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:1415
static DNS_RECORDW r2
Definition: record.c:38
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
Status
Definition: gdiplustypes.h:24
tree_header header
Definition: btrfs_drv.h:442
Definition: typedefs.h:119
static NTSTATUS add_metadata_reloc_parent(_Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, LIST_ENTRY *items, uint64_t address, metadata_reloc **mr2, LIST_ENTRY *rollback)
Definition: balance.c:230
#define EXTENT_TYPE_PREALLOC
Definition: btrfs.h:72
#define EXTENT_TYPE_REGULAR
Definition: btrfs.h:71
#define ERR(fmt,...)
Definition: debug.h:110
uint8_t data[1]
Definition: btrfs.h:352
Definition: btrfs.h:136
UINT64 uint64_t
Definition: types.h:77
Definition: list.h:27
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY * rollback
Definition: btrfs_drv.h:1357
uint64_t offset
Definition: btrfs.h:358
#define TYPE_EXTENT_DATA
Definition: btrfs.h:26
return STATUS_SUCCESS
Definition: btrfs.c:3014
EXTENT_DATA * ed
Definition: write.c:2804
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
uint64_t size
Definition: balance.c:50
uint64_t address
Definition: balance.c:49

Referenced by add_data_reloc().

◆ finish_removing_device()

static NTSTATUS finish_removing_device ( _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension Vcb,
device dev 
)
static

Definition at line 2590 of file balance.c.

2590  {
2591  KEY searchkey;
2592  traverse_ptr tp;
2593  NTSTATUS Status;
2594  LIST_ENTRY* le;
2596 
2597  if (Vcb->need_write) {
2598  Status = do_write(Vcb, NULL);
2599 
2600  if (!NT_SUCCESS(Status))
2601  ERR("do_write returned %08lx\n", Status);
2602  } else
2604 
2605  free_trees(Vcb);
2606 
2607  if (!NT_SUCCESS(Status))
2608  return Status;
2609 
2610  // remove entry in chunk tree
2611 
2612  searchkey.obj_id = 1;
2613  searchkey.obj_type = TYPE_DEV_ITEM;
2614  searchkey.offset = dev->devitem.dev_id;
2615 
2616  Status = find_item(Vcb, Vcb->chunk_root, &tp, &searchkey, false, NULL);
2617  if (!NT_SUCCESS(Status)) {
2618  ERR("find_item returned %08lx\n", Status);
2619  return Status;
2620  }
2621 
2622  if (!keycmp(searchkey, tp.item->key)) {
2624 
2625  if (!NT_SUCCESS(Status)) {
2626  ERR("delete_tree_item returned %08lx\n", Status);
2627  return Status;
2628  }
2629  }
2630 
2631  // remove stats entry in device tree
2632 
2633  searchkey.obj_id = 0;
2634  searchkey.obj_type = TYPE_DEV_STATS;
2635  searchkey.offset = dev->devitem.dev_id;
2636 
2637  Status = find_item(Vcb, Vcb->dev_root, &tp, &searchkey, false, NULL);
2638  if (!NT_SUCCESS(Status)) {
2639  ERR("find_item returned %08lx\n", Status);
2640  return Status;
2641  }
2642 
2643  if (!keycmp(searchkey, tp.item->key)) {
2645 
2646  if (!NT_SUCCESS(Status)) {
2647  ERR("delete_tree_item returned %08lx\n", Status);
2648  return Status;
2649  }
2650  }
2651 
2652  // update superblock
2653 
2654  Vcb->superblock.num_devices--;
2655  Vcb->superblock.total_bytes -= dev->devitem.num_bytes;
2656  Vcb->devices_loaded--;
2657 
2658  RemoveEntryList(&dev->list_entry);
2659 
2660  // flush
2661 
2662  Status = do_write(Vcb, NULL);
2663  if (!NT_SUCCESS(Status))
2664  ERR("do_write returned %08lx\n", Status);
2665 
2666  free_trees(Vcb);
2667 
2668  if (!NT_SUCCESS(Status))
2669  return Status;
2670 
2671  if (!dev->readonly && dev->devobj) {
2673  if (!NT_SUCCESS(Status))
2674  WARN("remove_superblocks returned %08lx\n", Status);
2675  }
2676 
2677  // remove entry in volume list
2678 
2679  vde = Vcb->vde;
2680 
2681  if (dev->devobj) {
2682  pdo_device_extension* pdode = vde->pdode;
2683 
2685 
2686  le = pdode->children.Flink;
2687  while (le != &pdode->children) {
2689 
2690  if (RtlCompareMemory(&dev->devitem.device_uuid, &vc->uuid, sizeof(BTRFS_UUID)) == sizeof(BTRFS_UUID)) {
2693  UNICODE_STRING mmdevpath;
2694 
2695  pdode->children_loaded--;
2696 
2697  if (vc->had_drive_letter) { // re-add entry to mountmgr
2700  if (!NT_SUCCESS(Status))
2701  ERR("IoGetDeviceObjectPointer returned %08lx\n", Status);
2702  else {
2703  MOUNTDEV_NAME mdn;
2704 
2705  Status = dev_ioctl(dev->devobj, IOCTL_MOUNTDEV_QUERY_DEVICE_NAME, NULL, 0, &mdn, sizeof(MOUNTDEV_NAME), true, NULL);
2707  ERR("IOCTL_MOUNTDEV_QUERY_DEVICE_NAME returned %08lx\n", Status);
2708  else {
2709  MOUNTDEV_NAME* mdn2;
2710  ULONG mdnsize = (ULONG)offsetof(MOUNTDEV_NAME, Name[0]) + mdn.NameLength;
2711 
2712  mdn2 = ExAllocatePoolWithTag(PagedPool, mdnsize, ALLOC_TAG);
2713  if (!mdn2)
2714  ERR("out of memory\n");
2715  else {
2716  Status = dev_ioctl(dev->devobj, IOCTL_MOUNTDEV_QUERY_DEVICE_NAME, NULL, 0, mdn2, mdnsize, true, NULL);
2717  if (!NT_SUCCESS(Status))
2718  ERR("IOCTL_MOUNTDEV_QUERY_DEVICE_NAME returned %08lx\n", Status);
2719  else {
2721 
2722  name.Buffer = mdn2->Name;
2723  name.Length = name.MaximumLength = mdn2->NameLength;
2724 
2726  if (!NT_SUCCESS(Status))
2727  WARN("mountmgr_add_drive_letter returned %08lx\n", Status);
2728  }
2729 
2730  ExFreePool(mdn2);
2731  }
2732  }
2733 
2735  }
2736  }
2737 
2738  ExFreePool(vc->pnp_name.Buffer);
2740  ExFreePool(vc);
2741 
2743 
2744  break;
2745  }
2746 
2747  le = le->Flink;
2748  }
2749 
2750  if (pdode->children_loaded > 0 && vde->device->Characteristics & FILE_REMOVABLE_MEDIA) {
2751  vde->device->Characteristics &= ~FILE_REMOVABLE_MEDIA;
2752 
2753  le = pdode->children.Flink;
2754  while (le != &pdode->children) {
2756 
2757  if (vc->devobj->Characteristics & FILE_REMOVABLE_MEDIA) {
2758  vde->device->Characteristics |= FILE_REMOVABLE_MEDIA;
2759  break;
2760  }
2761 
2762  le = le->Flink;
2763  }
2764  }
2765 
2766  pdode->num_children = Vcb->superblock.num_devices;
2767 
2769 
2770  // free dev
2771 
2772  if (dev->trim && !dev->readonly && !Vcb->options.no_trim)
2774  }
2775 
2776  while (!IsListEmpty(&dev->space)) {
2777  LIST_ENTRY* le2 = RemoveHeadList(&dev->space);
2779 
2780  ExFreePool(s);
2781  }
2782 
2783  ExFreePool(dev);
2784 
2785  if (Vcb->trim) {
2786  Vcb->trim = false;
2787 
2788  le = Vcb->devices.Flink;
2789  while (le != &Vcb->devices) {
2790  device* dev2 = CONTAINING_RECORD(le, device, list_entry);
2791 
2792  if (dev2->trim) {
2793  Vcb->trim = true;
2794  break;
2795  }
2796 
2797  le = le->Flink;
2798  }
2799  }
2800 
2802 
2803  return STATUS_SUCCESS;
2804 }
uint64_t obj_id
Definition: btrfs.h:137
#define TYPE_DEV_ITEM
Definition: btrfs.h:43
UNICODE_STRING pnp_name
Definition: btrfs_drv.h:867
void trim_whole_device(device *dev)
Definition: fsctl.c:2710
uint8_t obj_type
Definition: btrfs.h:138
#define TYPE_DEV_STATS
Definition: btrfs.h:46
NTSTATUS do_write(device_extension *Vcb, PIRP Irp)
Definition: flushthread.c:7789
PDEVICE_OBJECT device
Definition: btrfs_drv.h:883
#define keycmp(key1, key2)
Definition: btrfs_drv.h:1024
#define WARN(fmt,...)
Definition: debug.h:112
LONG NTSTATUS
Definition: precomp.h:26
NTSTATUS NTAPI IoGetDeviceObjectPointer(IN PUNICODE_STRING ObjectName, IN ACCESS_MASK DesiredAccess, OUT PFILE_OBJECT *FileObject, OUT PDEVICE_OBJECT *DeviceObject)
Definition: device.c:1435
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
uint64_t offset
Definition: btrfs.h:139
#define MOUNTMGR_DEVICE_NAME
Definition: imports.h:76
NTSTATUS mountmgr_add_drive_letter(PDEVICE_OBJECT mountmgr, PUNICODE_STRING devpath)
Definition: volume.c:917
BTRFS_UUID uuid
Definition: btrfs_drv.h:862
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
uint64_t num_children
Definition: btrfs_drv.h:902
#define ALLOC_TAG
Definition: btrfs_drv.h:91
#define IOCTL_MOUNTDEV_QUERY_DEVICE_NAME
Definition: imports.h:93
Definition: devices.h:37
#define FILE_REMOVABLE_MEDIA
Definition: nt_native.h:807
bool trim
Definition: btrfs_drv.h:541
smooth NULL
Definition: ftsmooth.c:416
#define offsetof(TYPE, MEMBER)
PDEVICE_OBJECT devobj
Definition: btrfs_drv.h:865
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
struct pdo_device_extension * pdode
Definition: btrfs_drv.h:886
void free_trees(device_extension *Vcb)
Definition: treefuncs.c:794
_Inout_ PFILE_OBJECT FileObject
Definition: cdprocs.h:588
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
#define FSRTL_VOLUME_CHANGE_SIZE
Definition: fsrtltypes.h:101
_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:121
uint64_t children_loaded
Definition: btrfs_drv.h:903
NTSTATUS NTAPI FsRtlNotifyVolumeEvent(IN PFILE_OBJECT FileObject, IN ULONG EventCode)
Definition: pnp.c:38
WCHAR Name[1]
Definition: imports.h:144
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
NTSTATUS dev_ioctl(_In_ PDEVICE_OBJECT DeviceObject, _In_ ULONG ControlCode, _In_reads_bytes_opt_(InputBufferSize) PVOID InputBuffer, _In_ ULONG InputBufferSize, _Out_writes_bytes_opt_(OutputBufferSize) PVOID OutputBuffer, _In_ ULONG OutputBufferSize, _In_ bool Override, _Out_opt_ IO_STATUS_BLOCK *iosb)
Definition: btrfs.c:2888
bool had_drive_letter
Definition: btrfs_drv.h:870
#define Vcb
Definition: cdprocs.h:1415
ERESOURCE child_lock
Definition: btrfs_drv.h:904
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
* PFILE_OBJECT
Definition: iotypes.h:1978
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
tree_data * item
Definition: btrfs_drv.h:518
PFILE_OBJECT fileobj
Definition: btrfs_drv.h:866
Status
Definition: gdiplustypes.h:24
GLdouble s
Definition: gl.h:2039
Definition: typedefs.h:119
static NTSTATUS remove_superblocks(device *dev)
Definition: balance.c:2561
#define ERR(fmt,...)
Definition: debug.h:110
Definition: btrfs.h:136
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
Definition: list.h:27
USHORT NameLength
Definition: imports.h:143
uint64_t dev_id
Definition: name.c:38
LIST_ENTRY list_entry
Definition: btrfs_drv.h:875
unsigned int ULONG
Definition: retypes.h:1
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
LIST_ENTRY children
Definition: btrfs_drv.h:905
return STATUS_SUCCESS
Definition: btrfs.c:3014
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
NTSTATUS delete_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _Inout_ traverse_ptr *tp)
Definition: treefuncs.c:990
GLuint const GLchar * name
Definition: glext.h:6031

Referenced by _Function_class_().

◆ get_chunk_dup_type()

static __inline uint64_t get_chunk_dup_type ( chunk c)
static

Definition at line 2208 of file balance.c.

2208  {
2209  if (c->chunk_item->type & BLOCK_FLAG_RAID0)
2210  return BLOCK_FLAG_RAID0;
2211  else if (c->chunk_item->type & BLOCK_FLAG_RAID1)
2212  return BLOCK_FLAG_RAID1;
2213  else if (c->chunk_item->type & BLOCK_FLAG_DUPLICATE)
2214  return BLOCK_FLAG_DUPLICATE;
2215  else if (c->chunk_item->type & BLOCK_FLAG_RAID10)
2216  return BLOCK_FLAG_RAID10;
2217  else if (c->chunk_item->type & BLOCK_FLAG_RAID5)
2218  return BLOCK_FLAG_RAID5;
2219  else if (c->chunk_item->type & BLOCK_FLAG_RAID6)
2220  return BLOCK_FLAG_RAID6;
2221  else if (c->chunk_item->type & BLOCK_FLAG_RAID1C3)
2222  return BLOCK_FLAG_RAID1C3;
2223  else if (c->chunk_item->type & BLOCK_FLAG_RAID1C4)
2224  return BLOCK_FLAG_RAID1C4;
2225  else
2226  return BLOCK_FLAG_SINGLE;
2227 }
#define BLOCK_FLAG_SINGLE
Definition: btrfsioctl.h:140
#define BLOCK_FLAG_RAID1C3
Definition: btrfs.h:83
#define BLOCK_FLAG_RAID10
Definition: shellext.h:81
#define BLOCK_FLAG_RAID0
Definition: shellext.h:78
const GLubyte * c
Definition: glext.h:8905
#define BLOCK_FLAG_RAID6
Definition: shellext.h:83
#define BLOCK_FLAG_RAID1C4
Definition: btrfs.h:84
#define BLOCK_FLAG_DUPLICATE
Definition: shellext.h:80
#define BLOCK_FLAG_RAID5
Definition: shellext.h:82
#define BLOCK_FLAG_RAID1
Definition: shellext.h:79

Referenced by should_balance_chunk().

◆ load_balance_args()

static void load_balance_args ( btrfs_balance_opts opts,
BALANCE_ARGS args 
)
static

Definition at line 2496 of file balance.c.

2496  {
2498 
2499  if (args->flags & BALANCE_ARGS_FLAGS_PROFILES) {
2501  opts->profiles = args->profiles;
2502  }
2503 
2504  if (args->flags & BALANCE_ARGS_FLAGS_USAGE) {
2506 
2507  opts->usage_start = 0;
2508  opts->usage_end = (uint8_t)args->usage;
2509  } else if (args->flags & BALANCE_ARGS_FLAGS_USAGE_RANGE) {
2511 
2512  opts->usage_start = (uint8_t)args->usage_start;
2513  opts->usage_end = (uint8_t)args->usage_end;
2514  }
2515 
2516  if (args->flags & BALANCE_ARGS_FLAGS_DEVID) {
2518  opts->devid = args->devid;
2519  }
2520 
2521  if (args->flags & BALANCE_ARGS_FLAGS_DRANGE) {
2523  opts->drange_start = args->drange_start;
2524  opts->drange_end = args->drange_end;
2525  }
2526 
2527  if (args->flags & BALANCE_ARGS_FLAGS_VRANGE) {
2529  opts->vrange_start = args->vrange_start;
2530  opts->vrange_end = args->vrange_end;
2531  }
2532 
2533  if (args->flags & BALANCE_ARGS_FLAGS_LIMIT) {
2535 
2536  opts->limit_start = 0;
2537  opts->limit_end = args->limit;
2538  } else if (args->flags & BALANCE_ARGS_FLAGS_LIMIT_RANGE) {
2540 
2541  opts->limit_start = args->limit_start;
2542  opts->limit_end = args->limit_end;
2543  }
2544 
2545  if (args->flags & BALANCE_ARGS_FLAGS_STRIPES_RANGE) {
2547 
2548  opts->stripes_start = (uint16_t)args->stripes_start;
2549  opts->stripes_end = (uint16_t)args->stripes_end;
2550  }
2551 
2552  if (args->flags & BALANCE_ARGS_FLAGS_CONVERT) {
2554  opts->convert = args->convert;
2555 
2556  if (args->flags & BALANCE_ARGS_FLAGS_SOFT)
2557  opts->flags |= BTRFS_BALANCE_OPTS_SOFT;
2558  }
2559 }
#define BALANCE_ARGS_FLAGS_DRANGE
Definition: btrfs.h:471
#define BALANCE_ARGS_FLAGS_LIMIT_RANGE
Definition: btrfs.h:474
#define BTRFS_BALANCE_OPTS_PROFILES
Definition: btrfsioctl.h:130
#define BALANCE_ARGS_FLAGS_VRANGE
Definition: btrfs.h:472
#define BALANCE_ARGS_FLAGS_STRIPES_RANGE
Definition: btrfs.h:475
#define BALANCE_ARGS_FLAGS_PROFILES
Definition: btrfs.h:468
#define BALANCE_ARGS_FLAGS_LIMIT
Definition: btrfs.h:473
uint16_t stripes_end
Definition: btrfsioctl.h:153
#define BTRFS_BALANCE_OPTS_VRANGE
Definition: btrfsioctl.h:133
unsigned short int uint16_t
Definition: acefiex.h:54
#define uint16_t
Definition: nsiface.idl:60
Definition: match.c:390
#define BALANCE_ARGS_FLAGS_USAGE_RANGE
Definition: btrfs.h:478
uint64_t limit_start
Definition: btrfsioctl.h:150
#define BALANCE_ARGS_FLAGS_SOFT
Definition: btrfs.h:477
#define BTRFS_BALANCE_OPTS_USAGE
Definition: btrfsioctl.h:136
uint64_t vrange_start
Definition: btrfsioctl.h:148
#define BTRFS_BALANCE_OPTS_CONVERT
Definition: btrfsioctl.h:137
#define BTRFS_BALANCE_OPTS_SOFT
Definition: btrfsioctl.h:138
uint64_t limit_end
Definition: btrfsioctl.h:151
#define BALANCE_ARGS_FLAGS_CONVERT
Definition: btrfs.h:476
uint64_t drange_end
Definition: btrfsioctl.h:147
#define BTRFS_BALANCE_OPTS_LIMIT
Definition: btrfsioctl.h:134
#define BTRFS_BALANCE_OPTS_ENABLED
Definition: btrfsioctl.h:129
#define BTRFS_BALANCE_OPTS_DRANGE
Definition: btrfsioctl.h:132
BYTE uint8_t
Definition: msvideo1.c:66
uint16_t stripes_start
Definition: btrfsioctl.h:152
#define uint8_t
Definition: nsiface.idl:59
#define BALANCE_ARGS_FLAGS_USAGE
Definition: btrfs.h:469
uint64_t vrange_end
Definition: btrfsioctl.h:149
uint64_t drange_start
Definition: btrfsioctl.h:146
#define BALANCE_ARGS_FLAGS_DEVID
Definition: btrfs.h:470
#define BTRFS_BALANCE_OPTS_DEVID
Definition: btrfsioctl.h:131
#define BTRFS_BALANCE_OPTS_STRIPES
Definition: btrfsioctl.h:135

Referenced by look_for_balance_item().

◆ look_for_balance_item()

NTSTATUS look_for_balance_item ( _Requires_lock_held_(_Curr_->tree_lock) device_extension Vcb)

Definition at line 3632 of file balance.c.

3632  {
3633  KEY searchkey;
3634  traverse_ptr tp;
3635  NTSTATUS Status;
3636  BALANCE_ITEM* bi;
3637  OBJECT_ATTRIBUTES oa;
3638  int i;
3639 
3640  searchkey.obj_id = BALANCE_ITEM_ID;
3641  searchkey.obj_type = TYPE_TEMP_ITEM;
3642  searchkey.offset = 0;
3643 
3644  Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, false, NULL);
3645  if (!NT_SUCCESS(Status)) {
3646  ERR("find_item returned %08lx\n", Status);
3647  return Status;
3648  }
3649 
3650  if (keycmp(tp.item->key, searchkey)) {
3651  TRACE("no balance item found\n");
3652  return STATUS_NOT_FOUND;
3653  }
3654 
3655  if (tp.item->size < sizeof(BALANCE_ITEM)) {
3656  WARN("(%I64x,%x,%I64x) was %u bytes, expected %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset,
3657  tp.item->size, sizeof(BALANCE_ITEM));
3658  return STATUS_INTERNAL_ERROR;
3659  }
3660 
3661  bi = (BALANCE_ITEM*)tp.item->data;
3662 
3663  if (bi->flags & BALANCE_FLAGS_DATA)
3664  load_balance_args(&Vcb->balance.opts[BALANCE_OPTS_DATA], &bi->data);
3665 
3666  if (bi->flags & BALANCE_FLAGS_METADATA)
3667  load_balance_args(&Vcb->balance.opts[BALANCE_OPTS_METADATA], &bi->metadata);
3668 
3669  if (bi->flags & BALANCE_FLAGS_SYSTEM)
3670  load_balance_args(&Vcb->balance.opts[BALANCE_OPTS_SYSTEM], &bi->system);
3671 
3672  // do the heuristics that Linux driver does
3673 
3674  for (i = 0; i < 3; i++) {
3675  if (Vcb->balance.opts[i].flags & BTRFS_BALANCE_OPTS_ENABLED) {
3676  // if converting, don't redo chunks already done
3677