Skip to content

Commit 3bce876

Browse files
Josef Bacikmasoncl
authored andcommitted
Btrfs: don't steal from the global reserve if we don't have the space
btrfs_evict_inode() needs to be more careful about stealing from the global_rsv. We dont' want to end up aborting commit with ENOSPC just because the evict_inode code was too greedy. Signed-off-by: Chris Mason <[email protected]>
1 parent 365c531 commit 3bce876

File tree

1 file changed

+44
-2
lines changed

1 file changed

+44
-2
lines changed

fs/btrfs/inode.c

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5010,6 +5010,7 @@ void btrfs_evict_inode(struct inode *inode)
50105010
struct btrfs_trans_handle *trans;
50115011
struct btrfs_root *root = BTRFS_I(inode)->root;
50125012
struct btrfs_block_rsv *rsv, *global_rsv;
5013+
int steal_from_global = 0;
50135014
u64 min_size = btrfs_calc_trunc_metadata_size(root, 1);
50145015
int ret;
50155016

@@ -5077,9 +5078,20 @@ void btrfs_evict_inode(struct inode *inode)
50775078
* hard as possible to get this to work.
50785079
*/
50795080
if (ret)
5080-
ret = btrfs_block_rsv_migrate(global_rsv, rsv, min_size);
5081+
steal_from_global++;
5082+
else
5083+
steal_from_global = 0;
5084+
ret = 0;
50815085

5082-
if (ret) {
5086+
/*
5087+
* steal_from_global == 0: we reserved stuff, hooray!
5088+
* steal_from_global == 1: we didn't reserve stuff, boo!
5089+
* steal_from_global == 2: we've committed, still not a lot of
5090+
* room but maybe we'll have room in the global reserve this
5091+
* time.
5092+
* steal_from_global == 3: abandon all hope!
5093+
*/
5094+
if (steal_from_global > 2) {
50835095
btrfs_warn(root->fs_info,
50845096
"Could not get space for a delete, will truncate on mount %d",
50855097
ret);
@@ -5095,6 +5107,36 @@ void btrfs_evict_inode(struct inode *inode)
50955107
goto no_delete;
50965108
}
50975109

5110+
/*
5111+
* We can't just steal from the global reserve, we need tomake
5112+
* sure there is room to do it, if not we need to commit and try
5113+
* again.
5114+
*/
5115+
if (steal_from_global) {
5116+
if (!btrfs_check_space_for_delayed_refs(trans, root))
5117+
ret = btrfs_block_rsv_migrate(global_rsv, rsv,
5118+
min_size);
5119+
else
5120+
ret = -ENOSPC;
5121+
}
5122+
5123+
/*
5124+
* Couldn't steal from the global reserve, we have too much
5125+
* pending stuff built up, commit the transaction and try it
5126+
* again.
5127+
*/
5128+
if (ret) {
5129+
ret = btrfs_commit_transaction(trans, root);
5130+
if (ret) {
5131+
btrfs_orphan_del(NULL, inode);
5132+
btrfs_free_block_rsv(root, rsv);
5133+
goto no_delete;
5134+
}
5135+
continue;
5136+
} else {
5137+
steal_from_global = 0;
5138+
}
5139+
50985140
trans->block_rsv = rsv;
50995141

51005142
ret = btrfs_truncate_inode_items(trans, root, inode, 0, 0);

0 commit comments

Comments
 (0)