aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ctree.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-11-07 13:31:03 -0500
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:03:57 -0400
commit34a3821873aeabff2607c8093bce82cd1fbcfd60 (patch)
treebf204e4a0b45fd764b7fadea23e45034021675c4 /fs/btrfs/ctree.c
parente644d021e328d3902559e5db687383f2da85993c (diff)
Btrfs: Change push_leaf_{leaf,right} to empty the src leave during item deletion
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/ctree.c')
-rw-r--r--fs/btrfs/ctree.c74
1 files changed, 50 insertions, 24 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index ea9b46699349..1b47fe71e0b4 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -1394,19 +1394,21 @@ int btrfs_leaf_free_space(struct btrfs_root *root, struct extent_buffer *leaf)
1394 * room, 0 if everything worked out and < 0 if there were major errors. 1394 * room, 0 if everything worked out and < 0 if there were major errors.
1395 */ 1395 */
1396static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root 1396static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
1397 *root, struct btrfs_path *path, int data_size) 1397 *root, struct btrfs_path *path, int data_size,
1398 int empty)
1398{ 1399{
1399 struct extent_buffer *left = path->nodes[0]; 1400 struct extent_buffer *left = path->nodes[0];
1400 struct extent_buffer *right; 1401 struct extent_buffer *right;
1401 struct extent_buffer *upper; 1402 struct extent_buffer *upper;
1402 struct btrfs_disk_key disk_key; 1403 struct btrfs_disk_key disk_key;
1403 int slot; 1404 int slot;
1404 int i; 1405 u32 i;
1405 int free_space; 1406 int free_space;
1406 int push_space = 0; 1407 int push_space = 0;
1407 int push_items = 0; 1408 int push_items = 0;
1408 struct btrfs_item *item; 1409 struct btrfs_item *item;
1409 u32 left_nritems; 1410 u32 left_nritems;
1411 u32 nr;
1410 u32 right_nritems; 1412 u32 right_nritems;
1411 u32 data_end; 1413 u32 data_end;
1412 u32 this_item_size; 1414 u32 this_item_size;
@@ -1447,7 +1449,13 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
1447 return 1; 1449 return 1;
1448 } 1450 }
1449 1451
1450 for (i = left_nritems - 1; i >= 1; i--) { 1452 if (empty)
1453 nr = 0;
1454 else
1455 nr = 1;
1456
1457 i = left_nritems - 1;
1458 while (i >= nr) {
1451 item = btrfs_item_nr(left, i); 1459 item = btrfs_item_nr(left, i);
1452 1460
1453 if (path->slots[0] == i) 1461 if (path->slots[0] == i)
@@ -1466,6 +1474,9 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
1466 break; 1474 break;
1467 push_items++; 1475 push_items++;
1468 push_space += this_item_size + sizeof(*item); 1476 push_space += this_item_size + sizeof(*item);
1477 if (i == 0)
1478 break;
1479 i--;
1469 } 1480 }
1470 if (left->map_token) { 1481 if (left->map_token) {
1471 unmap_extent_buffer(left, left->map_token, KM_USER1); 1482 unmap_extent_buffer(left, left->map_token, KM_USER1);
@@ -1477,11 +1488,12 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
1477 return 1; 1488 return 1;
1478 } 1489 }
1479 1490
1480 if (push_items == left_nritems) 1491 if (!empty && push_items == left_nritems)
1481 WARN_ON(1); 1492 WARN_ON(1);
1482 1493
1483 /* push left to right */ 1494 /* push left to right */
1484 right_nritems = btrfs_header_nritems(right); 1495 right_nritems = btrfs_header_nritems(right);
1496
1485 push_space = btrfs_item_end_nr(left, left_nritems - push_items); 1497 push_space = btrfs_item_end_nr(left, left_nritems - push_items);
1486 push_space -= leaf_data_end(root, left); 1498 push_space -= leaf_data_end(root, left);
1487 1499
@@ -1511,7 +1523,6 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
1511 right_nritems += push_items; 1523 right_nritems += push_items;
1512 btrfs_set_header_nritems(right, right_nritems); 1524 btrfs_set_header_nritems(right, right_nritems);
1513 push_space = BTRFS_LEAF_DATA_SIZE(root); 1525 push_space = BTRFS_LEAF_DATA_SIZE(root);
1514
1515 for (i = 0; i < right_nritems; i++) { 1526 for (i = 0; i < right_nritems; i++) {
1516 item = btrfs_item_nr(right, i); 1527 item = btrfs_item_nr(right, i);
1517 if (!right->map_token) { 1528 if (!right->map_token) {
@@ -1532,7 +1543,8 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
1532 left_nritems -= push_items; 1543 left_nritems -= push_items;
1533 btrfs_set_header_nritems(left, left_nritems); 1544 btrfs_set_header_nritems(left, left_nritems);
1534 1545
1535 btrfs_mark_buffer_dirty(left); 1546 if (left_nritems)
1547 btrfs_mark_buffer_dirty(left);
1536 btrfs_mark_buffer_dirty(right); 1548 btrfs_mark_buffer_dirty(right);
1537 1549
1538 btrfs_item_key(right, &disk_key, 0); 1550 btrfs_item_key(right, &disk_key, 0);
@@ -1555,7 +1567,8 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
1555 * least data_size bytes. returns zero if the push worked, nonzero otherwise 1567 * least data_size bytes. returns zero if the push worked, nonzero otherwise
1556 */ 1568 */
1557static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root 1569static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
1558 *root, struct btrfs_path *path, int data_size) 1570 *root, struct btrfs_path *path, int data_size,
1571 int empty)
1559{ 1572{
1560 struct btrfs_disk_key disk_key; 1573 struct btrfs_disk_key disk_key;
1561 struct extent_buffer *right = path->nodes[0]; 1574 struct extent_buffer *right = path->nodes[0];
@@ -1568,6 +1581,7 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
1568 struct btrfs_item *item; 1581 struct btrfs_item *item;
1569 u32 old_left_nritems; 1582 u32 old_left_nritems;
1570 u32 right_nritems; 1583 u32 right_nritems;
1584 u32 nr;
1571 int ret = 0; 1585 int ret = 0;
1572 int wret; 1586 int wret;
1573 u32 this_item_size; 1587 u32 this_item_size;
@@ -1607,7 +1621,12 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
1607 return 1; 1621 return 1;
1608 } 1622 }
1609 1623
1610 for (i = 0; i < right_nritems - 1; i++) { 1624 if (empty)
1625 nr = right_nritems;
1626 else
1627 nr = right_nritems - 1;
1628
1629 for (i = 0; i < nr; i++) {
1611 item = btrfs_item_nr(right, i); 1630 item = btrfs_item_nr(right, i);
1612 if (!right->map_token) { 1631 if (!right->map_token) {
1613 map_extent_buffer(right, (unsigned long)item, 1632 map_extent_buffer(right, (unsigned long)item,
@@ -1637,7 +1656,7 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
1637 free_extent_buffer(left); 1656 free_extent_buffer(left);
1638 return 1; 1657 return 1;
1639 } 1658 }
1640 if (push_items == btrfs_header_nritems(right)) 1659 if (!empty && push_items == btrfs_header_nritems(right))
1641 WARN_ON(1); 1660 WARN_ON(1);
1642 1661
1643 /* push data from right to left */ 1662 /* push data from right to left */
@@ -1681,20 +1700,26 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
1681 } 1700 }
1682 1701
1683 /* fixup right node */ 1702 /* fixup right node */
1684 push_space = btrfs_item_offset_nr(right, push_items - 1) - 1703 if (push_items > right_nritems) {
1685 leaf_data_end(root, right); 1704 printk("push items %d nr %u\n", push_items, right_nritems);
1686 memmove_extent_buffer(right, btrfs_leaf_data(right) + 1705 WARN_ON(1);
1687 BTRFS_LEAF_DATA_SIZE(root) - push_space, 1706 }
1688 btrfs_leaf_data(right) + 1707
1689 leaf_data_end(root, right), push_space); 1708 if (push_items < right_nritems) {
1690 1709 push_space = btrfs_item_offset_nr(right, push_items - 1) -
1691 memmove_extent_buffer(right, btrfs_item_nr_offset(0), 1710 leaf_data_end(root, right);
1711 memmove_extent_buffer(right, btrfs_leaf_data(right) +
1712 BTRFS_LEAF_DATA_SIZE(root) - push_space,
1713 btrfs_leaf_data(right) +
1714 leaf_data_end(root, right), push_space);
1715
1716 memmove_extent_buffer(right, btrfs_item_nr_offset(0),
1692 btrfs_item_nr_offset(push_items), 1717 btrfs_item_nr_offset(push_items),
1693 (btrfs_header_nritems(right) - push_items) * 1718 (btrfs_header_nritems(right) - push_items) *
1694 sizeof(struct btrfs_item)); 1719 sizeof(struct btrfs_item));
1695 1720
1696 right_nritems = btrfs_header_nritems(right) - push_items; 1721 }
1697 btrfs_set_header_nritems(right, right_nritems); 1722 btrfs_set_header_nritems(right, right_nritems - push_items);
1698 push_space = BTRFS_LEAF_DATA_SIZE(root); 1723 push_space = BTRFS_LEAF_DATA_SIZE(root);
1699 1724
1700 for (i = 0; i < right_nritems; i++) { 1725 for (i = 0; i < right_nritems; i++) {
@@ -1717,7 +1742,8 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
1717 } 1742 }
1718 1743
1719 btrfs_mark_buffer_dirty(left); 1744 btrfs_mark_buffer_dirty(left);
1720 btrfs_mark_buffer_dirty(right); 1745 if (right_nritems)
1746 btrfs_mark_buffer_dirty(right);
1721 1747
1722 btrfs_item_key(right, &disk_key, 0); 1748 btrfs_item_key(right, &disk_key, 0);
1723 wret = fixup_low_keys(trans, root, path, &disk_key, 1); 1749 wret = fixup_low_keys(trans, root, path, &disk_key, 1);
@@ -1768,12 +1794,12 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
1768 1794
1769 /* first try to make some room by pushing left and right */ 1795 /* first try to make some room by pushing left and right */
1770 if (ins_key->type != BTRFS_DIR_ITEM_KEY) { 1796 if (ins_key->type != BTRFS_DIR_ITEM_KEY) {
1771 wret = push_leaf_right(trans, root, path, data_size); 1797 wret = push_leaf_right(trans, root, path, data_size, 0);
1772 if (wret < 0) { 1798 if (wret < 0) {
1773 return wret; 1799 return wret;
1774 } 1800 }
1775 if (wret) { 1801 if (wret) {
1776 wret = push_leaf_left(trans, root, path, data_size); 1802 wret = push_leaf_left(trans, root, path, data_size, 0);
1777 if (wret < 0) 1803 if (wret < 0)
1778 return wret; 1804 return wret;
1779 } 1805 }
@@ -2403,13 +2429,13 @@ int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root,
2403 slot = path->slots[1]; 2429 slot = path->slots[1];
2404 extent_buffer_get(leaf); 2430 extent_buffer_get(leaf);
2405 2431
2406 wret = push_leaf_right(trans, root, path, 1); 2432 wret = push_leaf_right(trans, root, path, 1, 1);
2407 if (wret < 0 && wret != -ENOSPC) 2433 if (wret < 0 && wret != -ENOSPC)
2408 ret = wret; 2434 ret = wret;
2409 2435
2410 if (path->nodes[0] == leaf && 2436 if (path->nodes[0] == leaf &&
2411 btrfs_header_nritems(leaf)) { 2437 btrfs_header_nritems(leaf)) {
2412 wret = push_leaf_left(trans, root, path, 1); 2438 wret = push_leaf_left(trans, root, path, 1, 1);
2413 if (wret < 0 && wret != -ENOSPC) 2439 if (wret < 0 && wret != -ENOSPC)
2414 ret = wret; 2440 ret = wret;
2415 } 2441 }