ReactOS  0.4.14-dev-317-g96040ec
balance.c File Reference
#include "btrfs_drv.h"
#include "btrfsioctl.h"
#include <ntddstor.h>
Include dependency graph for balance.c:

Go to the source code of this file.

Classes

struct  metadata_reloc
 
struct  metadata_reloc_ref
 
struct  data_reloc
 
struct  data_reloc_ref
 

Macros

#define DEVICE_DSM_FLAG_TRIM_NOT_FS_ALLOCATED   0x80000000
 
#define BALANCE_UNIT   0x100000
 

Functions

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

Macro Definition Documentation

◆ BALANCE_UNIT

#define BALANCE_UNIT   0x100000

Definition at line 74 of file balance.c.

◆ DEVICE_DSM_FLAG_TRIM_NOT_FS_ALLOCATED

#define DEVICE_DSM_FLAG_TRIM_NOT_FS_ALLOCATED   0x80000000

Definition at line 71 of file balance.c.

Function Documentation

◆ _Function_class_()

_Function_class_ ( KSTART_ROUTINE  )

Definition at line 3046 of file balance.c.

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

◆ add_balance_item()

static NTSTATUS add_balance_item ( device_extension Vcb)
static

Definition at line 2377 of file balance.c.

2377  {
2378  KEY searchkey;
2379  traverse_ptr tp;
2380  NTSTATUS Status;
2381  BALANCE_ITEM* bi;
2382 
2383  searchkey.obj_id = BALANCE_ITEM_ID;
2384  searchkey.obj_type = TYPE_TEMP_ITEM;
2385  searchkey.offset = 0;
2386 
2387  ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
2388 
2389  Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, false, NULL);
2390  if (!NT_SUCCESS(Status)) {
2391  ERR("find_item returned %08x\n", Status);
2392  goto end;
2393  }
2394 
2395  if (!keycmp(tp.item->key, searchkey)) {
2397  if (!NT_SUCCESS(Status)) {
2398  ERR("delete_tree_item returned %08x\n", Status);
2399  goto end;
2400  }
2401  }
2402 
2404  if (!bi) {
2405  ERR("out of memory\n");
2407  goto end;
2408  }
2409 
2410  RtlZeroMemory(bi, sizeof(BALANCE_ITEM));
2411 
2412  if (Vcb->balance.opts[BALANCE_OPTS_DATA].flags & BTRFS_BALANCE_OPTS_ENABLED) {
2413  bi->flags |= BALANCE_FLAGS_DATA;
2414  copy_balance_args(&Vcb->balance.opts[BALANCE_OPTS_DATA], &bi->data);
2415  }
2416 
2417  if (Vcb->balance.opts[BALANCE_OPTS_METADATA].flags & BTRFS_BALANCE_OPTS_ENABLED) {
2419  copy_balance_args(&Vcb->balance.opts[BALANCE_OPTS_METADATA], &bi->metadata);
2420  }
2421 
2422  if (Vcb->balance.opts[BALANCE_OPTS_SYSTEM].flags & BTRFS_BALANCE_OPTS_ENABLED) {
2423  bi->flags |= BALANCE_FLAGS_SYSTEM;
2424  copy_balance_args(&Vcb->balance.opts[BALANCE_OPTS_SYSTEM], &bi->system);
2425  }
2426 
2427  Status = insert_tree_item(Vcb, Vcb->root_root, BALANCE_ITEM_ID, TYPE_TEMP_ITEM, 0, bi, sizeof(BALANCE_ITEM), NULL, NULL);
2428  if (!NT_SUCCESS(Status)) {
2429  ERR("insert_tree_item returned %08x\n", Status);
2430  ExFreePool(bi);
2431  goto end;
2432  }
2433 
2435 
2436 end:
2437  if (NT_SUCCESS(Status)) {
2438  Status = do_write(Vcb, NULL);
2439  if (!NT_SUCCESS(Status))
2440  ERR("do_write returned %08x\n", Status);
2441  }
2442 
2443  free_trees(Vcb);
2444 
2445  ExReleaseResourceLite(&Vcb->tree_lock);
2446 
2447  return Status;
2448 }
#define BALANCE_ITEM_ID
Definition: btrfs.h:86
uint64_t obj_id
Definition: btrfs.h:128
uint8_t obj_type
Definition: btrfs.h:129
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define BALANCE_OPTS_SYSTEM
Definition: btrfs_drv.h:672
NTSTATUS do_write(device_extension *Vcb, PIRP Irp)
Definition: flushthread.c:7667
#define keycmp(key1, key2)
Definition: btrfs_drv.h:991
LONG NTSTATUS
Definition: precomp.h:26
uint64_t flags
Definition: btrfs.h:503
GLuint GLuint end
Definition: gl.h:1545
BALANCE_ARGS data
Definition: btrfs.h:504
uint64_t offset
Definition: btrfs.h:130
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
#define ALLOC_TAG
Definition: btrfs_drv.h:91
smooth NULL
Definition: ftsmooth.c:416
void free_trees(device_extension *Vcb)
Definition: treefuncs.c:793
#define TYPE_TEMP_ITEM
Definition: btrfs.h:45
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2855
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1425
static void copy_balance_args(btrfs_balance_opts *opts, BALANCE_ARGS *args)
Definition: balance.c:2317
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
NTSTATUS insert_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _In_ uint64_t obj_id, _In_ uint8_t obj_type, _In_ uint64_t offset, _In_reads_bytes_opt_(size) _When_(return >=0, __drv_aliasesMem) void *data, _In_ uint16_t size, _Out_opt_ traverse_ptr *ptp, _In_opt_ PIRP Irp)
Definition: treefuncs.c:857
#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:129
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
Definition: btrfs.h:127
#define BALANCE_FLAGS_SYSTEM
Definition: btrfs.h:455
BALANCE_ARGS metadata
Definition: btrfs.h:505
#define BALANCE_FLAGS_DATA
Definition: btrfs.h:454
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
BALANCE_ARGS system
Definition: btrfs.h:506
#define BALANCE_OPTS_METADATA
Definition: btrfs_drv.h:671
return STATUS_SUCCESS
Definition: btrfs.c:2938
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
NTSTATUS delete_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _Inout_ traverse_ptr *tp)
Definition: treefuncs.c:989
#define BALANCE_FLAGS_METADATA
Definition: btrfs.h:456
#define BALANCE_OPTS_DATA
Definition: btrfs_drv.h:670

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

