Loading fs/btrfs/ctree.h +13 −2 Original line number Diff line number Diff line Loading @@ -439,6 +439,8 @@ struct btrfs_space_info { struct list_head list; /* Protected by the spinlock 'lock'. */ struct list_head ro_bgs; struct list_head priority_tickets; struct list_head tickets; struct rw_semaphore groups_sem; /* for block groups in our same type */ Loading Loading @@ -2624,6 +2626,15 @@ enum btrfs_reserve_flush_enum { BTRFS_RESERVE_FLUSH_ALL, }; enum btrfs_flush_state { FLUSH_DELAYED_ITEMS_NR = 1, FLUSH_DELAYED_ITEMS = 2, FLUSH_DELALLOC = 3, FLUSH_DELALLOC_WAIT = 4, ALLOC_CHUNK = 5, COMMIT_TRANS = 6, }; int btrfs_check_data_free_space(struct inode *inode, u64 start, u64 len); int btrfs_alloc_data_chunk_ondemand(struct inode *inode, u64 bytes); void btrfs_free_reserved_data_space(struct inode *inode, u64 start, u64 len); Loading Loading @@ -2661,8 +2672,8 @@ int btrfs_block_rsv_refill(struct btrfs_root *root, struct btrfs_block_rsv *block_rsv, u64 min_reserved, enum btrfs_reserve_flush_enum flush); int btrfs_block_rsv_migrate(struct btrfs_block_rsv *src_rsv, struct btrfs_block_rsv *dst_rsv, u64 num_bytes); struct btrfs_block_rsv *dst_rsv, u64 num_bytes, int update_size); int btrfs_cond_migrate_bytes(struct btrfs_fs_info *fs_info, struct btrfs_block_rsv *dest, u64 num_bytes, int min_factor); Loading fs/btrfs/delayed-inode.c +25 −43 Original line number Diff line number Diff line Loading @@ -553,7 +553,7 @@ static int btrfs_delayed_item_reserve_metadata(struct btrfs_trans_handle *trans, dst_rsv = &root->fs_info->delayed_block_rsv; num_bytes = btrfs_calc_trans_metadata_size(root, 1); ret = btrfs_block_rsv_migrate(src_rsv, dst_rsv, num_bytes); ret = btrfs_block_rsv_migrate(src_rsv, dst_rsv, num_bytes, 1); if (!ret) { trace_btrfs_space_reservation(root->fs_info, "delayed_item", item->key.objectid, Loading Loading @@ -597,6 +597,29 @@ static int btrfs_delayed_inode_reserve_metadata( num_bytes = btrfs_calc_trans_metadata_size(root, 1); /* * If our block_rsv is the delalloc block reserve then check and see if * we have our extra reservation for updating the inode. If not fall * through and try to reserve space quickly. * * We used to try and steal from the delalloc block rsv or the global * reserve, but we'd steal a full reservation, which isn't kind. We are * here through delalloc which means we've likely just cowed down close * to the leaf that contains the inode, so we would steal less just * doing the fallback inode update, so if we do end up having to steal * from the global block rsv we hopefully only steal one or two blocks * worth which is less likely to hurt us. */ if (src_rsv && src_rsv->type == BTRFS_BLOCK_RSV_DELALLOC) { spin_lock(&BTRFS_I(inode)->lock); if (test_and_clear_bit(BTRFS_INODE_DELALLOC_META_RESERVED, &BTRFS_I(inode)->runtime_flags)) release = true; else src_rsv = NULL; spin_unlock(&BTRFS_I(inode)->lock); } /* * btrfs_dirty_inode will update the inode under btrfs_join_transaction * which doesn't reserve space for speed. This is a problem since we Loading Loading @@ -626,51 +649,10 @@ static int btrfs_delayed_inode_reserve_metadata( num_bytes, 1); } return ret; } else if (src_rsv->type == BTRFS_BLOCK_RSV_DELALLOC) { spin_lock(&BTRFS_I(inode)->lock); if (test_and_clear_bit(BTRFS_INODE_DELALLOC_META_RESERVED, &BTRFS_I(inode)->runtime_flags)) { spin_unlock(&BTRFS_I(inode)->lock); release = true; goto migrate; } spin_unlock(&BTRFS_I(inode)->lock); /* Ok we didn't have space pre-reserved. This shouldn't happen * too often but it can happen if we do delalloc to an existing * inode which gets dirtied because of the time update, and then * isn't touched again until after the transaction commits and * then we try to write out the data. First try to be nice and * reserve something strictly for us. If not be a pain and try * to steal from the delalloc block rsv. */ ret = btrfs_block_rsv_add(root, dst_rsv, num_bytes, BTRFS_RESERVE_NO_FLUSH); if (!ret) goto out; ret = btrfs_block_rsv_migrate(src_rsv, dst_rsv, num_bytes, 1); ret = btrfs_block_rsv_migrate(src_rsv, dst_rsv, num_bytes); if (!ret) goto out; if (btrfs_test_opt(root, ENOSPC_DEBUG)) { btrfs_debug(root->fs_info, "block rsv migrate returned %d", ret); WARN_ON(1); } /* * Ok this is a problem, let's just steal from the global rsv * since this really shouldn't happen that often. */ ret = btrfs_block_rsv_migrate(&root->fs_info->global_block_rsv, dst_rsv, num_bytes); goto out; } migrate: ret = btrfs_block_rsv_migrate(src_rsv, dst_rsv, num_bytes); out: /* * Migrate only takes a reservation, it doesn't touch the size of the * block_rsv. This is to simplify people who don't normally have things Loading Loading
fs/btrfs/ctree.h +13 −2 Original line number Diff line number Diff line Loading @@ -439,6 +439,8 @@ struct btrfs_space_info { struct list_head list; /* Protected by the spinlock 'lock'. */ struct list_head ro_bgs; struct list_head priority_tickets; struct list_head tickets; struct rw_semaphore groups_sem; /* for block groups in our same type */ Loading Loading @@ -2624,6 +2626,15 @@ enum btrfs_reserve_flush_enum { BTRFS_RESERVE_FLUSH_ALL, }; enum btrfs_flush_state { FLUSH_DELAYED_ITEMS_NR = 1, FLUSH_DELAYED_ITEMS = 2, FLUSH_DELALLOC = 3, FLUSH_DELALLOC_WAIT = 4, ALLOC_CHUNK = 5, COMMIT_TRANS = 6, }; int btrfs_check_data_free_space(struct inode *inode, u64 start, u64 len); int btrfs_alloc_data_chunk_ondemand(struct inode *inode, u64 bytes); void btrfs_free_reserved_data_space(struct inode *inode, u64 start, u64 len); Loading Loading @@ -2661,8 +2672,8 @@ int btrfs_block_rsv_refill(struct btrfs_root *root, struct btrfs_block_rsv *block_rsv, u64 min_reserved, enum btrfs_reserve_flush_enum flush); int btrfs_block_rsv_migrate(struct btrfs_block_rsv *src_rsv, struct btrfs_block_rsv *dst_rsv, u64 num_bytes); struct btrfs_block_rsv *dst_rsv, u64 num_bytes, int update_size); int btrfs_cond_migrate_bytes(struct btrfs_fs_info *fs_info, struct btrfs_block_rsv *dest, u64 num_bytes, int min_factor); Loading
fs/btrfs/delayed-inode.c +25 −43 Original line number Diff line number Diff line Loading @@ -553,7 +553,7 @@ static int btrfs_delayed_item_reserve_metadata(struct btrfs_trans_handle *trans, dst_rsv = &root->fs_info->delayed_block_rsv; num_bytes = btrfs_calc_trans_metadata_size(root, 1); ret = btrfs_block_rsv_migrate(src_rsv, dst_rsv, num_bytes); ret = btrfs_block_rsv_migrate(src_rsv, dst_rsv, num_bytes, 1); if (!ret) { trace_btrfs_space_reservation(root->fs_info, "delayed_item", item->key.objectid, Loading Loading @@ -597,6 +597,29 @@ static int btrfs_delayed_inode_reserve_metadata( num_bytes = btrfs_calc_trans_metadata_size(root, 1); /* * If our block_rsv is the delalloc block reserve then check and see if * we have our extra reservation for updating the inode. If not fall * through and try to reserve space quickly. * * We used to try and steal from the delalloc block rsv or the global * reserve, but we'd steal a full reservation, which isn't kind. We are * here through delalloc which means we've likely just cowed down close * to the leaf that contains the inode, so we would steal less just * doing the fallback inode update, so if we do end up having to steal * from the global block rsv we hopefully only steal one or two blocks * worth which is less likely to hurt us. */ if (src_rsv && src_rsv->type == BTRFS_BLOCK_RSV_DELALLOC) { spin_lock(&BTRFS_I(inode)->lock); if (test_and_clear_bit(BTRFS_INODE_DELALLOC_META_RESERVED, &BTRFS_I(inode)->runtime_flags)) release = true; else src_rsv = NULL; spin_unlock(&BTRFS_I(inode)->lock); } /* * btrfs_dirty_inode will update the inode under btrfs_join_transaction * which doesn't reserve space for speed. This is a problem since we Loading Loading @@ -626,51 +649,10 @@ static int btrfs_delayed_inode_reserve_metadata( num_bytes, 1); } return ret; } else if (src_rsv->type == BTRFS_BLOCK_RSV_DELALLOC) { spin_lock(&BTRFS_I(inode)->lock); if (test_and_clear_bit(BTRFS_INODE_DELALLOC_META_RESERVED, &BTRFS_I(inode)->runtime_flags)) { spin_unlock(&BTRFS_I(inode)->lock); release = true; goto migrate; } spin_unlock(&BTRFS_I(inode)->lock); /* Ok we didn't have space pre-reserved. This shouldn't happen * too often but it can happen if we do delalloc to an existing * inode which gets dirtied because of the time update, and then * isn't touched again until after the transaction commits and * then we try to write out the data. First try to be nice and * reserve something strictly for us. If not be a pain and try * to steal from the delalloc block rsv. */ ret = btrfs_block_rsv_add(root, dst_rsv, num_bytes, BTRFS_RESERVE_NO_FLUSH); if (!ret) goto out; ret = btrfs_block_rsv_migrate(src_rsv, dst_rsv, num_bytes, 1); ret = btrfs_block_rsv_migrate(src_rsv, dst_rsv, num_bytes); if (!ret) goto out; if (btrfs_test_opt(root, ENOSPC_DEBUG)) { btrfs_debug(root->fs_info, "block rsv migrate returned %d", ret); WARN_ON(1); } /* * Ok this is a problem, let's just steal from the global rsv * since this really shouldn't happen that often. */ ret = btrfs_block_rsv_migrate(&root->fs_info->global_block_rsv, dst_rsv, num_bytes); goto out; } migrate: ret = btrfs_block_rsv_migrate(src_rsv, dst_rsv, num_bytes); out: /* * Migrate only takes a reservation, it doesn't touch the size of the * block_rsv. This is to simplify people who don't normally have things Loading