ReactOS  0.4.15-dev-4853-g3a72a52
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 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 71 of file balance.c.

Function Documentation

◆ _Function_class_()

_Function_class_ ( KSTART_ROUTINE  )

Definition at line 3047 of file balance.c.

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

◆ add_balance_item()

static NTSTATUS add_balance_item ( device_extension Vcb)
static

Definition at line 2378 of file balance.c.

2378  {
2379  KEY searchkey;
2380  traverse_ptr tp;
2381  NTSTATUS Status;
2382  BALANCE_ITEM* bi;
2383 
2384  searchkey.obj_id = BALANCE_ITEM_ID;
2385  searchkey.obj_type = TYPE_TEMP_ITEM;
2386  searchkey.offset = 0;
2387 
2388  ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
2389 
2390  Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, false, NULL);
2391  if (!NT_SUCCESS(Status)) {
2392  ERR("find_item returned %08lx\n", Status);
2393  goto end;
2394  }
2395 
2396  if (!keycmp(tp.item->key, searchkey)) {
2398  if (!NT_SUCCESS(Status)) {
2399  ERR("delete_tree_item returned %08lx\n", Status);
2400  goto end;
2401  }
2402  }
2403 
2405  if (!bi) {
2406  ERR("out of memory\n");
2408  goto end;
2409  }
2410 
2411  RtlZeroMemory(bi, sizeof(BALANCE_ITEM));
2412 
2413  if (Vcb->balance.opts[BALANCE_OPTS_DATA].flags & BTRFS_BALANCE_OPTS_ENABLED) {
2414  bi->flags |= BALANCE_FLAGS_DATA;
2415  copy_balance_args(&Vcb->balance.opts[BALANCE_OPTS_DATA], &bi->data);
2416  }
2417 
2418  if (Vcb->balance.opts[BALANCE_OPTS_METADATA].flags & BTRFS_BALANCE_OPTS_ENABLED) {
2420  copy_balance_args(&Vcb->balance.opts[BALANCE_OPTS_METADATA], &bi->metadata);
2421  }
2422 
2423  if (Vcb->balance.opts[BALANCE_OPTS_SYSTEM].flags & BTRFS_BALANCE_OPTS_ENABLED) {
2424  bi->flags |= BALANCE_FLAGS_SYSTEM;
2425  copy_balance_args(&Vcb->balance.opts[BALANCE_OPTS_SYSTEM], &bi->system);
2426  }
2427 
2428  Status = insert_tree_item(Vcb, Vcb->root_root, BALANCE_ITEM_ID, TYPE_TEMP_ITEM, 0, bi, sizeof(BALANCE_ITEM), NULL, NULL);
2429  if (!NT_SUCCESS(Status)) {
2430  ERR("insert_tree_item returned %08lx\n", Status);
2431  ExFreePool(bi);
2432  goto end;
2433  }
2434 
2436 
2437 end:
2438  if (NT_SUCCESS(Status)) {
2439  Status = do_write(Vcb, NULL);
2440  if (!NT_SUCCESS(Status))
2441  ERR("do_write returned %08lx\n", Status);
2442  }
2443 
2444  free_trees(Vcb);
2445 
2446  ExReleaseResourceLite(&Vcb->tree_lock);
2447 
2448  return Status;
2449 }
#define BALANCE_ITEM_ID
Definition: btrfs.h:92
uint64_t obj_id
Definition: btrfs.h:144
uint8_t obj_type
Definition: btrfs.h:145
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define BALANCE_OPTS_SYSTEM
Definition: btrfs_drv.h:687
NTSTATUS do_write(device_extension *Vcb, PIRP Irp)
Definition: flushthread.c:7759
#define keycmp(key1, key2)
Definition: btrfs_drv.h:1008
LONG NTSTATUS
Definition: precomp.h:26
uint64_t flags
Definition: btrfs.h:525
BALANCE_ARGS data
Definition: btrfs.h:526
uint64_t offset
Definition: btrfs.h:146
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
#define ALLOC_TAG
Definition: btrfs_drv.h:87
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) __attribute__((nonnull(1
#define TYPE_TEMP_ITEM
Definition: btrfs.h:49
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2965
Status
Definition: gdiplustypes.h:24
NTSTATUS find_item(_In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _Out_ traverse_ptr *tp, _In_ const KEY *searchkey, _In_ bool ignore, _In_opt_ PIRP Irp) __attribute__((nonnull(1
#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:2318
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
GLuint GLuint end
Definition: gl.h:1545
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
tree_data * item
Definition: btrfs_drv.h:502
#define BTRFS_BALANCE_OPTS_ENABLED
Definition: btrfsioctl.h:130
NTSTATUS NTSTATUS bool bool void free_trees(device_extension *Vcb) __attribute__((nonnull(1)))
#define ERR(fmt,...)
Definition: debug.h:110
Definition: btrfs.h:143
#define BALANCE_FLAGS_SYSTEM
Definition: btrfs.h:477
BALANCE_ARGS metadata
Definition: btrfs.h:527
#define BALANCE_FLAGS_DATA
Definition: btrfs.h:476
NTSTATUS NTSTATUS delete_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _Inout_ traverse_ptr *tp) __attribute__((nonnull(1
#define NULL
Definition: types.h:112
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
BALANCE_ARGS system
Definition: btrfs.h:528
#define STATUS_SUCCESS
Definition: shellext.h:65
#define BALANCE_OPTS_METADATA
Definition: btrfs_drv.h:686
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define BALANCE_FLAGS_METADATA
Definition: btrfs.h:478
#define BALANCE_OPTS_DATA
Definition: btrfs_drv.h:685

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 1316 of file balance.c.

1317  {
1318  NTSTATUS Status;
1319  data_reloc* dr;
1320  EXTENT_ITEM* ei;
1321  uint16_t len;
1322  uint64_t inline_rc;
1323  uint8_t* ptr;
1324 
1326  if (!dr) {
1327  ERR("out of memory\n");
1329  }
1330 
1331  dr->address = tp->item->key.obj_id;
1332  dr->size = tp->item->key.offset;
1333  dr->ei = (EXTENT_ITEM*)tp->item->data;
1334  InitializeListHead(&dr->refs);
1335 
1337  if (!NT_SUCCESS(Status)) {
1338  ERR("delete_tree_item returned %08lx\n", Status);
1339  return Status;
1340  }
1341 
1342  if (!c)
1344 
1345  if (c) {
1347 
1348  c->used -= tp->item->key.offset;
1349 
1351 
1353  }
1354 
1355  ei = (EXTENT_ITEM*)tp->item->data;
1356  inline_rc = 0;
1357 
1358  len = tp->item->size - sizeof(EXTENT_ITEM);
1359  ptr = (uint8_t*)tp->item->data + sizeof(EXTENT_ITEM);
1360 
1361  while (len > 0) {
1362  uint8_t secttype = *ptr;
1363  uint16_t sectlen = secttype == TYPE_EXTENT_DATA_REF ? sizeof(EXTENT_DATA_REF) : (secttype == TYPE_SHARED_DATA_REF ? sizeof(SHARED_DATA_REF) : 0);
1364 
1365  len--;
1366 
1367  if (sectlen > len) {
1368  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);
1369  return STATUS_INTERNAL_ERROR;
1370  }
1371 
1372  if (sectlen == 0) {
1373  ERR("(%I64x,%x,%I64x): unrecognized extent type %x\n", tp->item->key.obj_id, tp->item->key.obj_type, tp->item->key.offset, secttype);
1374  return STATUS_INTERNAL_ERROR;
1375  }
1376 
1377  if (secttype == TYPE_EXTENT_DATA_REF) {
1378  EXTENT_DATA_REF* edr = (EXTENT_DATA_REF*)(ptr + sizeof(uint8_t));
1379 
1380  inline_rc += edr->count;
1381 
1382  Status = data_reloc_add_tree_edr(Vcb, metadata_items, dr, edr, rollback);
1383  if (!NT_SUCCESS(Status)) {
1384  ERR("data_reloc_add_tree_edr returned %08lx\n", Status);
1385  return Status;
1386  }
1387  } else if (secttype == TYPE_SHARED_DATA_REF) {
1388  metadata_reloc* mr;
1390 
1392  if (!ref) {
1393  ERR("out of memory\n");
1395  }
1396 
1397  ref->type = TYPE_SHARED_DATA_REF;
1398  RtlCopyMemory(&ref->sdr, ptr + sizeof(uint8_t), sizeof(SHARED_DATA_REF));
1399  inline_rc += ref->sdr.count;
1400 
1401  Status = add_metadata_reloc_parent(Vcb, metadata_items, ref->sdr.offset, &mr, rollback);
1402  if (!NT_SUCCESS(Status)) {
1403  ERR("add_metadata_reloc_parent returned %08lx\n", Status);
1404  ExFreePool(ref);
1405  return Status;
1406  }
1407 
1408  ref->parent = mr;
1409 
1410  InsertTailList(&dr->refs, &ref->list_entry);
1411  } else {
1412  ERR("unexpected tree type %x\n", secttype);
1413  return STATUS_INTERNAL_ERROR;
1414  }
1415 
1416 
1417  len -= sectlen;
1418  ptr += sizeof(uint8_t) + sectlen;
1419  }
1420 
1421  if (inline_rc < ei->refcount) { // look for non-inline entries
1422  traverse_ptr tp2 = *tp, next_tp;
1423 
1424  while (find_next_item(Vcb, &tp2, &next_tp, false, NULL)) {
1425  tp2 = next_tp;
1426 
1427  if (tp2.item->key.obj_id == tp->item->key.obj_id) {
1428  if (tp2.item->key.obj_type == TYPE_EXTENT_DATA_REF && tp2.item->size >= sizeof(EXTENT_DATA_REF)) {
1429  Status = data_reloc_add_tree_edr(Vcb, metadata_items, dr, (EXTENT_DATA_REF*)tp2.item->data, rollback);
1430  if (!NT_SUCCESS(Status)) {
1431  ERR("data_reloc_add_tree_edr returned %08lx\n", Status);
1432  return Status;
1433  }
1434 
1435  Status = delete_tree_item(Vcb, &tp2);
1436  if (!NT_SUCCESS(Status)) {
1437  ERR("delete_tree_item returned %08lx\n", Status);
1438  return Status;
1439  }
1440  } else if (tp2.item->key.obj_type == TYPE_SHARED_DATA_REF && tp2.item->size >= sizeof(uint32_t)) {
1441  metadata_reloc* mr;
1443 
1445  if (!ref) {
1446  ERR("out of memory\n");
1448  }
1449 
1450  ref->type = TYPE_SHARED_DATA_REF;
1451  ref->sdr.offset = tp2.item->key.offset;
1452  ref->sdr.count = *((uint32_t*)tp2.item->data);
1453 
1454  Status = add_metadata_reloc_parent(Vcb, metadata_items, ref->sdr.offset, &mr, rollback);
1455  if (!NT_SUCCESS(Status)) {
1456  ERR("add_metadata_reloc_parent returned %08lx\n", Status);
1457  ExFreePool(ref);
1458  return Status;
1459  }
1460 
1461  ref->parent = mr;
1462  InsertTailList(&dr->refs, &ref->list_entry);
1463 
1464  Status = delete_tree_item(Vcb, &tp2);
1465  if (!NT_SUCCESS(Status)) {
1466  ERR("delete_tree_item returned %08lx\n", Status);
1467  return Status;
1468  }
1469  }
1470  } else
1471  break;
1472  }
1473  }
1474 
1476 
1477  return STATUS_SUCCESS;
1478 }
LIST_ENTRY list_entry
Definition: balance.c:55
uint64_t obj_id
Definition: btrfs.h:144
uint8_t obj_type
Definition: btrfs.h:145
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
LONG NTSTATUS
Definition: precomp.h:26
uint16_t size
Definition: btrfs_drv.h:414
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:1217
unsigned short int uint16_t
Definition: acefiex.h:54
#define InsertTailList(ListHead, Entry)
NTSTATUS NTSTATUS 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) __attribute__((nonnull(1
LIST_ENTRY list_entry
Definition: send.c:49
Definition: send.c:48
uint64_t offset
Definition: btrfs.h:146
uint8_t * data
Definition: btrfs_drv.h:415
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
#define ALLOC_TAG
Definition: btrfs_drv.h:87
void space_list_add(chunk *c, uint64_t address, uint64_t length, LIST_ENTRY *rollback)
Definition: free-space.c:2146
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:420
#define release_chunk_lock(c, Vcb)
Definition: btrfs_drv.h:1132
#define TYPE_EXTENT_DATA_REF
Definition: btrfs.h:38
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2965
Status
Definition: gdiplustypes.h:24
#define TYPE_SHARED_DATA_REF
Definition: btrfs.h:41
#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:502
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:226
BYTE uint8_t
Definition: msvideo1.c:66
#define ERR(fmt,...)
Definition: debug.h:110
UINT64 uint64_t
Definition: types.h:77
#define uint8_t
Definition: nsiface.idl:59
#define acquire_chunk_lock(c, Vcb)
Definition: btrfs_drv.h:1131
NTSTATUS NTSTATUS delete_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _Inout_ traverse_ptr *tp) __attribute__((nonnull(1
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define NULL
Definition: types.h:112
_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:1355
UINT32 uint32_t
Definition: types.h:75
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
EXTENT_ITEM * ei
Definition: balance.c:53
#define STATUS_SUCCESS
Definition: shellext.h:65
static TCHAR * items[]
Definition: page1.c:45
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
NTSTATUS NTSTATUS NTSTATUS NTSTATUS NTSTATUS chunk * get_chunk_from_address(device_extension *Vcb, uint64_t address) __attribute__((nonnull(1)))
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 1541 of file balance.c.

1541  {
1542  NTSTATUS Status;
1543  LIST_ENTRY* le;
1544  uint64_t rc = 0;
1545  uint16_t inline_len;
1546  bool all_inline = true;
1547  data_reloc_ref* first_noninline = NULL;
1548  EXTENT_ITEM* ei;
1549  uint8_t* ptr;
1550 
1551  inline_len = sizeof(EXTENT_ITEM);
1552 
1554 
1555  le = dr->refs.Flink;
1556  while (le != &dr->refs) {
1558  uint16_t extlen = 0;
1559 
1560  if (ref->type == TYPE_EXTENT_DATA_REF) {
1561  extlen += sizeof(EXTENT_DATA_REF);
1562  rc += ref->edr.count;
1563  } else if (ref->type == TYPE_SHARED_DATA_REF) {
1564  extlen += sizeof(SHARED_DATA_REF);
1565  rc++;
1566  }
1567 
1568  if (all_inline) {
1569  if ((ULONG)(inline_len + 1 + extlen) > (Vcb->superblock.node_size >> 2)) {
1570  all_inline = false;
1571  first_noninline = ref;
1572  } else
1573  inline_len += extlen + 1;
1574  }
1575 
1576  le = le->Flink;
1577  }
1578 
1579  ei = ExAllocatePoolWithTag(PagedPool, inline_len, ALLOC_TAG);
1580  if (!ei) {
1581  ERR("out of memory\n");
1583  }
1584 
1585  ei->refcount = rc;
1586  ei->generation = dr->ei->generation;
1587  ei->flags = dr->ei->flags;
1588  ptr = (uint8_t*)&ei[1];
1589 
1590  le = dr->refs.Flink;
1591  while (le != &dr->refs) {
1593 
1594  if (ref == first_noninline)
1595  break;
1596 
1597  *ptr = ref->type;
1598  ptr++;
1599 
1600  if (ref->type == TYPE_EXTENT_DATA_REF) {
1602 
1603  RtlCopyMemory(edr, &ref->edr, sizeof(EXTENT_DATA_REF));
1604 
1605  ptr += sizeof(EXTENT_DATA_REF);
1606  } else if (ref->type == TYPE_SHARED_DATA_REF) {
1608 
1609  sdr->offset = ref->parent->new_address;
1610  sdr->count = ref->sdr.count;
1611 
1612  ptr += sizeof(SHARED_DATA_REF);
1613  }
1614 
1615  le = le->Flink;
1616  }
1617 
1618  Status = insert_tree_item(Vcb, Vcb->extent_root, dr->new_address, TYPE_EXTENT_ITEM, dr->size, ei, inline_len, NULL, NULL);
1619  if (!NT_SUCCESS(Status)) {
1620  ERR("insert_tree_item returned %08lx\n", Status);
1621  return Status;
1622  }
1623 
1624  if (!all_inline) {
1625  le = &first_noninline->list_entry;
1626 
1627  while (le != &dr->refs) {
1629 
1630  if (ref->type == TYPE_EXTENT_DATA_REF) {
1631  EXTENT_DATA_REF* edr;
1632 
1634  if (!edr) {
1635  ERR("out of memory\n");
1637  }
1638 
1639  RtlCopyMemory(edr, &ref->edr, sizeof(EXTENT_DATA_REF));
1640 
1641  Status = insert_tree_item(Vcb, Vcb->extent_root, dr->new_address, TYPE_EXTENT_DATA_REF, ref->hash, edr, sizeof(EXTENT_DATA_REF), NULL, NULL);
1642  if (!NT_SUCCESS(Status)) {
1643  ERR("insert_tree_item returned %08lx\n", Status);
1644  return Status;
1645  }
1646  } else if (ref->type == TYPE_SHARED_DATA_REF) {
1647  uint32_t* sdr;
1648 
1650  if (!sdr) {
1651  ERR("out of memory\n");
1653  }
1654 
1655  *sdr = ref->sdr.count;
1656 
1657  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);
1658  if (!NT_SUCCESS(Status)) {
1659  ERR("insert_tree_item returned %08lx\n", Status);
1660  return Status;
1661  }
1662  }
1663 
1664  le = le->Flink;
1665  }
1666  }
1667 
1668  return STATUS_SUCCESS;
1669 }
#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:1480
#define ALLOC_TAG
Definition: btrfs_drv.h:87
uint64_t refcount
Definition: btrfs.h:392
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
#define TYPE_EXTENT_ITEM
Definition: btrfs.h:35
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) __attribute__((nonnull(1
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:38
Status
Definition: gdiplustypes.h:24
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define TYPE_SHARED_DATA_REF
Definition: btrfs.h:41
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1415
#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:442
Definition: typedefs.h:119
BYTE uint8_t
Definition: msvideo1.c:66
uint64_t generation
Definition: btrfs.h:393
#define ERR(fmt,...)
Definition: debug.h:110
UINT64 uint64_t
Definition: types.h:77
Definition: list.h:27
#define NULL
Definition: types.h:112
UINT32 uint32_t
Definition: types.h:75
unsigned int ULONG
Definition: retypes.h:1
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
EXTENT_ITEM * ei
Definition: balance.c:53
#define STATUS_SUCCESS
Definition: shellext.h:65
uint64_t flags
Definition: btrfs.h:394
uint64_t offset
Definition: btrfs.h:441
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 73 of file balance.c.

74  {
76  metadata_reloc* mr;
77  EXTENT_ITEM* ei;
78  uint16_t len;
79  uint64_t inline_rc;
80  uint8_t* ptr;
81 
83  if (!mr) {
84  ERR("out of memory\n");
86  }
87 
88  mr->address = tp->item->key.obj_id;
89  mr->data = NULL;
90  mr->ei = (EXTENT_ITEM*)tp->item->data;
91  mr->system = false;
93 
95  if (!NT_SUCCESS(Status)) {
96  ERR("delete_tree_item returned %08lx\n", Status);
97  ExFreePool(mr);
98  return Status;
99  }
100 
101  if (!c)
103 
104  if (c) {
106 
107  c->used -= Vcb->superblock.node_size;
108 
109  space_list_add(c, tp->item->key.obj_id, Vcb->superblock.node_size, rollback);
110 
112  }
113 
114  ei = (EXTENT_ITEM*)tp->item->data;
115  inline_rc = 0;
116 
117  len = tp->item->size - sizeof(EXTENT_ITEM);
118  ptr = (uint8_t*)tp->item->data + sizeof(EXTENT_ITEM);
119  if (!skinny) {
120  len -= sizeof(EXTENT_ITEM2);
121  ptr += sizeof(EXTENT_ITEM2);
122  }
123 
124  while (len > 0) {
125  uint8_t secttype = *ptr;
126  uint16_t sectlen = secttype == TYPE_TREE_BLOCK_REF ? sizeof(TREE_BLOCK_REF) : (secttype == TYPE_SHARED_BLOCK_REF ? sizeof(SHARED_BLOCK_REF) : 0);
128 
129  len--;
130 
131  if (sectlen > len) {
132  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);
133  return STATUS_INTERNAL_ERROR;
134  }
135 
136  if (sectlen == 0) {
137  ERR("(%I64x,%x,%I64x): unrecognized extent type %x\n", tp->item->key.obj_id, tp->item->key.obj_type, tp->item->key.offset, secttype);
138  return STATUS_INTERNAL_ERROR;
139  }
140 
142  if (!ref) {
143  ERR("out of memory\n");
145  }
146 
147  if (secttype == TYPE_TREE_BLOCK_REF) {
148  ref->type = TYPE_TREE_BLOCK_REF;
149  RtlCopyMemory(&ref->tbr, ptr + sizeof(uint8_t), sizeof(TREE_BLOCK_REF));
150  inline_rc++;
151  } else if (secttype == TYPE_SHARED_BLOCK_REF) {
152  ref->type = TYPE_SHARED_BLOCK_REF;
153  RtlCopyMemory(&ref->sbr, ptr + sizeof(uint8_t), sizeof(SHARED_BLOCK_REF));
154  inline_rc++;
155  } else {
156  ERR("unexpected tree type %x\n", secttype);
157  ExFreePool(ref);
158  return STATUS_INTERNAL_ERROR;
159  }
160 
161  ref->parent = NULL;
162  ref->top = false;
164 
165  len -= sectlen;
166  ptr += sizeof(uint8_t) + sectlen;
167  }
168 
169  if (inline_rc < ei->refcount) { // look for non-inline entries
170  traverse_ptr tp2 = *tp, next_tp;
171 
172  while (find_next_item(Vcb, &tp2, &next_tp, false, NULL)) {
173  tp2 = next_tp;
174 
175  if (tp2.item->key.obj_id == tp->item->key.obj_id) {
176  if (tp2.item->key.obj_type == TYPE_TREE_BLOCK_REF) {
178  if (!ref) {
179  ERR("out of memory\n");
181  }
182 
183  ref->type = TYPE_TREE_BLOCK_REF;
184  ref->tbr.offset = tp2.item->key.offset;
185  ref->parent = NULL;
186  ref->top = false;
188 
189  Status = delete_tree_item(Vcb, &tp2);
190  if (!NT_SUCCESS(Status)) {
191  ERR("delete_tree_item returned %08lx\n", Status);
192  return Status;
193  }
194  } else if (tp2.item->key.obj_type == TYPE_SHARED_BLOCK_REF) {
196  if (!ref) {
197  ERR("out of memory\n");
199  }
200 
201  ref->type = TYPE_SHARED_BLOCK_REF;
202  ref->sbr.offset = tp2.item->key.offset;
203  ref->parent = NULL;
204  ref->top = false;
206 
207  Status = delete_tree_item(Vcb, &tp2);
208  if (!NT_SUCCESS(Status)) {
209  ERR("delete_tree_item returned %08lx\n", Status);
210  return Status;
211  }
212  }
213  } else
214  break;
215  }
216  }
217 
219 
220  if (mr2)
221  *mr2 = mr;
222 
223  return STATUS_SUCCESS;
224 }
uint64_t obj_id
Definition: btrfs.h:144
LIST_ENTRY list_entry
Definition: balance.c:31
uint8_t obj_type
Definition: btrfs.h:145
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
LONG NTSTATUS
Definition: precomp.h:26
uint16_t size
Definition: btrfs_drv.h:414
#define TYPE_TREE_BLOCK_REF
Definition: btrfs.h:37
unsigned short int uint16_t
Definition: acefiex.h:54
tree_header * data
Definition: balance.c:26
#define InsertTailList(ListHead, Entry)
NTSTATUS NTSTATUS 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) __attribute__((nonnull(1
LIST_ENTRY list_entry
Definition: send.c:49
Definition: send.c:48
uint64_t offset
Definition: btrfs.h:146
uint8_t * data
Definition: btrfs_drv.h:415
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
#define ALLOC_TAG
Definition: btrfs_drv.h:87
void space_list_add(chunk *c, uint64_t address, uint64_t length, LIST_ENTRY *rollback)
Definition: free-space.c:2146
GLenum GLint ref
Definition: glext.h:6028
static PVOID ptr
Definition: dispmode.c:27
#define release_chunk_lock(c, Vcb)
Definition: btrfs_drv.h:1132
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2965
Status
Definition: gdiplustypes.h:24
EXTENT_ITEM * ei
Definition: balance.c:27
bool system
Definition: balance.c:29
#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:40
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
tree_data * item
Definition: btrfs_drv.h:502
GLenum GLsizei len
Definition: glext.h:6722
BYTE uint8_t
Definition: msvideo1.c:66
#define ERR(fmt,...)
Definition: debug.h:110
UINT64 uint64_t
Definition: types.h:77
#define uint8_t
Definition: nsiface.idl:59
#define acquire_chunk_lock(c, Vcb)
Definition: btrfs_drv.h:1131
NTSTATUS NTSTATUS delete_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _Inout_ traverse_ptr *tp) __attribute__((nonnull(1
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
uint64_t address
Definition: balance.c:24
#define NULL
Definition: types.h:112
_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:1355
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define STATUS_SUCCESS
Definition: shellext.h:65
static TCHAR * items[]
Definition: page1.c:45
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
NTSTATUS NTSTATUS NTSTATUS NTSTATUS NTSTATUS chunk * get_chunk_from_address(device_extension *Vcb, uint64_t address) __attribute__((nonnull(1)))
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 322 of file balance.c.

322  {
324  LIST_ENTRY* le;
325  uint64_t rc = 0;
326  uint16_t inline_len;
327  bool all_inline = true;
328  metadata_reloc_ref* first_noninline = NULL;
329  EXTENT_ITEM* ei;
330  uint8_t* ptr;
331 
332  inline_len = sizeof(EXTENT_ITEM);
333  if (!(Vcb->superblock.incompat_flags & BTRFS_INCOMPAT_FLAGS_SKINNY_METADATA))
334  inline_len += sizeof(EXTENT_ITEM2);
335 
337 
338  le = mr->refs.Flink;
339  while (le != &mr->refs) {
341  uint16_t extlen = 0;
342 
343  rc++;
344 
345  if (ref->type == TYPE_TREE_BLOCK_REF)
346  extlen += sizeof(TREE_BLOCK_REF);
347  else if (ref->type == TYPE_SHARED_BLOCK_REF)
348  extlen += sizeof(SHARED_BLOCK_REF);
349 
350  if (all_inline) {
351  if ((ULONG)(inline_len + 1 + extlen) > (Vcb->superblock.node_size >> 2)) {
352  all_inline = false;
353  first_noninline = ref;
354  } else
355  inline_len += extlen + 1;
356  }
357 
358  le = le->Flink;
359  }
360 
361  ei = ExAllocatePoolWithTag(PagedPool, inline_len, ALLOC_TAG);
362  if (!ei) {
363  ERR("out of memory\n");
365  }
366 
367  ei->refcount = rc;
368  ei->generation = mr->ei->generation;
369  ei->flags = mr->ei->flags;
370  ptr = (uint8_t*)&ei[1];
371 
372  if (!(Vcb->superblock.incompat_flags & BTRFS_INCOMPAT_FLAGS_SKINNY_METADATA)) {
373  EXTENT_ITEM2* ei2 = (EXTENT_ITEM2*)ptr;
374 
375  ei2->firstitem = *(KEY*)&mr->data[1];
376  ei2->level = mr->data->level;
377 
378  ptr += sizeof(EXTENT_ITEM2);
379  }
380 
381  le = mr->refs.Flink;
382  while (le != &mr->refs) {
384 
385  if (ref == first_noninline)
386  break;
387 
388  *ptr = ref->type;
389  ptr++;
390 
391  if (ref->type == TYPE_TREE_BLOCK_REF) {
393 
394  tbr->offset = ref->tbr.offset;
395 
396  ptr += sizeof(TREE_BLOCK_REF);
397  } else if (ref->type == TYPE_SHARED_BLOCK_REF) {
399 
400  sbr->offset = ref->parent->new_address;
401 
402  ptr += sizeof(SHARED_BLOCK_REF);
403  }
404 
405  le = le->Flink;
406  }
407 
408  if (Vcb->superblock.incompat_flags & BTRFS_INCOMPAT_FLAGS_SKINNY_METADATA)
409  Status = insert_tree_item(Vcb, Vcb->extent_root, mr->new_address, TYPE_METADATA_ITEM, mr->data->level, ei, inline_len, NULL, NULL);
410  else
411  Status = insert_tree_item(Vcb, Vcb->extent_root, mr->new_address, TYPE_EXTENT_ITEM, Vcb->superblock.node_size, ei, inline_len, NULL, NULL);
412 
413  if (!NT_SUCCESS(Status)) {
414  ERR("insert_tree_item returned %08lx\n", Status);
415  ExFreePool(ei);
416  return Status;
417  }
418 
419  if (!all_inline) {
420  le = &first_noninline->list_entry;
421 
422  while (le != &mr->refs) {
424 
425  if (ref->type == TYPE_TREE_BLOCK_REF) {
426  Status = insert_tree_item(Vcb, Vcb->extent_root, mr->new_address, TYPE_TREE_BLOCK_REF, ref->tbr.offset, NULL, 0, NULL, NULL);
427  if (!NT_SUCCESS(Status)) {
428  ERR("insert_tree_item returned %08lx\n", Status);
429  return Status;
430  }
431  } else if (ref->type == TYPE_SHARED_BLOCK_REF) {
432  Status = insert_tree_item(Vcb, Vcb->extent_root, mr->new_address, TYPE_SHARED_BLOCK_REF, ref->parent->new_address, NULL, 0, NULL, NULL);
433  if (!NT_SUCCESS(Status)) {
434  ERR("insert_tree_item returned %08lx\n", Status);
435  return Status;
436  }
437  }
438 
439  le = le->Flink;
440  }
441  }
442 
444  if (mr->data->level > 0) {
445  uint16_t i;
446  internal_node* in = (internal_node*)&mr->data[1];
447 
448  for (i = 0; i < mr->data->num_items; i++) {
450 
451  if (sbrrc > 0) {
452  SHARED_BLOCK_REF sbr;
453 
454  sbr.offset = mr->new_address;
455 
456  Status = increase_extent_refcount(Vcb, in[i].address, Vcb->superblock.node_size, TYPE_SHARED_BLOCK_REF, &sbr, NULL, 0, NULL);
457  if (!NT_SUCCESS(Status)) {
458  ERR("increase_extent_refcount returned %08lx\n", Status);
459  return Status;
460  }
461 
462  sbr.offset = mr->address;
463 
464  Status = decrease_extent_refcount(Vcb, in[i].address, Vcb->superblock.node_size, TYPE_SHARED_BLOCK_REF, &sbr, NULL, 0,
465  sbr.offset, false, NULL);
466  if (!NT_SUCCESS(Status)) {
467  ERR("decrease_extent_refcount returned %08lx\n", Status);
468  return Status;
469  }
470  }
471  }
472  } else {
473  uint16_t i;
474  leaf_node* ln = (leaf_node*)&mr->data[1];
475 
476  for (i = 0; i < mr->data->num_items; i++) {
477  if (ln[i].key.obj_type == TYPE_EXTENT_DATA && ln[i].size >= sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2)) {
478  EXTENT_DATA* ed = (EXTENT_DATA*)((uint8_t*)mr->data + sizeof(tree_header) + ln[i].offset);
479 
480  if (ed->type == EXTENT_TYPE_REGULAR || ed->type == EXTENT_TYPE_PREALLOC) {
481  EXTENT_DATA2* ed2 = (EXTENT_DATA2*)ed->data;
482 
483  if (ed2->size > 0) { // not sparse
485 
486  if (sdrrc > 0) {
487  SHARED_DATA_REF sdr;
488  chunk* c;
489 
490  sdr.offset = mr->new_address;
491  sdr.count = sdrrc;
492 
494  if (!NT_SUCCESS(Status)) {
495  ERR("increase_extent_refcount returned %08lx\n", Status);
496  return Status;
497  }
498 
499  sdr.offset = mr->address;
500 
502  sdr.offset, false, NULL);
503  if (!NT_SUCCESS(Status)) {
504  ERR("decrease_extent_refcount returned %08lx\n", Status);
505  return Status;
506  }
507 
509 
510  if (c) {
511  // check changed_extents
512 
513  ExAcquireResourceExclusiveLite(&c->changed_extents_lock, true);
514 
515  le = c->changed_extents.Flink;
516 
517  while (le != &c->changed_extents) {
519 
520  if (ce->address == ed2->address) {
521  LIST_ENTRY* le2;
522 
523  le2 = ce->refs.Flink;
524  while (le2 != &ce->refs) {
526 
527  if (cer->type == TYPE_SHARED_DATA_REF && cer->sdr.offset == mr->address) {
528  cer->sdr.offset = mr->new_address;
529  break;
530  }
531 
532  le2 = le2->Flink;
533  }
534 
535  le2 = ce->old_refs.Flink;
536  while (le2 != &ce->old_refs) {
538 
539  if (cer->type == TYPE_SHARED_DATA_REF && cer->sdr.offset == mr->address) {
540  cer->sdr.offset = mr->new_address;
541  break;
542  }
543 
544  le2 = le2->Flink;
545  }
546 
547  break;
548  }
549 
550  le = le->Flink;
551  }
552 
553  ExReleaseResourceLite(&c->changed_extents_lock);
554  }
555  }
556  }
557  }
558  }
559  }
560  }
561  }
562 
563  return STATUS_SUCCESS;
564 }
SHARED_DATA_REF sdr
Definition: btrfs_drv.h:607
uint64_t new_address
Definition: balance.c:25
uint8_t type
Definition: btrfs.h:363
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
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:157
#define TYPE_TREE_BLOCK_REF
Definition: btrfs.h:37
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:123
unsigned short int uint16_t
Definition: acefiex.h:54
tree_header * data
Definition: balance.c:26
#define TYPE_METADATA_ITEM
Definition: btrfs.h:36
if(dx==0 &&dy==0)
Definition: linetemp.h:174
#define HEADER_FLAG_SHARED_BACKREF
Definition: btrfs.h:150
LIST_ENTRY old_refs
Definition: btrfs_drv.h:598
#define HEADER_FLAG_MIXED_BACKREF
Definition: btrfs.h:151
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:87
uint64_t refcount
Definition: btrfs.h:392
uint64_t address
Definition: btrfs.h:368
GLenum GLint ref
Definition: glext.h:6028
static PVOID ptr
Definition: dispmode.c:27
#define TYPE_EXTENT_ITEM
Definition: btrfs.h:35
uint64_t size
Definition: btrfs.h:369
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) __attribute__((nonnull(1
uint64_t offset
Definition: btrfs.h:413
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
Status
Definition: gdiplustypes.h:24
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define TYPE_SHARED_DATA_REF
Definition: btrfs.h:41
EXTENT_ITEM * ei
Definition: balance.c:27
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
GLintptr offset
Definition: glext.h:5920
#define Vcb
Definition: cdprocs.h:1415
const GLubyte * c
Definition: glext.h:8905
KEY firstitem
Definition: btrfs.h:398
uint8_t level
Definition: btrfs.h:162
#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:280
#define TYPE_SHARED_BLOCK_REF
Definition: btrfs.h:40
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
uint64_t offset
Definition: btrfs.h:437
uint32_t count
Definition: btrfs.h:442
uint8_t level
Definition: btrfs.h:399
Definition: typedefs.h:119
#define EXTENT_TYPE_PREALLOC
Definition: btrfs.h:76
BYTE uint8_t
Definition: msvideo1.c:66
uint64_t generation
Definition: btrfs.h:393
#define EXTENT_TYPE_REGULAR
Definition: btrfs.h:75
#define ERR(fmt,...)
Definition: debug.h:110
uint8_t data[1]
Definition: btrfs.h:364
Definition: btrfs.h:143
UINT64 uint64_t
Definition: types.h:77
GLuint in
Definition: glext.h:9616
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
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:597
Definition: list.h:27
#define NULL
Definition: types.h:112
UINT32 uint32_t
Definition: types.h:75
uint64_t address
Definition: btrfs_drv.h:590
#define c
Definition: ke_i.h:80
unsigned int ULONG
Definition: retypes.h:1
uint32_t num_items
Definition: btrfs.h:161
#define EXTENT_ITEM_SHARED_BACKREFS
Definition: btrfs.h:389
#define STATUS_SUCCESS
Definition: shellext.h:65
uint64_t flags
Definition: btrfs.h:394
#define TYPE_EXTENT_DATA
Definition: btrfs.h:30
uint64_t offset
Definition: btrfs.h:441
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
NTSTATUS NTSTATUS NTSTATUS NTSTATUS NTSTATUS chunk * get_chunk_from_address(device_extension *Vcb, uint64_t address) __attribute__((nonnull(1)))
Definition: copy.c:22
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 226 of file balance.c.

227  {
228  LIST_ENTRY* le;
229  KEY searchkey;
231  bool skinny = false;
233 
234  le = items->Flink;
235  while (le != items) {
237 
238  if (mr->address == address) {
239  *mr2 = mr;
240  return STATUS_SUCCESS;
241  }
242 
243  le = le->Flink;
244  }
245 
246  searchkey.obj_id = address;
247  searchkey.obj_type = TYPE_METADATA_ITEM;
248  searchkey.offset = 0xffffffffffffffff;
249 
250  Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, false, NULL);
251  if (!NT_SUCCESS(Status)) {
252  ERR("find_item returned %08lx\n", Status);
253  return Status;
254  }
255 
257  skinny = true;
258  else if (tp.item->key.obj_id == address && tp.item->key.obj_type == TYPE_EXTENT_ITEM && tp.item->key.offset == Vcb->superblock.node_size &&
259  tp.item->size >= sizeof(EXTENT_ITEM)) {
261 
262  if (!(ei->flags & EXTENT_ITEM_TREE_BLOCK)) {
263  ERR("EXTENT_ITEM for %I64x found, but tree flag not set\n", address);
264  return STATUS_INTERNAL_ERROR;
265  }
266  } else {
267  ERR("could not find valid EXTENT_ITEM for address %I64x\n", address);
268  return STATUS_INTERNAL_ERROR;
269  }
270 
271  Status = add_metadata_reloc(Vcb, items, &tp, skinny, mr2, NULL, rollback);
272  if (!NT_SUCCESS(Status)) {
273  ERR("add_metadata_reloc returned %08lx\n", Status);
274  return Status;
275  }
276 
277  return STATUS_SUCCESS;
278 }
uint64_t obj_id
Definition: btrfs.h:144
uint8_t obj_type
Definition: btrfs.h:145
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:73
LONG NTSTATUS
Definition: precomp.h:26
uint16_t size
Definition: btrfs_drv.h:414
#define TYPE_METADATA_ITEM
Definition: btrfs.h:36
if(dx==0 &&dy==0)
Definition: linetemp.h:174
uint64_t offset
Definition: btrfs.h:146
uint8_t * data
Definition: btrfs_drv.h:415
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
#define TYPE_EXTENT_ITEM
Definition: btrfs.h:35
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:2965
Status
Definition: gdiplustypes.h:24
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
NTSTATUS find_item(_In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _Out_ traverse_ptr *tp, _In_ const KEY *searchkey, _In_ bool ignore, _In_opt_ PIRP Irp) __attribute__((nonnull(1
#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:502
Definition: typedefs.h:119
#define ERR(fmt,...)
Definition: debug.h:110
Definition: btrfs.h:143
#define EXTENT_ITEM_TREE_BLOCK
Definition: btrfs.h:388
uint64_t address
Definition: balance.c:24
Definition: list.h:27
#define NULL
Definition: types.h:112
_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:1355
#define STATUS_SUCCESS
Definition: shellext.h:65
uint64_t flags
Definition: btrfs.h:394
static TCHAR * items[]
Definition: page1.c:45

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 1671 of file balance.c.

1671  {
1672  KEY searchkey;
1673  traverse_ptr tp;
1674  NTSTATUS Status;
1675  bool b;
1676  LIST_ENTRY items, metadata_items, rollback, *le;
1677  uint64_t loaded = 0, num_loaded = 0;
1678  chunk* newchunk = NULL;
1679  uint8_t* data = NULL;
1680 
1681  TRACE("chunk %I64x\n", c->offset);
1682 
1685  InitializeListHead(&metadata_items);
1686 
1687  ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
1688 
1689  searchkey.obj_id = c->offset;
1690  searchkey.obj_type = TYPE_EXTENT_ITEM;
1691  searchkey.offset = 0xffffffffffffffff;
1692 
1693  Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, false, NULL);
1694  if (!NT_SUCCESS(Status)) {
1695  ERR("find_item returned %08lx\n", Status);
1696  goto end;
1697  }
1698 
1699  do {
1700  traverse_ptr next_tp;
1701 
1702  if (tp.item->key.obj_id >= c->offset + c->chunk_item->size)
1703  break;
1704 
1705  if (tp.item->key.obj_id >= c->offset && tp.item->key.obj_type == TYPE_EXTENT_ITEM) {
1706  bool tree = false;
1707 
1708  if (tp.item->key.obj_type == TYPE_EXTENT_ITEM && tp.item->size >= sizeof(EXTENT_ITEM)) {
1709  EXTENT_ITEM* ei = (EXTENT_ITEM*)tp.item->data;
1710 
1712  tree = true;
1713  }
1714 
1715  if (!tree) {
1716  Status = add_data_reloc(Vcb, &items, &metadata_items, &tp, c, &rollback);
1717 
1718  if (!NT_SUCCESS(Status)) {
1719  ERR("add_data_reloc returned %08lx\n", Status);
1720  goto end;
1721  }
1722 
1723  loaded += tp.item->key.offset;
1724  num_loaded++;
1725 
1726  if (loaded >= 0x1000000 || num_loaded >= 100) // only do so much at a time, so we don't block too obnoxiously
1727  break;
1728  }
1729  }
1730 
1731  b = find_next_item(Vcb, &tp, &next_tp, false, NULL);
1732 
1733  if (b)
1734  tp = next_tp;
1735  } while (b);
1736 
1737  if (IsListEmpty(&items)) {
1738  *changed = false;
1740  goto end;
1741  } else
1742  *changed = true;
1743 
1745  if (!data) {
1746  ERR("out of memory\n");
1748  goto end;
1749  }
1750 
1751  le = items.Flink;
1752  while (le != &items) {
1754  bool done = false;
1755  LIST_ENTRY* le2;
1756  void* csum;
1757  RTL_BITMAP bmp;
1758  ULONG* bmparr;
1759  ULONG bmplen, runlength, index, lastoff;
1760 
1761  if (newchunk) {
1762  acquire_chunk_lock(newchunk, Vcb);
1763 
1764  if (find_data_address_in_chunk(Vcb, newchunk, dr->size, &dr->new_address)) {
1765  newchunk->used += dr->size;
1766  space_list_subtract(newchunk, dr->new_address, dr->size, &rollback);
1767  done = true;
1768  }
1769 
1770  release_chunk_lock(newchunk, Vcb);
1771  }
1772 
1773  if (!done) {
1774  ExAcquireResourceExclusiveLite(&Vcb->chunk_lock, true);
1775 
1776  le2 = Vcb->chunks.Flink;
1777  while (le2 != &Vcb->chunks) {
1778  chunk* c2 = CONTAINING_RECORD(le2, chunk, list_entry);
1779 
1780  if (!c2->readonly && !c2->reloc && c2 != newchunk && c2->chunk_item->type == Vcb->data_flags) {
1781  acquire_chunk_lock(c2, Vcb);
1782 
1783  if ((c2->chunk_item->size - c2->used) >= dr->size) {
1784  if (find_data_address_in_chunk(Vcb, c2, dr->size, &dr->new_address)) {
1785  c2->used += dr->size;
1786  space_list_subtract(c2, dr->new_address, dr->size, &rollback);
1787  release_chunk_lock(c2, Vcb);
1788  newchunk = c2;
1789  done = true;
1790  break;
1791  }
1792  }
1793 
1794  release_chunk_lock(c2, Vcb);
1795  }
1796 
1797  le2 = le2->Flink;
1798  }
1799 
1800  // allocate new chunk if necessary
1801  if (!done) {
1802  Status = alloc_chunk(Vcb, Vcb->data_flags, &newchunk, false);
1803 
1804  if (!NT_SUCCESS(Status)) {
1805  ERR("alloc_chunk returned %08lx\n", Status);
1806  ExReleaseResourceLite(&Vcb->chunk_lock);
1807  goto end;
1808  }
1809 
1810  acquire_chunk_lock(newchunk, Vcb);
1811 
1812  newchunk->balance_num = Vcb->balance.balance_num;
1813 
1814  if (!find_data_address_in_chunk(Vcb, newchunk, dr->size, &dr->new_address)) {
1815  release_chunk_lock(newchunk, Vcb);
1816  ExReleaseResourceLite(&Vcb->chunk_lock);
1817  ERR("could not find address in new chunk\n");
1819  goto end;
1820  } else {
1821  newchunk->used += dr->size;
1822  space_list_subtract(newchunk, dr->new_address, dr->size, &rollback);
1823  }
1824 
1825  release_chunk_lock(newchunk, Vcb);
1826  }
1827 
1828  ExReleaseResourceLite(&Vcb->chunk_lock);
1829  }
1830 
1831  dr->newchunk = newchunk;
1832 
1833  bmplen = (ULONG)(dr->size >> Vcb->sector_shift);
1834 
1835  bmparr = ExAllocatePoolWithTag(PagedPool, (ULONG)sector_align(bmplen + 1, sizeof(ULONG)), ALLOC_TAG);
1836  if (!bmparr) {
1837  ERR("out of memory\n");
1839  goto end;
1840  }
1841 
1842  csum = ExAllocatePoolWithTag(PagedPool, (ULONG)((dr->size * Vcb->csum_size) >> Vcb->sector_shift), ALLOC_TAG);
1843  if (!csum) {
1844  ERR("out of memory\n");
1845  ExFreePool(bmparr);
1847  goto end;
1848  }
1849 
1850  RtlInitializeBitMap(&bmp, bmparr, bmplen);
1851  RtlSetAllBits(&bmp); // 1 = no csum, 0 = csum
1852 
1853  searchkey.obj_id = EXTENT_CSUM_ID;
1854  searchkey.obj_type = TYPE_EXTENT_CSUM;
1855  searchkey.offset = dr->address;
1856 
1857  Status = find_item(Vcb, Vcb->checksum_root, &tp, &searchkey, false, NULL);
1858  if (!NT_SUCCESS(Status) && Status != STATUS_NOT_FOUND) {
1859  ERR("find_item returned %08lx\n", Status);
1860  ExFreePool(csum);
1861  ExFreePool(bmparr);
1862  goto end;
1863  }
1864 
1865  if (Status != STATUS_NOT_FOUND) {
1866  do {
1867  traverse_ptr next_tp;
1868 
1869  if (tp.item->key.obj_type == TYPE_EXTENT_CSUM) {
1870  if (tp.item->key.offset >= dr->address + dr->size)
1871  break;
1872  else if (tp.item->size >= Vcb->csum_size && tp.item->key.offset + (((unsigned int)tp.item->size << Vcb->sector_shift) / Vcb->csum_size) >= dr->address) {
1873  uint64_t cs = max(dr->address, tp.item->key.offset);
1874  uint64_t ce = min(dr->address + dr->size, tp.item->key.offset + (((unsigned int)tp.item->size << Vcb->sector_shift) / Vcb->csum_size));
1875 
1876  RtlCopyMemory((uint8_t*)csum + (((cs - dr->address) * Vcb->csum_size) >> Vcb->sector_shift),
1877  tp.item->data + (((cs - tp.item->key.offset) * Vcb->csum_size) >> Vcb->sector_shift),
1878  (ULONG)(((ce - cs) * Vcb->csum_size) >> Vcb->sector_shift));
1879 
1880  RtlClearBits(&bmp, (ULONG)((cs - dr->address) >> Vcb->sector_shift), (ULONG)((ce - cs) >> Vcb->sector_shift));
1881 
1882  if (ce == dr->address + dr->size)
1883  break;
1884  }
1885  }
1886 
1887  if (find_next_item(Vcb, &tp, &next_tp, false, NULL))
1888  tp = next_tp;
1889  else
1890  break;
1891  } while (true);
1892  }
1893 
1894  lastoff = 0;
1895  runlength = RtlFindFirstRunClear(&bmp, &index);
1896 
1897  while (runlength != 0) {
1898  if (index >= bmplen)
1899  break;
1900 
1901  if (index + runlength >= bmplen) {
1902  runlength = bmplen - index;
1903 
1904  if (runlength == 0)
1905  break;
1906  }
1907 
1908  if (index > lastoff) {
1909  ULONG off = lastoff;
1910  ULONG size = index - lastoff;
1911 
1912  // handle no csum run
1913  do {
1914  ULONG rl;
1915 
1916  if (size << Vcb->sector_shift > BALANCE_UNIT)
1917  rl = BALANCE_UNIT >> Vcb->sector_shift;
1918  else
1919  rl = size;
1920 
1921  Status = read_data(Vcb, dr->address + (off << Vcb->sector_shift), rl << Vcb->sector_shift, NULL, false, data,
1922  c, NULL, NULL, 0, false, NormalPagePriority);
1923  if (!NT_SUCCESS(Status)) {
1924  ERR("read_data returned %08lx\n", Status);
1925  ExFreePool(csum);
1926  ExFreePool(bmparr);
1927  goto end;
1928  }
1929 
1930  Status = write_data_complete(Vcb, dr->new_address + (off << Vcb->sector_shift), data, rl << Vcb->sector_shift,
1931  NULL, newchunk, false, 0, NormalPagePriority);
1932  if (!NT_SUCCESS(Status)) {
1933  ERR("write_data_complete returned %08lx\n", Status);
1934  ExFreePool(csum);
1935  ExFreePool(bmparr);
1936  goto end;
1937  }
1938 
1939  size -= rl;
1940  off += rl;
1941  } while (size > 0);
1942  }
1943 
1944  add_checksum_entry(Vcb, dr->new_address + (index << Vcb->sector_shift), runlength, (uint8_t*)csum + (index * Vcb->csum_size), NULL);
1945  add_checksum_entry(Vcb, dr->address + (index << Vcb->sector_shift), runlength, NULL, NULL);
1946 
1947  // handle csum run
1948  do {
1949  ULONG rl;
1950 
1951  if (runlength << Vcb->sector_shift > BALANCE_UNIT)
1952  rl = BALANCE_UNIT >> Vcb->sector_shift;
1953  else
1954  rl = runlength;
1955 
1956  Status = read_data(Vcb, dr->address + (index << Vcb->sector_shift), rl << Vcb->sector_shift,
1957  (uint8_t*)csum + (index * Vcb->csum_size), false, data, c, NULL, NULL, 0, false, NormalPagePriority);
1958  if (!NT_SUCCESS(Status)) {
1959  ERR("read_data returned %08lx\n", Status);
1960  ExFreePool(csum);
1961  ExFreePool(bmparr);
1962  goto end;
1963  }
1964 
1965  Status = write_data_complete(Vcb, dr->new_address + (index << Vcb->sector_shift), data, rl << Vcb->sector_shift,
1966  NULL, newchunk, false, 0, NormalPagePriority);
1967  if (!NT_SUCCESS(Status)) {
1968  ERR("write_data_complete returned %08lx\n", Status);
1969  ExFreePool(csum);
1970  ExFreePool(bmparr);
1971  goto end;
1972  }
1973 
1974  runlength -= rl;
1975  index += rl;
1976  } while (runlength > 0);
1977 
1978  lastoff = index;
1979  runlength = RtlFindNextForwardRunClear(&bmp, index, &index);
1980  }
1981 
1982  ExFreePool(csum);
1983  ExFreePool(bmparr);
1984 
1985  // handle final nocsum run
1986  if (lastoff < dr->size >> Vcb->sector_shift) {
1987  ULONG off = lastoff;
1988  ULONG size = (ULONG)((dr->size >> Vcb->sector_shift) - lastoff);
1989 
1990  do {
1991  ULONG rl;
1992 
1993  if (size << Vcb->sector_shift > BALANCE_UNIT)
1994  rl = BALANCE_UNIT >> Vcb->sector_shift;
1995  else
1996  rl = size;
1997 
1998  Status = read_data(Vcb, dr->address + (off << Vcb->sector_shift), rl << Vcb->sector_shift, NULL, false, data,
1999  c, NULL, NULL, 0, false, NormalPagePriority);
2000  if (!NT_SUCCESS(Status)) {
2001  ERR("read_data returned %08lx\n", Status);
2002  goto end;
2003  }
2004 
2005  Status = write_data_complete(Vcb, dr->new_address + (off << Vcb->sector_shift), data, rl << Vcb->sector_shift,
2006  NULL, newchunk, false, 0, NormalPagePriority);
2007  if (!NT_SUCCESS(Status)) {
2008  ERR("write_data_complete returned %08lx\n", Status);
2009  goto end;
2010  }
2011 
2012  size -= rl;
2013  off += rl;
2014  } while (size > 0);
2015  }
2016 
2017  le = le->Flink;
2018  }
2019 
2020  ExFreePool(data);
2021  data = NULL;
2022 
2023  Status = write_metadata_items(Vcb, &metadata_items, &items, NULL, &rollback);
2024  if (!NT_SUCCESS(Status)) {
2025  ERR("write_metadata_items returned %08lx\n", Status);
2026  goto end;
2027  }
2028 
2029  le = items.Flink;
2030  while (le != &items) {
2032 
2034  if (!NT_SUCCESS(Status)) {
2035  ERR("add_data_reloc_extent_item returned %08lx\n", Status);
2036  goto end;
2037  }
2038 
2039  le = le->Flink;
2040  }
2041 
2042  le = c->changed_extents.Flink;
2043  while (le != &c->changed_extents) {
2044  LIST_ENTRY *le2, *le3;
2046 
2047  le3 = le->Flink;
2048 
2049  le2 = items.Flink;
2050  while (le2 != &items) {
2052 
2053  if (ce->address == dr->address) {
2054  ce->address = dr->new_address;
2057  break;
2058  }
2059 
2060  le2 = le2->Flink;
2061  }
2062 
2063  le = le3;
2064  }
2065 
2067 
2068  Vcb->need_write = true;
2069 
2070 end:
2071  if (NT_SUCCESS(Status)) {
2072  // update extents in cache inodes before we flush
2073  le = Vcb->chunks.Flink;
2074  while (le != &Vcb->chunks) {
2076 
2077  if (c2->cache) {
2078  LIST_ENTRY* le2;
2079 
2080  ExAcquireResourceExclusiveLite(c2->cache->Header.Resource, true);
2081 
2082  le2 = c2->cache->extents.Flink;
2083  while (le2 != &c2->cache->extents) {
2085 
2086  if (!ext->ignore) {
2087  if (ext->extent_data.type == EXTENT_TYPE_REGULAR || ext->extent_data.type == EXTENT_TYPE_PREALLOC) {
2088  EXTENT_DATA2* ed2 = (EXTENT_DATA2*)ext->extent_data.data;
2089 
2090  if (ed2->size > 0 && ed2->address >= c->offset && ed2->address < c->offset + c->chunk_item->size) {
2091  LIST_ENTRY* le3 = items.Flink;
2092  while (le3 != &items) {
2094 
2095  if (ed2->address == dr->address) {
2096  ed2->address = dr->new_address;
2097  break;
2098  }
2099 
2100  le3 = le3->Flink;
2101  }
2102  }
2103  }
2104  }
2105 
2106  le2 = le2->Flink;
2107  }
2108 
2109  ExReleaseResourceLite(c2->cache->Header.Resource);
2110  }
2111 
2112  le = le->Flink;
2113  }
2114 
2115  Status = do_write(Vcb, NULL);
2116  if (!NT_SUCCESS(Status))
2117  ERR("do_write returned %08lx\n", Status);
2118  }
2119 
2120  if (NT_SUCCESS(Status)) {
2122 
2123  // update open FCBs
2124  // FIXME - speed this up(?)
2125 
2126  le = Vcb->all_fcbs.Flink;
2127  while (le != &Vcb->all_fcbs) {
2128  struct _fcb* fcb = CONTAINING_RECORD(le, struct _fcb, list_entry_all);
2129  LIST_ENTRY* le2;
2130 
2131  ExAcquireResourceExclusiveLite(fcb->Header.Resource, true);
2132 
2133  le2 = fcb->extents.Flink;
2134  while (le2 != &fcb->extents) {
2136 
2137  if (!ext->ignore) {
2138  if (ext->extent_data.type == EXTENT_TYPE_REGULAR || ext->extent_data.type == EXTENT_TYPE_PREALLOC) {
2139  EXTENT_DATA2* ed2 = (EXTENT_DATA2*)ext->extent_data.data;
2140 
2141  if (ed2->size > 0 && ed2->address >= c->offset && ed2->address < c->offset + c->chunk_item->size) {
2142  LIST_ENTRY* le3 = items.Flink;
2143  while (le3 != &items) {
2145 
2146  if (ed2->address == dr->address) {
2147  ed2->address = dr->new_address;
2148  break;
2149  }
2150 
2151  le3 = le3->Flink;
2152  }
2153  }
2154  }
2155  }
2156 
2157  le2 = le2->Flink;
2158  }
2159 
2160  ExReleaseResourceLite(fcb->Header.Resource);
2161 
2162  le = le->Flink;
2163  }
2164  } else
2166 
2167  free_trees(Vcb);
2168 
2169  ExReleaseResourceLite(&Vcb->tree_lock);
2170 
2171  if (data)
2172  ExFreePool(data);
2173 
2174  while (!IsListEmpty(&items)) {
2176 
2177  while (!IsListEmpty(&dr->refs)) {
2179 
2180  ExFreePool(ref);
2181  }
2182 
2183  ExFreePool(dr);
2184  }
2185 
2186  while (!IsListEmpty(&metadata_items)) {
2188 
2189  while (!IsListEmpty(&mr->refs)) {
2191 
2192  ExFreePool(ref);
2193  }
2194 
2195  if (mr->data)
2196  ExFreePool(mr->data);
2197 
2198  ExFreePool(mr);
2199  }
2200 
2201  return Status;
2202 }
uint64_t obj_id
Definition: btrfs.h:144
#define max(a, b)
Definition: svc.c:63
uint8_t obj_type
Definition: btrfs.h:145
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
LIST_ENTRY list_entry
Definition: btrfs_drv.h:599
NTSTATUS do_write(device_extension *Vcb, PIRP Irp)
Definition: flushthread.c:7759
NTSYSAPI void WINAPI RtlInitializeBitMap(PRTL_BITMAP, PULONG, ULONG)
LONG NTSTATUS
Definition: precomp.h:26
uint16_t size
Definition: btrfs_drv.h:414
uint64_t used
Definition: btrfs_drv.h:558
bool readonly
Definition: btrfs_drv.h:573
tree_header * data
Definition: balance.c:26
#define InsertTailList(ListHead, Entry)
NTSTATUS NTSTATUS 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) __attribute__((nonnull(1
if(dx==0 &&dy==0)
Definition: linetemp.h:174
_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:146
uint8_t * data
Definition: btrfs_drv.h:415
LIST_ENTRY list_entry_all
Definition: btrfs_drv.h:337
#define TYPE_EXTENT_CSUM
Definition: btrfs.h:31
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:87
uint64_t size
Definition: btrfs.h:340
uint32_t cs
Definition: isohybrid.c:75
uint64_t address
Definition: btrfs.h:368
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
char ext[3]
Definition: mkdosfs.c:358
#define TYPE_EXTENT_ITEM
Definition: btrfs.h:35
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
#define release_chunk_lock(c, Vcb)
Definition: btrfs_drv.h:1132
uint64_t size
Definition: btrfs.h:369
bool reloc
Definition: btrfs_drv.h:574
GLuint index
Definition: glext.h:6031
NTSTATUS alloc_chunk(device_extension *Vcb, uint64_t flags, chunk **pc, bool full_size) __attribute__((nonnull(1
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:2965
FSRTL_ADVANCED_FCB_HEADER Header
Definition: btrfs_drv.h:283
Status
Definition: gdiplustypes.h:24
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
NTSTATUS find_item(_In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _Out_ traverse_ptr *tp, _In_ const KEY *searchkey, _In_ bool ignore, _In_opt_ PIRP Irp) __attribute__((nonnull(1
#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:1541
const GLubyte * c
Definition: glext.h:8905
NTSTATUS NTSTATUS void clear_rollback(LIST_ENTRY *rollback) __attribute__((nonnull(1)))
LIST_ENTRY extents
Definition: btrfs_drv.h:300
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:1316
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
GLuint GLuint end
Definition: gl.h:1545
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
tree_data * item
Definition: btrfs_drv.h:502
#define index(s, c)
Definition: various.h:29
LIST_ENTRY changed_extents
Definition: btrfs_drv.h:566
void add_checksum_entry(device_extension *Vcb, uint64_t address, ULONG length, void *csum, PIRP Irp)
Definition: flushthread.c:2596
Definition: typedefs.h:119
void do_rollback(device_extension *Vcb, LIST_ENTRY *rollback) __attribute__((nonnull(1
#define EXTENT_TYPE_PREALLOC
Definition: btrfs.h:76
BYTE uint8_t
Definition: msvideo1.c:66
NTSTATUS NTSTATUS 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) __attribute__((nonnull(1
#define BALANCE_UNIT
Definition: balance.c:71
#define EXTENT_TYPE_REGULAR
Definition: btrfs.h:75
NTSTATUS NTSTATUS bool bool void free_trees(device_extension *Vcb) __attribute__((nonnull(1)))
#define ERR(fmt,...)
Definition: debug.h:110
NTSYSAPI void WINAPI RtlClearBits(PRTL_BITMAP, ULONG, ULONG)
Definition: btrfs.h:143
#define EXTENT_CSUM_ID
Definition: btrfs.h:91
UINT64 uint64_t
Definition: types.h:77
void space_list_subtract(chunk *c, uint64_t address, uint64_t length, LIST_ENTRY *rollback)
Definition: free-space.c:2234
#define EXTENT_ITEM_TREE_BLOCK
Definition: btrfs.h:388
#define acquire_chunk_lock(c, Vcb)
Definition: btrfs_drv.h:1131
#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
#define NULL
Definition: types.h:112
_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:1355
uint64_t address
Definition: btrfs_drv.h:590
CHUNK_ITEM * chunk_item
Definition: btrfs_drv.h:555
NTSYSAPI ULONG WINAPI RtlFindNextForwardRunClear(PCRTL_BITMAP, ULONG, PULONG)
Definition: ffs.h:52
ULONG balance_num
Definition: btrfs_drv.h:583
#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
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
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:566
#define STATUS_SUCCESS
Definition: shellext.h:65
uint64_t flags
Definition: btrfs.h:394
uint64_t type
Definition: btrfs.h:343
static TCHAR * items[]
Definition: page1.c:45
fcb * cache
Definition: btrfs_drv.h:561
static uint64_t __inline sector_align(uint64_t n, uint64_t a)
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
NTSTATUS bool find_data_address_in_chunk(device_extension *Vcb, chunk *c, uint64_t length, uint64_t *address) __attribute__((nonnull(1
uint64_t size
Definition: balance.c:50
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 1100 of file balance.c.

1100  {
1101  KEY searchkey;
1102  traverse_ptr tp;
1103  NTSTATUS Status;
1104  bool b;
1106  uint32_t loaded = 0;
1107 
1108  TRACE("chunk %I64x\n", c->offset);
1109 
1112 
1113  ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
1114 
1115  searchkey.obj_id = c->offset;
1116  searchkey.obj_type = TYPE_METADATA_ITEM;
1117  searchkey.offset = 0xffffffffffffffff;
1118 
1119  Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, false, NULL);
1120  if (!NT_SUCCESS(Status)) {
1121  ERR("find_item returned %08lx\n", Status);
1122  goto end;
1123  }
1124 
1125  do {
1126  traverse_ptr next_tp;
1127 
1128  if (tp.item->key.obj_id >= c->offset + c->chunk_item->size)
1129  break;
1130 
1131  if (tp.item->key.obj_id >= c->offset && (tp.item->key.obj_type == TYPE_EXTENT_ITEM || tp.item->key.obj_type == TYPE_METADATA_ITEM)) {
1132  bool tree = false, skinny = false;
1133 
1134  if (tp.item->key.obj_type == TYPE_METADATA_ITEM && tp.item->size >= sizeof(EXTENT_ITEM)) {
1135  tree = true;
1136  skinny = true;
1137  } else if (tp.item->key.obj_type == TYPE_EXTENT_ITEM && tp.item->key.offset == Vcb->superblock.node_size &&
1138  tp.item->size >= sizeof(EXTENT_ITEM)) {
1139  EXTENT_ITEM* ei = (EXTENT_ITEM*)tp.item->data;
1140 
1142  tree = true;
1143  }
1144 
1145  if (tree) {
1146  Status = add_metadata_reloc(Vcb, &items, &tp, skinny, NULL, c, &rollback);
1147 
1148  if (!NT_SUCCESS(Status)) {
1149  ERR("add_metadata_reloc returned %08lx\n", Status);
1150  goto end;
1151  }
1152 
1153  loaded++;
1154 
1155  if (loaded >= 64) // only do 64 at a time
1156  break;
1157  }
1158  }
1159 
1160  b = find_next_item(Vcb, &tp, &next_tp, false, NULL);
1161 
1162  if (b)
1163  tp = next_tp;
1164  } while (b);
1165 
1166  if (IsListEmpty(&items)) {
1167  *changed = false;
1169  goto end;
1170  } else
1171  *changed = true;
1172 
1174  if (!NT_SUCCESS(Status)) {
1175  ERR("write_metadata_items returned %08lx\n", Status);
1176  goto end;
1177  }
1178 
1180 
1181  Vcb->need_write = true;
1182 
1183 end:
1184  if (NT_SUCCESS(Status)) {
1185  Status = do_write(Vcb, NULL);
1186  if (!NT_SUCCESS(Status))
1187  ERR("do_write returned %08lx\n", Status);
1188  }
1189 
1190  if (NT_SUCCESS(Status))
1192  else
1194 
1195  free_trees(Vcb);
1196 
1197  ExReleaseResourceLite(&Vcb->tree_lock);
1198 
1199  while (!IsListEmpty(&items)) {
1201 
1202  while (!IsListEmpty(&mr->refs)) {
1204 
1205  ExFreePool(ref);
1206  }
1207 
1208  if (mr->data)
1209  ExFreePool(mr->data);
1210 
1211  ExFreePool(mr);
1212  }
1213 
1214  return Status;
1215 }
uint64_t obj_id
Definition: btrfs.h:144
uint8_t obj_type
Definition: btrfs.h:145
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:73
NTSTATUS do_write(device_extension *Vcb, PIRP Irp)
Definition: flushthread.c:7759
LONG NTSTATUS
Definition: precomp.h:26
uint16_t size
Definition: btrfs_drv.h:414
tree_header * data
Definition: balance.c:26
NTSTATUS NTSTATUS 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) __attribute__((nonnull(1
#define TYPE_METADATA_ITEM
Definition: btrfs.h:36
if(dx==0 &&dy==0)
Definition: linetemp.h:174
_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:146
uint8_t * data
Definition: btrfs_drv.h:415
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
#define TYPE_EXTENT_ITEM
Definition: btrfs.h:35
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
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:2965
Status
Definition: gdiplustypes.h:24
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
#define TRACE(s)
Definition: solgame.cpp:4
NTSTATUS find_item(_In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _Out_ traverse_ptr *tp, _In_ const KEY *searchkey, _In_ bool ignore, _In_opt_ PIRP Irp) __attribute__((nonnull(1
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1415
const GLubyte * c
Definition: glext.h:8905
NTSTATUS NTSTATUS void clear_rollback(LIST_ENTRY *rollback) __attribute__((nonnull(1)))
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
BOOL loaded
Definition: xmlview.c:54
GLuint GLuint end
Definition: gl.h:1545
tree_data * item
Definition: btrfs_drv.h:502
Definition: typedefs.h:119
void do_rollback(device_extension *Vcb, LIST_ENTRY *rollback) __attribute__((nonnull(1
NTSTATUS NTSTATUS bool bool void free_trees(device_extension *Vcb) __attribute__((nonnull(1)))
#define ERR(fmt,...)
Definition: debug.h:110
Definition: btrfs.h:143
#define EXTENT_ITEM_TREE_BLOCK
Definition: btrfs.h:388
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
Definition: list.h:27
#define NULL
Definition: types.h:112
_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:1355
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:566
#define STATUS_SUCCESS
Definition: shellext.h:65
uint64_t flags
Definition: btrfs.h:394
static TCHAR * items[]
Definition: page1.c:45
#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 2318 of file balance.c.

2318  {
2319  if (opts->flags & BTRFS_BALANCE_OPTS_PROFILES) {
2320  args->profiles = opts->profiles;
2322  }
2323 
2324  if (opts->flags & BTRFS_BALANCE_OPTS_USAGE) {
2325  if (args->usage_start == 0) {
2327  args->usage_start = opts->usage_start;
2328  args->usage_end = opts->usage_end;
2329  } else {
2330  args->flags |= BALANCE_ARGS_FLAGS_USAGE;
2331  args->usage = opts->usage_end;
2332  }
2333  }
2334 
2335  if (opts->flags & BTRFS_BALANCE_OPTS_DEVID) {
2336  args->devid = opts->devid;
2337  args->flags |= BALANCE_ARGS_FLAGS_DEVID;
2338  }
2339 
2340  if (opts->flags & BTRFS_BALANCE_OPTS_DRANGE) {
2341  args->drange_start = opts->drange_start;
2342  args->drange_end = opts->drange_end;
2343  args->flags |= BALANCE_ARGS_FLAGS_DRANGE;
2344  }
2345 
2346  if (opts->flags & BTRFS_BALANCE_OPTS_VRANGE) {
2347  args->vrange_start = opts->vrange_start;
2348  args->vrange_end = opts->vrange_end;
2349  args->flags |= BALANCE_ARGS_FLAGS_VRANGE;
2350  }
2351 
2352  if (opts->flags & BTRFS_BALANCE_OPTS_CONVERT) {
2353  args->convert = opts->convert;
2354  args->flags |= BALANCE_ARGS_FLAGS_CONVERT;
2355 
2356  if (opts->flags & BTRFS_BALANCE_OPTS_SOFT)
2357  args->flags |= BALANCE_ARGS_FLAGS_SOFT;
2358  }
2359 
2360  if (opts->flags & BTRFS_BALANCE_OPTS_LIMIT) {
2361  if (args->limit_start == 0) {
2363  args->limit_start = (uint32_t)opts->limit_start;
2364  args->limit_end = (uint32_t)opts->limit_end;
2365  } else {
2366  args->flags |= BALANCE_ARGS_FLAGS_LIMIT;
2367  args->limit = opts->limit_end;
2368  }
2369  }
2370 
2371  if (opts->flags & BTRFS_BALANCE_OPTS_STRIPES) {
2372  args->stripes_start = opts->stripes_start;
2373  args->stripes_end = opts->stripes_end;
2375  }
2376 }
#define BALANCE_ARGS_FLAGS_DRANGE
Definition: btrfs.h:483
#define BALANCE_ARGS_FLAGS_LIMIT_RANGE
Definition: btrfs.h:486
#define BTRFS_BALANCE_OPTS_PROFILES
Definition: btrfsioctl.h:131
#define BALANCE_ARGS_FLAGS_VRANGE
Definition: btrfs.h:484
#define BALANCE_ARGS_FLAGS_STRIPES_RANGE
Definition: btrfs.h:487
#define BALANCE_ARGS_FLAGS_PROFILES
Definition: btrfs.h:480
#define BALANCE_ARGS_FLAGS_LIMIT
Definition: btrfs.h:485
uint16_t stripes_end
Definition: btrfsioctl.h:154
#define BTRFS_BALANCE_OPTS_VRANGE
Definition: btrfsioctl.h:134
Definition: match.c:390
#define BALANCE_ARGS_FLAGS_USAGE_RANGE
Definition: btrfs.h:490
uint64_t limit_start
Definition: btrfsioctl.h:151
#define BALANCE_ARGS_FLAGS_SOFT
Definition: btrfs.h:489
#define BTRFS_BALANCE_OPTS_USAGE
Definition: btrfsioctl.h:137
uint64_t vrange_start
Definition: btrfsioctl.h:149
#define BTRFS_BALANCE_OPTS_CONVERT
Definition: btrfsioctl.h:138
#define BTRFS_BALANCE_OPTS_SOFT
Definition: btrfsioctl.h:139
uint64_t limit_end
Definition: btrfsioctl.h:152
#define BALANCE_ARGS_FLAGS_CONVERT
Definition: btrfs.h:488
uint64_t drange_end
Definition: btrfsioctl.h:148
#define BTRFS_BALANCE_OPTS_LIMIT
Definition: btrfsioctl.h:135
#define BTRFS_BALANCE_OPTS_DRANGE
Definition: btrfsioctl.h:133
uint16_t stripes_start
Definition: btrfsioctl.h:153
#define BALANCE_ARGS_FLAGS_USAGE
Definition: btrfs.h:481
uint64_t vrange_end
Definition: btrfsioctl.h:150
uint64_t drange_start
Definition: btrfsioctl.h:147
#define BALANCE_ARGS_FLAGS_DEVID
Definition: btrfs.h:482
UINT32 uint32_t
Definition: types.h:75
#define BTRFS_BALANCE_OPTS_DEVID
Definition: btrfsioctl.h:132
#define uint32_t
Definition: nsiface.idl:61
#define BTRFS_BALANCE_OPTS_STRIPES
Definition: btrfsioctl.h:136

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 1217 of file balance.c.

1218  {
1219  NTSTATUS Status;
1220  LIST_ENTRY* le;
1221  KEY searchkey;
1222  traverse_ptr tp;
1223  root* r = NULL;
1224  metadata_reloc* mr;
1225  uint64_t last_tree = 0;
1227 
1228  le = Vcb->roots.Flink;
1229  while (le != &Vcb->roots) {
1231 
1232  if (r2->id == edr->root) {
1233  r = r2;
1234  break;
1235  }
1236 
1237  le = le->Flink;
1238  }
1239 
1240  if (!r) {
1241  ERR("could not find subvol %I64x\n", edr->root);
1242  return STATUS_INTERNAL_ERROR;
1243  }
1244 
1245  searchkey.obj_id = edr->objid;
1246  searchkey.obj_type = TYPE_EXTENT_DATA;
1247  searchkey.offset = 0;
1248 
1249  Status = find_item(Vcb, r, &tp, &searchkey, false, NULL);
1250  if (!NT_SUCCESS(Status)) {
1251  ERR("find_item returned %08lx\n", Status);
1252  return Status;
1253  }
1254 
1255  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)) {
1256  traverse_ptr tp2;
1257 
1258  if (find_next_item(Vcb, &tp, &tp2, false, NULL))
1259  tp = tp2;
1260  else {
1261  ERR("could not find EXTENT_DATA for inode %I64x in root %I64x\n", searchkey.obj_id, r->id);
1262  return STATUS_INTERNAL_ERROR;
1263  }
1264  }
1265 
1266  ref = NULL;
1267 
1268  while (tp.item->key.obj_id == searchkey.obj_id && tp.item->key.obj_type == searchkey.obj_type) {
1269  traverse_ptr tp2;
1270 
1271  if (tp.item->size >= sizeof(EXTENT_DATA)) {
1272  EXTENT_DATA* ed = (EXTENT_DATA*)tp.item->data;
1273 
1274  if ((ed->type == EXTENT_TYPE_PREALLOC || ed->type == EXTENT_TYPE_REGULAR) && tp.item->size >= offsetof(EXTENT_DATA, data[0]) + sizeof(EXTENT_DATA2)) {
1275  EXTENT_DATA2* ed2 = (EXTENT_DATA2*)ed->data;
1276 
1277  if (ed2->address == dr->address && ed2->size == dr->size && tp.item->key.offset - ed2->offset == edr->offset) {
1278  if (ref && last_tree == tp.tree->header.address)
1279  ref->edr.count++;
1280  else {
1282  if (!ref) {
1283  ERR("out of memory\n");
1285  }
1286 
1287  ref->type = TYPE_EXTENT_DATA_REF;
1288  RtlCopyMemory(&ref->edr, edr, sizeof(EXTENT_DATA_REF));
1289  ref->edr.count = 1;
1290 
1291  Status = add_metadata_reloc_parent(Vcb, metadata_items, tp.tree->header.address, &mr, rollback);
1292  if (!NT_SUCCESS(Status)) {
1293  ERR("add_metadata_reloc_parent returned %08lx\n", Status);
1294  ExFreePool(ref);
1295  return Status;
1296  }
1297 
1298  last_tree = tp.tree->header.address;
1299  ref->parent = mr;
1300 
1301  InsertTailList(&dr->refs, &ref->list_entry);
1302  }
1303  }
1304  }
1305  }
1306 
1307  if (find_next_item(Vcb, &tp, &tp2, false, NULL))
1308  tp = tp2;
1309  else
1310  break;
1311  }
1312 
1313  return STATUS_SUCCESS;
1314 }
uint64_t obj_id
Definition: btrfs.h:144
uint8_t type
Definition: btrfs.h:363
uint8_t obj_type
Definition: btrfs.h:145
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
uint64_t offset
Definition: btrfs.h:419
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
LONG NTSTATUS
Definition: precomp.h:26
uint64_t objid
Definition: btrfs.h:418
uint16_t size
Definition: btrfs_drv.h:414
#define InsertTailList(ListHead, Entry)
NTSTATUS NTSTATUS 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) __attribute__((nonnull(1
if(dx==0 &&dy==0)
Definition: linetemp.h:174
LIST_ENTRY list_entry
Definition: send.c:49
Definition: send.c:48
uint64_t offset
Definition: btrfs.h:146
uint8_t * data
Definition: btrfs_drv.h:415
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
#define ALLOC_TAG
Definition: btrfs_drv.h:87
uint64_t address
Definition: btrfs.h:156
tree * tree
Definition: btrfs_drv.h:501
uint64_t address
Definition: btrfs.h:368
GLenum GLint ref
Definition: glext.h:6028
LIST_ENTRY refs
Definition: balance.c:54
#define offsetof(TYPE, MEMBER)
uint64_t size
Definition: btrfs.h:369
uint64_t root
Definition: btrfs.h:417
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:38
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2965
Status
Definition: gdiplustypes.h:24
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
NTSTATUS find_item(_In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _Out_ traverse_ptr *tp, _In_ const KEY *searchkey, _In_ bool ignore, _In_opt_ PIRP Irp) __attribute__((nonnull(1
#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:502
tree_header header
Definition: btrfs_drv.h:426
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:226
#define EXTENT_TYPE_PREALLOC
Definition: btrfs.h:76
#define EXTENT_TYPE_REGULAR
Definition: btrfs.h:75
#define ERR(fmt,...)
Definition: debug.h:110
uint8_t data[1]
Definition: btrfs.h:364
Definition: btrfs.h:143
UINT64 uint64_t
Definition: types.h:77
Definition: list.h:27
#define NULL
Definition: types.h:112
_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:1355
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint64_t offset
Definition: btrfs.h:370
#define STATUS_SUCCESS
Definition: shellext.h:65
#define TYPE_EXTENT_DATA
Definition: btrfs.h:30
#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 2586 of file balance.c.

2586  {
2587  KEY searchkey;
2588  traverse_ptr tp;
2589  NTSTATUS Status;
2590  LIST_ENTRY* le;
2592 
2593  if (Vcb->need_write) {
2594  Status = do_write(Vcb, NULL);
2595 
2596  if (!NT_SUCCESS(Status))
2597  ERR("do_write returned %08lx\n", Status);
2598  } else
2600 
2601  free_trees(Vcb);
2602 
2603  if (!NT_SUCCESS(Status))
2604  return Status;
2605 
2606  // remove entry in chunk tree
2607 
2608  searchkey.obj_id = 1;
2609  searchkey.obj_type = TYPE_DEV_ITEM;
2610  searchkey.offset = dev->devitem.dev_id;
2611 
2612  Status = find_item(Vcb, Vcb->chunk_root, &tp, &searchkey, false, NULL);
2613  if (!NT_SUCCESS(Status)) {
2614  ERR("find_item returned %08lx\n", Status);
2615  return Status;
2616  }
2617 
2618  if (!keycmp(searchkey, tp.item->key)) {
2620 
2621  if (!NT_SUCCESS(Status)) {
2622  ERR("delete_tree_item returned %08lx\n", Status);
2623  return Status;
2624  }
2625  }
2626 
2627  // remove stats entry in device tree
2628 
2629  searchkey.obj_id = 0;
2630  searchkey.obj_type = TYPE_DEV_STATS;
2631  searchkey.offset = dev->devitem.dev_id;
2632 
2633  Status = find_item(Vcb, Vcb->dev_root, &tp, &searchkey, false, NULL);
2634  if (!NT_SUCCESS(Status)) {
2635  ERR("find_item returned %08lx\n", Status);
2636  return Status;
2637  }
2638 
2639  if (!keycmp(searchkey, tp.item->key)) {
2641 
2642  if (!NT_SUCCESS(Status)) {
2643  ERR("delete_tree_item returned %08lx\n", Status);
2644  return Status;
2645  }
2646  }
2647 
2648  // update superblock
2649 
2650  Vcb->superblock.num_devices--;
2651  Vcb->superblock.total_bytes -= dev->devitem.num_bytes;
2652  Vcb->devices_loaded--;
2653 
2654  RemoveEntryList(&dev->list_entry);
2655 
2656  // flush
2657 
2658  Status = do_write(Vcb, NULL);
2659  if (!NT_SUCCESS(Status))
2660  ERR("do_write returned %08lx\n", Status);
2661 
2662  free_trees(Vcb);
2663 
2664  if (!NT_SUCCESS(Status))
2665  return Status;
2666 
2667  if (!dev->readonly && dev->devobj) {
2669  if (!NT_SUCCESS(Status))
2670  WARN("remove_superblocks returned %08lx\n", Status);
2671  }
2672 
2673  // remove entry in volume list
2674 
2675  vde = Vcb->vde;
2676 
2677  if (dev->devobj) {
2678  pdo_device_extension* pdode = vde->pdode;
2679 
2681 
2682  le = pdode->children.Flink;
2683  while (le != &pdode->children) {
2685 
2686  if (RtlCompareMemory(&dev->devitem.device_uuid, &vc->uuid, sizeof(BTRFS_UUID)) == sizeof(BTRFS_UUID)) {
2689  UNICODE_STRING mmdevpath;
2690 
2691  pdode->children_loaded--;
2692 
2693  if (vc->had_drive_letter) { // re-add entry to mountmgr
2696  if (!NT_SUCCESS(Status))
2697  ERR("IoGetDeviceObjectPointer returned %08lx\n", Status);
2698  else {
2699  MOUNTDEV_NAME mdn;
2700 
2701  Status = dev_ioctl(dev->devobj, IOCTL_MOUNTDEV_QUERY_DEVICE_NAME, NULL, 0, &mdn, sizeof(MOUNTDEV_NAME), true, NULL);
2703  ERR("IOCTL_MOUNTDEV_QUERY_DEVICE_NAME returned %08lx\n", Status);
2704  else {
2705  MOUNTDEV_NAME* mdn2;
2706  ULONG mdnsize = (ULONG)offsetof(MOUNTDEV_NAME, Name[0]) + mdn.NameLength;
2707 
2708  mdn2 = ExAllocatePoolWithTag(PagedPool, mdnsize, ALLOC_TAG);
2709  if (!mdn2)
2710  ERR("out of memory\n");
2711  else {
2712  Status = dev_ioctl(dev->devobj, IOCTL_MOUNTDEV_QUERY_DEVICE_NAME, NULL, 0, mdn2, mdnsize, true, NULL);
2713  if (!NT_SUCCESS(Status))
2714  ERR("IOCTL_MOUNTDEV_QUERY_DEVICE_NAME returned %08lx\n", Status);
2715  else {
2717 
2718  name.Buffer = mdn2->Name;
2719  name.Length = name.MaximumLength = mdn2->NameLength;
2720 
2722  if (!NT_SUCCESS(Status))
2723  WARN("mountmgr_add_drive_letter returned %08lx\n", Status);
2724  }
2725 
2726  ExFreePool(mdn2);
2727  }
2728  }
2729 
2731  }
2732  }
2733 
2734  ExFreePool(vc->pnp_name.Buffer);
2736  ExFreePool(vc);
2737 
2739 
2740  break;
2741  }
2742 
2743  le = le->Flink;
2744  }
2745 
2746  if (pdode->children_loaded > 0 && vde->device->Characteristics & FILE_REMOVABLE_MEDIA) {
2747  vde->device->Characteristics &= ~FILE_REMOVABLE_MEDIA;
2748 
2749  le = pdode->children.Flink;
2750  while (le != &pdode->children) {
2752 
2753  if (vc->devobj->Characteristics & FILE_REMOVABLE_MEDIA) {
2754  vde->device->Characteristics |= FILE_REMOVABLE_MEDIA;
2755  break;
2756  }
2757 
2758  le = le->Flink;
2759  }
2760  }
2761 
2762  pdode->num_children = Vcb->superblock.num_devices;
2763 
2765 
2766  // free dev
2767 
2768  if (dev->trim && !dev->readonly && !Vcb->options.no_trim)
2770  }
2771 
2772  while (!IsListEmpty(&dev->space)) {
2773  LIST_ENTRY* le2 = RemoveHeadList(&dev->space);
2775 
2776  ExFreePool(s);
2777  }
2778 
2779  ExFreePool(dev);
2780 
2781  if (Vcb->trim) {
2782  Vcb->trim = false;
2783 
2784  le = Vcb->devices.Flink;
2785  while (le != &Vcb->devices) {
2786  device* dev2 = CONTAINING_RECORD(le, device, list_entry);
2787 
2788  if (dev2->trim) {
2789  Vcb->trim = true;
2790  break;
2791  }
2792 
2793  le = le->Flink;
2794  }
2795  }
2796 
2798 
2799  return STATUS_SUCCESS;
2800 }
uint64_t obj_id
Definition: btrfs.h:144
#define TYPE_DEV_ITEM
Definition: btrfs.h:47
UNICODE_STRING pnp_name
Definition: btrfs_drv.h:851
void trim_whole_device(device *dev)
Definition: fsctl.c:2712
uint8_t obj_type
Definition: btrfs.h:145
#define TYPE_DEV_STATS
Definition: btrfs.h:50
NTSTATUS do_write(device_extension *Vcb, PIRP Irp)
Definition: flushthread.c:7759
PDEVICE_OBJECT device
Definition: btrfs_drv.h:867
#define keycmp(key1, key2)
Definition: btrfs_drv.h:1008
#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
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
uint64_t offset
Definition: btrfs.h:146
#define MOUNTMGR_DEVICE_NAME
Definition: imports.h:76
NTSTATUS mountmgr_add_drive_letter(PDEVICE_OBJECT mountmgr, PUNICODE_STRING devpath)
Definition: volume.c:832
BTRFS_UUID uuid
Definition: btrfs_drv.h:846
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:886
#define ALLOC_TAG
Definition: btrfs_drv.h:87
#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:525
#define offsetof(TYPE, MEMBER)
PDEVICE_OBJECT devobj
Definition: btrfs_drv.h:849
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
struct pdo_device_extension * pdode
Definition: btrfs_drv.h:870
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_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:547
#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:2965
Status
Definition: gdiplustypes.h:24
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
uint64_t children_loaded
Definition: btrfs_drv.h:887
NTSTATUS NTAPI FsRtlNotifyVolumeEvent(IN PFILE_OBJECT FileObject, IN ULONG EventCode)
Definition: pnp.c:38
NTSTATUS find_item(_In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _Out_ traverse_ptr *tp, _In_ const KEY *searchkey, _In_ bool ignore, _In_opt_ PIRP Irp) __attribute__((nonnull(1
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:2923
bool had_drive_letter
Definition: btrfs_drv.h:854
#define Vcb
Definition: cdprocs.h:1415
#define ObDereferenceObject
Definition: obfuncs.h:203
ERESOURCE child_lock
Definition: btrfs_drv.h:888
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
* PFILE_OBJECT
Definition: iotypes.h:1998
#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:502
PFILE_OBJECT fileobj
Definition: btrfs_drv.h:850
GLdouble s
Definition: gl.h:2039
Definition: typedefs.h:119
static NTSTATUS remove_superblocks(device *dev)
Definition: balance.c:2557
NTSTATUS NTSTATUS bool bool void free_trees(device_extension *Vcb) __attribute__((nonnull(1)))
#define ERR(fmt,...)
Definition: debug.h:110
Definition: btrfs.h:143
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
NTSTATUS NTSTATUS delete_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _Inout_ traverse_ptr *tp) __attribute__((nonnull(1
Definition: list.h:27
#define NULL
Definition: types.h:112
USHORT NameLength
Definition: imports.h:143
uint64_t dev_id
Definition: name.c:38
LIST_ENTRY list_entry
Definition: btrfs_drv.h:859
unsigned int ULONG
Definition: retypes.h:1
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define STATUS_SUCCESS
Definition: shellext.h:65
LIST_ENTRY children
Definition: btrfs_drv.h:889
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
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 2204 of file balance.c.

2204  {
2205  if (c->chunk_item->type & BLOCK_FLAG_RAID0)
2206  return BLOCK_FLAG_RAID0;
2207  else if (c->chunk_item->type & BLOCK_FLAG_RAID1)
2208  return BLOCK_FLAG_RAID1;
2209  else if (c->chunk_item->type & BLOCK_FLAG_DUPLICATE)
2210  return BLOCK_FLAG_DUPLICATE;
2211  else if (c->chunk_item->type & BLOCK_FLAG_RAID10)
2212  return BLOCK_FLAG_RAID10;
2213  else if (c->chunk_item->type & BLOCK_FLAG_RAID5)
2214  return BLOCK_FLAG_RAID5;
2215  else if (c->chunk_item->type & BLOCK_FLAG_RAID6)
2216  return BLOCK_FLAG_RAID6;
2217  else if (c->chunk_item->type & BLOCK_FLAG_RAID1C3)
2218  return BLOCK_FLAG_RAID1C3;
2219  else if (c->chunk_item->type & BLOCK_FLAG_RAID1C4)
2220  return BLOCK_FLAG_RAID1C4;
2221  else
2222  return BLOCK_FLAG_SINGLE;
2223 }
#define BLOCK_FLAG_SINGLE
Definition: btrfsioctl.h:141
#define BLOCK_FLAG_RAID1C3
Definition: btrfs.h:87
#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:88
#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 2492 of file balance.c.

2492  {
2494 
2495  if (args->flags & BALANCE_ARGS_FLAGS_PROFILES) {
2497  opts->profiles = args->profiles;
2498  }
2499 
2500  if (args->flags & BALANCE_ARGS_FLAGS_USAGE) {
2502 
2503  opts->usage_start = 0;
2504  opts->usage_end = (uint8_t)args->usage;
2505  } else if (args->flags & BALANCE_ARGS_FLAGS_USAGE_RANGE) {
2507 
2508  opts->usage_start = (uint8_t)args->usage_start;
2509  opts->usage_end = (uint8_t)args->usage_end;
2510  }
2511 
2512  if (args->flags & BALANCE_ARGS_FLAGS_DEVID) {
2514  opts->devid = args->devid;
2515  }
2516 
2517  if (args->flags & BALANCE_ARGS_FLAGS_DRANGE) {
2519  opts->drange_start = args->drange_start;
2520  opts->drange_end = args->drange_end;
2521  }
2522 
2523  if (args->flags & BALANCE_ARGS_FLAGS_VRANGE) {
2525  opts->vrange_start = args->vrange_start;
2526  opts->vrange_end = args->vrange_end;
2527  }
2528 
2529  if (args->flags & BALANCE_ARGS_FLAGS_LIMIT) {
2531 
2532  opts->limit_start = 0;
2533  opts->limit_end = args->limit;
2534  } else if (args->flags & BALANCE_ARGS_FLAGS_LIMIT_RANGE) {
2536 
2537  opts->limit_start = args->limit_start;
2538  opts->limit_end = args->limit_end;
2539  }
2540 
2541  if (args->flags & BALANCE_ARGS_FLAGS_STRIPES_RANGE) {
2543 
2544  opts->stripes_start = (uint16_t)args->stripes_start;
2545  opts->stripes_end = (uint16_t)args->stripes_end;
2546  }
2547 
2548  if (args->flags & BALANCE_ARGS_FLAGS_CONVERT) {
2550  opts->convert = args->convert;
2551 
2552  if (args->flags & BALANCE_ARGS_FLAGS_SOFT)
2553  opts->flags |= BTRFS_BALANCE_OPTS_SOFT;
2554  }
2555 }
#define BALANCE_ARGS_FLAGS_DRANGE
Definition: btrfs.h:483
#define BALANCE_ARGS_FLAGS_LIMIT_RANGE
Definition: btrfs.h:486
#define BTRFS_BALANCE_OPTS_PROFILES
Definition: btrfsioctl.h:131
#define BALANCE_ARGS_FLAGS_VRANGE
Definition: btrfs.h:484
#define BALANCE_ARGS_FLAGS_STRIPES_RANGE
Definition: btrfs.h:487
#define BALANCE_ARGS_FLAGS_PROFILES
Definition: btrfs.h:480
#define BALANCE_ARGS_FLAGS_LIMIT
Definition: btrfs.h:485
uint16_t stripes_end
Definition: btrfsioctl.h:154
#define BTRFS_BALANCE_OPTS_VRANGE
Definition: btrfsioctl.h:134
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:490
uint64_t limit_start
Definition: btrfsioctl.h:151
#define BALANCE_ARGS_FLAGS_SOFT
Definition: btrfs.h:489
#define BTRFS_BALANCE_OPTS_USAGE
Definition: btrfsioctl.h:137
uint64_t vrange_start
Definition: btrfsioctl.h:149
#define BTRFS_BALANCE_OPTS_CONVERT
Definition: btrfsioctl.h:138
#define BTRFS_BALANCE_OPTS_SOFT
Definition: btrfsioctl.h:139
uint64_t limit_end
Definition: btrfsioctl.h:152
#define BALANCE_ARGS_FLAGS_CONVERT
Definition: btrfs.h:488
uint64_t drange_end
Definition: btrfsioctl.h:148
#define BTRFS_BALANCE_OPTS_LIMIT
Definition: btrfsioctl.h:135
#define BTRFS_BALANCE_OPTS_ENABLED
Definition: btrfsioctl.h:130
#define BTRFS_BALANCE_OPTS_DRANGE
Definition: btrfsioctl.h:133
BYTE uint8_t
Definition: msvideo1.c:66
uint16_t stripes_start
Definition: btrfsioctl.h:153
#define uint8_t
Definition: nsiface.idl:59
#define BALANCE_ARGS_FLAGS_USAGE
Definition: btrfs.h:481
uint64_t vrange_end
Definition: btrfsioctl.h:150
uint64_t drange_start
Definition: btrfsioctl.h:147
#define BALANCE_ARGS_FLAGS_DEVID
Definition: btrfs.h:482
#define BTRFS_BALANCE_OPTS_DEVID
Definition: btrfsioctl.h:132
#define BTRFS_BALANCE_OPTS_STRIPES
Definition: btrfsioctl.h:136

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 3628 of file balance.c.

3628  {
3629  KEY searchkey;
3630  traverse_ptr tp;
3631  NTSTATUS Status;
3632  BALANCE_ITEM* bi;
3633  OBJECT_ATTRIBUTES oa;
3634  int i;
3635 
3636  searchkey.obj_id = BALANCE_ITEM_ID;
3637  searchkey.obj_type = TYPE_TEMP_ITEM;
3638  searchkey.offset = 0;
3639 
3640  Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, false, NULL);
3641  if (!NT_SUCCESS(Status)) {
3642  ERR("find_item returned %08lx\n", Status);
3643  return Status;
3644  }
3645 
3646  if (keycmp(tp.item->key, searchkey)) {
3647  TRACE("no balance item found\n");
3648  return STATUS_NOT_FOUND;
3649  }
3650 
3651  if (tp.item->size < sizeof(BALANCE_ITEM)) {
3652  WARN("(%I64x,%x,%I64x) was %u bytes, expected %Iu\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset,
3653  tp.item->size, sizeof(BALANCE_ITEM));
3654  return STATUS_INTERNAL_ERROR;
3655  }
3656 
3657  bi = (BALANCE_ITEM*)tp.item->data;
3658 
3659  if (bi->flags & BALANCE_FLAGS_DATA)
3660  load_balance_args(&Vcb->balance.opts[BALANCE_OPTS_DATA], &bi->data);
3661 
3662  if (bi->flags & BALANCE_FLAGS_METADATA)
3663  load_balance_args(&Vcb->balance.opts[BALANCE_OPTS_METADATA], &bi->metadata);
3664 
3665  if (bi->flags & BALANCE_FLAGS_SYSTEM)
3666  load_balance_args(&Vcb->balance.opts[BALANCE_OPTS_SYSTEM], &bi->system);
3667 
3668  // do the heuristics that Linux driver does
3669 
3670  for (i = 0; i < 3; i++) {
3671  if (Vcb->balance.opts[i].flags & BTRFS_BALANCE_OPTS_ENABLED) {
3672  // if converting, don't redo chunks already done
3673 
3674  if (Vcb->balance.opts[i].flags & BTRFS_BALANCE_OPTS_CONVERT)
3675  Vcb->balance.opts[i].flags |= BTRFS_BALANCE_OPTS_SOFT;
3676 
3677  // don't balance chunks more than 90% filled - presumably these
3678  // have already been done
3679 
3680  if (!(Vcb->balance.opts[i].flags & BTRFS_BALANCE_OPTS_USAGE) &&
3681  !(Vcb->balance.opts[i].flags & BTRFS_BALANCE_OPTS_CONVERT)
3682  ) {
3683  Vcb->balance.opts[i].flags |= BTRFS_BALANCE_OPTS_USAGE;
3684  Vcb->balance.opts[i].usage_start = 0;
3685  Vcb->balance.opts[i].usage_end = 90;
3686  }
3687  }
3688  }
3689 
3690  if (Vcb->readonly || Vcb->options.skip_balance)
3691  Vcb->balance.paused = true;
3692  else
3693  Vcb->balance.paused = false;
3694 
3695  Vcb->balance.removing = false;
3696  Vcb->balance.shrinking = false;
3697  Vcb->balance.status = STATUS_SUCCESS;
3698  KeInitializeEvent(&Vcb->balance.event, NotificationEvent, !Vcb->balance.paused);
3699 
3701 
3702  Status = PsCreateSystemThread(&Vcb->balance.thread, 0, &oa, NULL, NULL, balance_thread, Vcb);
3703  if (!NT_SUCCESS(