1320  {
1321  NTSTATUS Status;
1322  data_reloc* dr;
1323  EXTENT_ITEM* ei;
1324  uint16_t len;
1325  uint64_t inline_rc;
1326  uint8_t* ptr;
1327 
1329  if (!dr) {
1330  ERR("out of memory\n");
1332  }
1333 
1334  dr->address = tp->item->key.obj_id;
1335  dr->size = tp->item->key.offset;
1336  dr->ei = (EXTENT_ITEM*)tp->item->data;
1337  InitializeListHead(&dr->refs);
1338 
1340  if (!NT_SUCCESS(Status)) {
1341  ERR("delete_tree_item returned %08x\n", Status);
1342  return Status;
1343  }
1344 
1345  if (!c)
1347 
1348  if (c) {
1350 
1351  c->used -= tp->item->key.offset;
1352 
1354 
1356  }
1357 
1358  ei = (EXTENT_ITEM*)tp->item->data;
1359  inline_rc = 0;
1360 
1361  len = tp->item->size - sizeof(EXTENT_ITEM);
1362  ptr = (uint8_t*)tp->item->data + sizeof(EXTENT_ITEM);
1363 
1364  while (len > 0) {
1365  uint8_t secttype = *ptr;
1366  uint16_t sectlen = secttype == TYPE_EXTENT_DATA_REF ? sizeof(EXTENT_DATA_REF) : (secttype == TYPE_SHARED_DATA_REF ? sizeof(SHARED_DATA_REF) : 0);
1367 
1368  len--;
1369 
1370  if (sectlen > len) {
1371  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);
1372  return STATUS_INTERNAL_ERROR;
1373  }
1374 
1375  if (sectlen == 0) {
1376  ERR("(%I64x,%x,%I64x): unrecognized extent type %x\n", tp->item->key.obj_id, tp->item->key.obj_type, tp->item->key.offset, secttype);
1377  return STATUS_INTERNAL_ERROR;
1378  }
1379 
1380  if (secttype == TYPE_EXTENT_DATA_REF) {
1381  EXTENT_DATA_REF* edr = (EXTENT_DATA_REF*)(ptr + sizeof(uint8_t));
1382 
1383  inline_rc += edr->count;
1384 
1385  Status = data_reloc_add_tree_edr(Vcb, metadata_items, dr, edr, rollback);
1386  if (!NT_SUCCESS(Status)) {
1387  ERR("data_reloc_add_tree_edr returned %08x\n", Status);
1388  return Status;
1389  }
1390  } else if (secttype == TYPE_SHARED_DATA_REF) {
1391  metadata_reloc* mr;
1393 
1395  if (!ref) {
1396  ERR("out of memory\n");
1398  }
1399 
1400  ref->type = TYPE_SHARED_DATA_REF;
1401  RtlCopyMemory(&ref->sdr, ptr + sizeof(uint8_t), sizeof(SHARED_DATA_REF));
1402  inline_rc += ref->sdr.count;
1403 
1404  Status = add_metadata_reloc_parent(Vcb, metadata_items, ref->sdr.offset, &mr, rollback);
1405  if (!NT_SUCCESS(Status)) {
1406  ERR("add_metadata_reloc_parent returned %08x\n", Status);
1407  ExFreePool(ref);
1408  return Status;
1409  }
1410 
1411  ref->parent = mr;
1412 
1413  InsertTailList(&dr->refs, &ref->list_entry);
1414  } else {
1415  ERR("unexpected tree type %x\n", secttype);
1416  return STATUS_INTERNAL_ERROR;
1417  }
1418 
1419 
1420  len -= sectlen;
1421  ptr += sizeof(uint8_t) + sectlen;
1422  }
1423 
1424  if (inline_rc < ei->refcount) { // look for non-inline entries
1425  traverse_ptr tp2 = *tp, next_tp;
1426 
1427  while (find_next_item(Vcb, &tp2, &next_tp, false, NULL)) {
1428  tp2 = next_tp;
1429 
1430  if (tp2.item->key.obj_id == tp->item->key.obj_id) {
1431  if (tp2.item->key.obj_type == TYPE_EXTENT_DATA_REF && tp2.item->size >= sizeof(EXTENT_DATA_REF)) {
1432  Status = data_reloc_add_tree_edr(Vcb, metadata_items, dr, (EXTENT_DATA_REF*)tp2.item->data, rollback);
1433  if (!NT_SUCCESS(Status)) {
1434  ERR("data_reloc_add_tree_edr returned %08x\n", Status);
1435  return Status;
1436  }
1437 
1438  Status = delete_tree_item(Vcb, &tp2);
1439  if (!NT_SUCCESS(Status)) {
1440  ERR("delete_tree_item returned %08x\n", Status);
1441  return Status;
1442  }
1443  } else if (tp2.item->key.obj_type == TYPE_SHARED_DATA_REF && tp2.item->size >= sizeof(uint32_t)) {
1444  metadata_reloc* mr;
1446 
1448  if (!ref) {
1449  ERR("out of memory\n");
1451  }
1452 
1453  ref->type = TYPE_SHARED_DATA_REF;
1454  ref->sdr.offset = tp2.item->key.offset;
1455  ref->sdr.count = *((uint32_t*)tp2.item->data);
1456 
1457  Status = add_metadata_reloc_parent(Vcb, metadata_items, ref->sdr.offset, &mr, rollback);
1458  if (!NT_SUCCESS(Status)) {
1459  ERR("add_metadata_reloc_parent returned %08x\n", Status);
1460  ExFreePool(ref);
1461  return Status;
1462  }
1463 
1464  ref->parent = mr;
1465  InsertTailList(&dr->refs, &ref->list_entry);
1466 
1467  Status = delete_tree_item(Vcb, &tp2);
1468  if (!NT_SUCCESS(Status)) {
1469  ERR("delete_tree_item returned %08x\n", Status);
1470  return Status;
1471  }
1472  }
1473  } else
1474  break;
1475  }
1476  }
1477 
1479 
1480  return STATUS_SUCCESS;
1481 }
LIST_ENTRY list_entry
Definition: balance.c:54
uint64_t obj_id
Definition: btrfs.h:128
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
uint8_t obj_type
Definition: btrfs.h:129
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
LONG NTSTATUS
Definition: precomp.h:26
uint16_t size
Definition: btrfs_drv.h:415
release_chunk_lock(c, Vcb)
static NTSTATUS data_reloc_add_tree_edr(_Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, LIST_ENTRY *metadata_items, data_reloc *dr, EXTENT_DATA_REF *edr, LIST_ENTRY *rollback)
Definition: balance.c:1220
unsigned short int uint16_t
Definition: acefiex.h:54
#define InsertTailList(ListHead, Entry)
LIST_ENTRY list_entry
Definition: send.c:48
Definition: send.c:47
uint64_t offset
Definition: btrfs.h:130
uint8_t * data
Definition: btrfs_drv.h:416
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:451
#define ALLOC_TAG
Definition: btrfs_drv.h:91
void space_list_add(chunk *c, uint64_t address, uint64_t length, LIST_ENTRY *rollback)
Definition: free-space.c:1958
GLenum GLint ref
Definition: glext.h:6028
static PVOID ptr
Definition: dispmode.c:27
LIST_ENTRY refs
Definition: balance.c:53
uint32_t count
Definition: btrfs.h:398
smooth NULL
Definition: ftsmooth.c:416
#define TYPE_EXTENT_DATA_REF
Definition: btrfs.h:34
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2855
#define TYPE_SHARED_DATA_REF
Definition: btrfs.h:37
bool find_next_item(_Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, const traverse_ptr *tp, traverse_ptr *next_tp, bool ignore, PIRP Irp)
Definition: treefuncs.c:592
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1425
const GLubyte * c
Definition: glext.h:8905
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
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:229
BYTE uint8_t
Definition: msvideo1.c:66
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
chunk * get_chunk_from_address(device_extension *Vcb, uint64_t address)
Definition: write.c:89
UINT64 uint64_t
Definition: types.h:77
#define uint8_t
Definition: nsiface.idl:59
#define acquire_chunk_lock(c, Vcb)
Definition: btrfs_drv.h:1104
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY * rollback
Definition: btrfs_drv.h:1314
UINT32 uint32_t
Definition: types.h:75
EXTENT_ITEM * ei
Definition: balance.c:52
static TCHAR * items[]
Definition: page1.c:45
return STATUS_SUCCESS
Definition: btrfs.c:2938
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
NTSTATUS delete_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _Inout_ traverse_ptr *tp)
Definition: treefuncs.c:989
uint64_t size
Definition: balance.c:49
uint64_t address
Definition: balance.c:48

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

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

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

