diff options
Diffstat (limited to 'fs/btrfs/extent-tree.c')
| -rw-r--r-- | fs/btrfs/extent-tree.c | 16 |
1 files changed, 16 insertions, 0 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 571f402d3fc4..6f080451fcb1 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
| @@ -3208,6 +3208,8 @@ static int cache_save_setup(struct btrfs_block_group_cache *block_group, | |||
| 3208 | return 0; | 3208 | return 0; |
| 3209 | } | 3209 | } |
| 3210 | 3210 | ||
| 3211 | if (trans->aborted) | ||
| 3212 | return 0; | ||
| 3211 | again: | 3213 | again: |
| 3212 | inode = lookup_free_space_inode(root, block_group, path); | 3214 | inode = lookup_free_space_inode(root, block_group, path); |
| 3213 | if (IS_ERR(inode) && PTR_ERR(inode) != -ENOENT) { | 3215 | if (IS_ERR(inode) && PTR_ERR(inode) != -ENOENT) { |
| @@ -3243,6 +3245,20 @@ again: | |||
| 3243 | */ | 3245 | */ |
| 3244 | BTRFS_I(inode)->generation = 0; | 3246 | BTRFS_I(inode)->generation = 0; |
| 3245 | ret = btrfs_update_inode(trans, root, inode); | 3247 | ret = btrfs_update_inode(trans, root, inode); |
| 3248 | if (ret) { | ||
| 3249 | /* | ||
| 3250 | * So theoretically we could recover from this, simply set the | ||
| 3251 | * super cache generation to 0 so we know to invalidate the | ||
| 3252 | * cache, but then we'd have to keep track of the block groups | ||
| 3253 | * that fail this way so we know we _have_ to reset this cache | ||
| 3254 | * before the next commit or risk reading stale cache. So to | ||
| 3255 | * limit our exposure to horrible edge cases lets just abort the | ||
| 3256 | * transaction, this only happens in really bad situations | ||
| 3257 | * anyway. | ||
| 3258 | */ | ||
| 3259 | btrfs_abort_transaction(trans, root, ret); | ||
| 3260 | goto out_put; | ||
| 3261 | } | ||
| 3246 | WARN_ON(ret); | 3262 | WARN_ON(ret); |
| 3247 | 3263 | ||
| 3248 | if (i_size_read(inode) > 0) { | 3264 | if (i_size_read(inode) > 0) { |
