diff options
author | Qu Wenruo <quwenruo@cn.fujitsu.com> | 2015-09-28 22:35:16 -0400 |
---|---|---|
committer | Chris Mason <clm@fb.com> | 2015-10-21 21:41:07 -0400 |
commit | b9d0b38928e21560550bd3c1a278d6e004d3bde6 (patch) | |
tree | 77fbb0603be74eb80066bee2c941c7904487b812 | |
parent | 94ed938aba557aa798acf496f09afb289b619fcd (diff) |
btrfs: Add handler for invalidate page
For btrfs_invalidatepage() and its variant evict_inode_truncate_page(),
there will be pages don't reach disk.
In that case, their reserved space won't be release nor freed by
finish_ordered_io() nor delayed_ref handler.
So we must free their qgroup reserved space, or we will leaking reserved
space again.
So this will patch will call btrfs_qgroup_free_data() for
invalidatepage() and its variant evict_inode_truncate_page().
And due to the nature of new btrfs_qgroup_reserve/free_data() reserved
space will only be reserved or freed once, so for pages which are
already flushed to disk, their reserved space will be released and freed
by delayed_ref handler.
Double free won't be a problem.
Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
Signed-off-by: Chris Mason <clm@fb.com>
-rw-r--r-- | fs/btrfs/inode.c | 24 |
1 files changed, 24 insertions, 0 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index ef5d3694b944..6670792704e8 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -5132,6 +5132,18 @@ static void evict_inode_truncate_pages(struct inode *inode) | |||
5132 | spin_unlock(&io_tree->lock); | 5132 | spin_unlock(&io_tree->lock); |
5133 | 5133 | ||
5134 | lock_extent_bits(io_tree, start, end, 0, &cached_state); | 5134 | lock_extent_bits(io_tree, start, end, 0, &cached_state); |
5135 | |||
5136 | /* | ||
5137 | * If still has DELALLOC flag, the extent didn't reach disk, | ||
5138 | * and its reserved space won't be freed by delayed_ref. | ||
5139 | * So we need to free its reserved space here. | ||
5140 | * (Refer to comment in btrfs_invalidatepage, case 2) | ||
5141 | * | ||
5142 | * Note, end is the bytenr of last byte, so we need + 1 here. | ||
5143 | */ | ||
5144 | if (state->state & EXTENT_DELALLOC) | ||
5145 | btrfs_qgroup_free_data(inode, start, end - start + 1); | ||
5146 | |||
5135 | clear_extent_bit(io_tree, start, end, | 5147 | clear_extent_bit(io_tree, start, end, |
5136 | EXTENT_LOCKED | EXTENT_DIRTY | | 5148 | EXTENT_LOCKED | EXTENT_DIRTY | |
5137 | EXTENT_DELALLOC | EXTENT_DO_ACCOUNTING | | 5149 | EXTENT_DELALLOC | EXTENT_DO_ACCOUNTING | |
@@ -8646,6 +8658,18 @@ static void btrfs_invalidatepage(struct page *page, unsigned int offset, | |||
8646 | } | 8658 | } |
8647 | } | 8659 | } |
8648 | 8660 | ||
8661 | /* | ||
8662 | * Qgroup reserved space handler | ||
8663 | * Page here will be either | ||
8664 | * 1) Already written to disk | ||
8665 | * In this case, its reserved space is released from data rsv map | ||
8666 | * and will be freed by delayed_ref handler finally. | ||
8667 | * So even we call qgroup_free_data(), it won't decrease reserved | ||
8668 | * space. | ||
8669 | * 2) Not written to disk | ||
8670 | * This means the reserved space should be freed here. | ||
8671 | */ | ||
8672 | btrfs_qgroup_free_data(inode, page_start, PAGE_CACHE_SIZE); | ||
8649 | if (!inode_evicting) { | 8673 | if (!inode_evicting) { |
8650 | clear_extent_bit(tree, page_start, page_end, | 8674 | clear_extent_bit(tree, page_start, page_end, |
8651 | EXTENT_LOCKED | EXTENT_DIRTY | | 8675 | EXTENT_LOCKED | EXTENT_DIRTY | |