77  {
79  metadata_reloc* mr;
80  EXTENT_ITEM* ei;
81  uint16_t len;
82  uint64_t inline_rc;
83  uint8_t* ptr;
84 
86  if (!mr) {
87  ERR("out of memory\n");
89  }
90 
91  mr->address = tp->item->key.obj_id;
92  mr->data = NULL;
93  mr->ei = (EXTENT_ITEM*)tp->item->data;
94  mr->system = false;
96 
98  if (!NT_SUCCESS(Status)) {
99  ERR("delete_tree_item returned %08x\n", Status);
100  ExFreePool(mr);
101  return Status;
102  }
103 
104  if (!c)
106 
107  if (c) {
109 
110  c->used -= Vcb->superblock.node_size;
111 
112  space_list_add(c, tp->item->key.obj_id, Vcb->superblock.node_size, rollback);
113 
115  }
116 
117  ei = (EXTENT_ITEM*)tp->item->data;
118  inline_rc = 0;
119 
120  len = tp->item->size - sizeof(EXTENT_ITEM);
121  ptr = (uint8_t*)tp->item->data + sizeof(EXTENT_ITEM);
122  if (!skinny) {
123  len -= sizeof(EXTENT_ITEM2);
124  ptr += sizeof(EXTENT_ITEM2);
125  }
126 
127  while (len > 0) {
128  uint8_t secttype = *ptr;
129  uint16_t sectlen = secttype == TYPE_TREE_BLOCK_REF ? sizeof(TREE_BLOCK_REF) : (secttype == TYPE_SHARED_BLOCK_REF ? sizeof(SHARED_BLOCK_REF) : 0);
131 
132  len--;
133 
134  if (sectlen > len) {
135  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);
136  return STATUS_INTERNAL_ERROR;
137  }
138 
139  if (sectlen == 0) {
140  ERR("(%I64x,%x,%I64x): unrecognized extent type %x\n", tp->item->key.obj_id, tp->item->key.obj_type, tp->item->key.offset, secttype);
141  return STATUS_INTERNAL_ERROR;
142  }
143 
145  if (!ref) {
146  ERR("out of memory\n");
148  }
149 
150  if (secttype == TYPE_TREE_BLOCK_REF) {
151  ref->type = TYPE_TREE_BLOCK_REF;
152  RtlCopyMemory(&ref->tbr, ptr + sizeof(uint8_t), sizeof(TREE_BLOCK_REF));
153  inline_rc++;
154  } else if (secttype == TYPE_SHARED_BLOCK_REF) {
155  ref->type = TYPE_SHARED_BLOCK_REF;
156  RtlCopyMemory(&ref->sbr, ptr + sizeof(uint8_t), sizeof(SHARED_BLOCK_REF));
157  inline_rc++;
158  } else {
159  ERR("unexpected tree type %x\n", secttype);
160  ExFreePool(ref);
161  return STATUS_INTERNAL_ERROR;
162  }
163 
164  ref->parent = NULL;
165  ref->top = false;
167 
168  len -= sectlen;
169  ptr += sizeof(uint8_t) + sectlen;
170  }
171 
172  if (inline_rc < ei->refcount) { // look for non-inline entries
173  traverse_ptr tp2 = *tp, next_tp;
174 
175  while (find_next_item(Vcb, &tp2, &next_tp, false, NULL)) {
176  tp2 = next_tp;
177 
178  if (tp2.item->key.obj_id == tp->item->key.obj_id) {
179  if (tp2.item->key.obj_type == TYPE_TREE_BLOCK_REF) {
181  if (!ref) {
182  ERR("out of memory\n");
184  }
185 
186  ref->type = TYPE_TREE_BLOCK_REF;
187  ref->tbr.offset = tp2.item->key.offset;
188  ref->parent = NULL;
189  ref->top = false;
191 
192  Status = delete_tree_item(Vcb, &tp2);
193  if (!NT_SUCCESS(Status)) {
194  ERR("delete_tree_item returned %08x\n", Status);
195  return Status;
196  }
197  } else if (tp2.item->key.obj_type == TYPE_SHARED_BLOCK_REF) {
199  if (!ref) {
200  ERR("out of memory\n");
202  }
203 
204  ref->type = TYPE_SHARED_BLOCK_REF;
205  ref->sbr.offset = tp2.item->key.offset;
206  ref->parent = NULL;
207  ref->top = false;
209 
210  Status = delete_tree_item(Vcb, &tp2);
211  if (!NT_SUCCESS(Status)) {
212  ERR("delete_tree_item returned %08x\n", Status);
213  return Status;
214  }
215  }
216  } else
217  break;
218  }
219  }
220 
222 
223  if (mr2)
224  *mr2 = mr;
225 
226  return STATUS_SUCCESS;
227 }
uint64_t obj_id
Definition: btrfs.h:128
LIST_ENTRY list_entry
Definition: balance.c:30
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
uint8_t obj_type
Definition: btrfs.h:129
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
LONG NTSTATUS
Definition: precomp.h:26
uint16_t size
Definition: btrfs_drv.h:415
#define TYPE_TREE_BLOCK_REF
Definition: btrfs.h:33
release_chunk_lock(c, Vcb)
unsigned short int uint16_t
Definition: acefiex.h:54
tree_header * data
Definition: balance.c:25
#define InsertTailList(ListHead, Entry)
LIST_ENTRY list_entry
Definition: send.c:48
Definition: send.c:47
uint64_t offset
Definition: btrfs.h:130
uint8_t * data
Definition: btrfs_drv.h:416
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:451
#define ALLOC_TAG
Definition: btrfs_drv.h:91
void space_list_add(chunk *c, uint64_t address, uint64_t length, LIST_ENTRY *rollback)
Definition: free-space.c:1958
GLenum GLint ref
Definition: glext.h:6028
static PVOID ptr
Definition: dispmode.c:27
smooth NULL
Definition: ftsmooth.c:416
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2855
EXTENT_ITEM * ei
Definition: balance.c:26
bool system
Definition: balance.c:28
bool find_next_item(_Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, const traverse_ptr *tp, traverse_ptr *next_tp, bool ignore, PIRP Irp)
Definition: treefuncs.c:592
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1425
const GLubyte * c
Definition: glext.h:8905
#define TYPE_SHARED_BLOCK_REF
Definition: btrfs.h:36
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
tree_data * item
Definition: btrfs_drv.h:502
GLenum GLsizei len
Definition: glext.h:6722
BYTE uint8_t
Definition: msvideo1.c:66
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
chunk * get_chunk_from_address(device_extension *Vcb, uint64_t address)
Definition: write.c:89
UINT64 uint64_t
Definition: types.h:77
#define uint8_t
Definition: nsiface.idl:59
#define acquire_chunk_lock(c, Vcb)
Definition: btrfs_drv.h:1104
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
uint64_t address
Definition: balance.c:23
_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:1314
static TCHAR * items[]
Definition: page1.c:45
return STATUS_SUCCESS
Definition: btrfs.c:2938
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
NTSTATUS delete_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _Inout_ traverse_ptr *tp)
Definition: treefuncs.c:989
LIST_ENTRY refs
Definition: balance.c:29

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

