// SPDX-License-Identifier: GPL-2.0
#include "bcachefs.h"
#include "alloc_foreground.h"
#include "btree_gc.h"
#include "btree_io.h"
#include "btree_iter.h"
#include "btree_journal_iter.h"
#include "btree_key_cache.h"
#include "btree_update_interior.h"
#include "btree_write_buffer.h"
#include "buckets.h"
#include "disk_accounting.h"
#include "errcode.h"
#include "error.h"
#include "journal.h"
#include "journal_io.h"
#include "journal_reclaim.h"
#include "replicas.h"
#include "snapshot.h"
#include <linux/prefetch.h>
static const char * const trans_commit_flags_strs[] = {
#define x(n, ...) #n,
BCH_TRANS_COMMIT_FLAGS()
#undef x
NULL
};
void bch2_trans_commit_flags_to_text(struct printbuf *out, enum bch_trans_commit_flags flags)
{
enum bch_watermark watermark = flags & BCH_WATERMARK_MASK;
prt_printf(out, "watermark=%s", bch2_watermarks[watermark]);
flags >>= BCH_WATERMARK_BITS;
if (flags) {
prt_char(out, ' ');
bch2_prt_bitflags(out, trans_commit_flags_strs, flags);
}
}
static void verify_update_old_key(struct btree_trans *trans, struct btree_insert_entry *i)
{
#ifdef CONFIG_BCACHEFS_DEBUG
struct bch_fs *c = trans->c;
struct bkey u;
struct bkey_s_c k = bch2_btree_path_peek_slot_exact(trans->paths + i->path, &u);
if (unlikely(trans->journal_replay_not_finished)) {
struct bkey_i *j_k =
bch2_journal_keys_peek_slot(c, i->btree_id, i->level, i->k->k.p);
if (j_k)
k = bkey_i_to_s_c(j_k);
}
u = *k.k;
u.needs_whiteout = i->old_k.needs_whiteout;
BUG_ON(memcmp(&i->old_k, &u, sizeof(struct bkey)));
BUG_ON(i->old_v != k.v);
#endif
}
static inline struct btree_path_level *insert_l(struct btree_trans *trans, struct btree_insert_entry *i)
{
return (trans->paths + i->path)->l + i->level;
}
static inline bool same_leaf_as_prev(struct btree_trans *trans,
struct btree_insert_entry *i)
{
return i != trans->updates &&
insert_l(trans, &i[0])->b == insert_l(trans, &i[-1])->b;
}
static inline bool same_leaf_as_next(struct btree_trans *trans,
struct btree_insert_entry *i)
{
return i + 1 < trans->updates + trans->nr_updates &&
insert_l(trans, &i[0])->b == insert_l(trans, &i[1])->b;
}
inline void bch2_btree_node_prep_for_write(struct btree_trans *trans,
struct btree_path *path,
struct btree *b)
{
struct bch_fs *c = trans->c;
if (<