Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

bcachefs: Fix interior update path btree_path uses

Since the btree_paths array is now about to become growable, we have to
be careful not to refer to paths by pointer across contexts where they
may be reallocated.

This fixes the remaining btree_interior_update() paths - split and
merge.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>

+51 -43
+5 -7
fs/bcachefs/btree_trans_commit.c
··· 823 823 824 824 if (!same_leaf_as_next(trans, i)) { 825 825 if (u64s_delta <= 0) { 826 - ret = bch2_foreground_maybe_merge(trans, trans->paths + i->path, 826 + ret = bch2_foreground_maybe_merge(trans, i->path, 827 827 i->level, flags); 828 828 if (unlikely(ret)) 829 829 return ret; ··· 877 877 struct bch_fs *c = trans->c; 878 878 879 879 switch (ret) { 880 - case -BCH_ERR_btree_insert_btree_node_full: { 881 - struct btree_path *path = trans->paths + i->path; 882 - 883 - ret = bch2_btree_split_leaf(trans, path, flags); 880 + case -BCH_ERR_btree_insert_btree_node_full: 881 + ret = bch2_btree_split_leaf(trans, i->path, flags); 884 882 if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) 885 - trace_and_count(c, trans_restart_btree_node_split, trans, trace_ip, path); 883 + trace_and_count(c, trans_restart_btree_node_split, trans, 884 + trace_ip, trans->paths + i->path); 886 885 break; 887 - } 888 886 case -BCH_ERR_btree_insert_need_mark_replicas: 889 887 ret = drop_locks_do(trans, 890 888 bch2_replicas_delta_list_mark(c, trans->fs_usage_deltas));
+40 -31
fs/bcachefs/btree_update_interior.c
··· 25 25 #include <linux/random.h> 26 26 27 27 static int bch2_btree_insert_node(struct btree_update *, struct btree_trans *, 28 - struct btree_path *, struct btree *, 28 + btree_path_idx_t, struct btree *, 29 29 struct keylist *, unsigned); 30 30 static void bch2_btree_update_add_new_node(struct btree_update *, struct btree *); 31 31 ··· 1454 1454 */ 1455 1455 static void btree_split_insert_keys(struct btree_update *as, 1456 1456 struct btree_trans *trans, 1457 - struct btree_path *path, 1457 + btree_path_idx_t path_idx, 1458 1458 struct btree *b, 1459 1459 struct keylist *keys) 1460 1460 { 1461 + struct btree_path *path = trans->paths + path_idx; 1462 + 1461 1463 if (!bch2_keylist_empty(keys) && 1462 1464 bpos_le(bch2_keylist_front(keys)->k.p, b->data->max_key)) { 1463 1465 struct btree_node_iter node_iter; ··· 1473 1471 } 1474 1472 1475 1473 static int btree_split(struct btree_update *as, struct btree_trans *trans, 1476 - struct btree_path *path, struct btree *b, 1474 + btree_path_idx_t path, struct btree *b, 1477 1475 struct keylist *keys, unsigned flags) 1478 1476 { 1479 1477 struct bch_fs *c = as->c; 1480 - struct btree *parent = btree_node_parent(path, b); 1478 + struct btree *parent = btree_node_parent(trans->paths + path, b); 1481 1479 struct btree *n1, *n2 = NULL, *n3 = NULL; 1482 1480 btree_path_idx_t path1 = 0, path2 = 0; 1483 1481 u64 start_time = local_clock(); 1484 1482 int ret = 0; 1485 1483 1486 1484 BUG_ON(!parent && (b != btree_node_root(c, b))); 1487 - BUG_ON(parent && !btree_node_intent_locked(path, b->c.level + 1)); 1485 + BUG_ON(parent && !btree_node_intent_locked(trans->paths + path, b->c.level + 1)); 1488 1486 1489 1487 bch2_btree_interior_update_will_free_node(as, b); 1490 1488 ··· 1512 1510 six_unlock_write(&n2->c.lock); 1513 1511 six_unlock_write(&n1->c.lock); 1514 1512 1515 - path1 = get_unlocked_mut_path(trans, path->btree_id, n1->c.level, n1->key.k.p); 1513 + path1 = get_unlocked_mut_path(trans, as->btree_id, n1->c.level, n1->key.k.p); 1516 1514 six_lock_increment(&n1->c.lock, SIX_LOCK_intent); 1517 1515 mark_btree_node_locked(trans, trans->paths + path1, n1->c.level, BTREE_NODE_INTENT_LOCKED); 1518 1516 bch2_btree_path_level_init(trans, trans->paths + path1, n1); 1519 1517 1520 - path2 = get_unlocked_mut_path(trans, path->btree_id, n2->c.level, n2->key.k.p); 1518 + path2 = get_unlocked_mut_path(trans, as->btree_id, n2->c.level, n2->key.k.p); 1521 1519 six_lock_increment(&n2->c.lock, SIX_LOCK_intent); 1522 1520 mark_btree_node_locked(trans, trans->paths + path2, n2->c.level, BTREE_NODE_INTENT_LOCKED); 1523 1521 bch2_btree_path_level_init(trans, trans->paths + path2, n2); ··· 1562 1560 bch2_btree_update_add_new_node(as, n1); 1563 1561 six_unlock_write(&n1->c.lock); 1564 1562 1565 - path1 = get_unlocked_mut_path(trans, path->btree_id, n1->c.level, n1->key.k.p); 1563 + path1 = get_unlocked_mut_path(trans, as->btree_id, n1->c.level, n1->key.k.p); 1566 1564 six_lock_increment(&n1->c.lock, SIX_LOCK_intent); 1567 1565 mark_btree_node_locked(trans, trans->paths + path1, n1->c.level, BTREE_NODE_INTENT_LOCKED); 1568 1566 bch2_btree_path_level_init(trans, trans->paths + path1, n1); ··· 1579 1577 if (ret) 1580 1578 goto err; 1581 1579 } else if (n3) { 1582 - bch2_btree_set_root(as, trans, path, n3); 1580 + bch2_btree_set_root(as, trans, trans->paths + path, n3); 1583 1581 } else { 1584 1582 /* Root filled up but didn't need to be split */ 1585 - bch2_btree_set_root(as, trans, path, n1); 1583 + bch2_btree_set_root(as, trans, trans->paths + path, n1); 1586 1584 } 1587 1585 1588 1586 if (n3) { ··· 1602 1600 * node after another thread has locked and updated the new node, thus 1603 1601 * seeing stale data: 1604 1602 */ 1605 - bch2_btree_node_free_inmem(trans, path, b); 1603 + bch2_btree_node_free_inmem(trans, trans->paths + path, b); 1606 1604 1607 1605 if (n3) 1608 - bch2_trans_node_add(trans, path, n3); 1606 + bch2_trans_node_add(trans, trans->paths + path, n3); 1609 1607 if (n2) 1610 1608 bch2_trans_node_add(trans, trans->paths + path2, n2); 1611 1609 bch2_trans_node_add(trans, trans->paths + path1, n1); ··· 1667 1665 * 1668 1666 * @as: btree_update object 1669 1667 * @trans: btree_trans object 1670 - * @path: path that points to current node 1668 + * @path_idx: path that points to current node 1671 1669 * @b: node to insert keys into 1672 1670 * @keys: list of keys to insert 1673 1671 * @flags: transaction commit flags ··· 1679 1677 * for leaf nodes -- inserts into interior nodes have to be atomic. 1680 1678 */ 1681 1679 static int bch2_btree_insert_node(struct btree_update *as, struct btree_trans *trans, 1682 - struct btree_path *path, struct btree *b, 1680 + btree_path_idx_t path_idx, struct btree *b, 1683 1681 struct keylist *keys, unsigned flags) 1684 1682 { 1685 1683 struct bch_fs *c = as->c; 1684 + struct btree_path *path = trans->paths + path_idx; 1686 1685 int old_u64s = le16_to_cpu(btree_bset_last(b)->u64s); 1687 1686 int old_live_u64s = b->nr.live_u64s; 1688 1687 int live_u64s_added, u64s_added; ··· 1736 1733 return btree_trans_restart(trans, BCH_ERR_transaction_restart_split_race); 1737 1734 } 1738 1735 1739 - return btree_split(as, trans, path, b, keys, flags); 1736 + return btree_split(as, trans, path_idx, b, keys, flags); 1740 1737 } 1741 1738 1742 1739 int bch2_btree_split_leaf(struct btree_trans *trans, 1743 - struct btree_path *path, 1740 + btree_path_idx_t path, 1744 1741 unsigned flags) 1745 1742 { 1746 - struct btree *b = path_l(path)->b; 1743 + /* btree_split & merge may both cause paths array to be reallocated */ 1744 + 1745 + struct btree *b = path_l(trans->paths + path)->b; 1747 1746 struct btree_update *as; 1748 1747 unsigned l; 1749 1748 int ret = 0; 1750 1749 1751 - as = bch2_btree_update_start(trans, path, path->level, 1750 + as = bch2_btree_update_start(trans, trans->paths + path, 1751 + trans->paths[path].level, 1752 1752 true, flags); 1753 1753 if (IS_ERR(as)) 1754 1754 return PTR_ERR(as); ··· 1764 1758 1765 1759 bch2_btree_update_done(as, trans); 1766 1760 1767 - for (l = path->level + 1; btree_node_intent_locked(path, l) && !ret; l++) 1761 + for (l = trans->paths[path].level + 1; 1762 + btree_node_intent_locked(&trans->paths[path], l) && !ret; 1763 + l++) 1768 1764 ret = bch2_foreground_maybe_merge(trans, path, l, flags); 1769 1765 1770 1766 return ret; 1771 1767 } 1772 1768 1773 1769 int __bch2_foreground_maybe_merge(struct btree_trans *trans, 1774 - struct btree_path *path, 1770 + btree_path_idx_t path, 1775 1771 unsigned level, 1776 1772 unsigned flags, 1777 1773 enum btree_node_sibling sib) ··· 1786 1778 struct btree *b, *m, *n, *prev, *next, *parent; 1787 1779 struct bpos sib_pos; 1788 1780 size_t sib_u64s; 1781 + enum btree_id btree = trans->paths[path].btree_id; 1789 1782 btree_path_idx_t sib_path = 0, new_path = 0; 1790 1783 u64 start_time = local_clock(); 1791 1784 int ret = 0; 1792 1785 1793 - BUG_ON(!path->should_be_locked); 1794 - BUG_ON(!btree_node_locked(path, level)); 1786 + BUG_ON(!trans->paths[path].should_be_locked); 1787 + BUG_ON(!btree_node_locked(&trans->paths[path], level)); 1795 1788 1796 - b = path->l[level].b; 1789 + b = trans->paths[path].l[level].b; 1797 1790 1798 1791 if ((sib == btree_prev_sib && bpos_eq(b->data->min_key, POS_MIN)) || 1799 1792 (sib == btree_next_sib && bpos_eq(b->data->max_key, SPOS_MAX))) { ··· 1806 1797 ? bpos_predecessor(b->data->min_key) 1807 1798 : bpos_successor(b->data->max_key); 1808 1799 1809 - sib_path = bch2_path_get(trans, path->btree_id, sib_pos, 1800 + sib_path = bch2_path_get(trans, btree, sib_pos, 1810 1801 U8_MAX, level, BTREE_ITER_INTENT, _THIS_IP_); 1811 1802 ret = bch2_btree_path_traverse(trans, sib_path, false); 1812 1803 if (ret) ··· 1816 1807 1817 1808 m = trans->paths[sib_path].l[level].b; 1818 1809 1819 - if (btree_node_parent(path, b) != 1810 + if (btree_node_parent(trans->paths + path, b) != 1820 1811 btree_node_parent(trans->paths + sib_path, m)) { 1821 1812 b->sib_u64s[sib] = U16_MAX; 1822 1813 goto out; ··· 1870 1861 if (b->sib_u64s[sib] > c->btree_foreground_merge_threshold) 1871 1862 goto out; 1872 1863 1873 - parent = btree_node_parent(path, b); 1874 - as = bch2_btree_update_start(trans, path, level, false, 1864 + parent = btree_node_parent(trans->paths + path, b); 1865 + as = bch2_btree_update_start(trans, trans->paths + path, level, false, 1875 1866 BCH_TRANS_COMMIT_no_enospc|flags); 1876 1867 ret = PTR_ERR_OR_ZERO(as); 1877 1868 if (ret) ··· 1901 1892 bch2_btree_update_add_new_node(as, n); 1902 1893 six_unlock_write(&n->c.lock); 1903 1894 1904 - new_path = get_unlocked_mut_path(trans, path->btree_id, n->c.level, n->key.k.p); 1895 + new_path = get_unlocked_mut_path(trans, btree, n->c.level, n->key.k.p); 1905 1896 six_lock_increment(&n->c.lock, SIX_LOCK_intent); 1906 1897 mark_btree_node_locked(trans, trans->paths + new_path, n->c.level, BTREE_NODE_INTENT_LOCKED); 1907 1898 bch2_btree_path_level_init(trans, trans->paths + new_path, n); ··· 1922 1913 bch2_btree_update_get_open_buckets(as, n); 1923 1914 bch2_btree_node_write(c, n, SIX_LOCK_intent, 0); 1924 1915 1925 - bch2_btree_node_free_inmem(trans, path, b); 1916 + bch2_btree_node_free_inmem(trans, trans->paths + path, b); 1926 1917 bch2_btree_node_free_inmem(trans, trans->paths + sib_path, m); 1927 1918 1928 - bch2_trans_node_add(trans, path, n); 1919 + bch2_trans_node_add(trans, trans->paths + path, n); 1929 1920 1930 1921 bch2_trans_verify_paths(trans); 1931 1922 ··· 1984 1975 1985 1976 if (parent) { 1986 1977 bch2_keylist_add(&as->parent_keys, &n->key); 1987 - ret = bch2_btree_insert_node(as, trans, btree_iter_path(trans, iter), 1978 + ret = bch2_btree_insert_node(as, trans, iter->path, 1988 1979 parent, &as->parent_keys, flags); 1989 1980 if (ret) 1990 1981 goto err;
+6 -5
fs/bcachefs/btree_update_interior.h
··· 117 117 struct btree *, 118 118 struct bkey_format); 119 119 120 - int bch2_btree_split_leaf(struct btree_trans *, struct btree_path *, unsigned); 120 + int bch2_btree_split_leaf(struct btree_trans *, btree_path_idx_t, unsigned); 121 121 122 - int __bch2_foreground_maybe_merge(struct btree_trans *, struct btree_path *, 122 + int __bch2_foreground_maybe_merge(struct btree_trans *, btree_path_idx_t, 123 123 unsigned, unsigned, enum btree_node_sibling); 124 124 125 125 static inline int bch2_foreground_maybe_merge_sibling(struct btree_trans *trans, 126 - struct btree_path *path, 126 + btree_path_idx_t path_idx, 127 127 unsigned level, unsigned flags, 128 128 enum btree_node_sibling sib) 129 129 { 130 + struct btree_path *path = trans->paths + path_idx; 130 131 struct btree *b; 131 132 132 133 EBUG_ON(!btree_node_locked(path, level)); ··· 136 135 if (b->sib_u64s[sib] > trans->c->btree_foreground_merge_threshold) 137 136 return 0; 138 137 139 - return __bch2_foreground_maybe_merge(trans, path, level, flags, sib); 138 + return __bch2_foreground_maybe_merge(trans, path_idx, level, flags, sib); 140 139 } 141 140 142 141 static inline int bch2_foreground_maybe_merge(struct btree_trans *trans, 143 - struct btree_path *path, 142 + btree_path_idx_t path, 144 143 unsigned level, 145 144 unsigned flags) 146 145 {