325  {
327  LIST_ENTRY* le;
328  uint64_t rc = 0;
329  uint16_t inline_len;
330  bool all_inline = true;
331  metadata_reloc_ref* first_noninline = NULL;
332  EXTENT_ITEM* ei;
333  uint8_t* ptr;
334 
335  inline_len = sizeof(EXTENT_ITEM);
336  if (!(Vcb->superblock.incompat_flags & BTRFS_INCOMPAT_FLAGS_SKINNY_METADATA))
337  inline_len += sizeof(EXTENT_ITEM2);
338 
340 
341  le = mr->refs.Flink;
342  while (le != &mr->refs) {
344  uint16_t extlen = 0;
345 
346  rc++;
347 
348  if (ref->type == TYPE_TREE_BLOCK_REF)
349  extlen += sizeof(TREE_BLOCK_REF);
350  else if (ref->type == TYPE_SHARED_BLOCK_REF)
351  extlen += sizeof(SHARED_BLOCK_REF);
352 
353  if (all_inline) {
354  if ((ULONG)(inline_len + 1 + extlen) > (Vcb->superblock.node_size >> 2)) {
355  all_inline = false;
356  first_noninline = ref;
357  } else
358  inline_len += extlen + 1;
359  }
360 
361  le = le->Flink;
362  }
363 
364  ei = ExAllocatePoolWithTag(PagedPool, inline_len, ALLOC_TAG);
365  if (!ei) {
366  ERR("out of memory\n");
368  }
369 
370  ei->refcount = rc;
371  ei->generation = mr->ei->generation;
372  ei->flags = mr->ei->flags;
373  ptr = (uint8_t*)&ei[1];
374 
375  if (!(Vcb->superblock.incompat_flags & BTRFS_INCOMPAT_FLAGS_SKINNY_METADATA)) {
376  EXTENT_ITEM2* ei2 = (EXTENT_ITEM2*)ptr;
377 
378  ei2->firstitem = *(KEY*)&mr->data[1];
379  ei2->level = mr->data->level;
380 
381  ptr += sizeof(EXTENT_ITEM2);
382  }
383 
384  le = mr->refs.Flink;
385  while (le != &mr->refs) {
387 
388  if (ref == first_noninline)
389  break;
390 
391  *ptr = ref->type;
392  ptr++;
393 
394  if (ref->type == TYPE_TREE_BLOCK_REF) {
396 
397  tbr->offset = ref->tbr.offset;
398 
399  ptr += sizeof(TREE_BLOCK_REF);
400  } else if (ref->type == TYPE_SHARED_BLOCK_REF) {
402 
403  sbr->offset = ref->parent->new_address;
404 
405  ptr += sizeof(SHARED_BLOCK_REF);
406  }
407 
408  le = le->Flink;
409  }
410 
411  if (Vcb->superblock.incompat_flags & BTRFS_INCOMPAT_FLAGS_SKINNY_METADATA)
412  Status = insert_tree_item(Vcb, Vcb->extent_root, mr->new_address, TYPE_METADATA_ITEM, mr->data->level, ei, inline_len, NULL, NULL);
413  else
414  Status = insert_tree_item(Vcb, Vcb->extent_root, mr->new_address, TYPE_EXTENT_ITEM, Vcb->superblock.node_size, ei, inline_len, NULL, NULL);
415 
416  if (!NT_SUCCESS(Status)) {
417  ERR("insert_tree_item returned %08x\n", Status);
418  ExFreePool(ei);
419  return Status;
420  }
421 
422  if (!all_inline) {
423  le = &first_noninline->list_entry;
424 
425  while (le != &mr->refs) {
427 
428  if (ref->type == TYPE_TREE_BLOCK_REF) {
429  Status = insert_tree_item(Vcb, Vcb->extent_root, mr->new_address, TYPE_TREE_BLOCK_REF, ref->tbr.offset, NULL, 0, NULL, NULL);
430  if (!NT_SUCCESS(Status)) {
431  ERR("insert_tree_item returned %08x\n", Status);
432  return Status;
433  }
434  } else if (ref->type == TYPE_SHARED_BLOCK_REF) {
435  Status = insert_tree_item(Vcb, Vcb->extent_root, mr->new_address, TYPE_SHARED_BLOCK_REF, ref->parent->new_address, NULL, 0, NULL, NULL);
436  if (!NT_SUCCESS(Status)) {
437  ERR("insert_tree_item returned %08x\n", Status);
438  return Status;
439  }
440  }
441 
442  le = le->Flink;
443  }
444  }
445 
447  if (mr->data->level > 0) {
448  uint16_t i;
449  internal_node* in = (internal_node*)&mr->data[1];
450 
451  for (i = 0; i < mr->data->num_items; i++) {
453 
454  if (sbrrc > 0) {
455  SHARED_BLOCK_REF sbr;
456 
457  sbr.offset = mr->new_address;
458 
459  Status = increase_extent_refcount(Vcb, in[i].address, Vcb->superblock.node_size, TYPE_SHARED_BLOCK_REF, &sbr, NULL, 0, NULL);
460  if (!NT_SUCCESS(Status)) {
461  ERR("increase_extent_refcount returned %08x\n", Status);
462  return Status;
463  }
464 
465  sbr.offset = mr->address;
466 
467  Status = decrease_extent_refcount(Vcb, in[i].address, Vcb->superblock.node_size, TYPE_SHARED_BLOCK_REF, &sbr, NULL, 0,
468  sbr.offset, false, NULL);
469  if (!NT_SUCCESS(Status)) {
470  ERR("decrease_extent_refcount returned %08x\n", Status);
471  return Status;
472  }
473  }
474  }
475  } else {
476  uint16_t i;
477  leaf_node* ln = (leaf_node*)&mr->data[1];
478 
479  for (i = 0; i < mr->data->num_items; i++) {
480  if (ln[i].key.obj_type == TYPE_EXTENT_DATA && ln[i].size >= sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2)) {
481  EXTENT_DATA* ed = (EXTENT_DATA*)((uint8_t*)mr->data + sizeof(tree_header) + ln[i].offset);
482 
485 
486  if (ed2->size > 0) { // not sparse
488 
489  if (sdrrc > 0) {
490  SHARED_DATA_REF sdr;
491  chunk* c;
492 
493  sdr.offset = mr->new_address;
494  sdr.count = sdrrc;
495 
497  if (!NT_SUCCESS(Status)) {
498  ERR("increase_extent_refcount returned %08x\n", Status);
499  return Status;
500  }
501 
502  sdr.offset = mr->address;
503 
505  sdr.offset, false, NULL);
506  if (!NT_SUCCESS(Status)) {
507  ERR("decrease_extent_refcount returned %08x\n", Status);
508  return Status;
509  }
510 
512 
513  if (c) {
514  // check changed_extents
515 
516  ExAcquireResourceExclusiveLite(&c->changed_extents_lock, true);
517 
518  le = c->changed_extents.Flink;
519 
520  while (le != &c->changed_extents) {
522 
523  if (ce->address == ed2->address) {
524  LIST_ENTRY* le2;
525 
526  le2 = ce->refs.Flink;
527  while (le2 != &ce->refs) {
529 
530  if (cer->type == TYPE_SHARED_DATA_REF && cer->sdr.offset == mr->address) {
531  cer->sdr.offset = mr->new_address;
532  break;
533  }
534 
535  le2 = le2->Flink;
536  }
537 
538  le2 = ce->old_refs.Flink;
539  while (le2 != &ce->old_refs) {
541 
542  if (cer->type == TYPE_SHARED_DATA_REF && cer->sdr.offset == mr->address) {
543  cer->sdr.offset = mr->new_address;
544  break;
545  }
546 
547  le2 = le2->Flink;
548  }
549 
550  break;
551  }
552 
553  le = le->Flink;
554  }
555 
556  ExReleaseResourceLite(&c->changed_extents_lock);
557  }
558  }
559  }
560  }
561  }
562  }
563  }
564  }
565 
566  return STATUS_SUCCESS;
567 }
SHARED_DATA_REF sdr
Definition: btrfs_drv.h:607
uint64_t new_address
Definition: balance.c:24
uint8_t type
Definition: btrfs.h:341
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
EXTENT_DATA2 * ed2
Definition: write.c:2819
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:902
LONG NTSTATUS
Definition: precomp.h:26
uint64_t flags
Definition: btrfs.h:141
GLintptr offset
Definition: glext.h:5920
#define TYPE_TREE_BLOCK_REF
Definition: btrfs.h:33
NTSTATUS increase_extent_refcount(device_extension *Vcb, uint64_t address, uint64_t size, uint8_t type, void *data, KEY *firstitem, uint8_t level, PIRP Irp)
Definition: extent-tree.c:453
#define BTRFS_INCOMPAT_FLAGS_SKINNY_METADATA
Definition: btrfs.h:114
unsigned short int uint16_t
Definition: acefiex.h:54
tree_header * data
Definition: balance.c:25
#define TYPE_METADATA_ITEM
Definition: btrfs.h:32
#define HEADER_FLAG_SHARED_BACKREF
Definition: btrfs.h:134
LIST_ENTRY old_refs
Definition: btrfs_drv.h:598
#define HEADER_FLAG_MIXED_BACKREF
Definition: btrfs.h:135
Definition: send.c:47
LIST_ENTRY list_entry
Definition: balance.c:44
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
#define ALLOC_TAG
Definition: btrfs_drv.h:91
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
uint64_t refcount
Definition: btrfs.h:370
uint64_t address
Definition: btrfs.h:346
GLenum GLint ref
Definition: glext.h:6028
static PVOID ptr
Definition: dispmode.c:27
smooth NULL
Definition: ftsmooth.c:416
#define TYPE_EXTENT_ITEM
Definition: btrfs.h:31
uint64_t size
Definition: btrfs.h:347
uint64_t offset
Definition: btrfs.h:391
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
#define TYPE_SHARED_DATA_REF
Definition: btrfs.h:37
EXTENT_ITEM * ei
Definition: balance.c:26
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1425
const GLubyte * c
Definition: glext.h:8905
KEY firstitem
Definition: btrfs.h:376
uint8_t level
Definition: btrfs.h:146
#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:2118
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
static void sort_metadata_reloc_refs(metadata_reloc *mr)
Definition: balance.c:283
NTSTATUS insert_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _In_ root *r, _In_ uint64_t obj_id, _In_ uint8_t obj_type, _In_ uint64_t offset, _In_reads_bytes_opt_(size) _When_(return >=0, __drv_aliasesMem) void *data, _In_ uint16_t size, _Out_opt_ traverse_ptr *ptp, _In_opt_ PIRP Irp)
Definition: treefuncs.c:857
#define TYPE_SHARED_BLOCK_REF
Definition: btrfs.h:36
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
uint64_t offset
Definition: btrfs.h:415
uint32_t count
Definition: btrfs.h:420
uint8_t level
Definition: btrfs.h:377
Definition: typedefs.h:117
#define EXTENT_TYPE_PREALLOC
Definition: btrfs.h:72
BYTE uint8_t
Definition: msvideo1.c:66
uint64_t generation
Definition: btrfs.h:371
#define EXTENT_TYPE_REGULAR
Definition: btrfs.h:71
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
uint8_t data[1]
Definition: btrfs.h:342
Definition: btrfs.h:127
chunk * get_chunk_from_address(device_extension *Vcb, uint64_t address)
Definition: write.c:89
UINT64 uint64_t
Definition: types.h:77
GLuint in
Definition: glext.h:9616
uint32_t find_extent_shared_data_refcount(device_extension *Vcb, uint64_t address, uint64_t parent, PIRP Irp)
Definition: extent-tree.c:2219
uint64_t address
Definition: balance.c:23
LIST_ENTRY refs
Definition: btrfs_drv.h:597
Definition: list.h:27
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:145
#define EXTENT_ITEM_SHARED_BACKREFS
Definition: btrfs.h:367
uint64_t flags
Definition: btrfs.h:372
#define TYPE_EXTENT_DATA
Definition: btrfs.h:26
return STATUS_SUCCESS
Definition: btrfs.c:2938
uint64_t offset
Definition: btrfs.h:419
EXTENT_DATA * ed
Definition: write.c:2818
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
Definition: path.c:42
LIST_ENTRY refs
Definition: balance.c:29

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

