]> git.sesse.net Git - bcachefs-tools-debian/blobdiff - libbcachefs/btree_io.h
Update bcachefs sources to 4837f82ee1 bcachefs: Use cached iterators for alloc btree
[bcachefs-tools-debian] / libbcachefs / btree_io.h
index f279071686290851e0e0ea1aeed77eb17d7a754b..f3d7ec749b61870511d2641df3ecd01f5ef6a540 100644 (file)
@@ -1,6 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 #ifndef _BCACHEFS_BTREE_IO_H
 #define _BCACHEFS_BTREE_IO_H
 
+#include "bkey_methods.h"
+#include "bset.h"
+#include "btree_locking.h"
 #include "extents.h"
 #include "io_types.h"
 
@@ -11,9 +15,9 @@ struct btree_iter;
 
 struct btree_read_bio {
        struct bch_fs           *c;
-       unsigned                submit_time_us;
        u64                     start_time;
-       struct extent_pick_ptr  pick;
+       unsigned                have_ioref:1;
+       struct extent_ptr_decoded       pick;
        struct work_struct      work;
        struct bio              bio;
 };
@@ -46,23 +50,24 @@ static inline void btree_node_wait_on_io(struct btree *b)
 static inline bool btree_node_may_write(struct btree *b)
 {
        return list_empty_careful(&b->write_blocked) &&
-               !b->will_make_reachable;
+               (!b->written || !b->will_make_reachable);
 }
 
 enum compact_mode {
        COMPACT_LAZY,
-       COMPACT_WRITTEN,
-       COMPACT_WRITTEN_NO_WRITE_LOCK,
+       COMPACT_ALL,
 };
 
-bool __bch2_compact_whiteouts(struct bch_fs *, struct btree *, enum compact_mode);
+bool bch2_compact_whiteouts(struct bch_fs *, struct btree *,
+                           enum compact_mode);
 
-static inline unsigned should_compact_bset_lazy(struct btree *b, struct bset_tree *t)
+static inline bool should_compact_bset_lazy(struct btree *b,
+                                           struct bset_tree *t)
 {
-       unsigned bset_u64s = le16_to_cpu(bset(b, t)->u64s);
-       unsigned dead_u64s = bset_u64s - b->nr.bset_u64s[t - b->set];
+       unsigned total_u64s = bset_u64s(t);
+       unsigned dead_u64s = bset_dead_u64s(b, t);
 
-       return dead_u64s > 128 && dead_u64s * 3 > bset_u64s;
+       return dead_u64s > 64 && dead_u64s * 3 > total_u64s;
 }
 
 static inline bool bch2_maybe_compact_whiteouts(struct bch_fs *c, struct btree *b)
@@ -71,7 +76,7 @@ static inline bool bch2_maybe_compact_whiteouts(struct bch_fs *c, struct btree *
 
        for_each_bset(b, t)
                if (should_compact_bset_lazy(b, t))
-                       return __bch2_compact_whiteouts(c, b, COMPACT_LAZY);
+                       return bch2_compact_whiteouts(c, b, COMPACT_LAZY);
 
        return false;
 }
@@ -98,42 +103,37 @@ bool bch2_btree_post_write_cleanup(struct bch_fs *, struct btree *);
 void bch2_btree_node_write(struct bch_fs *, struct btree *,
                          enum six_lock_type);
 
