diff options
| -rw-r--r-- | fs/btrfs/ctree.h | 3 | ||||
| -rw-r--r-- | fs/btrfs/disk-io.c | 15 | ||||
| -rw-r--r-- | fs/btrfs/extent-tree.c | 11 | ||||
| -rw-r--r-- | fs/btrfs/extent_io.c | 61 | ||||
| -rw-r--r-- | fs/btrfs/extent_io.h | 10 | ||||
| -rw-r--r-- | fs/btrfs/file.c | 23 | ||||
| -rw-r--r-- | fs/btrfs/inode.c | 111 | ||||
| -rw-r--r-- | fs/btrfs/ioctl.c | 2 | ||||
| -rw-r--r-- | fs/btrfs/relocation.c | 2 |
9 files changed, 148 insertions, 90 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 3a36b1fb553a..3f704a816137 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
| @@ -2311,7 +2311,8 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans, | |||
| 2311 | u32 min_type); | 2311 | u32 min_type); |
| 2312 | 2312 | ||
| 2313 | int btrfs_start_delalloc_inodes(struct btrfs_root *root, int delay_iput); | 2313 | int btrfs_start_delalloc_inodes(struct btrfs_root *root, int delay_iput); |
| 2314 | int btrfs_set_extent_delalloc(struct inode *inode, u64 start, u64 end); | 2314 | int btrfs_set_extent_delalloc(struct inode *inode, u64 start, u64 end, |
| 2315 | struct extent_state **cached_state); | ||
| 2315 | int btrfs_writepages(struct address_space *mapping, | 2316 | int btrfs_writepages(struct address_space *mapping, |
| 2316 | struct writeback_control *wbc); | 2317 | struct writeback_control *wbc); |
| 2317 | int btrfs_create_subvol_root(struct btrfs_trans_handle *trans, | 2318 | int btrfs_create_subvol_root(struct btrfs_trans_handle *trans, |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 0427183e3e05..11d0ad30e203 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
| @@ -263,13 +263,15 @@ static int csum_tree_block(struct btrfs_root *root, struct extent_buffer *buf, | |||
| 263 | static int verify_parent_transid(struct extent_io_tree *io_tree, | 263 | static int verify_parent_transid(struct extent_io_tree *io_tree, |
| 264 | struct extent_buffer *eb, u64 parent_transid) | 264 | struct extent_buffer *eb, u64 parent_transid) |
| 265 | { | 265 | { |
| 266 | struct extent_state *cached_state = NULL; | ||
| 266 | int ret; | 267 | int ret; |
| 267 | 268 | ||
| 268 | if (!parent_transid || btrfs_header_generation(eb) == parent_transid) | 269 | if (!parent_transid || btrfs_header_generation(eb) == parent_transid) |
| 269 | return 0; | 270 | return 0; |
| 270 | 271 | ||
| 271 | lock_extent(io_tree, eb->start, eb->start + eb->len - 1, GFP_NOFS); | 272 | lock_extent_bits(io_tree, eb->start, eb->start + eb->len - 1, |
| 272 | if (extent_buffer_uptodate(io_tree, eb) && | 273 | 0, &cached_state, GFP_NOFS); |
| 274 | if (extent_buffer_uptodate(io_tree, eb, cached_state) && | ||
| 273 | btrfs_header_generation(eb) == parent_transid) { | 275 | btrfs_header_generation(eb) == parent_transid) { |
| 274 | ret = 0; | 276 | ret = 0; |
| 275 | goto out; | 277 | goto out; |
| @@ -282,10 +284,10 @@ static int verify_parent_transid(struct extent_io_tree *io_tree, | |||
| 282 | (unsigned long long)btrfs_header_generation(eb)); | 284 | (unsigned long long)btrfs_header_generation(eb)); |
| 283 | } | 285 | } |
| 284 | ret = 1; | 286 | ret = 1; |
| 285 | clear_extent_buffer_uptodate(io_tree, eb); | 287 | clear_extent_buffer_uptodate(io_tree, eb, &cached_state); |
| 286 | out: | 288 | out: |
| 287 | unlock_extent(io_tree, eb->start, eb->start + eb->len - 1, | 289 | unlock_extent_cached(io_tree, eb->start, eb->start + eb->len - 1, |
| 288 | GFP_NOFS); | 290 | &cached_state, GFP_NOFS); |
| 289 | return ret; | 291 | return ret; |
| 290 | } | 292 | } |
| 291 | 293 | ||
| @@ -2497,7 +2499,8 @@ int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid) | |||
| 2497 | int ret; | 2499 | int ret; |
| 2498 | struct inode *btree_inode = buf->first_page->mapping->host; | 2500 | struct inode *btree_inode = buf->first_page->mapping->host; |
| 2499 | 2501 | ||
| 2500 | ret = extent_buffer_uptodate(&BTRFS_I(btree_inode)->io_tree, buf); | 2502 | ret = extent_buffer_uptodate(&BTRFS_I(btree_inode)->io_tree, buf, |
| 2503 | NULL); | ||
| 2501 | if (!ret) | 2504 | if (!ret) |
| 2502 | return ret; | 2505 | return ret; |
| 2503 | 2506 | ||
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 559f72489b3b..1727b26fb194 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
| @@ -6561,6 +6561,7 @@ static noinline int invalidate_extent_cache(struct btrfs_root *root, | |||
| 6561 | struct btrfs_key key; | 6561 | struct btrfs_key key; |
| 6562 | struct inode *inode = NULL; | 6562 | struct inode *inode = NULL; |
| 6563 | struct btrfs_file_extent_item *fi; | 6563 | struct btrfs_file_extent_item *fi; |
| 6564 | struct extent_state *cached_state = NULL; | ||
| 6564 | u64 num_bytes; | 6565 | u64 num_bytes; |
| 6565 | u64 skip_objectid = 0; | 6566 | u64 skip_objectid = 0; |
| 6566 | u32 nritems; | 6567 | u32 nritems; |
| @@ -6589,12 +6590,14 @@ static noinline int invalidate_extent_cache(struct btrfs_root *root, | |||
| 6589 | } | 6590 | } |
| 6590 | num_bytes = btrfs_file_extent_num_bytes(leaf, fi); | 6591 | num_bytes = btrfs_file_extent_num_bytes(leaf, fi); |
| 6591 | 6592 | ||
| 6592 | lock_extent(&BTRFS_I(inode)->io_tree, key.offset, | 6593 | lock_extent_bits(&BTRFS_I(inode)->io_tree, key.offset, |
| 6593 | key.offset + num_bytes - 1, GFP_NOFS); | 6594 | key.offset + num_bytes - 1, 0, &cached_state, |
| 6595 | GFP_NOFS); | ||
| 6594 | btrfs_drop_extent_cache(inode, key.offset, | 6596 | btrfs_drop_extent_cache(inode, key.offset, |
| 6595 | key.offset + num_bytes - 1, 1); | 6597 | key.offset + num_bytes - 1, 1); |
| 6596 | unlock_extent(&BTRFS_I(inode)->io_tree, key.offset, | 6598 | unlock_extent_cached(&BTRFS_I(inode)->io_tree, key.offset, |
| 6597 | key.offset + num_bytes - 1, GFP_NOFS); | 6599 | key.offset + num_bytes - 1, &cached_state, |
| 6600 | GFP_NOFS); | ||
| 6598 | cond_resched(); | 6601 | cond_resched(); |
| 6599 | } | 6602 | } |
| 6600 | iput(inode); | 6603 | iput(inode); |
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 3c17c9eb0d98..c99121ac5d6b 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
| @@ -513,7 +513,10 @@ int clear_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, | |||
| 513 | u64 last_end; | 513 | u64 last_end; |
| 514 | int err; | 514 | int err; |
| 515 | int set = 0; | 515 | int set = 0; |
| 516 | int clear = 0; | ||
| 516 | 517 | ||
| 518 | if (bits & (EXTENT_IOBITS | EXTENT_BOUNDARY)) | ||
| 519 | clear = 1; | ||
| 517 | again: | 520 | again: |
| 518 | if (!prealloc && (mask & __GFP_WAIT)) { | 521 | if (!prealloc && (mask & __GFP_WAIT)) { |
| 519 | prealloc = alloc_extent_state(mask); | 522 | prealloc = alloc_extent_state(mask); |
| @@ -524,14 +527,20 @@ again: | |||
| 524 | spin_lock(&tree->lock); | 527 | spin_lock(&tree->lock); |
| 525 | if (cached_state) { | 528 | if (cached_state) { |
| 526 | cached = *cached_state; | 529 | cached = *cached_state; |
| 527 | *cached_state = NULL; | 530 | |
| 528 | cached_state = NULL; | 531 | if (clear) { |
| 532 | *cached_state = NULL; | ||
| 533 | cached_state = NULL; | ||
| 534 | } | ||
| 535 | |||
| 529 | if (cached && cached->tree && cached->start == start) { | 536 | if (cached && cached->tree && cached->start == start) { |
| 530 | atomic_dec(&cached->refs); | 537 | if (clear) |
| 538 | atomic_dec(&cached->refs); | ||
| 531 | state = cached; | 539 | state = cached; |
| 532 | goto hit_next; | 540 | goto hit_next; |
| 533 | } | 541 | } |
| 534 | free_extent_state(cached); | 542 | if (clear) |
| 543 | free_extent_state(cached); | ||
| 535 | } | 544 | } |
| 536 | /* | 545 | /* |
| 537 | * this search will find the extents that end after | 546 | * this search will find the extents that end after |
| @@ -946,11 +955,11 @@ int clear_extent_bits(struct extent_io_tree *tree, u64 start, u64 end, | |||
| 946 | } | 955 | } |
| 947 | 956 | ||
| 948 | int set_extent_delalloc(struct extent_io_tree *tree, u64 start, u64 end, | 957 | int set_extent_delalloc(struct extent_io_tree *tree, u64 start, u64 end, |
| 949 | gfp_t mask) | 958 | struct extent_state **cached_state, gfp_t mask) |
| 950 | { | 959 | { |
| 951 | return set_extent_bit(tree, start, end, | 960 | return set_extent_bit(tree, start, end, |
| 952 | EXTENT_DELALLOC | EXTENT_DIRTY | EXTENT_UPTODATE, | 961 | EXTENT_DELALLOC | EXTENT_DIRTY | EXTENT_UPTODATE, |
| 953 | 0, NULL, NULL, mask); | 962 | 0, NULL, cached_state, mask); |
| 954 | } | 963 | } |
| 955 | 964 | ||
| 956 | int clear_extent_dirty(struct extent_io_tree *tree, u64 start, u64 end, | 965 | int clear_extent_dirty(struct extent_io_tree *tree, u64 start, u64 end, |
| @@ -984,10 +993,11 @@ int set_extent_uptodate(struct extent_io_tree *tree, u64 start, u64 end, | |||
| 984 | } | 993 | } |
| 985 | 994 | ||
| 986 | static int clear_extent_uptodate(struct extent_io_tree *tree, u64 start, | 995 | static int clear_extent_uptodate(struct extent_io_tree *tree, u64 start, |
| 987 | u64 end, gfp_t mask) | 996 | u64 end, struct extent_state **cached_state, |
| 997 | gfp_t mask) | ||
| 988 | { | 998 | { |
| 989 | return clear_extent_bit(tree, start, end, EXTENT_UPTODATE, 0, 0, | 999 | return clear_extent_bit(tree, start, end, EXTENT_UPTODATE, 0, 0, |
| 990 | NULL, mask); | 1000 | cached_state, mask); |
| 991 | } | 1001 | } |
| 992 | 1002 | ||
| 993 | int wait_on_extent_writeback(struct extent_io_tree *tree, u64 start, u64 end) | 1003 | int wait_on_extent_writeback(struct extent_io_tree *tree, u64 start, u64 end) |
| @@ -1727,7 +1737,7 @@ static void end_bio_extent_writepage(struct bio *bio, int err) | |||
| 1727 | } | 1737 | } |
| 1728 | 1738 | ||
| 1729 | if (!uptodate) { | 1739 | if (!uptodate) { |
| 1730 | clear_extent_uptodate(tree, start, end, GFP_NOFS); | 1740 | clear_extent_uptodate(tree, start, end, NULL, GFP_NOFS); |
| 1731 | ClearPageUptodate(page); | 1741 | ClearPageUptodate(page); |
| 1732 | SetPageError(page | ||