230  {
231  LIST_ENTRY* le;
232  KEY searchkey;
234  bool skinny = false;
236 
237  le = items->Flink;
238  while (le != items) {
240 
241  if (mr->address == address) {
242  *mr2 = mr;
243  return STATUS_SUCCESS;
244  }
245 
246  le = le->Flink;
247  }
248 
249  searchkey.obj_id = address;
250  searchkey.obj_type = TYPE_METADATA_ITEM;
251  searchkey.offset = 0xffffffffffffffff;
252 
253  Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, false, NULL);
254  if (!NT_SUCCESS(Status)) {
255  ERR("find_item returned %08x\n", Status);
256  return Status;
257  }
258 
260  skinny = true;
261  else if (tp.item->key.obj_id == address && tp.item->key.obj_type == TYPE_EXTENT_ITEM && tp.item->key.offset == Vcb->superblock.node_size &&
262  tp.item->size >= sizeof(EXTENT_ITEM)) {
264 
265  if (!(ei->flags & EXTENT_ITEM_TREE_BLOCK)) {
266  ERR("EXTENT_ITEM for %I64x found, but tree flag not set\n", address);
267  return STATUS_INTERNAL_ERROR;
268  }
269  } else {
270  ERR("could not find valid EXTENT_ITEM for address %I64x\n", address);
271  return STATUS_INTERNAL_ERROR;
272  }
273 
274  Status = add_metadata_reloc(Vcb, items, &tp, skinny, mr2, NULL, rollback);
275  if (!NT_SUCCESS(Status)) {
276  ERR("add_metadata_reloc returned %08x\n", Status);
277  return Status;
278  }
279 
280  return STATUS_SUCCESS;
281 }
uint64_t obj_id
Definition: btrfs.h:128
uint8_t obj_type
Definition: btrfs.h:129
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:76
LONG NTSTATUS
Definition: precomp.h:26
uint16_t size
Definition: btrfs_drv.h:415
#define TYPE_METADATA_ITEM
Definition: btrfs.h:32
uint64_t offset
Definition: btrfs.h:130
uint8_t * data
Definition: btrfs_drv.h:416
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:451
smooth NULL
Definition: ftsmooth.c:416
#define TYPE_EXTENT_ITEM
Definition: btrfs.h:31
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2855
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1425
GLuint address
Definition: glext.h:9393
tree_data * item
Definition: btrfs_drv.h:502
Definition: typedefs.h:117
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
Definition: btrfs.h:127
#define EXTENT_ITEM_TREE_BLOCK
Definition: btrfs.h:366
uint64_t address
Definition: balance.c:23
Definition: list.h:27
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY * rollback
Definition: btrfs_drv.h:1314
uint64_t flags
Definition: btrfs.h:372
static TCHAR * items[]
Definition: page1.c:45
return STATUS_SUCCESS
Definition: btrfs.c:2938

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

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

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

1103  {
1104  KEY searchkey;
1105  traverse_ptr tp;
1106  NTSTATUS Status;
1107  bool b;
1109  uint32_t loaded = 0;
1110 
1111  TRACE("chunk %I64x\n", c->offset);
1112 
1115 
1116  ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
1117 
1118  searchkey.obj_id = c->offset;
1119  searchkey.obj_type = TYPE_METADATA_ITEM;
1120  searchkey.offset = 0xffffffffffffffff;
1121 
1122  Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, false, NULL);
1123  if (!NT_SUCCESS(Status)) {
1124  ERR("find_item returned %08x\n", Status);
1125  goto end;
1126  }
1127 
1128  do {
1129  traverse_ptr next_tp;
1130 
1131  if (tp.item->key.obj_id >= c->offset + c->chunk_item->size)
1132  break;
1133 
1134  if (tp.item->key.obj_id >= c->offset && (tp.item->key.obj_type == TYPE_EXTENT_ITEM || tp.item->key.obj_type == TYPE_METADATA_ITEM)) {
1135  bool tree = false, skinny = false;
1136 
1137  if (tp.item->key.obj_type == TYPE_METADATA_ITEM && tp.item->size >= sizeof(EXTENT_ITEM)) {
1138  tree = true;
1139  skinny = true;
1140  } else if (tp.item->key.obj_type == TYPE_EXTENT_ITEM && tp.item->key.offset == Vcb->superblock.node_size &&
1141  tp.item->size >= sizeof(EXTENT_ITEM)) {
1142  EXTENT_ITEM* ei = (EXTENT_ITEM*)tp.item->data;
1143 
1145  tree = true;
1146  }
1147 
1148  if (tree) {
1149  Status = add_metadata_reloc(Vcb, &items, &tp, skinny, NULL, c, &rollback);
1150 
1151  if (!NT_SUCCESS(Status)) {
1152  ERR("add_metadata_reloc returned %08x\n", Status);
1153  goto end;
1154  }
1155 
1156  loaded++;
1157 
1158  if (loaded >= 64) // only do 64 at a time
1159  break;
1160  }
1161  }
1162 
1163  b = find_next_item(Vcb, &tp, &next_tp, false, NULL);
1164 
1165  if (b)
1166  tp = next_tp;
1167  } while (b);
1168 
1169  if (IsListEmpty(&items)) {
1170  *changed = false;
1172  goto end;
1173  } else
1174  *changed = true;
1175 
1177  if (!NT_SUCCESS(Status)) {
1178  ERR("write_metadata_items returned %08x\n", Status);
1179  goto end;
1180  }
1181 
1183 
1184  Vcb->need_write = true;
1185 
1186 end:
1187  if (NT_SUCCESS(Status)) {
1188  Status = do_write(Vcb, NULL);
1189  if (!NT_SUCCESS(Status))
1190  ERR("do_write returned %08x\n", Status);
1191  }
1192 
1193  if (NT_SUCCESS(Status))
1195  else
1197 
1198  free_trees(Vcb);
1199 
1200  ExReleaseResourceLite(&Vcb->tree_lock);
1201 
1202  while (!IsListEmpty(&items)) {
1204 
1205  while (!IsListEmpty(&mr->refs)) {
1207 
1208  ExFreePool(ref);
1209  }
1210 
1211  if (mr->data)
1212  ExFreePool(mr->data);
1213 
1214  ExFreePool(mr);
1215  }
1216 
1217  return Status;
1218 }
uint64_t obj_id
Definition: btrfs.h:128
void do_rollback(device_extension *Vcb, LIST_ENTRY *rollback)
Definition: treefuncs.c:1049
void clear_rollback(LIST_ENTRY *rollback)
Definition: treefuncs.c:1028
uint8_t obj_type
Definition: btrfs.h:129
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:76
NTSTATUS do_write(device_extension *Vcb, PIRP Irp)
Definition: flushthread.c:7667
LONG NTSTATUS
Definition: precomp.h:26
uint16_t size
Definition: btrfs_drv.h:415
GLuint GLuint end
Definition: gl.h:1545
tree_header * data
Definition: balance.c:25
#define TYPE_METADATA_ITEM
Definition: btrfs.h:32
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
Definition: send.c:47
uint64_t offset
Definition: btrfs.h:130
uint8_t * data
Definition: btrfs_drv.h:416
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
smooth NULL
Definition: ftsmooth.c:416
#define TYPE_EXTENT_ITEM
Definition: btrfs.h:31
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
void free_trees(device_extension *Vcb)
Definition: treefuncs.c:793
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:2855
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
#define TRACE(s)
Definition: solgame.cpp:4
bool find_next_item(_Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, const traverse_ptr *tp, traverse_ptr *next_tp, bool ignore, PIRP Irp)
Definition: treefuncs.c:592
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1425
const GLubyte * c
Definition: glext.h:8905
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
BOOL loaded
Definition: xmlview.c:54
tree_data * item
Definition: btrfs_drv.h:502
Definition: typedefs.h:117
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
Definition: btrfs.h:127
#define EXTENT_ITEM_TREE_BLOCK
Definition: btrfs.h:366
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
Definition: list.h:27
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY * rollback
Definition: btrfs_drv.h:1314
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:569
uint64_t flags
Definition: btrfs.h:372
static TCHAR * items[]
Definition: page1.c:45
return STATUS_SUCCESS
Definition: btrfs.c:2938
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
LIST_ENTRY refs
Definition: balance.c:29

