|
@@ -572,7 +572,7 @@ cont:
|
|
|
}
|
|
|
if (ret <= 0) {
|
|
|
unsigned long clear_flags = EXTENT_DELALLOC |
|
|
|
- EXTENT_DEFRAG;
|
|
|
+ EXTENT_DELALLOC_NEW | EXTENT_DEFRAG;
|
|
|
unsigned long page_error_op;
|
|
|
|
|
|
clear_flags |= (ret < 0) ? EXTENT_DO_ACCOUNTING : 0;
|
|
@@ -879,6 +879,7 @@ out_free:
|
|
|
async_extent->start +
|
|
|
async_extent->ram_size - 1,
|
|
|
NULL, EXTENT_LOCKED | EXTENT_DELALLOC |
|
|
|
+ EXTENT_DELALLOC_NEW |
|
|
|
EXTENT_DEFRAG | EXTENT_DO_ACCOUNTING,
|
|
|
PAGE_UNLOCK | PAGE_CLEAR_DIRTY |
|
|
|
PAGE_SET_WRITEBACK | PAGE_END_WRITEBACK |
|
|
@@ -974,6 +975,7 @@ static noinline int cow_file_range(struct inode *inode,
|
|
|
extent_clear_unlock_delalloc(inode, start, end,
|
|
|
delalloc_end, NULL,
|
|
|
EXTENT_LOCKED | EXTENT_DELALLOC |
|
|
|
+ EXTENT_DELALLOC_NEW |
|
|
|
EXTENT_DEFRAG, PAGE_UNLOCK |
|
|
|
PAGE_CLEAR_DIRTY | PAGE_SET_WRITEBACK |
|
|
|
PAGE_END_WRITEBACK);
|
|
@@ -1086,8 +1088,8 @@ out_reserve:
|
|
|
btrfs_dec_block_group_reservations(fs_info, ins.objectid);
|
|
|
btrfs_free_reserved_extent(fs_info, ins.objectid, ins.offset, 1);
|
|
|
out_unlock:
|
|
|
- clear_bits = EXTENT_LOCKED | EXTENT_DELALLOC | EXTENT_DEFRAG |
|
|
|
- EXTENT_CLEAR_META_RESV;
|
|
|
+ clear_bits = EXTENT_LOCKED | EXTENT_DELALLOC | EXTENT_DELALLOC_NEW |
|
|
|
+ EXTENT_DEFRAG | EXTENT_CLEAR_META_RESV;
|
|
|
page_ops = PAGE_UNLOCK | PAGE_CLEAR_DIRTY | PAGE_SET_WRITEBACK |
|
|
|
PAGE_END_WRITEBACK;
|
|
|
/*
|
|
@@ -1775,6 +1777,14 @@ static void btrfs_set_bit_hook(struct inode *inode,
|
|
|
btrfs_add_delalloc_inodes(root, inode);
|
|
|
spin_unlock(&BTRFS_I(inode)->lock);
|
|
|
}
|
|
|
+
|
|
|
+ if (!(state->state & EXTENT_DELALLOC_NEW) &&
|
|
|
+ (*bits & EXTENT_DELALLOC_NEW)) {
|
|
|
+ spin_lock(&BTRFS_I(inode)->lock);
|
|
|
+ BTRFS_I(inode)->new_delalloc_bytes += state->end + 1 -
|
|
|
+ state->start;
|
|
|
+ spin_unlock(&BTRFS_I(inode)->lock);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -1840,6 +1850,14 @@ static void btrfs_clear_bit_hook(struct btrfs_inode *inode,
|
|
|
btrfs_del_delalloc_inode(root, inode);
|
|
|
spin_unlock(&inode->lock);
|
|
|
}
|
|
|
+
|
|
|
+ if ((state->state & EXTENT_DELALLOC_NEW) &&
|
|
|
+ (*bits & EXTENT_DELALLOC_NEW)) {
|
|
|
+ spin_lock(&inode->lock);
|
|
|
+ ASSERT(inode->new_delalloc_bytes >= len);
|
|
|
+ inode->new_delalloc_bytes -= len;
|
|
|
+ spin_unlock(&inode->lock);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -2872,6 +2890,13 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent)
|
|
|
u64 logical_len = ordered_extent->len;
|
|
|
bool nolock;
|
|
|
bool truncated = false;
|
|
|
+ bool range_locked = false;
|
|
|
+ bool clear_new_delalloc_bytes = false;
|
|
|
+
|
|
|
+ if (!test_bit(BTRFS_ORDERED_NOCOW, &ordered_extent->flags) &&
|
|
|
+ !test_bit(BTRFS_ORDERED_PREALLOC, &ordered_extent->flags) &&
|
|
|
+ !test_bit(BTRFS_ORDERED_DIRECT, &ordered_extent->flags))
|
|
|
+ clear_new_delalloc_bytes = true;
|
|
|
|
|
|
nolock = btrfs_is_free_space_inode(BTRFS_I(inode));
|
|
|
|
|
@@ -2920,6 +2945,7 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent)
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
+ range_locked = true;
|
|
|
lock_extent_bits(io_tree, ordered_extent->file_offset,
|
|
|
ordered_extent->file_offset + ordered_extent->len - 1,
|
|
|
&cached_state);
|
|
@@ -2945,7 +2971,7 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent)
|
|
|
if (IS_ERR(trans)) {
|
|
|
ret = PTR_ERR(trans);
|
|
|
trans = NULL;
|
|
|
- goto out_unlock;
|
|
|
+ goto out;
|
|
|
}
|
|
|
|
|
|
trans->block_rsv = &fs_info->delalloc_block_rsv;
|
|
@@ -2977,7 +3003,7 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent)
|
|
|
trans->transid);
|
|
|
if (ret < 0) {
|
|
|
btrfs_abort_transaction(trans, ret);
|
|
|
- goto out_unlock;
|
|
|
+ goto out;
|
|
|
}
|
|
|
|
|
|
add_pending_csums(trans, inode, &ordered_extent->list);
|
|
@@ -2986,14 +3012,26 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent)
|
|
|
ret = btrfs_update_inode_fallback(trans, root, inode);
|
|
|
if (ret) { /* -ENOMEM or corruption */
|
|
|
btrfs_abort_transaction(trans, ret);
|
|
|
- goto out_unlock;
|
|
|
+ goto out;
|
|
|
}
|
|
|
ret = 0;
|
|
|
-out_unlock:
|
|
|
- unlock_extent_cached(io_tree, ordered_extent->file_offset,
|
|
|
- ordered_extent->file_offset +
|
|
|
- ordered_extent->len - 1, &cached_state, GFP_NOFS);
|
|
|
out:
|
|
|
+ if (range_locked || clear_new_delalloc_bytes) {
|
|
|
+ unsigned int clear_bits = 0;
|
|
|
+
|
|
|
+ if (range_locked)
|
|
|
+ clear_bits |= EXTENT_LOCKED;
|
|
|
+ if (clear_new_delalloc_bytes)
|
|
|
+ clear_bits |= EXTENT_DELALLOC_NEW;
|
|
|
+ clear_extent_bit(&BTRFS_I(inode)->io_tree,
|
|
|
+ ordered_extent->file_offset,
|
|
|
+ ordered_extent->file_offset +
|
|
|
+ ordered_extent->len - 1,
|
|
|
+ clear_bits,
|
|
|
+ (clear_bits & EXTENT_LOCKED) ? 1 : 0,
|
|
|
+ 0, &cached_state, GFP_NOFS);
|
|
|
+ }
|
|
|
+
|
|
|
if (root != fs_info->tree_root)
|
|
|
btrfs_delalloc_release_metadata(BTRFS_I(inode),
|
|
|
ordered_extent->len);
|
|
@@ -8906,6 +8944,7 @@ again:
|
|
|
if (!inode_evicting)
|
|
|
clear_extent_bit(tree, start, end,
|
|
|
EXTENT_DIRTY | EXTENT_DELALLOC |
|
|
|
+ EXTENT_DELALLOC_NEW |
|
|
|
EXTENT_LOCKED | EXTENT_DO_ACCOUNTING |
|
|
|
EXTENT_DEFRAG, 1, 0, &cached_state,
|
|
|
GFP_NOFS);
|
|
@@ -8963,8 +9002,8 @@ again:
|
|
|
if (!inode_evicting) {
|
|
|
clear_extent_bit(tree, page_start, page_end,
|
|
|
EXTENT_LOCKED | EXTENT_DIRTY |
|
|
|
- EXTENT_DELALLOC | EXTENT_DO_ACCOUNTING |
|
|
|
- EXTENT_DEFRAG, 1, 1,
|
|
|
+ EXTENT_DELALLOC | EXTENT_DELALLOC_NEW |
|
|
|
+ EXTENT_DO_ACCOUNTING | EXTENT_DEFRAG, 1, 1,
|
|
|
&cached_state, GFP_NOFS);
|
|
|
|
|
|
__btrfs_releasepage(page, GFP_NOFS);
|
|
@@ -9335,6 +9374,7 @@ struct inode *btrfs_alloc_inode(struct super_block *sb)
|
|
|
ei->last_sub_trans = 0;
|
|
|
ei->logged_trans = 0;
|
|
|
ei->delalloc_bytes = 0;
|
|
|
+ ei->new_delalloc_bytes = 0;
|
|
|
ei->defrag_bytes = 0;
|
|
|
ei->disk_i_size = 0;
|
|
|
ei->flags = 0;
|
|
@@ -9400,6 +9440,7 @@ void btrfs_destroy_inode(struct inode *inode)
|
|
|
WARN_ON(BTRFS_I(inode)->outstanding_extents);
|
|
|
WARN_ON(BTRFS_I(inode)->reserved_extents);
|
|
|
WARN_ON(BTRFS_I(inode)->delalloc_bytes);
|
|
|
+ WARN_ON(BTRFS_I(inode)->new_delalloc_bytes);
|
|
|
WARN_ON(BTRFS_I(inode)->csum_bytes);
|
|
|
WARN_ON(BTRFS_I(inode)->defrag_bytes);
|
|
|
|
|
@@ -9523,7 +9564,7 @@ static int btrfs_getattr(struct vfsmount *mnt,
|
|
|
stat->dev = BTRFS_I(inode)->root->anon_dev;
|
|
|
|
|
|
spin_lock(&BTRFS_I(inode)->lock);
|
|
|
- delalloc_bytes = BTRFS_I(inode)->delalloc_bytes;
|
|
|
+ delalloc_bytes = BTRFS_I(inode)->new_delalloc_bytes;
|
|
|
spin_unlock(&BTRFS_I(inode)->lock);
|
|
|
stat->blocks = (ALIGN(inode_get_bytes(inode), blocksize) +
|
|
|
ALIGN(delalloc_bytes, blocksize)) >> 9;
|