diff options
-rw-r--r-- | fs/btrfs/ctree.c | 44 | ||||
-rw-r--r-- | fs/btrfs/extent_map.c | 45 |
2 files changed, 39 insertions, 50 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 17a322663f3b..e8466940fa30 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -1588,6 +1588,11 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1588 | if (!path->nodes[1]) | 1588 | if (!path->nodes[1]) |
1589 | return 1; | 1589 | return 1; |
1590 | 1590 | ||
1591 | right_nritems = btrfs_header_nritems(right); | ||
1592 | if (right_nritems == 0) { | ||
1593 | return 1; | ||
1594 | } | ||
1595 | |||
1591 | left = read_tree_block(root, btrfs_node_blockptr(path->nodes[1], | 1596 | left = read_tree_block(root, btrfs_node_blockptr(path->nodes[1], |
1592 | slot - 1), root->leafsize); | 1597 | slot - 1), root->leafsize); |
1593 | free_space = btrfs_leaf_free_space(root, left); | 1598 | free_space = btrfs_leaf_free_space(root, left); |
@@ -1604,18 +1609,13 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1604 | free_extent_buffer(left); | 1609 | free_extent_buffer(left); |
1605 | return 1; | 1610 | return 1; |
1606 | } | 1611 | } |
1612 | |||
1607 | free_space = btrfs_leaf_free_space(root, left); | 1613 | free_space = btrfs_leaf_free_space(root, left); |
1608 | if (free_space < data_size + sizeof(struct btrfs_item)) { | 1614 | if (free_space < data_size + sizeof(struct btrfs_item)) { |
1609 | free_extent_buffer(left); | 1615 | free_extent_buffer(left); |
1610 | return 1; | 1616 | return 1; |
1611 | } | 1617 | } |
1612 | 1618 | ||
1613 | right_nritems = btrfs_header_nritems(right); | ||
1614 | if (right_nritems == 0) { | ||
1615 | free_extent_buffer(left); | ||
1616 | return 1; | ||
1617 | } | ||
1618 | |||
1619 | for (i = 0; i < right_nritems - 1; i++) { | 1619 | for (i = 0; i < right_nritems - 1; i++) { |
1620 | item = btrfs_item_nr(right, i); | 1620 | item = btrfs_item_nr(right, i); |
1621 | if (!right->map_token) { | 1621 | if (!right->map_token) { |
@@ -1772,21 +1772,25 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1772 | struct btrfs_disk_key disk_key; | 1772 | struct btrfs_disk_key disk_key; |
1773 | 1773 | ||
1774 | /* first try to make some room by pushing left and right */ | 1774 | /* first try to make some room by pushing left and right */ |
1775 | wret = push_leaf_left(trans, root, path, data_size); | 1775 | if (ins_key->type != BTRFS_DIR_ITEM_KEY) { |
1776 | if (wret < 0) { | ||
1777 | return wret; | ||
1778 | } | ||
1779 | if (wret) { | ||
1780 | wret = push_leaf_right(trans, root, path, data_size); | 1776 | wret = push_leaf_right(trans, root, path, data_size); |
1781 | if (wret < 0) | 1777 | if (wret < 0) { |
1782 | return wret; | 1778 | return wret; |
1783 | } | 1779 | } |
1784 | l = path->nodes[0]; | 1780 | if (wret) { |
1781 | wret = push_leaf_left(trans, root, path, data_size); | ||
1782 | if (wret < 0) | ||
1783 | return wret; | ||
1784 | } | ||
1785 | l = path->nodes[0]; | ||
1785 | 1786 | ||
1786 | /* did the pushes work? */ | 1787 | /* did the pushes work? */ |
1787 | if (btrfs_leaf_free_space(root, l) >= | 1788 | if (btrfs_leaf_free_space(root, l) >= |
1788 | sizeof(struct btrfs_item) + data_size) { | 1789 | sizeof(struct btrfs_item) + data_size) { |
1789 | return 0; | 1790 | return 0; |
1791 | } | ||
1792 | } else { | ||
1793 | l = path->nodes[0]; | ||
1790 | } | 1794 | } |
1791 | 1795 | ||
1792 | if (!path->nodes[1]) { | 1796 | if (!path->nodes[1]) { |
@@ -2388,13 +2392,13 @@ int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
2388 | slot = path->slots[1]; | 2392 | slot = path->slots[1]; |
2389 | extent_buffer_get(leaf); | 2393 | extent_buffer_get(leaf); |
2390 | 2394 | ||
2391 | wret = push_leaf_left(trans, root, path, 1); | 2395 | wret = push_leaf_right(trans, root, path, 1); |
2392 | if (wret < 0 && wret != -ENOSPC) | 2396 | if (wret < 0 && wret != -ENOSPC) |
2393 | ret = wret; | 2397 | ret = wret; |
2394 | 2398 | ||
2395 | if (path->nodes[0] == leaf && | 2399 | if (path->nodes[0] == leaf && |
2396 | btrfs_header_nritems(leaf)) { | 2400 | btrfs_header_nritems(leaf)) { |
2397 | wret = push_leaf_right(trans, root, path, 1); | 2401 | wret = push_leaf_left(trans, root, path, 1); |
2398 | if (wret < 0 && wret != -ENOSPC) | 2402 | if (wret < 0 && wret != -ENOSPC) |
2399 | ret = wret; | 2403 | ret = wret; |
2400 | } | 2404 | } |
diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c index 3c81f5eab155..caaf0bf0e059 100644 --- a/fs/btrfs/extent_map.c +++ b/fs/btrfs/extent_map.c | |||
@@ -1986,12 +1986,15 @@ static inline struct page *extent_buffer_page(struct extent_buffer *eb, | |||
1986 | unsigned long i) | 1986 | unsigned long i) |
1987 | { | 1987 | { |
1988 | struct page *p; | 1988 | struct page *p; |
1989 | struct address_space *mapping; | ||
1989 | 1990 | ||
1990 | if (i == 0) | 1991 | if (i == 0) |
1991 | return eb->first_page; | 1992 | return eb->first_page; |
1992 | i += eb->start >> PAGE_CACHE_SHIFT; | 1993 | i += eb->start >> PAGE_CACHE_SHIFT; |
1993 | p = find_get_page(eb->first_page->mapping, i); | 1994 | mapping = eb->first_page->mapping; |
1994 | page_cache_release(p); | 1995 | read_lock_irq(&mapping->tree_lock); |
1996 | p = radix_tree_lookup(&mapping->page_tree, i); | ||
1997 | read_unlock_irq(&mapping->tree_lock); | ||
1995 | return p; | 1998 | return p; |
1996 | } | 1999 | } |
1997 | 2000 | ||
@@ -2365,9 +2368,7 @@ void read_extent_buffer(struct extent_buffer *eb, void *dstv, | |||
2365 | WARN_ON(start > eb->len); | 2368 | WARN_ON(start > eb->len); |
2366 | WARN_ON(start + len > eb->start + eb->len); | 2369 | WARN_ON(start + len > eb->start + eb->len); |
2367 | 2370 | ||
2368 | offset = start & ((unsigned long)PAGE_CACHE_SIZE - 1); | 2371 | offset = (start_offset + start) & ((unsigned long)PAGE_CACHE_SIZE - 1); |
2369 | if (i == 0) | ||
2370 | offset += start_offset; | ||
2371 | 2372 | ||
2372 | while(len > 0) { | 2373 | while(len > 0) { |
2373 | page = extent_buffer_page(eb, i); | 2374 | page = extent_buffer_page(eb, i); |
@@ -2475,9 +2476,7 @@ int memcmp_extent_buffer(struct extent_buffer *eb, const void *ptrv, | |||
2475 | WARN_ON(start > eb->len); | 2476 | WARN_ON(start > eb->len); |
2476 | WARN_ON(start + len > eb->start + eb->len); | 2477 | WARN_ON(start + len > eb->start + eb->len); |
2477 | 2478 | ||
2478 | offset = start & ((unsigned long)PAGE_CACHE_SIZE - 1); | 2479 | offset = (start_offset + start) & ((unsigned long)PAGE_CACHE_SIZE - 1); |
2479 | if (i == 0) | ||
2480 | offset += start_offset; | ||
2481 | 2480 | ||
2482 | while(len > 0) { | 2481 | while(len > 0) { |
2483 | page = extent_buffer_page(eb, i); | 2482 | page = extent_buffer_page(eb, i); |
@@ -2514,9 +2513,7 @@ void write_extent_buffer(struct extent_buffer *eb, const void *srcv, | |||
2514 | WARN_ON(start > eb->len); | 2513 | WARN_ON(start > eb->len); |
2515 | WARN_ON(start + len > eb->start + eb->len); | 2514 | WARN_ON(start + len > eb->start + eb->len); |
2516 | 2515 | ||
2517 | offset = start & ((unsigned long)PAGE_CACHE_SIZE - 1); | 2516 | offset = (start_offset + start) & ((unsigned long)PAGE_CACHE_SIZE - 1); |
2518 | if (i == 0) | ||
2519 | offset += start_offset; | ||
2520 | 2517 | ||
2521 | while(len > 0) { | 2518 | while(len > 0) { |
2522 | page = extent_buffer_page(eb, i); | 2519 | page = extent_buffer_page(eb, i); |
@@ -2548,9 +2545,7 @@ void memset_extent_buffer(struct extent_buffer *eb, char c, | |||
2548 | WARN_ON(start > eb->len); | 2545 | WARN_ON(start > eb->len); |
2549 | WARN_ON(start + len > eb->start + eb->len); | 2546 | WARN_ON(start + len > eb->start + eb->len); |
2550 | 2547 | ||
2551 | offset = start & ((unsigned long)PAGE_CACHE_SIZE - 1); | 2548 | offset = (start_offset + start) & ((unsigned long)PAGE_CACHE_SIZE - 1); |
2552 | if (i == 0) | ||
2553 | offset += start_offset; | ||
2554 | 2549 | ||
2555 | while(len > 0) { | 2550 | while(len > 0) { |
2556 | page = extent_buffer_page(eb, i); | 2551 | page = extent_buffer_page(eb, i); |
@@ -2582,9 +2577,8 @@ void copy_extent_buffer(struct extent_buffer *dst, struct extent_buffer *src, | |||
2582 | 2577 | ||
2583 | WARN_ON(src->len != dst_len); | 2578 | WARN_ON(src->len != dst_len); |
2584 | 2579 | ||
2585 | offset = dst_offset & ((unsigned long)PAGE_CACHE_SIZE - 1); | 2580 | offset = (start_offset + dst_offset) & |
2586 | if (i == 0) | 2581 | ((unsigned long)PAGE_CACHE_SIZE - 1); |
2587 | offset += start_offset; | ||
2588 | 2582 | ||
2589 | while(len > 0) { | 2583 | while(len > 0) { |
2590 | page = extent_buffer_page(dst, i); | 2584 | page = extent_buffer_page(dst, i); |
@@ -2664,19 +2658,14 @@ void memcpy_extent_buffer(struct extent_buffer *dst, unsigned long dst_offset, | |||
2664 | } | 2658 | } |
2665 | 2659 | ||
2666 | while(len > 0) { | 2660 | while(len > 0) { |
2667 | dst_off_in_page = dst_offset & | 2661 | dst_off_in_page = (start_offset + dst_offset) & |
2668 | ((unsigned long)PAGE_CACHE_SIZE - 1); | 2662 | ((unsigned long)PAGE_CACHE_SIZE - 1); |
2669 | src_off_in_page = src_offset & | 2663 | src_off_in_page = (start_offset + src_offset) & |
2670 | ((unsigned long)PAGE_CACHE_SIZE - 1); | 2664 | ((unsigned long)PAGE_CACHE_SIZE - 1); |
2671 | 2665 | ||
2672 | dst_i = (start_offset + dst_offset) >> PAGE_CACHE_SHIFT; | 2666 | dst_i = (start_offset + dst_offset) >> PAGE_CACHE_SHIFT; |
2673 | src_i = (start_offset + src_offset) >> PAGE_CACHE_SHIFT; | 2667 | src_i = (start_offset + src_offset) >> PAGE_CACHE_SHIFT; |
2674 | 2668 | ||
2675 | if (src_i == 0) | ||
2676 | src_off_in_page += start_offset; | ||
2677 | if (dst_i == 0) | ||
2678 | dst_off_in_page += start_offset; | ||
2679 | |||
2680 | cur = min(len, (unsigned long)(PAGE_CACHE_SIZE - | 2669 | cur = min(len, (unsigned long)(PAGE_CACHE_SIZE - |
2681 | src_off_in_page)); | 2670 | src_off_in_page)); |
2682 | cur = min_t(unsigned long, cur, | 2671 | cur = min_t(unsigned long, cur, |
@@ -2723,14 +2712,10 @@ void memmove_extent_buffer(struct extent_buffer *dst, unsigned long dst_offset, | |||
2723 | dst_i = (start_offset + dst_end) >> PAGE_CACHE_SHIFT; | 2712 | dst_i = (start_offset + dst_end) >> PAGE_CACHE_SHIFT; |
2724 | src_i = (start_offset + src_end) >> PAGE_CACHE_SHIFT; | 2713 | src_i = (start_offset + src_end) >> PAGE_CACHE_SHIFT; |
2725 | 2714 | ||
2726 | dst_off_in_page = dst_end & | 2715 | dst_off_in_page = (start_offset + dst_end) & |
2727 | ((unsigned long)PAGE_CACHE_SIZE - 1); | 2716 | ((unsigned long)PAGE_CACHE_SIZE - 1); |
2728 | src_off_in_page = src_end & | 2717 | src_off_in_page = (start_offset + src_end) & |
2729 | ((unsigned long)PAGE_CACHE_SIZE - 1); | 2718 | ((unsigned long)PAGE_CACHE_SIZE - 1); |
2730 | if (src_i == 0) | ||
2731 | src_off_in_page += start_offset; | ||
2732 | if (dst_i == 0) | ||
2733 | dst_off_in_page += start_offset; | ||
2734 | 2719 | ||
2735 | cur = min_t(unsigned long, len, src_off_in_page + 1); | 2720 | cur = min_t(unsigned long, len, src_off_in_page + 1); |
2736 | cur = min(cur, dst_off_in_page + 1); | 2721 | cur = min(cur, dst_off_in_page + 1); |