Referenced by _Function_class_().

◆ copy_balance_args()

static void copy_balance_args ( btrfs_balance_opts opts,
BALANCE_ARGS args 
)
static

Definition at line 2317 of file balance.c.

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

Referenced by add_balance_item().

◆ data_reloc_add_tree_edr()

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

Definition at line 1220 of file balance.c.

1221  {
1222  NTSTATUS Status;
1223  LIST_ENTRY* le;
1224  KEY searchkey;
1225  traverse_ptr tp;
1226  root* r = NULL;
1227  metadata_reloc* mr;
1228  uint64_t last_tree = 0;
1230 
1231  le = Vcb->roots.Flink;
1232  while (le != &Vcb->roots) {
1234 
1235  if (r2->id == edr->root) {
1236  r = r2;
1237  break;
1238  }
1239 
1240  le = le->Flink;
1241  }
1242 
1243  if (!r) {
1244  ERR("could not find subvol %I64x\n", edr->count);
1245  return STATUS_INTERNAL_ERROR;
1246  }
1247 
1248  searchkey.obj_id = edr->objid;
1249  searchkey.obj_type = TYPE_EXTENT_DATA;
1250  searchkey.offset = 0;
1251 
1252  Status = find_item(Vcb, r, &tp, &searchkey, false, NULL);
1253  if (!NT_SUCCESS(Status)) {
1254  ERR("find_item returned %08x\n", Status);
1255  return Status;
1256  }
1257 
1258  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)) {
1259  traverse_ptr tp2;
1260 
1261  if (find_next_item(Vcb, &tp, &tp2, false, NULL))
1262  tp = tp2;
1263  else {
1264  ERR("could not find EXTENT_DATA for inode %I64x in root %I64x\n", searchkey.obj_id, r->id);
1265  return STATUS_INTERNAL_ERROR;
1266  }
1267  }
1268 
1269  ref = NULL;
1270 
1271  while (tp.item->key.obj_id == searchkey.obj_id && tp.item->key.obj_type == searchkey.obj_type) {
1272  traverse_ptr tp2;
1273 
1274  if (tp.item->size >= sizeof(EXTENT_DATA)) {
1276 
1279 
1280  if (ed2->address == dr->address && ed2->size == dr->size && tp.item->key.offset - ed2->offset == edr->offset) {
1281  if (ref && last_tree == tp.tree->header.address)
1282  ref->edr.count++;
1283  else {
1285  if (!ref) {
1286  ERR("out of memory\n");
1288  }
1289 
1290  ref->type = TYPE_EXTENT_DATA_REF;
1291  RtlCopyMemory(&ref->edr, edr, sizeof(EXTENT_DATA_REF));
1292  ref->edr.count = 1;
1293 
1294  Status = add_metadata_reloc_parent(Vcb, metadata_items, tp.tree->header.address, &mr, rollback);
1295  if (!NT_SUCCESS(Status)) {
1296  ERR("add_metadata_reloc_parent returned %08x\n", Status);
1297  ExFreePool(ref);
1298  return Status;
1299  }
1300 
1301  last_tree = tp.tree->header.address;
1302  ref->parent = mr;
1303 
1304  InsertTailList(&dr->refs, &ref->list_entry);
1305  }
1306  }
1307  }
1308  }
1309 
1310  if (find_next_item(Vcb, &tp, &tp2, false, NULL))
1311  tp = tp2;
1312  else
1313  break;
1314  }
1315 
1316  return STATUS_SUCCESS;
1317 }
uint64_t obj_id
Definition: btrfs.h:128
uint8_t type
Definition: btrfs.h:341
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
uint8_t obj_type
Definition: btrfs.h:129
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
EXTENT_DATA2 * ed2
Definition: write.c:2819
uint64_t offset
Definition: btrfs.h:397
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
LONG NTSTATUS
Definition: precomp.h:26
uint64_t objid
Definition: btrfs.h:396
uint16_t size
Definition: btrfs_drv.h:415
#define InsertTailList(ListHead, Entry)
LIST_ENTRY list_entry
Definition: send.c:48
Definition: send.c:47
uint64_t offset
Definition: btrfs.h:130
uint8_t * data
Definition: btrfs_drv.h:416
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:451
#define ALLOC_TAG
Definition: btrfs_drv.h:91
uint64_t address
Definition: btrfs.h:140
tree * tree
Definition: btrfs_drv.h:501
uint64_t address
Definition: btrfs.h:346
GLenum GLint ref
Definition: glext.h:6028
LIST_ENTRY refs
Definition: balance.c:53
uint32_t count
Definition: btrfs.h:398
smooth NULL
Definition: ftsmooth.c:416
#define offsetof(TYPE, MEMBER)
uint64_t size
Definition: btrfs.h:347
uint64_t root
Definition: btrfs.h:395
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
#define TYPE_EXTENT_DATA_REF
Definition: btrfs.h:34
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2855
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
bool find_next_item(_Requires_lock_held_(_Curr_->tree_lock) device_extension *Vcb, const traverse_ptr *tp, traverse_ptr *next_tp, bool ignore, PIRP Irp)
Definition: treefuncs.c:592
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Vcb
Definition: cdprocs.h:1425
static DNS_RECORDW r2
Definition: record.c:38
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:427
Definition: typedefs.h:117
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:229
#define EXTENT_TYPE_PREALLOC
Definition: btrfs.h:72
#define EXTENT_TYPE_REGULAR
Definition: btrfs.h:71
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
uint8_t data[1]
Definition: btrfs.h:342
Definition: btrfs.h:127
UINT64 uint64_t
Definition: types.h:77
Definition: list.h:27
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY * rollback
Definition: btrfs_drv.h:1314
uint64_t offset
Definition: btrfs.h:348
#define TYPE_EXTENT_DATA
Definition: btrfs.h:26
return STATUS_SUCCESS
Definition: btrfs.c:2938
EXTENT_DATA * ed
Definition: write.c:2818
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
uint64_t size
Definition: balance.c:49
uint64_t address
Definition: balance.c:48

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

