* [koverstreet-bcachefs:master 31/106] fs/bcachefs/btree/interior.c:2966:17: sparse: sparse: restricted __le16 degrades to integer
@ 2026-09-16 12:12 kernel test robot
0 siblings, 0 replies; 2+ messages in thread
From: kernel test robot @ 2026-09-16 12:12 UTC (permalink / raw)
To: Kent Overstreet; +Cc: oe-kbuild-all
tree: https://github.com/koverstreet/bcachefs master
head: ca944a61e079450f82be88c91e349638c75cf4b6
commit: 8fa192c9e9735f5801a191e8a37e5376fc279a57 [31/106] bcachefs: __bch2_foreground_maybe_merge: 3-way merge support
config: openrisc-randconfig-r112-20260915 (https://download.01.org/0day-ci/archive/20260916/202609162001.Z8972Qwj-lkp@intel.com/config)
compiler: or1k-linux-gcc (GCC) 15.2.0
sparse: v0.6.5-rc1
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260916/202609162001.Z8972Qwj-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202609162001.Z8972Qwj-lkp@intel.com/
sparse warnings: (new ones prefixed by >>)
fs/bcachefs/btree/interior.c:1270:33: sparse: sparse: mixing different enum types:
fs/bcachefs/btree/interior.c:1270:33: sparse: unsigned int enum bch_trans_commit_flags
fs/bcachefs/btree/interior.c:1270:33: sparse: unsigned int enum bch_watermark
>> fs/bcachefs/btree/interior.c:2966:17: sparse: sparse: restricted __le16 degrades to integer
vim +2966 fs/bcachefs/btree/interior.c
2723
2724 int __bch2_foreground_maybe_merge(struct btree_trans *trans,
2725 btree_path_idx_t path,
2726 unsigned level,
2727 enum bch_trans_commit_flags flags,
2728 u64 *merge_count)
2729 {
2730 struct bch_fs *c = trans->c;
2731 struct btree_update *as = NULL;
2732 enum btree_id btree = trans->paths[path].btree_id;
2733 u64 start_time = local_clock();
2734 int ret = 0;
2735
2736 CLASS(darray_merge_node, srcs)();
2737 CLASS(darray_merge_node, dsts)();
2738
2739 try(darray_make_room(&srcs, 3));
2740 try(darray_make_room(&dsts, 2));
2741
2742 bch2_trans_verify_not_unlocked_or_in_restart(trans);
2743 BUG_ON(!trans->paths[path].should_be_locked);
2744 BUG_ON(!btree_node_locked(&trans->paths[path], level));
2745
2746 /*
2747 * Work around a deadlock caused by the btree write buffer not doing
2748 * merges and leaving tons of merges for us to do - we really don't need
2749 * to be doing merges at all from the interior update path, and if the
2750 * interior update path is generating too many new interior updates we
2751 * deadlock:
2752 */
2753 if ((flags & BCH_WATERMARK_MASK) == BCH_WATERMARK_interior_updates)
2754 return 0;
2755
2756 if ((flags & BCH_WATERMARK_MASK) <= BCH_WATERMARK_reclaim) {
2757 flags &= ~BCH_WATERMARK_MASK;
2758 flags |= BCH_WATERMARK_btree;
2759 flags |= BCH_TRANS_COMMIT_journal_reclaim;
2760 }
2761
2762 struct btree *b = trans->paths[path].l[level].b;
2763
2764 if (bpos_eq(b->data->min_key, POS_MIN))
2765 b->sib_u64s[btree_prev_sib] = U16_MAX;
2766 if (bpos_eq(b->data->max_key, SPOS_MAX))
2767 b->sib_u64s[btree_next_sib] = U16_MAX;
2768
2769 /*
2770 * Push srcs in left-to-right order so srcs is naturally sorted: prev
2771 * sibling first (if merging left), then caller's node, then next
2772 * sibling (if merging right). The caller's path takes an extra ref so
2773 * the destructor can put it uniformly with helper-acquired paths.
2774 */
2775 try(btree_merge_push_pos(trans, &srcs, btree, level, path, btree_prev_sib));
2776
2777 __btree_path_get(trans, trans->paths + path, true);
2778 BUG_ON(darray_push(&srcs, ((struct btree_merge_node) {
2779 trans, b, path, b->nr.live_u64s,
2780 })));
2781
2782 try(btree_merge_push_pos(trans, &srcs, btree, level, path, btree_next_sib));
2783
2784 if (srcs.nr == 1)
2785 return 0;
2786
2787 event_inc_trace(c, btree_node_merge_attempt, buf, ({
2788 unsigned total_u64s = 0;
2789 darray_for_each(srcs, s) {
2790 if (s->b)
2791 bch2_btree_pos_to_text(&buf, c, s->b);
2792 else
2793 prt_str(&buf, "(evicted node)");
2794 prt_printf(&buf, "\nlive u64s %u (%zu%% full)\n",
2795 s->live_u64s,
2796 s->live_u64s * 100 / btree_max_u64s(c));
2797 total_u64s += s->live_u64s;
2798 }
2799
2800 prt_printf(&buf, "Pivot sib_u64s %u %u threshold %u\n",
2801 b->sib_u64s[btree_prev_sib],
2802 b->sib_u64s[btree_next_sib],
2803 c->btree.foreground_merge_threshold);
2804 bch2_btree_pos_to_text(&buf, c, b);
2805
2806 prt_printf(&buf, "\ntotal_u64s %u per-node max %zu nr_dsts %un",
2807 total_u64s, BTREE_FOREGROUND_MERGE_HIGHER_THRESHOLD(c),
2808 max_t(unsigned, 1,
2809 DIV_ROUND_UP(total_u64s, BTREE_FOREGROUND_MERGE_HIGHER_THRESHOLD(c))));
2810 }));
2811
2812 struct bkey_format new_f;
2813 unsigned nr_dsts = compute_merge(c, b, &srcs, NULL, &new_f);
2814 if (nr_dsts >= srcs.nr)
2815 goto out;
2816
2817 /*
2818 * Estimate-based gate said the merge will fit — fill (or re-traverse)
2819 * any srcs whose path isn't currently should_be_locked. Deferred srcs
2820 * pushed without a real read fall here; so do any srcs whose locks
2821 * may have been dropped since push (a !should_be_locked path won't
2822 * get relocked by unlock/relock cycles).
2823 *
2824 * On parent-identity mismatch, poison that side's cached estimate
2825 * and drop the src — saves us the bch2_btree_update_start cost that
2826 * the post-update_start recheck would otherwise discover.
2827 */
2828 for (unsigned i = 0; i < srcs.nr;) {
2829 struct btree_merge_node *s = &srcs.data[i];
2830
2831 if (trans->paths[s->path_idx].should_be_locked) {
2832 i++;
2833 continue;
2834 }
2835
2836 ret = bch2_btree_path_traverse(trans, s->path_idx, 0);
2837 if (ret)
2838 goto err;
2839
2840 s->b = trans->paths[s->path_idx].l[level].b;
2841 s->live_u64s = s->b->nr.live_u64s;
2842
2843 if (btree_node_parent(trans->paths + s->path_idx, s->b) !=
2844 trans->paths[path].l[level + 1].b) {
2845 enum btree_node_sibling bad =
2846 bpos_lt(s->b->data->max_key, b->data->min_key)
2847 ? btree_prev_sib
2848 : btree_next_sib;
2849 b->sib_u64s[bad] = U16_MAX;
2850 btree_merge_node_put(*s);
2851 darray_remove_item(&srcs, s);
2852 continue;
2853 }
2854
2855 btree_path_set_should_be_locked(trans, trans->paths + s->path_idx);
2856 i++;
2857 }
2858
2859 try(btree_merge_topology_check(c, &srcs));
2860
2861 if (srcs.nr == 1)
2862 goto out;
2863
2864 /*
2865 * Post deferred-fill, every surviving src must have ->b set so that
2866 * compute_merge() / merge_node_u64s_and_format() takes the precise
2867 * format-aware path. The estimate-only fallback (sum of live_u64s)
2868 * doesn't account for format growth on repack and would let an
2869 * infeasible merge through, blowing up later in btree_pack_into_dsts
2870 * or sort_into.
2871 */
2872 darray_for_each(srcs, s)
2873 BUG_ON(!s->b);
2874
2875 nr_dsts = compute_merge(c, b, &srcs, &dsts, &new_f);
2876 if (nr_dsts >= srcs.nr)
2877 goto out;
2878
2879 BUG_ON(nr_dsts > 2);
2880
2881 as = bch2_btree_update_start(trans, trans->paths + path, level, nr_dsts == 2,
2882 0, BCH_TRANS_COMMIT_no_enospc|flags, 0);
2883 ret = PTR_ERR_OR_ZERO(as);
2884 if (ret) {
2885 as = NULL;
2886 goto err;
2887 }
2888
2889 /*
2890 * update_start upgraded path's locks to cover parent nodes; re-read
2891 * parent and re-verify all srcs still share it. The earlier check in
2892 * btree_merge_push_pos() was racy because parents weren't locked.
2893 *
2894 * On mismatch, identify which side the bad sibling is on by bpos
2895 * comparison and poison just that side's cached estimate.
2896 */
2897 struct btree *parent = btree_node_parent(trans->paths + path, b);
2898 darray_for_each(srcs, s) {
2899 if (s->path_idx == path)
2900 continue;
2901 if (btree_node_parent(trans->paths + s->path_idx, s->b) != parent) {
2902 enum btree_node_sibling bad_sib =
2903 bpos_lt(s->b->data->max_key, b->data->min_key)
2904 ? btree_prev_sib
2905 : btree_next_sib;
2906 b->sib_u64s[bad_sib] = U16_MAX;
2907 bch2_btree_update_free(as, trans);
2908 as = NULL;
2909 ret = 0;
2910 goto out;
2911 }
2912 }
2913
2914 as->node_start = srcs.data[0].b->data->min_key;
2915 as->node_end = srcs.data[srcs.nr - 1].b->data->max_key;
2916
2917 darray_for_each(srcs, s) {
2918 ret = bch2_btree_node_lock_write(trans, trans->paths + s->path_idx, &s->b->c);
2919 if (ret)
2920 goto err_free_update;
2921 }
2922
2923 /*
2924 * Allocate destination nodes: 1 for plain N->1, 2 for the 3->2 case.
2925 * compute_merge() already populated dsts entries with their per-dst
2926 * format and max_key — here we just attach trans + a freshly allocated
2927 * btree node to each. path_idx is filled in after the pack since each
2928 * dst's key.k.p (== max_key) is set inside btree_set_max().
2929 */
2930 darray_for_each(dsts, d) {
2931 d->trans = trans;
2932 d->b = bch2_btree_node_alloc(as, trans, level);
2933 }
2934
2935 if (nr_dsts == 1) {
2936 struct btree *n = dsts.data[0].b;
2937 u64 max_seq = 0;
2938
2939 darray_for_each(srcs, s)
2940 max_seq = max(max_seq, BTREE_NODE_SEQ(s->b->data));
2941 SET_BTREE_NODE_SEQ(n->data, max_seq + 1);
2942
2943 btree_set_min(n, srcs.data[0].b->data->min_key);
2944 btree_set_max(n, dsts.data[0].max_key);
2945
2946 n->data->format = dsts.data[0].format;
2947 btree_node_set_format(n, n->data->format);
2948
2949 darray_for_each(srcs, s)
2950 bch2_btree_sort_into(c, n, s->b);
2951
2952 ret = bch2_btree_node_check_topology(trans, n);
2953 BUG_ON(ret);
2954
2955 btree_node_reset_sib_u64s(n);
2956 } else {
2957 btree_pack_into_dsts(as, trans, &srcs, &dsts);
2958 }
2959
2960 /*
2961 * Diagnostic: each dst's packed content must fit in btree_buf_bytes
2962 * with room for the +8 varint slop in btree_node_write. Mirrors
2963 * bch2_btree_node_format_fits()'s strict-less-than check.
2964 */
2965 darray_for_each(dsts, d)
> 2966 BUG_ON(__vstruct_bytes(struct btree_node, d->b->data->u64s) >=
2967 btree_buf_bytes(d->b));
2968
2969 darray_for_each(dsts, d) {
2970 bch2_btree_build_aux_trees(d->b);
2971 bch2_btree_update_add_new_node(as, d->b);
2972
2973 d->path_idx = bch2_path_get_unlocked_mut(trans, btree,
2974 d->b->c.level, d->b->key.k.p, false);
2975 six_lock_increment(&d->b->c.lock, SIX_LOCK_intent);
2976 mark_btree_node_locked(trans, trans->paths + d->path_idx,
2977 d->b->c.level, BTREE_NODE_WRITE_LOCKED);
2978 bch2_btree_path_level_init(trans, trans->paths + d->path_idx, d->b);
2979 }
2980
2981 /*
2982 * Conceptually: every src becomes a delete, every dst becomes a new
2983 * key, sorted and deduped (a new key at the same .p as a delete
2984 * subsumes the delete). For N -> 1 the last src's .p equals the dst's
2985 * .p (the dst's max_key was set to the last src's max_key), so the
2986 * last src's delete is the only one that gets dropped.
2987 *
2988 * Both parent_keys (the in-memory parent update) and new_nodes (the
2989 * journal record) need each surviving delete; emit them together.
2990 */
2991 struct btree_merge_node *src = srcs.data;
2992 struct btree_merge_node *dst = dsts.data;
2993 while (src || dst) {
2994 if (src && dst && bpos_eq(src->b->key.k.p, dst->b->key.k.p)) {
2995 bch2_btree_update_add_node(c, &as->new_nodes, dst->b);
2996 bch2_keylist_add(&as->parent_keys, &dst->b->key);
2997 src++;
2998 dst++;
2999 } else if (src && (dst ? bpos_lt(src->b->key.k.p, dst->b->key.k.p) : true)) {
3000 struct bkey_i delete;
3001 bkey_init(&delete.k);
3002 delete.k.p = src->b->key.k.p;
3003 bch2_keylist_add(&as->parent_keys, &delete);
3004 bch2_btree_update_add_key(&as->new_nodes, level, &delete);
3005 src++;
3006 } else {
3007 bch2_btree_update_add_node(c, &as->new_nodes, dst->b);
3008 bch2_keylist_add(&as->parent_keys, &dst->b->key);
3009 dst++;
3010 }
3011
3012 if (src == srcs.data + srcs.nr)
3013 src = NULL;
3014 if (dst == dsts.data + dsts.nr)
3015 dst = NULL;
3016 }
3017
3018 bch2_trans_verify_paths(trans);
3019
3020 ret = bch2_btree_insert_node(as, trans, path, parent, &as->parent_keys);
3021 if (ret)
3022 goto err_free_new_node;
3023
3024 event_inc_trace(c, btree_node_merge, buf, ({
3025 btree_node_op_log(&buf, c, b, &srcs, &dsts);
3026 }));
3027
3028 darray_for_each(srcs, s)
3029 bch2_btree_interior_update_will_free_node(as, s->b);
3030
3031 bch2_trans_verify_paths(trans);
3032
3033 darray_for_each(dsts, d) {
3034 bch2_btree_update_get_open_buckets(as, d->b);
3035 bch2_btree_node_write_trans(trans, d->b, SIX_LOCK_write, 0);
3036 }
3037
3038 darray_for_each(srcs, s)
3039 bch2_btree_node_free_inmem(trans, trans->paths + s->path_idx, s->b);
3040
3041 darray_for_each(dsts, d)
3042 bch2_trans_node_add(trans, trans->paths + d->path_idx, d->b);
3043
3044 bch2_trans_verify_paths(trans);
3045
3046 darray_for_each(dsts, d)
3047 six_unlock_intent(&d->b->c.lock);
3048
3049 bch2_btree_update_done(as, trans);
3050
3051 bch2_time_stats_update(&c->times[BCH_TIME_btree_node_merge], start_time);
3052
3053 if (merge_count)
3054 (*merge_count)++;
3055 out:
3056 err:
3057 bch2_trans_verify_locks(trans);
3058 if (ret == -BCH_ERR_journal_reclaim_would_deadlock)
3059 ret = 0;
3060 if (!ret)
3061 ret = bch2_trans_relock(trans);
3062 return ret;
3063 err_free_new_node:
3064 darray_for_each(dsts, d)
3065 bch2_btree_node_free_never_used(as, trans, d->b);
3066 err_free_update:
3067 darray_for_each_reverse(srcs, s)
3068 if (btree_node_write_locked(trans->paths + s->path_idx, s->b->c.level))
3069 bch2_btree_node_unlock_write(trans, trans->paths + s->path_idx, s->b);
3070 if (as)
3071 bch2_btree_update_free(as, trans);
3072 goto out;
3073 }
3074
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 2+ messages in thread* [koverstreet-bcachefs:master 31/106] fs/bcachefs/btree/interior.c:2966:17: sparse: sparse: restricted __le16 degrades to integer
@ 2026-05-16 4:15 kernel test robot
0 siblings, 0 replies; 2+ messages in thread
From: kernel test robot @ 2026-05-16 4:15 UTC (permalink / raw)
To: Kent Overstreet; +Cc: oe-kbuild-all
tree: https://github.com/koverstreet/bcachefs master
head: ca944a61e079450f82be88c91e349638c75cf4b6
commit: 8fa192c9e9735f5801a191e8a37e5376fc279a57 [31/106] bcachefs: __bch2_foreground_maybe_merge: 3-way merge support
config: sh-randconfig-r123-20260514 (https://download.01.org/0day-ci/archive/20260516/202605161217.8LGbaYru-lkp@intel.com/config)
compiler: sh4-linux-gcc (GCC) 11.5.0
sparse: v0.6.5-rc1
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260516/202605161217.8LGbaYru-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202605161217.8LGbaYru-lkp@intel.com/
sparse warnings: (new ones prefixed by >>)
fs/bcachefs/btree/interior.c:1270:33: sparse: sparse: mixing different enum types:
fs/bcachefs/btree/interior.c:1270:33: sparse: unsigned int enum bch_trans_commit_flags
fs/bcachefs/btree/interior.c:1270:33: sparse: unsigned int enum bch_watermark
>> fs/bcachefs/btree/interior.c:2966:17: sparse: sparse: restricted __le16 degrades to integer
vim +2966 fs/bcachefs/btree/interior.c
2723
2724 int __bch2_foreground_maybe_merge(struct btree_trans *trans,
2725 btree_path_idx_t path,
2726 unsigned level,
2727 enum bch_trans_commit_flags flags,
2728 u64 *merge_count)
2729 {
2730 struct bch_fs *c = trans->c;
2731 struct btree_update *as = NULL;
2732 enum btree_id btree = trans->paths[path].btree_id;
2733 u64 start_time = local_clock();
2734 int ret = 0;
2735
2736 CLASS(darray_merge_node, srcs)();
2737 CLASS(darray_merge_node, dsts)();
2738
2739 try(darray_make_room(&srcs, 3));
2740 try(darray_make_room(&dsts, 2));
2741
2742 bch2_trans_verify_not_unlocked_or_in_restart(trans);
2743 BUG_ON(!trans->paths[path].should_be_locked);
2744 BUG_ON(!btree_node_locked(&trans->paths[path], level));
2745
2746 /*
2747 * Work around a deadlock caused by the btree write buffer not doing
2748 * merges and leaving tons of merges for us to do - we really don't need
2749 * to be doing merges at all from the interior update path, and if the
2750 * interior update path is generating too many new interior updates we
2751 * deadlock:
2752 */
2753 if ((flags & BCH_WATERMARK_MASK) == BCH_WATERMARK_interior_updates)
2754 return 0;
2755
2756 if ((flags & BCH_WATERMARK_MASK) <= BCH_WATERMARK_reclaim) {
2757 flags &= ~BCH_WATERMARK_MASK;
2758 flags |= BCH_WATERMARK_btree;
2759 flags |= BCH_TRANS_COMMIT_journal_reclaim;
2760 }
2761
2762 struct btree *b = trans->paths[path].l[level].b;
2763
2764 if (bpos_eq(b->data->min_key, POS_MIN))
2765 b->sib_u64s[btree_prev_sib] = U16_MAX;
2766 if (bpos_eq(b->data->max_key, SPOS_MAX))
2767 b->sib_u64s[btree_next_sib] = U16_MAX;
2768
2769 /*
2770 * Push srcs in left-to-right order so srcs is naturally sorted: prev
2771 * sibling first (if merging left), then caller's node, then next
2772 * sibling (if merging right). The caller's path takes an extra ref so
2773 * the destructor can put it uniformly with helper-acquired paths.
2774 */
2775 try(btree_merge_push_pos(trans, &srcs, btree, level, path, btree_prev_sib));
2776
2777 __btree_path_get(trans, trans->paths + path, true);
2778 BUG_ON(darray_push(&srcs, ((struct btree_merge_node) {
2779 trans, b, path, b->nr.live_u64s,
2780 })));
2781
2782 try(btree_merge_push_pos(trans, &srcs, btree, level, path, btree_next_sib));
2783
2784 if (srcs.nr == 1)
2785 return 0;
2786
2787 event_inc_trace(c, btree_node_merge_attempt, buf, ({
2788 unsigned total_u64s = 0;
2789 darray_for_each(srcs, s) {
2790 if (s->b)
2791 bch2_btree_pos_to_text(&buf, c, s->b);
2792 else
2793 prt_str(&buf, "(evicted node)");
2794 prt_printf(&buf, "\nlive u64s %u (%zu%% full)\n",
2795 s->live_u64s,
2796 s->live_u64s * 100 / btree_max_u64s(c));
2797 total_u64s += s->live_u64s;
2798 }
2799
2800 prt_printf(&buf, "Pivot sib_u64s %u %u threshold %u\n",
2801 b->sib_u64s[btree_prev_sib],
2802 b->sib_u64s[btree_next_sib],
2803 c->btree.foreground_merge_threshold);
2804 bch2_btree_pos_to_text(&buf, c, b);
2805
2806 prt_printf(&buf, "\ntotal_u64s %u per-node max %zu nr_dsts %un",
2807 total_u64s, BTREE_FOREGROUND_MERGE_HIGHER_THRESHOLD(c),
2808 max_t(unsigned, 1,
2809 DIV_ROUND_UP(total_u64s, BTREE_FOREGROUND_MERGE_HIGHER_THRESHOLD(c))));
2810 }));
2811
2812 struct bkey_format new_f;
2813 unsigned nr_dsts = compute_merge(c, b, &srcs, NULL, &new_f);
2814 if (nr_dsts >= srcs.nr)
2815 goto out;
2816
2817 /*
2818 * Estimate-based gate said the merge will fit — fill (or re-traverse)
2819 * any srcs whose path isn't currently should_be_locked. Deferred srcs
2820 * pushed without a real read fall here; so do any srcs whose locks
2821 * may have been dropped since push (a !should_be_locked path won't
2822 * get relocked by unlock/relock cycles).
2823 *
2824 * On parent-identity mismatch, poison that side's cached estimate
2825 * and drop the src — saves us the bch2_btree_update_start cost that
2826 * the post-update_start recheck would otherwise discover.
2827 */
2828 for (unsigned i = 0; i < srcs.nr;) {
2829 struct btree_merge_node *s = &srcs.data[i];
2830
2831 if (trans->paths[s->path_idx].should_be_locked) {
2832 i++;
2833 continue;
2834 }
2835
2836 ret = bch2_btree_path_traverse(trans, s->path_idx, 0);
2837 if (ret)
2838 goto err;
2839
2840 s->b = trans->paths[s->path_idx].l[level].b;
2841 s->live_u64s = s->b->nr.live_u64s;
2842
2843 if (btree_node_parent(trans->paths + s->path_idx, s->b) !=
2844 trans->paths[path].l[level + 1].b) {
2845 enum btree_node_sibling bad =
2846 bpos_lt(s->b->data->max_key, b->data->min_key)
2847 ? btree_prev_sib
2848 : btree_next_sib;
2849 b->sib_u64s[bad] = U16_MAX;
2850 btree_merge_node_put(*s);
2851 darray_remove_item(&srcs, s);
2852 continue;
2853 }
2854
2855 btree_path_set_should_be_locked(trans, trans->paths + s->path_idx);
2856 i++;
2857 }
2858
2859 try(btree_merge_topology_check(c, &srcs));
2860
2861 if (srcs.nr == 1)
2862 goto out;
2863
2864 /*
2865 * Post deferred-fill, every surviving src must have ->b set so that
2866 * compute_merge() / merge_node_u64s_and_format() takes the precise
2867 * format-aware path. The estimate-only fallback (sum of live_u64s)
2868 * doesn't account for format growth on repack and would let an
2869 * infeasible merge through, blowing up later in btree_pack_into_dsts
2870 * or sort_into.
2871 */
2872 darray_for_each(srcs, s)
2873 BUG_ON(!s->b);
2874
2875 nr_dsts = compute_merge(c, b, &srcs, &dsts, &new_f);
2876 if (nr_dsts >= srcs.nr)
2877 goto out;
2878
2879 BUG_ON(nr_dsts > 2);
2880
2881 as = bch2_btree_update_start(trans, trans->paths + path, level, nr_dsts == 2,
2882 0, BCH_TRANS_COMMIT_no_enospc|flags, 0);
2883 ret = PTR_ERR_OR_ZERO(as);
2884 if (ret) {
2885 as = NULL;
2886 goto err;
2887 }
2888
2889 /*
2890 * update_start upgraded path's locks to cover parent nodes; re-read
2891 * parent and re-verify all srcs still share it. The earlier check in
2892 * btree_merge_push_pos() was racy because parents weren't locked.
2893 *
2894 * On mismatch, identify which side the bad sibling is on by bpos
2895 * comparison and poison just that side's cached estimate.
2896 */
2897 struct btree *parent = btree_node_parent(trans->paths + path, b);
2898 darray_for_each(srcs, s) {
2899 if (s->path_idx == path)
2900 continue;
2901 if (btree_node_parent(trans->paths + s->path_idx, s->b) != parent) {
2902 enum btree_node_sibling bad_sib =
2903 bpos_lt(s->b->data->max_key, b->data->min_key)
2904 ? btree_prev_sib
2905 : btree_next_sib;
2906 b->sib_u64s[bad_sib] = U16_MAX;
2907 bch2_btree_update_free(as, trans);
2908 as = NULL;
2909 ret = 0;
2910 goto out;
2911 }
2912 }
2913
2914 as->node_start = srcs.data[0].b->data->min_key;
2915 as->node_end = srcs.data[srcs.nr - 1].b->data->max_key;
2916
2917 darray_for_each(srcs, s) {
2918 ret = bch2_btree_node_lock_write(trans, trans->paths + s->path_idx, &s->b->c);
2919 if (ret)
2920 goto err_free_update;
2921 }
2922
2923 /*
2924 * Allocate destination nodes: 1 for plain N->1, 2 for the 3->2 case.
2925 * compute_merge() already populated dsts entries with their per-dst
2926 * format and max_key — here we just attach trans + a freshly allocated
2927 * btree node to each. path_idx is filled in after the pack since each
2928 * dst's key.k.p (== max_key) is set inside btree_set_max().
2929 */
2930 darray_for_each(dsts, d) {
2931 d->trans = trans;
2932 d->b = bch2_btree_node_alloc(as, trans, level);
2933 }
2934
2935 if (nr_dsts == 1) {
2936 struct btree *n = dsts.data[0].b;
2937 u64 max_seq = 0;
2938
2939 darray_for_each(srcs, s)
2940 max_seq = max(max_seq, BTREE_NODE_SEQ(s->b->data));
2941 SET_BTREE_NODE_SEQ(n->data, max_seq + 1);
2942
2943 btree_set_min(n, srcs.data[0].b->data->min_key);
2944 btree_set_max(n, dsts.data[0].max_key);
2945
2946 n->data->format = dsts.data[0].format;
2947 btree_node_set_format(n, n->data->format);
2948
2949 darray_for_each(srcs, s)
2950 bch2_btree_sort_into(c, n, s->b);
2951
2952 ret = bch2_btree_node_check_topology(trans, n);
2953 BUG_ON(ret);
2954
2955 btree_node_reset_sib_u64s(n);
2956 } else {
2957 btree_pack_into_dsts(as, trans, &srcs, &dsts);
2958 }
2959
2960 /*
2961 * Diagnostic: each dst's packed content must fit in btree_buf_bytes
2962 * with room for the +8 varint slop in btree_node_write. Mirrors
2963 * bch2_btree_node_format_fits()'s strict-less-than check.
2964 */
2965 darray_for_each(dsts, d)
> 2966 BUG_ON(__vstruct_bytes(struct btree_node, d->b->data->u64s) >=
2967 btree_buf_bytes(d->b));
2968
2969 darray_for_each(dsts, d) {
2970 bch2_btree_build_aux_trees(d->b);
2971 bch2_btree_update_add_new_node(as, d->b);
2972
2973 d->path_idx = bch2_path_get_unlocked_mut(trans, btree,
2974 d->b->c.level, d->b->key.k.p, false);
2975 six_lock_increment(&d->b->c.lock, SIX_LOCK_intent);
2976 mark_btree_node_locked(trans, trans->paths + d->path_idx,
2977 d->b->c.level, BTREE_NODE_WRITE_LOCKED);
2978 bch2_btree_path_level_init(trans, trans->paths + d->path_idx, d->b);
2979 }
2980
2981 /*
2982 * Conceptually: every src becomes a delete, every dst becomes a new
2983 * key, sorted and deduped (a new key at the same .p as a delete
2984 * subsumes the delete). For N -> 1 the last src's .p equals the dst's
2985 * .p (the dst's max_key was set to the last src's max_key), so the
2986 * last src's delete is the only one that gets dropped.
2987 *
2988 * Both parent_keys (the in-memory parent update) and new_nodes (the
2989 * journal record) need each surviving delete; emit them together.
2990 */
2991 struct btree_merge_node *src = srcs.data;
2992 struct btree_merge_node *dst = dsts.data;
2993 while (src || dst) {
2994 if (src && dst && bpos_eq(src->b->key.k.p, dst->b->key.k.p)) {
2995 bch2_btree_update_add_node(c, &as->new_nodes, dst->b);
2996 bch2_keylist_add(&as->parent_keys, &dst->b->key);
2997 src++;
2998 dst++;
2999 } else if (src && (dst ? bpos_lt(src->b->key.k.p, dst->b->key.k.p) : true)) {
3000 struct bkey_i delete;
3001 bkey_init(&delete.k);
3002 delete.k.p = src->b->key.k.p;
3003 bch2_keylist_add(&as->parent_keys, &delete);
3004 bch2_btree_update_add_key(&as->new_nodes, level, &delete);
3005 src++;
3006 } else {
3007 bch2_btree_update_add_node(c, &as->new_nodes, dst->b);
3008 bch2_keylist_add(&as->parent_keys, &dst->b->key);
3009 dst++;
3010 }
3011
3012 if (src == srcs.data + srcs.nr)
3013 src = NULL;
3014 if (dst == dsts.data + dsts.nr)
3015 dst = NULL;
3016 }
3017
3018 bch2_trans_verify_paths(trans);
3019
3020 ret = bch2_btree_insert_node(as, trans, path, parent, &as->parent_keys);
3021 if (ret)
3022 goto err_free_new_node;
3023
3024 event_inc_trace(c, btree_node_merge, buf, ({
3025 btree_node_op_log(&buf, c, b, &srcs, &dsts);
3026 }));
3027
3028 darray_for_each(srcs, s)
3029 bch2_btree_interior_update_will_free_node(as, s->b);
3030
3031 bch2_trans_verify_paths(trans);
3032
3033 darray_for_each(dsts, d) {
3034 bch2_btree_update_get_open_buckets(as, d->b);
3035 bch2_btree_node_write_trans(trans, d->b, SIX_LOCK_write, 0);
3036 }
3037
3038 darray_for_each(srcs, s)
3039 bch2_btree_node_free_inmem(trans, trans->paths + s->path_idx, s->b);
3040
3041 darray_for_each(dsts, d)
3042 bch2_trans_node_add(trans, trans->paths + d->path_idx, d->b);
3043
3044 bch2_trans_verify_paths(trans);
3045
3046 darray_for_each(dsts, d)
3047 six_unlock_intent(&d->b->c.lock);
3048
3049 bch2_btree_update_done(as, trans);
3050
3051 bch2_time_stats_update(&c->times[BCH_TIME_btree_node_merge], start_time);
3052
3053 if (merge_count)
3054 (*merge_count)++;
3055 out:
3056 err:
3057 bch2_trans_verify_locks(trans);
3058 if (ret == -BCH_ERR_journal_reclaim_would_deadlock)
3059 ret = 0;
3060 if (!ret)
3061 ret = bch2_trans_relock(trans);
3062 return ret;
3063 err_free_new_node:
3064 darray_for_each(dsts, d)
3065 bch2_btree_node_free_never_used(as, trans, d->b);
3066 err_free_update:
3067 darray_for_each_reverse(srcs, s)
3068 if (btree_node_write_locked(trans->paths + s->path_idx, s->b->c.level))
3069 bch2_btree_node_unlock_write(trans, trans->paths + s->path_idx, s->b);
3070 if (as)
3071 bch2_btree_update_free(as, trans);
3072 goto out;
3073 }
3074
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-09-16 12:12 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-16 12:12 [koverstreet-bcachefs:master 31/106] fs/bcachefs/btree/interior.c:2966:17: sparse: sparse: restricted __le16 degrades to integer kernel test robot
-- strict thread matches above, loose matches on Subject: below --
2026-05-16 4:15 kernel test robot
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.