X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libbcachefs%2Fbtree_update.h;h=e0b1bde37484d990528aa9f78237d5b76bf2d440;hb=8a440895bf31ad7c45f6ad7d5766c6b83e2a7f3d;hp=c7c2930650d3f91da560187f2cd8941a522f7670;hpb=1cf4d51dc4661f336f5318c176a3561ddf5bf04f;p=bcachefs-tools-debian diff --git a/libbcachefs/btree_update.h b/libbcachefs/btree_update.h index c7c2930..e0b1bde 100644 --- a/libbcachefs/btree_update.h +++ b/libbcachefs/btree_update.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _BCACHEFS_BTREE_UPDATE_H #define _BCACHEFS_BTREE_UPDATE_H @@ -6,131 +7,138 @@ struct bch_fs; struct btree; -struct btree_insert; void bch2_btree_node_lock_for_insert(struct bch_fs *, struct btree *, struct btree_iter *); bool bch2_btree_bset_insert_key(struct btree_iter *, struct btree *, struct btree_node_iter *, struct bkey_i *); -void bch2_btree_journal_key(struct btree_insert *trans, struct btree_iter *, - struct bkey_i *); - -/* Normal update interface: */ - -struct btree_insert { - struct bch_fs *c; - struct disk_reservation *disk_res; - struct journal_res journal_res; - u64 *journal_seq; - struct extent_insert_hook *hook; - unsigned flags; - bool did_work; - - unsigned short nr; - struct btree_insert_entry { - struct btree_iter *iter; - struct bkey_i *k; - unsigned extra_res; - /* - * true if entire key was inserted - can only be false for - * extents - */ - bool done; - } *entries; +void bch2_btree_add_journal_pin(struct bch_fs *, struct btree *, u64); + +enum btree_insert_flags { + __BTREE_INSERT_NOUNLOCK, + __BTREE_INSERT_NOFAIL, + __BTREE_INSERT_NOCHECK_RW, + __BTREE_INSERT_LAZY_RW, + __BTREE_INSERT_USE_RESERVE, + __BTREE_INSERT_USE_ALLOC_RESERVE, + __BTREE_INSERT_JOURNAL_REPLAY, + __BTREE_INSERT_JOURNAL_RESERVED, + __BTREE_INSERT_JOURNAL_RECLAIM, + __BTREE_INSERT_NOWAIT, + __BTREE_INSERT_GC_LOCK_HELD, + __BCH_HASH_SET_MUST_CREATE, + __BCH_HASH_SET_MUST_REPLACE, }; -int __bch2_btree_insert_at(struct btree_insert *); - -#define _TENTH_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9, N, ...) N -#define COUNT_ARGS(...) _TENTH_ARG(__VA_ARGS__, 9, 8, 7, 6, 5, 4, 3, 2, 1) - -#define BTREE_INSERT_ENTRY(_iter, _k) \ - ((struct btree_insert_entry) { \ - .iter = (_iter), \ - .k = (_k), \ - .done = false, \ - }) - -#define BTREE_INSERT_ENTRY_EXTRA_RES(_iter, _k, _extra) \ - ((struct btree_insert_entry) { \ - .iter = (_iter), \ - .k = (_k), \ - .extra_res = (_extra), \ - .done = false, \ - }) - -/** - * bch_btree_insert_at - insert one or more keys at iterator positions - * @iter: btree iterator - * @insert_key: key to insert - * @disk_res: disk reservation - * @hook: extent insert callback - * - * Return values: - * -EINTR: locking changed, this function should be called again. Only returned - * if passed BTREE_INSERT_ATOMIC. - * -EROFS: filesystem read only - * -EIO: journal or btree node IO error - */ -#define bch2_btree_insert_at(_c, _disk_res, _hook, \ - _journal_seq, _flags, ...) \ - __bch2_btree_insert_at(&(struct btree_insert) { \ - .c = (_c), \ - .disk_res = (_disk_res), \ - .journal_seq = (_journal_seq), \ - .hook = (_hook), \ - .flags = (_flags), \ - .nr = COUNT_ARGS(__VA_ARGS__), \ - .entries = (struct btree_insert_entry[]) { \ - __VA_ARGS__ \ - }}) - /* - * Don't drop/retake locks: instead return -EINTR if need to upgrade to intent - * locks, -EAGAIN if need to wait on btree reserve + * Don't drop locks _after_ successfully updating btree: */ -#define BTREE_INSERT_ATOMIC (1 << 0) +#define BTREE_INSERT_NOUNLOCK (1 << __BTREE_INSERT_NOUNLOCK) /* Don't check for -ENOSPC: */ -#define BTREE_INSERT_NOFAIL (1 << 1) +#define BTREE_INSERT_NOFAIL (1 << __BTREE_INSERT_NOFAIL) + +#define BTREE_INSERT_NOCHECK_RW (1 << __BTREE_INSERT_NOCHECK_RW) +#define BTREE_INSERT_LAZY_RW (1 << __BTREE_INSERT_LAZY_RW) /* for copygc, or when merging btree nodes */ -#define BTREE_INSERT_USE_RESERVE (1 << 2) -#define BTREE_INSERT_USE_ALLOC_RESERVE (1 << 3) +#define BTREE_INSERT_USE_RESERVE (1 << __BTREE_INSERT_USE_RESERVE) +#define BTREE_INSERT_USE_ALLOC_RESERVE (1 << __BTREE_INSERT_USE_ALLOC_RESERVE) -/* - * Insert is for journal replay: don't get journal reservations, or mark extents - * (bch_mark_key) - */ -#define BTREE_INSERT_JOURNAL_REPLAY (1 << 4) +/* Insert is for journal replay - don't get journal reservations: */ +#define BTREE_INSERT_JOURNAL_REPLAY (1 << __BTREE_INSERT_JOURNAL_REPLAY) -/* Don't block on allocation failure (for new btree nodes: */ -#define BTREE_INSERT_NOWAIT (1 << 5) -#define BTREE_INSERT_GC_LOCK_HELD (1 << 6) +/* Indicates that we have pre-reserved space in the journal: */ +#define BTREE_INSERT_JOURNAL_RESERVED (1 << __BTREE_INSERT_JOURNAL_RESERVED) -#define BCH_HASH_SET_MUST_CREATE (1 << 7) -#define BCH_HASH_SET_MUST_REPLACE (1 << 8) +/* Insert is being called from journal reclaim path: */ +#define BTREE_INSERT_JOURNAL_RECLAIM (1 << __BTREE_INSERT_JOURNAL_RECLAIM) + +/* Don't block on allocation failure (for new btree nodes: */ +#define BTREE_INSERT_NOWAIT (1 << __BTREE_INSERT_NOWAIT) +#define BTREE_INSERT_GC_LOCK_HELD (1 << __BTREE_INSERT_GC_LOCK_HELD) -int bch2_btree_delete_at(struct btree_iter *, unsigned); +#define BCH_HASH_SET_MUST_CREATE (1 << __BCH_HASH_SET_MUST_CREATE) +#define BCH_HASH_SET_MUST_REPLACE (1 << __BCH_HASH_SET_MUST_REPLACE) -int bch2_btree_insert_list_at(struct btree_iter *, struct keylist *, - struct disk_reservation *, - struct extent_insert_hook *, u64 *, unsigned); +int bch2_btree_delete_at(struct btree_trans *, struct btree_iter *, unsigned); +int __bch2_btree_insert(struct btree_trans *, enum btree_id, struct bkey_i *); int bch2_btree_insert(struct bch_fs *, enum btree_id, struct bkey_i *, - struct disk_reservation *, - struct extent_insert_hook *, u64 *, int flags); -int bch2_btree_update(struct bch_fs *, enum btree_id, - struct bkey_i *, u64 *); + struct disk_reservation *, u64 *, int flags); +int bch2_btree_delete_at_range(struct btree_trans *, struct btree_iter *, + struct bpos, u64 *); int bch2_btree_delete_range(struct bch_fs *, enum btree_id, - struct bpos, struct bpos, struct bversion, - struct disk_reservation *, - struct extent_insert_hook *, u64 *); + struct bpos, struct bpos, u64 *); int bch2_btree_node_rewrite(struct bch_fs *c, struct btree_iter *, __le64, unsigned); int bch2_btree_node_update_key(struct bch_fs *, struct btree_iter *, - struct btree *, struct bkey_i_extent *); + struct btree *, struct bkey_i *); + +int bch2_trans_update(struct btree_trans *, struct btree_iter *, + struct bkey_i *, enum btree_trigger_flags); +int __bch2_trans_commit(struct btree_trans *); + +/** + * bch2_trans_commit - insert keys at given iterator positions + * + * This is main entry point for btree updates. + * + * Return values: + * -EINTR: locking changed, this function should be called again. + * -EROFS: filesystem read only + * -EIO: journal or btree node IO error + */ +static inline int bch2_trans_commit(struct btree_trans *trans, + struct disk_reservation *disk_res, + u64 *journal_seq, + unsigned flags) +{ + trans->disk_res = disk_res; + trans->journal_seq = journal_seq; + trans->flags = flags; + + return __bch2_trans_commit(trans); +} + +#define __bch2_trans_do(_trans, _disk_res, _journal_seq, _flags, _do) \ +({ \ + int _ret; \ + \ + while (1) { \ + _ret = (_do) ?: bch2_trans_commit(_trans, (_disk_res), \ + (_journal_seq), (_flags)); \ + if (_ret != -EINTR) \ + break; \ + bch2_trans_reset(_trans, 0); \ + } \ + \ + _ret; \ +}) + +#define bch2_trans_do(_c, _disk_res, _journal_seq, _flags, _do) \ +({ \ + struct btree_trans trans; \ + int _ret, _ret2; \ + \ + bch2_trans_init(&trans, (_c), 0, 0); \ + _ret = __bch2_trans_do(&trans, _disk_res, _journal_seq, _flags, \ + _do); \ + _ret2 = bch2_trans_exit(&trans); \ + \ + _ret ?: _ret2; \ +}) + +#define trans_for_each_update(_trans, _i) \ + for ((_i) = (_trans)->updates; \ + (_i) < (_trans)->updates + (_trans)->nr_updates; \ + (_i)++) + +#define trans_for_each_update2(_trans, _i) \ + for ((_i) = (_trans)->updates2; \ + (_i) < (_trans)->updates2 + (_trans)->nr_updates2; \ + (_i)++) #endif /* _BCACHEFS_BTREE_UPDATE_H */