2585  {
2586  KEY searchkey;
2587  traverse_ptr tp;
2588  NTSTATUS Status;
2589  LIST_ENTRY* le;
2591 
2592  if (Vcb->need_write) {
2593  Status = do_write(Vcb, NULL);
2594 
2595  if (!NT_SUCCESS(Status))
2596  ERR("do_write returned %08x\n", Status);
2597  } else
2599 
2600  free_trees(Vcb);
2601 
2602  if (!NT_SUCCESS(Status))
2603  return Status;
2604 
2605  // remove entry in chunk tree
2606 
2607  searchkey.obj_id = 1;
2608  searchkey.obj_type = TYPE_DEV_ITEM;
2609  searchkey.offset = dev->devitem.dev_id;
2610 
2611  Status = find_item(Vcb, Vcb->chunk_root, &tp, &searchkey, false, NULL);
2612  if (!NT_SUCCESS(Status)) {
2613  ERR("find_item returned %08x\n", Status);
2614  return Status;
2615  }
2616 
2617  if (!keycmp(searchkey, tp.item->key)) {
2619 
2620  if (!NT_SUCCESS(Status)) {
2621  ERR("delete_tree_item returned %08x\n", Status);
2622  return Status;
2623  }
2624  }
2625 
2626  // remove stats entry in device tree
2627 
2628  searchkey.obj_id = 0;
2629  searchkey.obj_type = TYPE_DEV_STATS;
2630  searchkey.offset = dev->devitem.dev_id;
2631 
2632  Status = find_item(Vcb, Vcb->dev_root, &tp, &searchkey, false, NULL);
2633  if (!NT_SUCCESS(Status)) {
2634  ERR("find_item returned %08x\n", Status);
2635  return Status;
2636  }
2637 
2638  if (!keycmp(searchkey, tp.item->key)) {
2640 
2641  if (!NT_SUCCESS(Status)) {
2642  ERR("delete_tree_item returned %08x\n", Status);
2643  return Status;
2644  }
2645  }
2646 
2647  // update superblock
2648 
2649  Vcb->superblock.num_devices--;
2650  Vcb->superblock.total_bytes -= dev->devitem.num_bytes;
2651  Vcb->devices_loaded--;
2652 
2653  RemoveEntryList(&dev->list_entry);
2654 
2655  // flush
2656 
2657  Status = do_write(Vcb, NULL);
2658  if (!NT_SUCCESS(Status))
2659  ERR("do_write returned %08x\n", Status);
2660 
2661  free_trees(Vcb);
2662 
2663  if (!NT_SUCCESS(Status))
2664  return Status;
2665 
2666  if (!dev->readonly && dev->devobj) {
2668  if (!NT_SUCCESS(Status))
2669  WARN("remove_superblocks returned %08x\n", Status);
2670  }
2671 
2672  // remove entry in volume list
2673 
2674  vde = Vcb->vde;
2675 
2676  if (dev->devobj) {
2677  pdo_device_extension* pdode = vde->pdode;
2678 
2680 
2681  le = pdode->children.Flink;
2682  while (le != &pdode->children) {
2684 
2685  if (RtlCompareMemory(&dev->devitem.device_uuid, &vc->uuid, sizeof(BTRFS_UUID)) == sizeof(BTRFS_UUID)) {
2688  UNICODE_STRING mmdevpath;
2689 
2690  pdode->children_loaded--;
2691 
2692  if (vc->had_drive_letter) { // re-add entry to mountmgr
2695  if (!NT_SUCCESS(Status))
2696  ERR("IoGetDeviceObjectPointer returned %08x\n", Status);
2697  else {
2698  MOUNTDEV_NAME mdn;
2699 
2700  Status = dev_ioctl(dev->devobj, IOCTL_MOUNTDEV_QUERY_DEVICE_NAME, NULL, 0, &mdn, sizeof(MOUNTDEV_NAME), true, NULL);
2702  ERR("IOCTL_MOUNTDEV_QUERY_DEVICE_NAME returned %08x\n", Status);
2703  else {
2704  MOUNTDEV_NAME* mdn2;
2705  ULONG mdnsize = (ULONG)offsetof(MOUNTDEV_NAME, Name[0]) + mdn.NameLength;
2706 
2707  mdn2 = ExAllocatePoolWithTag(PagedPool, mdnsize, ALLOC_TAG);
2708  if (!mdn2)
2709  ERR("out of memory\n");
2710  else {
2711  Status = dev_ioctl(dev->devobj, IOCTL_MOUNTDEV_QUERY_DEVICE_NAME, NULL, 0, mdn2, mdnsize, true, NULL);
2712  if (!NT_SUCCESS(Status))
2713  ERR("IOCTL_MOUNTDEV_QUERY_DEVICE_NAME returned %08x\n", Status);
2714  else {
2716 
2717  name.Buffer = mdn2->Name;
2718  name.Length = name.MaximumLength = mdn2->NameLength;
2719 
2721  if (!NT_SUCCESS(Status))
2722  WARN("mountmgr_add_drive_letter returned %08x\n", Status);
2723  }
2724 
2725  ExFreePool(mdn2);
2726  }
2727  }
2728 
2730  }
2731  }
2732 
2733  ExFreePool(vc->pnp_name.Buffer);
2735  ExFreePool(vc);
2736 
2738 
2739  break;
2740  }
2741 
2742  le = le->Flink;
2743  }
2744 
2745  if (pdode->children_loaded > 0 && vde->device->Characteristics & FILE_REMOVABLE_MEDIA) {
2746  vde->device->Characteristics &= ~FILE_REMOVABLE_MEDIA;
2747 
2748  le = pdode->children.Flink;
2749  while (le != &pdode->children) {
2751 
2752  if (vc->devobj->Characteristics & FILE_REMOVABLE_MEDIA) {
2753  vde->device->Characteristics |= FILE_REMOVABLE_MEDIA;
2754  break;
2755  }
2756 
2757  le = le->Flink;
2758  }
2759  }
2760 
2761  pdode->num_children = Vcb->superblock.num_devices;
2762 
2764 
2765  // free dev
2766 
2767  if (dev->trim && !dev->readonly && !Vcb->options.no_trim)
2769  }
2770 
2771  while (!IsListEmpty(&dev->space)) {
2772  LIST_ENTRY* le2 = RemoveHeadList(&dev->space);
2774 
2775  ExFreePool(s);
2776  }
2777 
2778  ExFreePool(dev);
2779 
2780  if (Vcb->trim) {
2781  Vcb->trim = false;
2782 
2783  le = Vcb->devices.Flink;
2784  while (le != &Vcb->devices) {
2785  device* dev2 = CONTAINING_RECORD(le, device, list_entry);
2786 
2787  if (dev2->trim) {
2788  Vcb->trim = true;
2789  break;
2790  }
2791 
2792  le = le->Flink;
2793  }
2794  }
2795 
2797 
2798  return STATUS_SUCCESS;
2799 }
uint64_t obj_id
Definition: btrfs.h:128
#define TYPE_DEV_ITEM
Definition: btrfs.h:43
UNICODE_STRING pnp_name
Definition: btrfs_drv.h:835
void trim_whole_device(device *dev)
Definition: fsctl.c:2708
uint8_t obj_type
Definition: btrfs.h:129
#define TYPE_DEV_STATS
Definition: btrfs.h:46
NTSTATUS do_write(device_extension *Vcb, PIRP Irp)
Definition: flushthread.c:7667
PDEVICE_OBJECT device
Definition: btrfs_drv.h:850
#define keycmp(key1, key2)
Definition: btrfs_drv.h:991
#define WARN(fmt,...)
Definition: debug.h:111
LONG NTSTATUS
Definition: precomp.h:26
NTSTATUS NTAPI IoGetDeviceObjectPointer(IN PUNICODE_STRING ObjectName, IN ACCESS_MASK DesiredAccess, OUT PFILE_OBJECT *FileObject, OUT PDEVICE_OBJECT *DeviceObject)
Definition: device.c:1435
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
uint64_t offset
Definition: btrfs.h:130
#define MOUNTMGR_DEVICE_NAME
Definition: imports.h:76
NTSTATUS mountmgr_add_drive_letter(PDEVICE_OBJECT mountmgr, PUNICODE_STRING devpath)
Definition: volume.c:904
BTRFS_UUID uuid
Definition: btrfs_drv.h:830
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:869
#define ALLOC_TAG
Definition: btrfs_drv.h:91
#define IOCTL_MOUNTDEV_QUERY_DEVICE_NAME
Definition: imports.h:93
Definition: devices.h:37
#define FILE_REMOVABLE_MEDIA
Definition: nt_native.h:807
bool trim
Definition: btrfs_drv.h:525
smooth NULL
Definition: ftsmooth.c:416
#define offsetof(TYPE, MEMBER)
PDEVICE_OBJECT devobj
Definition: btrfs_drv.h:833
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
struct pdo_device_extension * pdode
Definition: btrfs_drv.h:853
void free_trees(device_extension *Vcb)
Definition: treefuncs.c:793
_Inout_ PFILE_OBJECT FileObject
Definition: cdprocs.h:593
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
#define FSRTL_VOLUME_CHANGE_SIZE
Definition: fsrtltypes.h:101
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2855
static LONG find_item(PropertyBag *This, LPCOLESTR name)
Definition: propertybag.c:110
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
uint64_t children_loaded
Definition: btrfs_drv.h:870
NTSTATUS NTAPI FsRtlNotifyVolumeEvent(IN PFILE_OBJECT FileObject, IN ULONG EventCode)
Definition: pnp.c:38
WCHAR Name[1]
Definition: imports.h:144
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
NTSTATUS dev_ioctl(_In_ PDEVICE_OBJECT DeviceObject, _In_ ULONG ControlCode, _In_reads_bytes_opt_(InputBufferSize) PVOID InputBuffer, _In_ ULONG InputBufferSize, _Out_writes_bytes_opt_(OutputBufferSize) PVOID OutputBuffer, _In_ ULONG OutputBufferSize, _In_ bool Override, _Out_opt_ IO_STATUS_BLOCK *iosb)
Definition: btrfs.c:2813
bool had_drive_letter
Definition: btrfs_drv.h:838
#define Vcb
Definition: cdprocs.h:1425
ERESOURCE child_lock
Definition: btrfs_drv.h:871
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
* PFILE_OBJECT
Definition: iotypes.h:1955
#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:834
GLdouble s
Definition: gl.h:2039
Definition: typedefs.h:117
static NTSTATUS remove_superblocks(device *dev)
Definition: balance.c:2556
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
Definition: btrfs.h:127
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
Definition: list.h:27
USHORT NameLength
Definition: imports.h:143
uint64_t dev_id
Definition: name.c:36
LIST_ENTRY list_entry
Definition: btrfs_drv.h:842
unsigned int ULONG
Definition: retypes.h:1
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
LIST_ENTRY children
Definition: btrfs_drv.h:872
return STATUS_SUCCESS
Definition: btrfs.c:2938
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
NTSTATUS delete_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension *Vcb, _Inout_ traverse_ptr *tp)
Definition: treefuncs.c:989
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 2207 of file balance.c.

