diff options
Diffstat (limited to 'fs/btrfs')
-rw-r--r-- | fs/btrfs/transaction.c | 11 |
1 files changed, 10 insertions, 1 deletions
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 5b158da7e0bb..4583008217e6 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -181,6 +181,7 @@ static struct btrfs_trans_handle *start_transaction(struct btrfs_root *root, | |||
181 | { | 181 | { |
182 | struct btrfs_trans_handle *h; | 182 | struct btrfs_trans_handle *h; |
183 | struct btrfs_transaction *cur_trans; | 183 | struct btrfs_transaction *cur_trans; |
184 | int retries = 0; | ||
184 | int ret; | 185 | int ret; |
185 | 186 | ||
186 | if (root->fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) | 187 | if (root->fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) |
@@ -224,10 +225,18 @@ again: | |||
224 | 225 | ||
225 | if (num_items > 0) { | 226 | if (num_items > 0) { |
226 | ret = btrfs_trans_reserve_metadata(h, root, num_items); | 227 | ret = btrfs_trans_reserve_metadata(h, root, num_items); |
227 | if (ret == -EAGAIN) { | 228 | if (ret == -EAGAIN && !retries) { |
229 | retries++; | ||
228 | btrfs_commit_transaction(h, root); | 230 | btrfs_commit_transaction(h, root); |
229 | goto again; | 231 | goto again; |
232 | } else if (ret == -EAGAIN) { | ||
233 | /* | ||
234 | * We have already retried and got EAGAIN, so really we | ||
235 | * don't have space, so set ret to -ENOSPC. | ||
236 | */ | ||
237 | ret = -ENOSPC; | ||
230 | } | 238 | } |
239 | |||
231 | if (ret < 0) { | 240 | if (ret < 0) { |
232 | btrfs_end_transaction(h, root); | 241 | btrfs_end_transaction(h, root); |
233 | return ERR_PTR(ret); | 242 | return ERR_PTR(ret); |