root/fs/btrfs/block-rsv.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. block_rsv_release_bytes
  2. btrfs_block_rsv_migrate
  3. btrfs_init_block_rsv
  4. btrfs_init_metadata_block_rsv
  5. btrfs_alloc_block_rsv
  6. btrfs_free_block_rsv
  7. btrfs_block_rsv_add
  8. btrfs_block_rsv_check
  9. btrfs_block_rsv_refill
  10. __btrfs_block_rsv_release
  11. btrfs_block_rsv_use_bytes
  12. btrfs_block_rsv_add_bytes
  13. btrfs_cond_migrate_bytes
  14. btrfs_update_global_block_rsv
  15. btrfs_init_global_block_rsv
  16. btrfs_release_global_block_rsv
  17. get_block_rsv
  18. btrfs_use_block_rsv

   1 // SPDX-License-Identifier: GPL-2.0
   2 
   3 #include "misc.h"
   4 #include "ctree.h"
   5 #include "block-rsv.h"
   6 #include "space-info.h"
   7 #include "transaction.h"
   8 
   9 static u64 block_rsv_release_bytes(struct btrfs_fs_info *fs_info,
  10                                     struct btrfs_block_rsv *block_rsv,
  11                                     struct btrfs_block_rsv *dest, u64 num_bytes,
  12                                     u64 *qgroup_to_release_ret)
  13 {
  14         struct btrfs_space_info *space_info = block_rsv->space_info;
  15         u64 qgroup_to_release = 0;
  16         u64 ret;
  17 
  18         spin_lock(&block_rsv->lock);
  19         if (num_bytes == (u64)-1) {
  20                 num_bytes = block_rsv->size;
  21                 qgroup_to_release = block_rsv->qgroup_rsv_size;
  22         }
  23         block_rsv->size -= num_bytes;
  24         if (block_rsv->reserved >= block_rsv->size) {
  25                 num_bytes = block_rsv->reserved - block_rsv->size;
  26                 block_rsv->reserved = block_rsv->size;
  27                 block_rsv->full = 1;
  28         } else {
  29                 num_bytes = 0;
  30         }
  31         if (block_rsv->qgroup_rsv_reserved >= block_rsv->qgroup_rsv_size) {
  32                 qgroup_to_release = block_rsv->qgroup_rsv_reserved -
  33                                     block_rsv->qgroup_rsv_size;
  34                 block_rsv->qgroup_rsv_reserved = block_rsv->qgroup_rsv_size;
  35         } else {
  36                 qgroup_to_release = 0;
  37         }
  38         spin_unlock(&block_rsv->lock);
  39 
  40         ret = num_bytes;
  41         if (num_bytes > 0) {
  42                 if (dest) {
  43                         spin_lock(&dest->lock);
  44                         if (!dest->full) {
  45                                 u64 bytes_to_add;
  46 
  47                                 bytes_to_add = dest->size - dest->reserved;
  48                                 bytes_to_add = min(num_bytes, bytes_to_add);
  49                                 dest->reserved += bytes_to_add;
  50                                 if (dest->reserved >= dest->size)
  51                                         dest->full = 1;
  52                                 num_bytes -= bytes_to_add;
  53                         }
  54                         spin_unlock(&dest->lock);
  55                 }
  56                 if (num_bytes)
  57                         btrfs_space_info_free_bytes_may_use(fs_info,
  58                                                             space_info,
  59                                                             num_bytes);
  60         }
  61         if (qgroup_to_release_ret)
  62                 *qgroup_to_release_ret = qgroup_to_release;
  63         return ret;
  64 }
  65 
  66 int btrfs_block_rsv_migrate(struct btrfs_block_rsv *src,
  67                             struct btrfs_block_rsv *dst, u64 num_bytes,
  68                             bool update_size)
  69 {
  70         int ret;
  71 
  72         ret = btrfs_block_rsv_use_bytes(src, num_bytes);
  73         if (ret)
  74                 return ret;
  75 
  76         btrfs_block_rsv_add_bytes(dst, num_bytes, update_size);
  77         return 0;
  78 }
  79 
  80 void btrfs_init_block_rsv(struct btrfs_block_rsv *rsv, unsigned short type)
  81 {
  82         memset(rsv, 0, sizeof(*rsv));
  83         spin_lock_init(&rsv->lock);
  84         rsv->type = type;
  85 }
  86 
  87 void btrfs_init_metadata_block_rsv(struct btrfs_fs_info *fs_info,
  88                                    struct btrfs_block_rsv *rsv,
  89                                    unsigned short type)
  90 {
  91         btrfs_init_block_rsv(rsv, type);
  92         rsv->space_info = btrfs_find_space_info(fs_info,
  93                                             BTRFS_BLOCK_GROUP_METADATA);
  94 }
  95 
  96 struct btrfs_block_rsv *btrfs_alloc_block_rsv(struct btrfs_fs_info *fs_info,
  97                                               unsigned short type)
  98 {
  99         struct btrfs_block_rsv *block_rsv;
 100 
 101         block_rsv = kmalloc(sizeof(*block_rsv), GFP_NOFS);
 102         if (!block_rsv)
 103                 return NULL;
 104 
 105         btrfs_init_metadata_block_rsv(fs_info, block_rsv, type);
 106         return block_rsv;
 107 }
 108 
 109 void btrfs_free_block_rsv(struct btrfs_fs_info *fs_info,
 110                           struct btrfs_block_rsv *rsv)
 111 {
 112         if (!rsv)
 113                 return;
 114         btrfs_block_rsv_release(fs_info, rsv, (u64)-1);
 115         kfree(rsv);
 116 }
 117 
 118 int btrfs_block_rsv_add(struct btrfs_root *root,
 119                         struct btrfs_block_rsv *block_rsv, u64 num_bytes,
 120                         enum btrfs_reserve_flush_enum flush)
 121 {
 122         int ret;
 123 
 124         if (num_bytes == 0)
 125                 return 0;
 126 
 127         ret = btrfs_reserve_metadata_bytes(root, block_rsv, num_bytes, flush);
 128         if (!ret)
 129                 btrfs_block_rsv_add_bytes(block_rsv, num_bytes, true);
 130 
 131         return ret;
 132 }
 133 
 134 int btrfs_block_rsv_check(struct btrfs_block_rsv *block_rsv, int min_factor)
 135 {
 136         u64 num_bytes = 0;
 137         int ret = -ENOSPC;
 138 
 139         if (!block_rsv)
 140                 return 0;
 141 
 142         spin_lock(&block_rsv->lock);
 143         num_bytes = div_factor(block_rsv->size, min_factor);
 144         if (block_rsv->reserved >= num_bytes)
 145                 ret = 0;
 146         spin_unlock(&block_rsv->lock);
 147 
 148         return ret;
 149 }
 150 
 151 int btrfs_block_rsv_refill(struct btrfs_root *root,
 152                            struct btrfs_block_rsv *block_rsv, u64 min_reserved,
 153                            enum btrfs_reserve_flush_enum flush)
 154 {
 155         u64 num_bytes = 0;
 156         int ret = -ENOSPC;
 157 
 158         if (!block_rsv)
 159                 return 0;
 160 
 161         spin_lock(&block_rsv->lock);
 162         num_bytes = min_reserved;
 163         if (block_rsv->reserved >= num_bytes)
 164                 ret = 0;
 165         else
 166                 num_bytes -= block_rsv->reserved;
 167         spin_unlock(&block_rsv->lock);
 168 
 169         if (!ret)
 170                 return 0;
 171 
 172         ret = btrfs_reserve_metadata_bytes(root, block_rsv, num_bytes, flush);
 173         if (!ret) {
 174                 btrfs_block_rsv_add_bytes(block_rsv, num_bytes, false);
 175                 return 0;
 176         }
 177 
 178         return ret;
 179 }
 180 
 181 u64 __btrfs_block_rsv_release(struct btrfs_fs_info *fs_info,
 182                               struct btrfs_block_rsv *block_rsv,
 183                               u64 num_bytes, u64 *qgroup_to_release)
 184 {
 185         struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv;
 186         struct btrfs_block_rsv *delayed_rsv = &fs_info->delayed_refs_rsv;
 187         struct btrfs_block_rsv *target = NULL;
 188 
 189         /*
 190          * If we are the delayed_rsv then push to the global rsv, otherwise dump
 191          * into the delayed rsv if it is not full.
 192          */
 193         if (block_rsv == delayed_rsv)
 194                 target = global_rsv;
 195         else if (block_rsv != global_rsv && !delayed_rsv->full)
 196                 target = delayed_rsv;
 197 
 198         if (target && block_rsv->space_info != target->space_info)
 199                 target = NULL;
 200 
 201         return block_rsv_release_bytes(fs_info, block_rsv, target, num_bytes,
 202                                        qgroup_to_release);
 203 }
 204 
 205 int btrfs_block_rsv_use_bytes(struct btrfs_block_rsv *block_rsv, u64 num_bytes)
 206 {
 207         int ret = -ENOSPC;
 208 
 209         spin_lock(&block_rsv->lock);
 210         if (block_rsv->reserved >= num_bytes) {
 211                 block_rsv->reserved -= num_bytes;
 212                 if (block_rsv->reserved < block_rsv->size)
 213                         block_rsv->full = 0;
 214                 ret = 0;
 215         }
 216         spin_unlock(&block_rsv->lock);
 217         return ret;
 218 }
 219 
 220 void btrfs_block_rsv_add_bytes(struct btrfs_block_rsv *block_rsv,
 221                                u64 num_bytes, bool update_size)
 222 {
 223         spin_lock(&block_rsv->lock);
 224         block_rsv->reserved += num_bytes;
 225         if (update_size)
 226                 block_rsv->size += num_bytes;
 227         else if (block_rsv->reserved >= block_rsv->size)
 228                 block_rsv->full = 1;
 229         spin_unlock(&block_rsv->lock);
 230 }
 231 
 232 int btrfs_cond_migrate_bytes(struct btrfs_fs_info *fs_info,
 233                              struct btrfs_block_rsv *dest, u64 num_bytes,
 234                              int min_factor)
 235 {
 236         struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv;
 237         u64 min_bytes;
 238 
 239         if (global_rsv->space_info != dest->space_info)
 240                 return -ENOSPC;
 241 
 242         spin_lock(&global_rsv->lock);
 243         min_bytes = div_factor(global_rsv->size, min_factor);
 244         if (global_rsv->reserved < min_bytes + num_bytes) {
 245                 spin_unlock(&global_rsv->lock);
 246                 return -ENOSPC;
 247         }
 248         global_rsv->reserved -= num_bytes;
 249         if (global_rsv->reserved < global_rsv->size)
 250                 global_rsv->full = 0;
 251         spin_unlock(&global_rsv->lock);
 252 
 253         btrfs_block_rsv_add_bytes(dest, num_bytes, true);
 254         return 0;
 255 }
 256 
 257 void btrfs_update_global_block_rsv(struct btrfs_fs_info *fs_info)
 258 {
 259         struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv;
 260         struct btrfs_space_info *sinfo = block_rsv->space_info;
 261         u64 num_bytes;
 262         unsigned min_items;
 263 
 264         /*
 265          * The global block rsv is based on the size of the extent tree, the
 266          * checksum tree and the root tree.  If the fs is empty we want to set
 267          * it to a minimal amount for safety.
 268          */
 269         num_bytes = btrfs_root_used(&fs_info->extent_root->root_item) +
 270                 btrfs_root_used(&fs_info->csum_root->root_item) +
 271                 btrfs_root_used(&fs_info->tree_root->root_item);
 272 
 273         /*
 274          * We at a minimum are going to modify the csum root, the tree root, and
 275          * the extent root.
 276          */
 277         min_items = 3;
 278 
 279         /*
 280          * But we also want to reserve enough space so we can do the fallback
 281          * global reserve for an unlink, which is an additional 5 items (see the
 282          * comment in __unlink_start_trans for what we're modifying.)
 283          *
 284          * But we also need space for the delayed ref updates from the unlink,
 285          * so its 10, 5 for the actual operation, and 5 for the delayed ref
 286          * updates.
 287          */
 288         min_items += 10;
 289 
 290         num_bytes = max_t(u64, num_bytes,
 291                           btrfs_calc_insert_metadata_size(fs_info, min_items));
 292 
 293         spin_lock(&sinfo->lock);
 294         spin_lock(&block_rsv->lock);
 295 
 296         block_rsv->size = min_t(u64, num_bytes, SZ_512M);
 297 
 298         if (block_rsv->reserved < block_rsv->size) {
 299                 num_bytes = block_rsv->size - block_rsv->reserved;
 300                 block_rsv->reserved += num_bytes;
 301                 btrfs_space_info_update_bytes_may_use(fs_info, sinfo,
 302                                                       num_bytes);
 303         } else if (block_rsv->reserved > block_rsv->size) {
 304                 num_bytes = block_rsv->reserved - block_rsv->size;
 305                 btrfs_space_info_update_bytes_may_use(fs_info, sinfo,
 306                                                       -num_bytes);
 307                 block_rsv->reserved = block_rsv->size;
 308                 btrfs_try_granting_tickets(fs_info, sinfo);
 309         }
 310 
 311         if (block_rsv->reserved == block_rsv->size)
 312                 block_rsv->full = 1;
 313         else
 314                 block_rsv->full = 0;
 315 
 316         spin_unlock(&block_rsv->lock);
 317         spin_unlock(&sinfo->lock);
 318 }
 319 
 320 void btrfs_init_global_block_rsv(struct btrfs_fs_info *fs_info)
 321 {
 322         struct btrfs_space_info *space_info;
 323 
 324         space_info = btrfs_find_space_info(fs_info, BTRFS_BLOCK_GROUP_SYSTEM);
 325         fs_info->chunk_block_rsv.space_info = space_info;
 326 
 327         space_info = btrfs_find_space_info(fs_info, BTRFS_BLOCK_GROUP_METADATA);
 328         fs_info->global_block_rsv.space_info = space_info;
 329         fs_info->trans_block_rsv.space_info = space_info;
 330         fs_info->empty_block_rsv.space_info = space_info;
 331         fs_info->delayed_block_rsv.space_info = space_info;
 332         fs_info->delayed_refs_rsv.space_info = space_info;
 333 
 334         fs_info->extent_root->block_rsv = &fs_info->delayed_refs_rsv;
 335         fs_info->csum_root->block_rsv = &fs_info->delayed_refs_rsv;
 336         fs_info->dev_root->block_rsv = &fs_info->global_block_rsv;
 337         fs_info->tree_root->block_rsv = &fs_info->global_block_rsv;
 338         if (fs_info->quota_root)
 339                 fs_info->quota_root->block_rsv = &fs_info->global_block_rsv;
 340         fs_info->chunk_root->block_rsv = &fs_info->chunk_block_rsv;
 341 
 342         btrfs_update_global_block_rsv(fs_info);
 343 }
 344 
 345 void btrfs_release_global_block_rsv(struct btrfs_fs_info *fs_info)
 346 {
 347         btrfs_block_rsv_release(fs_info, &fs_info->global_block_rsv, (u64)-1);
 348         WARN_ON(fs_info->trans_block_rsv.size > 0);
 349         WARN_ON(fs_info->trans_block_rsv.reserved > 0);
 350         WARN_ON(fs_info->chunk_block_rsv.size > 0);
 351         WARN_ON(fs_info->chunk_block_rsv.reserved > 0);
 352         WARN_ON(fs_info->delayed_block_rsv.size > 0);
 353         WARN_ON(fs_info->delayed_block_rsv.reserved > 0);
 354         WARN_ON(fs_info->delayed_refs_rsv.reserved > 0);
 355         WARN_ON(fs_info->delayed_refs_rsv.size > 0);
 356 }
 357 
 358 static struct btrfs_block_rsv *get_block_rsv(
 359                                         const struct btrfs_trans_handle *trans,
 360                                         const struct btrfs_root *root)
 361 {
 362         struct btrfs_fs_info *fs_info = root->fs_info;
 363         struct btrfs_block_rsv *block_rsv = NULL;
 364 
 365         if (test_bit(BTRFS_ROOT_REF_COWS, &root->state) ||
 366             (root == fs_info->csum_root && trans->adding_csums) ||
 367             (root == fs_info->uuid_root))
 368                 block_rsv = trans->block_rsv;
 369 
 370         if (!block_rsv)
 371                 block_rsv = root->block_rsv;
 372 
 373         if (!block_rsv)
 374                 block_rsv = &fs_info->empty_block_rsv;
 375 
 376         return block_rsv;
 377 }
 378 
 379 struct btrfs_block_rsv *btrfs_use_block_rsv(struct btrfs_trans_handle *trans,
 380                                             struct btrfs_root *root,
 381                                             u32 blocksize)
 382 {
 383         struct btrfs_fs_info *fs_info = root->fs_info;
 384         struct btrfs_block_rsv *block_rsv;
 385         struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv;
 386         int ret;
 387         bool global_updated = false;
 388 
 389         block_rsv = get_block_rsv(trans, root);
 390 
 391         if (unlikely(block_rsv->size == 0))
 392                 goto try_reserve;
 393 again:
 394         ret = btrfs_block_rsv_use_bytes(block_rsv, blocksize);
 395         if (!ret)
 396                 return block_rsv;
 397 
 398         if (block_rsv->failfast)
 399                 return ERR_PTR(ret);
 400 
 401         if (block_rsv->type == BTRFS_BLOCK_RSV_GLOBAL && !global_updated) {
 402                 global_updated = true;
 403                 btrfs_update_global_block_rsv(fs_info);
 404                 goto again;
 405         }
 406 
 407         /*
 408          * The global reserve still exists to save us from ourselves, so don't
 409          * warn_on if we are short on our delayed refs reserve.
 410          */
 411         if (block_rsv->type != BTRFS_BLOCK_RSV_DELREFS &&
 412             btrfs_test_opt(fs_info, ENOSPC_DEBUG)) {
 413                 static DEFINE_RATELIMIT_STATE(_rs,
 414                                 DEFAULT_RATELIMIT_INTERVAL * 10,
 415                                 /*DEFAULT_RATELIMIT_BURST*/ 1);
 416                 if (__ratelimit(&_rs))
 417                         WARN(1, KERN_DEBUG
 418                                 "BTRFS: block rsv returned %d\n", ret);
 419         }
 420 try_reserve:
 421         ret = btrfs_reserve_metadata_bytes(root, block_rsv, blocksize,
 422                                            BTRFS_RESERVE_NO_FLUSH);
 423         if (!ret)
 424                 return block_rsv;
 425         /*
 426          * If we couldn't reserve metadata bytes try and use some from
 427          * the global reserve if its space type is the same as the global
 428          * reservation.
 429          */
 430         if (block_rsv->type != BTRFS_BLOCK_RSV_GLOBAL &&
 431             block_rsv->space_info == global_rsv->space_info) {
 432                 ret = btrfs_block_rsv_use_bytes(global_rsv, blocksize);
 433                 if (!ret)
 434                         return global_rsv;
 435         }
 436         return ERR_PTR(ret);
 437 }

/* [<][>][^][v][top][bottom][index][help] */