2207  {
2208  if (c->chunk_item->type & BLOCK_FLAG_RAID0)
2209  return BLOCK_FLAG_RAID0;
2210  else if (c->chunk_item->type & BLOCK_FLAG_RAID1)
2211  return BLOCK_FLAG_RAID1;
2212  else if (c->chunk_item->type & BLOCK_FLAG_DUPLICATE)
2213  return BLOCK_FLAG_DUPLICATE;
2214  else if (c->chunk_item->type & BLOCK_FLAG_RAID10)
2215  return BLOCK_FLAG_RAID10;
2216  else if (c->chunk_item->type & BLOCK_FLAG_RAID5)
2217  return BLOCK_FLAG_RAID5;
2218  else if (c->chunk_item->type & BLOCK_FLAG_RAID6)
2219  return BLOCK_FLAG_RAID6;
2220  else
2221  return BLOCK_FLAG_SINGLE;
2222 }
#define BLOCK_FLAG_SINGLE
Definition: btrfsioctl.h:140
#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_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 2491 of file balance.c.

2491  {
2493 
2494  if (args->flags & BALANCE_ARGS_FLAGS_PROFILES) {
2496  opts->profiles = args->profiles;
2497  }
2498 
2499  if (args->flags & BALANCE_ARGS_FLAGS_USAGE) {
2501 
2502  opts->usage_start = 0;
2503  opts->usage_end = (uint8_t)args->usage;
2504  } else if (args->flags & BALANCE_ARGS_FLAGS_USAGE_RANGE) {
2506 
2507  opts->usage_start = (uint8_t)args->usage_start;
2508  opts->usage_end = (uint8_t)args->usage_end;
2509  }
2510 
2511  if (args->flags & BALANCE_ARGS_FLAGS_DEVID) {
2513  opts->devid = args->devid;
2514  }
2515 
2516  if (args->flags & BALANCE_ARGS_FLAGS_DRANGE) {
2518  opts->drange_start = args->drange_start;
2519  opts->drange_end = args->drange_end;
2520  }
2521 
2522  if (args->flags & BALANCE_ARGS_FLAGS_VRANGE) {
2524  opts->vrange_start = args->vrange_start;
2525  opts->vrange_end = args->vrange_end;
2526  }
2527 
2528  if (args->flags & BALANCE_ARGS_FLAGS_LIMIT) {
2530 
2531  opts->limit_start = 0;
2532  opts->limit_end = args->limit;
2533  } else if (args->flags & BALANCE_ARGS_FLAGS_LIMIT_RANGE) {
2535 
2536  opts->limit_start = args->limit_start;
2537  opts->limit_end = args->limit_end;
2538  }
2539 
2540  if (args->flags & BALANCE_ARGS_FLAGS_STRIPES_RANGE) {
2542 
2543  opts->stripes_start = (uint16_t)args->stripes_start;
2544  opts->stripes_end = (uint16_t)args->stripes_end;
2545  }
2546 
2547  if (args->flags & BALANCE_ARGS_FLAGS_CONVERT) {
2549  opts->convert = args->convert;
2550 
2551  if (args->flags & BALANCE_ARGS_FLAGS_SOFT)
2552  opts->flags |= BTRFS_BALANCE_OPTS_SOFT;
2553  }
2554 }
#define BALANCE_ARGS_FLAGS_DRANGE
Definition: btrfs.h:461
#define BALANCE_ARGS_FLAGS_LIMIT_RANGE
Definition: btrfs.h:464
#define BTRFS_BALANCE_OPTS_PROFILES
Definition: btrfsioctl.h:130
#define BALANCE_ARGS_FLAGS_VRANGE
Definition: btrfs.h:462
#define BALANCE_ARGS_FLAGS_STRIPES_RANGE
Definition: btrfs.h:465
#define BALANCE_ARGS_FLAGS_PROFILES
Definition: btrfs.h:458
#define BALANCE_ARGS_FLAGS_LIMIT
Definition: btrfs.h:463
uint16_t stripes_end
Definition: btrfsioctl.h:153
#define BTRFS_BALANCE_OPTS_VRANGE
Definition: btrfsioctl.h:133
unsigned short int uint16_t
Definition: acefiex.h:54
#define uint16_t
Definition: nsiface.idl:60
Definition: match.c:390
#define BALANCE_ARGS_FLAGS_USAGE_RANGE
Definition: btrfs.h:468
uint64_t limit_start
Definition: btrfsioctl.h:150
#define BALANCE_ARGS_FLAGS_SOFT
Definition: btrfs.h:467
#define BTRFS_BALANCE_OPTS_USAGE
Definition: btrfsioctl.h:136
uint64_t vrange_start
Definition: btrfsioctl.h:148
#define BTRFS_BALANCE_OPTS_CONVERT
Definition: btrfsioctl.h:137
#define BTRFS_BALANCE_OPTS_SOFT
Definition: btrfsioctl.h:138
uint64_t limit_end
Definition: btrfsioctl.h:151
#define BALANCE_ARGS_FLAGS_CONVERT
Definition: btrfs.h:466
uint64_t drange_end
Definition: btrfsioctl.h:147
#define BTRFS_BALANCE_OPTS_LIMIT
Definition: btrfsioctl.h:134
#define BTRFS_BALANCE_OPTS_ENABLED
Definition: btrfsioctl.h:129
#define BTRFS_BALANCE_OPTS_DRANGE
Definition: btrfsioctl.h:132
BYTE uint8_t
Definition: msvideo1.c:66
uint16_t stripes_start
Definition: btrfsioctl.h:152
#define uint8_t
Definition: nsiface.idl:59
#define BALANCE_ARGS_FLAGS_USAGE
Definition: btrfs.h:459
uint64_t vrange_end
Definition: btrfsioctl.h:149
uint64_t drange_start
Definition: btrfsioctl.h:146
#define BALANCE_ARGS_FLAGS_DEVID
Definition: btrfs.h:460
#define BTRFS_BALANCE_OPTS_DEVID
Definition: btrfsioctl.h:131
#define BTRFS_BALANCE_OPTS_STRIPES
Definition: btrfsioctl.h:135

Referenced by look_for_balance_item().

◆ look_for_balance_item()

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

Definition at line 3625 of file balance.c.

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