-/*
- * btree_node_dirty() can be cleared with only a read lock,
- * and for bch2_btree_node_write_cond() we want to set need_write iff it's
- * still dirty:
- */
-static inline void set_btree_node_need_write_if_dirty(struct btree *b)
+static inline void btree_node_write_if_need(struct bch_fs *c, struct btree *b,
+                                           enum six_lock_type lock_held)
 {
-       unsigned long old, new, v = READ_ONCE(b->flags);
-
-       do {
-               old = new = v;
-
-               if (!(old & (1 << BTREE_NODE_dirty)))
-                       return;
-
-               new |= (1 << BTREE_NODE_need_write);
-       } while ((v = cmpxchg(&b->flags, old, new)) != old);
+       while (b->written &&
+              btree_node_need_write(b) &&
+              btree_node_may_write(b)) {
+               if (!btree_node_write_in_flight(b)) {
+                       bch2_btree_node_write(c, b, lock_held);
+                       break;
+               }
+
+               six_unlock_type(&b->c.lock, lock_held);
+               btree_node_wait_on_io(b);
+               btree_node_lock_type(c, b, lock_held);
+       }
 }
 
 #define bch2_btree_node_write_cond(_c, _b, cond)                       \
 do {                                                                   \
-       while ((_b)->written && btree_node_dirty(_b) && (cond)) {       \
-               if (!btree_node_may_write(_b)) {                        \
-                       set_btree_node_need_write_if_dirty(_b);         \
-                       break;                                          \
-               }                                                       \
+       unsigned long old, new, v = READ_ONCE((_b)->flags);             \
                                                                        \
-               if (!btree_node_write_in_flight(_b)) {                  \
-                       bch2_btree_node_write(_c, _b, SIX_LOCK_read);   \
+       do {                                                            \
+               old = new = v;                                          \
+                                                                       \
+               if (!(old & (1 << BTREE_NODE_dirty)) || !(cond))        \
                        break;                                          \
-               }                                                       \
                                                                        \
-               six_unlock_read(&(_b)->lock);                           \
-               btree_node_wait_on_io(_b);                              \
-               six_lock_read(&(_b)->lock);                             \
-       }                                                               \
+               new |= (1 << BTREE_NODE_need_write);                    \
+       } while ((v = cmpxchg(&(_b)->flags, old, new)) != old);         \
+                                                                       \
+       btree_node_write_if_need(_c, _b, SIX_LOCK_read);                \
 } while (0)
 
 void bch2_btree_flush_all_reads(struct bch_fs *);
@@ -141,4 +141,50 @@ void bch2_btree_flush_all_writes(struct bch_fs *);
 void bch2_btree_verify_flushed(struct bch_fs *);
 ssize_t bch2_dirty_btree_nodes_print(struct bch_fs *, char *);
 
+static inline void compat_bformat(unsigned level, enum btree_id btree_id,
+                                unsigned version, unsigned big_endian,
+                                int write, struct bkey_format *f)
+{
+       if (version < bcachefs_metadata_version_inode_btree_change &&
+           btree_id == BTREE_ID_INODES) {
+               swap(f->bits_per_field[BKEY_FIELD_INODE],
+                    f->bits_per_field[BKEY_FIELD_OFFSET]);
+               swap(f->field_offset[BKEY_FIELD_INODE],
+                    f->field_offset[BKEY_FIELD_OFFSET]);
+       }
+}
+
+static inline void compat_bpos(unsigned level, enum btree_id btree_id,
+                              unsigned version, unsigned big_endian,
+                              int write, struct bpos *p)
+{
+       if (big_endian != CPU_BIG_ENDIAN)
+               bch2_bpos_swab(p);
+
+       if (version < bcachefs_metadata_version_inode_btree_change &&
+           btree_id == BTREE_ID_INODES)
+               swap(p->inode, p->offset);
+}
+
+static inline void compat_btree_node(unsigned level, enum btree_id btree_id,
+                                    unsigned version, unsigned big_endian,
+                                    int write,
+                                    struct btree_node *bn)
+{
+       if (version < bcachefs_metadata_version_inode_btree_change &&
+           btree_node_type_is_extents(btree_id) &&
+           bkey_cmp(bn->min_key, POS_MIN) &&
+           write)
+               bn->min_key = bkey_predecessor(bn->min_key);
+
+       compat_bpos(level, btree_id, version, big_endian, write, &bn->min_key);
+       compat_bpos(level, btree_id, version, big_endian, write, &bn->max_key);
+
+       if (version < bcachefs_metadata_version_inode_btree_change &&
+           btree_node_type_is_extents(btree_id) &&
+           bkey_cmp(bn->min_key, POS_MIN) &&
+           !write)
+               bn->min_key = bkey_successor(bn->min_key);
+}
+
 #endif /* _BCACHEFS_BTREE_IO_H */