]> git.sesse.net Git - bcachefs-tools-debian/commitdiff
Update bcachefs sources to 25de2b00dc bcachefs: Change check for invalid key types
authorKent Overstreet <kent.overstreet@linux.dev>
Fri, 7 Jul 2023 08:24:54 +0000 (04:24 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Fri, 7 Jul 2023 08:25:07 +0000 (04:25 -0400)
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
78 files changed:
.bcachefs_revision
cmd_dump.c
include/linux/bio.h
include/linux/blkdev.h
libbcachefs/acl.c
libbcachefs/alloc_background.c
libbcachefs/alloc_background.h
libbcachefs/alloc_foreground.c
libbcachefs/alloc_types.h
libbcachefs/backpointers.c
libbcachefs/backpointers.h
libbcachefs/bcachefs.h
libbcachefs/bcachefs_format.h
libbcachefs/bkey_methods.c
libbcachefs/bkey_methods.h
libbcachefs/bset.c
libbcachefs/btree_cache.c
libbcachefs/btree_cache.h
libbcachefs/btree_gc.c
libbcachefs/btree_io.c
libbcachefs/btree_io.h
libbcachefs/btree_iter.c
libbcachefs/btree_iter.h
libbcachefs/btree_key_cache.c
libbcachefs/btree_locking.c
libbcachefs/btree_locking.h
libbcachefs/btree_types.h
libbcachefs/btree_update.h
libbcachefs/btree_update_interior.c
libbcachefs/btree_update_interior.h
libbcachefs/btree_update_leaf.c
libbcachefs/btree_write_buffer.c
libbcachefs/buckets.c
libbcachefs/buckets.h
libbcachefs/counters.c
libbcachefs/data_update.c
libbcachefs/dirent.c
libbcachefs/dirent.h
libbcachefs/ec.c
libbcachefs/ec.h
libbcachefs/extents.c
libbcachefs/extents.h
libbcachefs/fs-io.c
libbcachefs/fsck.c
libbcachefs/inode.c
libbcachefs/inode.h
libbcachefs/io.c
libbcachefs/io.h
libbcachefs/io_types.h
libbcachefs/journal.c
libbcachefs/journal.h
libbcachefs/journal_io.c
libbcachefs/journal_reclaim.c
libbcachefs/journal_sb.c
libbcachefs/journal_types.h
libbcachefs/lru.c
libbcachefs/lru.h
libbcachefs/migrate.c
libbcachefs/move.c
libbcachefs/movinggc.c
libbcachefs/opts.c
libbcachefs/opts.h
libbcachefs/quota.c
libbcachefs/quota.h
libbcachefs/recovery.c
libbcachefs/reflink.c
libbcachefs/reflink.h
libbcachefs/replicas.c
libbcachefs/subvolume.c
libbcachefs/subvolume.h
libbcachefs/super-io.c
libbcachefs/super-io.h
libbcachefs/super.c
libbcachefs/sysfs.c
libbcachefs/tests.c
libbcachefs/varint.c
libbcachefs/xattr.c
libbcachefs/xattr.h

index 08e43b298d061a378bef6c57c7d1a5c04b4c25d1..e6dc62bc895176a18cce247d7962a0ab53bb81b9 100644 (file)
@@ -1 +1 @@
-84f132d5696138bb038d2dc8f1162d2fab5ac832
+25de2b00dcca9bd801d37efd5e08c15dbf151825
index 76b44c58959684d8b8c6326f8cce42984e2be11d..59d73c3c30131f28dbce6b45271d8345c6bfd645 100644 (file)
@@ -84,7 +84,7 @@ static void dump_one_device(struct bch_fs *c, struct bch_dev *ca, int fd,
                if (ret)
                        die("error %s walking btree nodes", bch2_err_str(ret));
 
-               b = c->btree_roots[i].b;
+               b = bch2_btree_id_root(c, i)->b;
                if (!btree_node_fake(b)) {
                        ptrs = bch2_bkey_ptrs_c(bkey_i_to_s_c(&b->key));
 
index 0ad5a87dc8e893037fafd4b216cbc58518c2a390..1f8acca2c40503c970fe1e5c3c5f255225f52e6a 100644 (file)
@@ -234,7 +234,7 @@ enum {
 };
 
 struct bio *bio_alloc_bioset(struct block_device *, unsigned,
-                            unsigned, gfp_t, struct bio_set *);
+                            blk_opf_t, gfp_t, struct bio_set *);
 extern void bio_put(struct bio *);
 
 int bio_add_page(struct bio *, struct page *, unsigned, unsigned);
index f78621d8a3d8730ef560b458f635cc2ea460c0b7..9e0207758e161296251381303b88a49f954f10e5 100644 (file)
@@ -9,6 +9,7 @@
 #define BIO_MAX_VECS   256U
 
 typedef unsigned fmode_t;
+typedef __u32 __bitwise blk_opf_t;
 
 struct bio;
 struct user_namespace;
index ce7a460fb308b3463e921dfbfb10e9891469b5ed..b1a488860678cd9242f84e7ab5ddd2b1724cd26f 100644 (file)
@@ -225,6 +225,7 @@ struct posix_acl *bch2_get_acl(struct mnt_idmap *idmap,
        struct bch_inode_info *inode = to_bch_ei(dentry->d_inode);
        struct bch_fs *c = inode->v.i_sb->s_fs_info;
        struct bch_hash_info hash = bch2_hash_info_init(c, &inode->ei_inode);
+       struct xattr_search_key search = X_SEARCH(acl_to_xattr_type(type), "", 0);
        struct btree_trans trans;
        struct btree_iter iter = { NULL };
        struct bkey_s_c_xattr xattr;
@@ -237,9 +238,7 @@ retry:
        bch2_trans_begin(&trans);
 
        ret = bch2_hash_lookup(&trans, &iter, bch2_xattr_hash_desc,
-                       &hash, inode_inum(inode),
-                       &X_SEARCH(acl_to_xattr_type(type), "", 0),
-                       0);
+                       &hash, inode_inum(inode), &search, 0);
        if (ret) {
                if (!bch2_err_matches(ret, ENOENT))
                        acl = ERR_PTR(ret);
@@ -364,6 +363,7 @@ int bch2_acl_chmod(struct btree_trans *trans, subvol_inum inum,
                   struct posix_acl **new_acl)
 {
        struct bch_hash_info hash_info = bch2_hash_info_init(trans->c, inode);
+       struct xattr_search_key search = X_SEARCH(KEY_TYPE_XATTR_INDEX_POSIX_ACL_ACCESS, "", 0);
        struct btree_iter iter;
        struct bkey_s_c_xattr xattr;
        struct bkey_i_xattr *new;
@@ -372,9 +372,7 @@ int bch2_acl_chmod(struct btree_trans *trans, subvol_inum inum,
        int ret;
 
        ret = bch2_hash_lookup(trans, &iter, bch2_xattr_hash_desc,
-                              &hash_info, inum,
-                       &X_SEARCH(KEY_TYPE_XATTR_INDEX_POSIX_ACL_ACCESS, "", 0),
-                       BTREE_ITER_INTENT);
+                              &hash_info, inum, &search, BTREE_ITER_INTENT);
        if (ret)
                return bch2_err_matches(ret, ENOENT) ? 0 : ret;
 
index 9f831111143ec85dd23bcad163ff15d79a07587f..c59629bbbccec570cc6559825a4c29852d3bc81a 100644 (file)
@@ -223,7 +223,8 @@ static unsigned bch_alloc_v1_val_u64s(const struct bch_alloc *a)
 }
 
 int bch2_alloc_v1_invalid(const struct bch_fs *c, struct bkey_s_c k,
-                         unsigned flags, struct printbuf *err)
+                         enum bkey_invalid_flags flags,
+                         struct printbuf *err)
 {
        struct bkey_s_c_alloc a = bkey_s_c_to_alloc(k);
 
@@ -238,7 +239,8 @@ int bch2_alloc_v1_invalid(const struct bch_fs *c, struct bkey_s_c k,
 }
 
 int bch2_alloc_v2_invalid(const struct bch_fs *c, struct bkey_s_c k,
-                         unsigned flags, struct printbuf *err)
+                         enum bkey_invalid_flags flags,
+                         struct printbuf *err)
 {
        struct bkey_alloc_unpacked u;
 
@@ -251,7 +253,8 @@ int bch2_alloc_v2_invalid(const struct bch_fs *c, struct bkey_s_c k,
 }
 
 int bch2_alloc_v3_invalid(const struct bch_fs *c, struct bkey_s_c k,
-                         unsigned flags, struct printbuf *err)
+                         enum bkey_invalid_flags flags,
+                         struct printbuf *err)
 {
        struct bkey_alloc_unpacked u;
 
@@ -282,7 +285,7 @@ int bch2_alloc_v4_invalid(const struct bch_fs *c, struct bkey_s_c k,
        }
 
        if (rw == WRITE &&
-           !(flags & BKEY_INVALID_FROM_JOURNAL) &&
+           !(flags & BKEY_INVALID_JOURNAL) &&
            test_bit(BCH_FS_CHECK_BACKPOINTERS_DONE, &c->flags)) {
                unsigned i, bp_len = 0;
 
@@ -605,7 +608,8 @@ static unsigned alloc_gen(struct bkey_s_c k, unsigned offset)
 }
 
 int bch2_bucket_gens_invalid(const struct bch_fs *c, struct bkey_s_c k,
-                            unsigned flags, struct printbuf *err)
+                            enum bkey_invalid_flags flags,
+                            struct printbuf *err)
 {
        if (bkey_val_bytes(k.k) != sizeof(struct bch_bucket_gens)) {
                prt_printf(err, "bad val size (%lu != %zu)",
@@ -929,7 +933,7 @@ int bch2_trans_mark_alloc(struct btree_trans *trans,
  * This synthesizes deleted extents for holes, similar to BTREE_ITER_SLOTS for
  * extents style btrees, but works on non-extents btrees:
  */
-struct bkey_s_c bch2_get_key_or_hole(struct btree_iter *iter, struct bpos end, struct bkey *hole)
+static struct bkey_s_c bch2_get_key_or_hole(struct btree_iter *iter, struct bpos end, struct bkey *hole)
 {
        struct bkey_s_c k = bch2_btree_iter_peek_slot(iter);
 
@@ -1000,7 +1004,7 @@ static bool next_bucket(struct bch_fs *c, struct bpos *bucket)
        return ca != NULL;
 }
 
-struct bkey_s_c bch2_get_key_or_real_bucket_hole(struct btree_iter *iter, struct bkey *hole)
+static struct bkey_s_c bch2_get_key_or_real_bucket_hole(struct btree_iter *iter, struct bkey *hole)
 {
        struct bch_fs *c = iter->trans->c;
        struct bkey_s_c k;
@@ -1719,7 +1723,8 @@ static int bch2_discard_one_bucket(struct btree_trans *trans,
 write:
        ret =   bch2_trans_update(trans, &iter, &a->k_i, 0) ?:
                bch2_trans_commit(trans, NULL, NULL,
-                                 BTREE_INSERT_USE_RESERVE|BTREE_INSERT_NOFAIL);
+                                 BCH_WATERMARK_btree|
+                                 BTREE_INSERT_NOFAIL);
        if (ret)
                goto out;
 
@@ -1827,7 +1832,8 @@ static int invalidate_one_bucket(struct btree_trans *trans,
        ret =   bch2_trans_update(trans, &alloc_iter, &a->k_i,
                                BTREE_TRIGGER_BUCKET_INVALIDATE) ?:
                bch2_trans_commit(trans, NULL, NULL,
-                                 BTREE_INSERT_USE_RESERVE|BTREE_INSERT_NOFAIL);
+                                 BCH_WATERMARK_btree|
+                                 BTREE_INSERT_NOFAIL);
        if (ret)
                goto out;
 
index 3c4d6d40b1202683f1e6f3de02f42d17a13bf74a..d1bf45a4b404aaaeca4b11289bad4ba4b89f4b3d 100644 (file)
@@ -8,6 +8,8 @@
 #include "debug.h"
 #include "super.h"
 
+enum bkey_invalid_flags;
+
 /* How out of date a pointer gen is allowed to be: */
 #define BUCKET_GC_GEN_MAX      96U
 
@@ -147,10 +149,14 @@ struct bkey_i_alloc_v4 *bch2_alloc_to_v4_mut(struct btree_trans *, struct bkey_s
 
 int bch2_bucket_io_time_reset(struct btree_trans *, unsigned, size_t, int);
 
-int bch2_alloc_v1_invalid(const struct bch_fs *, struct bkey_s_c, unsigned, struct printbuf *);
-int bch2_alloc_v2_invalid(const struct bch_fs *, struct bkey_s_c, unsigned, struct printbuf *);
-int bch2_alloc_v3_invalid(const struct bch_fs *, struct bkey_s_c, unsigned, struct printbuf *);
-int bch2_alloc_v4_invalid(const struct bch_fs *, struct bkey_s_c, unsigned, struct printbuf *);
+int bch2_alloc_v1_invalid(const struct bch_fs *, struct bkey_s_c,
+                         enum bkey_invalid_flags, struct printbuf *);
+int bch2_alloc_v2_invalid(const struct bch_fs *, struct bkey_s_c,
+                         enum bkey_invalid_flags, struct printbuf *);
+int bch2_alloc_v3_invalid(const struct bch_fs *, struct bkey_s_c,
+                         enum bkey_invalid_flags, struct printbuf *);
+int bch2_alloc_v4_invalid(const struct bch_fs *, struct bkey_s_c,
+                         enum bkey_invalid_flags, struct printbuf *);
 void bch2_alloc_v4_swab(struct bkey_s);
 void bch2_alloc_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
 
@@ -187,7 +193,8 @@ void bch2_alloc_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
        .min_val_size   = 48,                           \
 })
 
-int bch2_bucket_gens_invalid(const struct bch_fs *, struct bkey_s_c, unsigned, struct printbuf *);
+int bch2_bucket_gens_invalid(const struct bch_fs *, struct bkey_s_c,
+                            enum bkey_invalid_flags, struct printbuf *);
 void bch2_bucket_gens_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
 
 #define bch2_bkey_ops_bucket_gens ((struct bkey_ops) { \
index c7db89b92dbffede6ccada0f07ecad57f9580576..6650c00017c2aace43d867255cf19b1f746eeb45 100644 (file)
@@ -191,11 +191,12 @@ long bch2_bucket_alloc_new_fs(struct bch_dev *ca)
 static inline unsigned open_buckets_reserved(enum bch_watermark watermark)
 {
        switch (watermark) {
+       case BCH_WATERMARK_reclaim:
        case BCH_WATERMARK_btree:
        case BCH_WATERMARK_btree_copygc:
-               return 0;
-       case BCH_WATERMARK_copygc:
                return OPEN_BUCKETS_COUNT / 4;
+       case BCH_WATERMARK_copygc:
+               return OPEN_BUCKETS_COUNT / 3;
        default:
                return OPEN_BUCKETS_COUNT / 2;
        }
index a01fddfba004127d40ec40c9cb811a33fcc5e0c5..c33a29954e59a4f25f374f11a1003bed9c7dacfb 100644 (file)
@@ -17,11 +17,12 @@ struct bucket_alloc_state {
 };
 
 #define BCH_WATERMARKS()               \
-       x(btree_copygc)                 \
-       x(btree)                        \
-       x(copygc)                       \
+       x(stripe)                       \
        x(normal)                       \
-       x(stripe)
+       x(copygc)                       \
+       x(btree)                        \
+       x(btree_copygc)                 \
+       x(reclaim)
 
 enum bch_watermark {
 #define x(name)        BCH_WATERMARK_##name,
@@ -30,6 +31,9 @@ enum bch_watermark {
        BCH_WATERMARK_NR,
 };
 
+#define BCH_WATERMARK_BITS     3
+#define BCH_WATERMARK_MASK     ~(~0 << BCH_WATERMARK_BITS)
+
 #define OPEN_BUCKETS_COUNT     1024
 
 #define WRITE_POINT_HASH_NR    32
index a270ff96e9b4bd7b5ec9171660a05d83d75d0252..f5ce9c922bcde0f80e9ca97601e7e14b59a7b5e1 100644 (file)
@@ -38,7 +38,8 @@ static bool extent_matches_bp(struct bch_fs *c,
 }
 
 int bch2_backpointer_invalid(const struct bch_fs *c, struct bkey_s_c k,
-                            unsigned flags, struct printbuf *err)
+                            enum bkey_invalid_flags flags,
+                            struct printbuf *err)
 {
        struct bkey_s_c_backpointer bp = bkey_s_c_to_backpointer(k);
        struct bpos bucket = bp_pos_to_bucket(c, bp.k->p);
@@ -272,6 +273,7 @@ struct bkey_s_c bch2_backpointer_get_key(struct btree_trans *trans,
                                         unsigned iter_flags)
 {
        struct bch_fs *c = trans->c;
+       struct btree_root *r = bch2_btree_id_root(c, bp.btree_id);
        struct bpos bucket = bp_pos_to_bucket(c, bp_pos);
        struct bkey_s_c k;
 
@@ -279,7 +281,7 @@ struct bkey_s_c bch2_backpointer_get_key(struct btree_trans *trans,
                                  bp.btree_id,
                                  bp.pos,
                                  0,
-                                 min(bp.level, c->btree_roots[bp.btree_id].level),
+                                 min(bp.level, r->level),
                                  iter_flags);
        k = bch2_btree_iter_peek_slot(iter);
        if (bkey_err(k)) {
@@ -287,8 +289,8 @@ struct bkey_s_c bch2_backpointer_get_key(struct btree_trans *trans,
                return k;
        }
 
-       if (bp.level == c->btree_roots[bp.btree_id].level + 1)
-               k = bkey_i_to_s_c(&c->btree_roots[bp.btree_id].key);
+       if (bp.level == r->level + 1)
+               k = bkey_i_to_s_c(&r->key);
 
        if (k.k && extent_matches_bp(c, bp.btree_id, bp.level, k, bucket, bp))
                return k;
@@ -531,6 +533,7 @@ static int check_btree_root_to_backpointers(struct btree_trans *trans,
                                            struct bpos_level *last_flushed)
 {
        struct bch_fs *c = trans->c;
+       struct btree_root *r = bch2_btree_id_root(c, btree_id);
        struct btree_iter iter;
        struct btree *b;
        struct bkey_s_c k;
@@ -539,8 +542,7 @@ static int check_btree_root_to_backpointers(struct btree_trans *trans,
        const union bch_extent_entry *entry;
        int ret;
 
-       bch2_trans_node_iter_init(trans, &iter, btree_id, POS_MIN, 0,
-                                 c->btree_roots[btree_id].level, 0);
+       bch2_trans_node_iter_init(trans, &iter, btree_id, POS_MIN, 0, r->level, 0);
        b = bch2_btree_iter_peek_node(&iter);
        ret = PTR_ERR_OR_ZERO(b);
        if (ret)
@@ -589,10 +591,10 @@ static size_t btree_nodes_fit_in_ram(struct bch_fs *c)
        return div_u64(mem_bytes >> 1, btree_bytes(c));
 }
 
-int bch2_get_btree_in_memory_pos(struct btree_trans *trans,
-                                unsigned btree_leaf_mask,
-                                unsigned btree_interior_mask,
-                                struct bbpos start, struct bbpos *end)
+static int bch2_get_btree_in_memory_pos(struct btree_trans *trans,
+                                       unsigned btree_leaf_mask,
+                                       unsigned btree_interior_mask,
+                                       struct bbpos start, struct bbpos *end)
 {
        struct btree_iter iter;
        struct bkey_s_c k;
@@ -640,14 +642,18 @@ static int bch2_check_extents_to_backpointers_pass(struct btree_trans *trans,
                                                   struct bpos bucket_start,
                                                   struct bpos bucket_end)
 {
+       struct bch_fs *c = trans->c;
        struct btree_iter iter;
        enum btree_id btree_id;
        struct bpos_level last_flushed = { UINT_MAX };
        int ret = 0;
 
-       for (btree_id = 0; btree_id < BTREE_ID_NR; btree_id++) {
+       for (btree_id = 0; btree_id < btree_id_nr_alive(c); btree_id++) {
                unsigned depth = btree_type_has_ptrs(btree_id) ? 0 : 1;
 
+               if (!bch2_btree_id_root(c, btree_id)->alive)
+                       continue;
+
                bch2_trans_node_iter_init(trans, &iter, btree_id, POS_MIN, 0,
                                          depth,
                                          BTREE_ITER_ALL_LEVELS|
@@ -689,8 +695,8 @@ static struct bpos bucket_pos_to_bp_safe(const struct bch_fs *c,
                : bucket;
 }
 
-int bch2_get_alloc_in_memory_pos(struct btree_trans *trans,
-                                struct bpos start, struct bpos *end)
+static int bch2_get_alloc_in_memory_pos(struct btree_trans *trans,
+                                       struct bpos start, struct bpos *end)
 {
        struct btree_iter alloc_iter;
        struct btree_iter bp_iter;
index c52954e2e875f57bbb9a8a3a6caed97464da4ec5..778b6778ae530d385744ae64886faf412ceed3f8 100644 (file)
@@ -8,7 +8,7 @@
 #include "super.h"
 
 int bch2_backpointer_invalid(const struct bch_fs *, struct bkey_s_c k,
-                            unsigned, struct printbuf *);
+                            enum bkey_invalid_flags, struct printbuf *);
 void bch2_backpointer_to_text(struct printbuf *, const struct bch_backpointer *);
 void bch2_backpointer_k_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
 void bch2_backpointer_swab(struct bkey_s);
index b8d50fe64b3c9c437083d85c7d814dd6ded24150..a8488d4e18e8af4e0d2308a9f4f47fae7d810b06 100644 (file)
@@ -749,7 +749,8 @@ struct bch_fs {
        struct bio_set          btree_bio;
        struct workqueue_struct *io_complete_wq;
 
-       struct btree_root       btree_roots[BTREE_ID_NR];
+       struct btree_root       btree_roots_known[BTREE_ID_NR];
+       DARRAY(struct btree_root) btree_roots_extra;
        struct mutex            btree_root_lock;
 
        struct btree_cache      btree_cache;
index ad87cdff854437fbb103158fce57b8fee1b34c1d..49b86bfda76bfebe2695ac4a6452aacb2b54dc72 100644 (file)
@@ -488,8 +488,9 @@ struct bch_csum {
        x(crc32,                1)              \
        x(crc64,                2)              \
        x(crc128,               3)              \
-       x(stripe_ptr,           4)
-#define BCH_EXTENT_ENTRY_MAX   5
+       x(stripe_ptr,           4)              \
+       x(rebalance,            5)
+#define BCH_EXTENT_ENTRY_MAX   6
 
 enum bch_extent_entry_type {
 #define x(f, n) BCH_EXTENT_ENTRY_##f = n,
@@ -624,6 +625,20 @@ struct bch_extent_reservation {
 #endif
 };
 
+struct bch_extent_rebalance {
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+       __u64                   type:7,
+                               unused:33,
+                               compression:8,
+                               target:16;
+#elif defined (__BIG_ENDIAN_BITFIELD)
+       __u64                   target:16,
+                               compression:8,
+                               unused:33,
+                               type:7;
+#endif
+};
+
 union bch_extent_entry {
 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ ||  __BITS_PER_LONG == 64
        unsigned long                   type;
@@ -1356,19 +1371,19 @@ static inline bool data_type_is_hidden(enum bch_data_type type)
 struct bch_replicas_entry_v0 {
        __u8                    data_type;
        __u8                    nr_devs;
-       __u8                    devs[];
+       __u8                    devs[0];
 } __packed;
 
 struct bch_sb_field_replicas_v0 {
        struct bch_sb_field     field;
-       struct bch_replicas_entry_v0 entries[];
+       struct bch_replicas_entry_v0 entries[0];
 } __packed __aligned(8);
 
 struct bch_replicas_entry {
        __u8                    data_type;
        __u8                    nr_devs;
        __u8                    nr_required;
-       __u8                    devs[];
+       __u8                    devs[0];
 } __packed;
 
 #define replicas_entry_bytes(_i)                                       \
@@ -1376,7 +1391,7 @@ struct bch_replicas_entry {
 
 struct bch_sb_field_replicas {
        struct bch_sb_field     field;
-       struct bch_replicas_entry entries[];
+       struct bch_replicas_entry entries[0];
 } __packed __aligned(8);
 
 /* BCH_SB_FIELD_quota: */
@@ -1559,8 +1574,6 @@ struct bch_sb_field_journal_seq_blacklist {
  * One common version number for all on disk data structures - superblock, btree
  * nodes, journal entries
  */
-#define BCH_JSET_VERSION_OLD                   2
-#define BCH_BSET_VERSION_OLD                   3
 
 #define BCH_METADATA_VERSIONS()                                \
        x(bkey_renumber,                10)             \
@@ -2195,13 +2208,25 @@ struct btree_node {
        };
 } __packed __aligned(8);
 
-LE64_BITMASK(BTREE_NODE_ID,    struct btree_node, flags,  0,  4);
+LE64_BITMASK(BTREE_NODE_ID_LO, struct btree_node, flags,  0,  4);
 LE64_BITMASK(BTREE_NODE_LEVEL, struct btree_node, flags,  4,  8);
 LE64_BITMASK(BTREE_NODE_NEW_EXTENT_OVERWRITE,
                                struct btree_node, flags,  8,  9);
-/* 9-32 unused */
+LE64_BITMASK(BTREE_NODE_ID_HI, struct btree_node, flags,  9, 25);
+/* 25-32 unused */
 LE64_BITMASK(BTREE_NODE_SEQ,   struct btree_node, flags, 32, 64);
 
+static inline __u64 BTREE_NODE_ID(struct btree_node *n)
+{
+       return BTREE_NODE_ID_LO(n) | (BTREE_NODE_ID_HI(n) << 4);
+}
+
+static inline void SET_BTREE_NODE_ID(struct btree_node *n, u64 v)
+{
+       SET_BTREE_NODE_ID_LO(n, v);
+       SET_BTREE_NODE_ID_HI(n, v >> 4);
+}
+
 struct btree_node_entry {
        struct bch_csum         csum;
 
@@ -2211,7 +2236,6 @@ struct btree_node_entry {
                __u8            pad[22];
                __le16          u64s;
                __u64           _data[0];
-
        };
        };
 } __packed __aligned(8);
index 79f3fbe925d5290235e15c6e4a44d270ba4c277b..1381166bfc55b7cad8600a1d313ed267f95dfa27 100644 (file)
@@ -118,17 +118,15 @@ const struct bkey_ops bch2_bkey_ops[] = {
 #undef x
 };
 
+const struct bkey_ops bch2_bkey_null_ops = {
+       .min_val_size = U8_MAX,
+};
+
 int bch2_bkey_val_invalid(struct bch_fs *c, struct bkey_s_c k,
-                         unsigned flags, struct printbuf *err)
+                         enum bkey_invalid_flags flags,
+                         struct printbuf *err)
 {
-       const struct bkey_ops *ops;
-
-       if (k.k->type >= KEY_TYPE_MAX) {
-               prt_printf(err, "invalid type (%u >= %u)", k.k->type, KEY_TYPE_MAX);
-               return -BCH_ERR_invalid_bkey;
-       }
-
-       ops = &bch2_bkey_ops[k.k->type];
+       const struct bkey_ops *ops = bch2_bkey_type_ops(k.k->type);
 
        if (bkey_val_bytes(k.k) < ops->min_val_size) {
                prt_printf(err, "bad val size (%zu < %u)",
@@ -136,6 +134,9 @@ int bch2_bkey_val_invalid(struct bch_fs *c, struct bkey_s_c k,
                return -BCH_ERR_invalid_bkey;
        }
 
+       if (!ops->key_invalid)
+               return 0;
+
        return ops->key_invalid(c, k, flags, err);
 }
 
@@ -215,14 +216,16 @@ static unsigned bch2_key_types_allowed[] = {
 
 int __bch2_bkey_invalid(struct bch_fs *c, struct bkey_s_c k,
                        enum btree_node_type type,
-                       unsigned flags, struct printbuf *err)
+                       enum bkey_invalid_flags flags,
+                       struct printbuf *err)
 {
        if (k.k->u64s < BKEY_U64s) {
                prt_printf(err, "u64s too small (%u < %zu)", k.k->u64s, BKEY_U64s);
                return -BCH_ERR_invalid_bkey;
        }
 
-       if (!(bch2_key_types_allowed[type] & (1U << k.k->type))) {
+       if (flags & BKEY_INVALID_COMMIT  &&
+           !(bch2_key_types_allowed[type] & (1U << k.k->type))) {
                prt_printf(err, "invalid key type for btree %s (%s)",
                           bch2_btree_ids[type], bch2_bkey_types[k.k->type]);
                return -BCH_ERR_invalid_bkey;
@@ -246,24 +249,23 @@ int __bch2_bkey_invalid(struct bch_fs *c, struct bkey_s_c k,
                }
        }
 
-       if (type != BKEY_TYPE_btree &&
-           !btree_type_has_snapshots(type) &&
-           k.k->p.snapshot) {
-               prt_printf(err, "nonzero snapshot");
-               return -BCH_ERR_invalid_bkey;
-       }
+       if (type != BKEY_TYPE_btree) {
+               if (!btree_type_has_snapshots((enum btree_id) type) &&
+                   k.k->p.snapshot) {
+                       prt_printf(err, "nonzero snapshot");
+                       return -BCH_ERR_invalid_bkey;
+               }
 
-       if (type != BKEY_TYPE_btree &&
-           btree_type_has_snapshots(type) &&
-           !k.k->p.snapshot) {
-               prt_printf(err, "snapshot == 0");
-               return -BCH_ERR_invalid_bkey;
-       }
+               if (btree_type_has_snapshots((enum btree_id) type) &&
+                   !k.k->p.snapshot) {
+                       prt_printf(err, "snapshot == 0");
+                       return -BCH_ERR_invalid_bkey;
+               }
 
-       if (type != BKEY_TYPE_btree &&
-           bkey_eq(k.k->p, POS_MAX)) {
-               prt_printf(err, "key at POS_MAX");
-               return -BCH_ERR_invalid_bkey;
+               if (bkey_eq(k.k->p, POS_MAX)) {
+                       prt_printf(err, "key at POS_MAX");
+                       return -BCH_ERR_invalid_bkey;
+               }
        }
 
        return 0;
@@ -271,7 +273,8 @@ int __bch2_bkey_invalid(struct bch_fs *c, struct bkey_s_c k,
 
 int bch2_bkey_invalid(struct bch_fs *c, struct bkey_s_c k,
                      enum btree_node_type type,
-                     unsigned flags, struct printbuf *err)
+                     enum bkey_invalid_flags flags,
+                     struct printbuf *err)
 {
        return __bch2_bkey_invalid(c, k, type, flags, err) ?:
                bch2_bkey_val_invalid(c, k, flags, err);
@@ -340,14 +343,10 @@ void bch2_bkey_to_text(struct printbuf *out, const struct bkey *k)
 void bch2_val_to_text(struct printbuf *out, struct bch_fs *c,
                      struct bkey_s_c k)
 {
-       if (k.k->type < KEY_TYPE_MAX) {
-               const struct bkey_ops *ops = &bch2_bkey_ops[k.k->type];
+       const struct bkey_ops *ops = bch2_bkey_type_ops(k.k->type);
 
-               if (likely(ops->val_to_text))
-                       ops->val_to_text(out, c, k);
-       } else {
-               prt_printf(out, "(invalid type %u)", k.k->type);
-       }
+       if (likely(ops->val_to_text))
+               ops->val_to_text(out, c, k);
 }
 
 void bch2_bkey_val_to_text(struct printbuf *out, struct bch_fs *c,
@@ -363,7 +362,7 @@ void bch2_bkey_val_to_text(struct printbuf *out, struct bch_fs *c,
 
 void bch2_bkey_swab_val(struct bkey_s k)
 {
-       const struct bkey_ops *ops = &bch2_bkey_ops[k.k->type];
+       const struct bkey_ops *ops = bch2_bkey_type_ops(k.k->type);
 
        if (ops->swab)
                ops->swab(k);
@@ -371,7 +370,7 @@ void bch2_bkey_swab_val(struct bkey_s k)
 
 bool bch2_bkey_normalize(struct bch_fs *c, struct bkey_s k)
 {
-       const struct bkey_ops *ops = &bch2_bkey_ops[k.k->type];
+       const struct bkey_ops *ops = bch2_bkey_type_ops(k.k->type);
 
        return ops->key_normalize
                ? ops->key_normalize(c, k)
@@ -380,11 +379,11 @@ bool bch2_bkey_normalize(struct bch_fs *c, struct bkey_s k)
 
 bool bch2_bkey_merge(struct bch_fs *c, struct bkey_s l, struct bkey_s_c r)
 {
-       const struct bkey_ops *ops = &bch2_bkey_ops[l.k->type];
+       const struct bkey_ops *ops = bch2_bkey_type_ops(l.k->type);
 
-       return bch2_bkey_maybe_mergable(l.k, r.k) &&
+       return ops->key_merge &&
+               bch2_bkey_maybe_mergable(l.k, r.k) &&
                (u64) l.k->size + r.k->size <= KEY_SIZE_MAX &&
-               bch2_bkey_ops[l.k->type].key_merge &&
                !bch2_key_merging_disabled &&
                ops->key_merge(c, l, r);
 }
@@ -484,7 +483,7 @@ void __bch2_bkey_compat(unsigned level, enum btree_id btree_id,
                                u->k.p.snapshot = write
                                        ? 0 : U32_MAX;
                        } else {
-                               u64 min_packed = f->field_offset[BKEY_FIELD_SNAPSHOT];
+                               u64 min_packed = le64_to_cpu(f->field_offset[BKEY_FIELD_SNAPSHOT]);
                                u64 max_packed = min_packed +
                                        ~(~0ULL << f->bits_per_field[BKEY_FIELD_SNAPSHOT]);
 
@@ -509,7 +508,7 @@ void __bch2_bkey_compat(unsigned level, enum btree_id btree_id,
                if (big_endian != CPU_BIG_ENDIAN)
                        bch2_bkey_swab_val(u);
 
-               ops = &bch2_bkey_ops[k->type];
+               ops = bch2_bkey_type_ops(k->type);
 
                if (ops->compat)
                        ops->compat(btree_id, version, big_endian, write, u);
index c2bd72f5d587241e7de3bc6b204a6829bb7fede8..36a08e3090db841b7574c0a7de2e550d5e79c299 100644 (file)
@@ -11,6 +11,13 @@ struct bkey;
 enum btree_node_type;
 
 extern const char * const bch2_bkey_types[];
+extern const struct bkey_ops bch2_bkey_null_ops;
+
+enum bkey_invalid_flags {
+       BKEY_INVALID_WRITE              = (1U << 0),
+       BKEY_INVALID_COMMIT             = (1U << 1),
+       BKEY_INVALID_JOURNAL            = (1U << 2),
+};
 
 /*
  * key_invalid: checks validity of @k, returns 0 if good or -EINVAL if bad. If
@@ -21,7 +28,7 @@ extern const char * const bch2_bkey_types[];
  */
 struct bkey_ops {
        int             (*key_invalid)(const struct bch_fs *c, struct bkey_s_c k,
-                                      unsigned flags, struct printbuf *err);
+                                      enum bkey_invalid_flags flags, struct printbuf *err);
        void            (*val_to_text)(struct printbuf *, struct bch_fs *,
                                       struct bkey_s_c);
        void            (*swab)(struct bkey_s);
@@ -41,7 +48,12 @@ struct bkey_ops {
 
 extern const struct bkey_ops bch2_bkey_ops[];
 
-#define BKEY_INVALID_FROM_JOURNAL              (1 << 1)
+static inline const struct bkey_ops *bch2_bkey_type_ops(enum bch_bkey_type type)
+{
+       return likely(type < KEY_TYPE_MAX)
+               ? &bch2_bkey_ops[type]
+               : &bch2_bkey_null_ops;
+}
 
 int bch2_bkey_val_invalid(struct bch_fs *, struct bkey_s_c, unsigned, struct printbuf *);
 int __bch2_bkey_invalid(struct bch_fs *, struct bkey_s_c,
@@ -75,7 +87,7 @@ static inline int bch2_mark_key(struct btree_trans *trans,
                struct bkey_s_c old, struct bkey_s_c new,
                unsigned flags)
 {
-       const struct bkey_ops *ops = &bch2_bkey_ops[old.k->type ?: new.k->type];
+       const struct bkey_ops *ops = bch2_bkey_type_ops(old.k->type ?: new.k->type);
 
        return ops->atomic_trigger
                ? ops->atomic_trigger(trans, btree, level, old, new, flags)
@@ -115,7 +127,7 @@ static inline int bch2_trans_mark_key(struct btree_trans *trans,
                                      struct bkey_s_c old, struct bkey_i *new,
                                      unsigned flags)
 {
-       const struct bkey_ops *ops = &bch2_bkey_ops[old.k->type ?: new->k.type];
+       const struct bkey_ops *ops = bch2_bkey_type_ops(old.k->type ?: new->k.type);
 
        return ops->trans_trigger
                ? ops->trans_trigger(trans, btree_id, level, old, new, flags)
index 4d55011551e0187e83ceaabb845b0f4855abf20f..bcdf28f39b9c3db2b1b3f14b093348f3a0412da6 100644 (file)
@@ -599,11 +599,10 @@ static inline unsigned bkey_mantissa(const struct bkey_packed *k,
        return (u16) v;
 }
 
-__always_inline
-static inline void make_bfloat(struct btree *b, struct bset_tree *t,
-                              unsigned j,
-                              struct bkey_packed *min_key,
-                              struct bkey_packed *max_key)
+static __always_inline void make_bfloat(struct btree *b, struct bset_tree *t,
+                                       unsigned j,
+                                       struct bkey_packed *min_key,
+                                       struct bkey_packed *max_key)
 {
        struct bkey_float *f = bkey_float(b, t, j);
        struct bkey_packed *m = tree_to_bkey(b, t, j);
index 5ffd8db7eda32c9c8912ecb770ef5383e6f7e198..191d6c1b1ba64801e7d660e3394c2fa5c0db7777 100644 (file)
@@ -32,13 +32,15 @@ void bch2_recalc_btree_reserve(struct bch_fs *c)
 {
        unsigned i, reserve = 16;
 
-       if (!c->btree_roots[0].b)
+       if (!c->btree_roots_known[0].b)
                reserve += 8;
 
-       for (i = 0; i < BTREE_ID_NR; i++)
-               if (c->btree_roots[i].b)
-                       reserve += min_t(unsigned, 1,
-                                        c->btree_roots[i].b->c.level) * 8;
+       for (i = 0; i < btree_id_nr_alive(c); i++) {
+               struct btree_root *r = bch2_btree_id_root(c, i);
+
+               if (r->b)
+                       reserve += min_t(unsigned, 1, r->b->c.level) * 8;
+       }
 
        c->btree_cache.reserve = reserve;
 }
@@ -457,9 +459,12 @@ void bch2_fs_btree_cache_exit(struct bch_fs *c)
 
        kvpfree(c->verify_ondisk, btree_bytes(c));
 
-       for (i = 0; i < BTREE_ID_NR; i++)
-               if (c->btree_roots[i].b)
-                       list_add(&c->btree_roots[i].b->list, &bc->live);
+       for (i = 0; i < btree_id_nr_alive(c); i++) {
+               struct btree_root *r = bch2_btree_id_root(c, i);
+
+               if (r->b)
+                       list_add(&r->b->list, &bc->live);
+       }
 
        list_splice(&bc->freeable, &bc->live);
 
index 4900ed45422eae2db978437fc8f1e32db7bd044e..00c9b92183e7969839d48240e3e4b05498a98ed7 100644 (file)
@@ -45,7 +45,11 @@ static inline u64 btree_ptr_hash_val(const struct bkey_i *k)
        case KEY_TYPE_btree_ptr:
                return *((u64 *) bkey_i_to_btree_ptr_c(k)->v.start);
        case KEY_TYPE_btree_ptr_v2:
-               return bkey_i_to_btree_ptr_v2_c(k)->v.seq;
+               /*
+                * The cast/deref is only necessary to avoid sparse endianness
+                * warnings:
+                */
+               return *((u64 *) &bkey_i_to_btree_ptr_v2_c(k)->v.seq);
        default:
                return 0;
        }
@@ -97,7 +101,27 @@ static inline unsigned btree_blocks(struct bch_fs *c)
        (BTREE_FOREGROUND_MERGE_THRESHOLD(c) +                  \
         (BTREE_FOREGROUND_MERGE_THRESHOLD(c) >> 2))
 
-#define btree_node_root(_c, _b)        ((_c)->btree_roots[(_b)->c.btree_id].b)
+static inline unsigned btree_id_nr_alive(struct bch_fs *c)
+{
+       return BTREE_ID_NR + c->btree_roots_extra.nr;
+}
+
+static inline struct btree_root *bch2_btree_id_root(struct bch_fs *c, unsigned id)
+{
+       if (likely(id < BTREE_ID_NR)) {
+               return &c->btree_roots_known[id];
+       } else {
+               unsigned idx = id - BTREE_ID_NR;
+
+               EBUG_ON(idx >= c->btree_roots_extra.nr);
+               return &c->btree_roots_extra.data[idx];
+       }
+}
+
+static inline struct btree *btree_node_root(struct bch_fs *c, struct btree *b)
+{
+       return bch2_btree_id_root(c, b->c.btree_id)->b;
+}
 
 void bch2_btree_node_to_text(struct printbuf *, struct bch_fs *,
                             const struct btree *);
index 529613f1d03ef1111884f449201aae12f5b3bc5d..1fc386761d9799763eb618ffef6b85742134699a 100644 (file)
@@ -529,8 +529,13 @@ static int bch2_repair_topology(struct bch_fs *c)
 
        bch2_trans_init(&trans, c, 0, 0);
 
-       for (i = 0; i < BTREE_ID_NR && !ret; i++) {
-               b = c->btree_roots[i].b;
+       for (i = 0; i < btree_id_nr_alive(c)&& !ret; i++) {
+               struct btree_root *r = bch2_btree_id_root(c, i);
+
+               if (!r->alive)
+                       continue;
+
+               b = r->b;
                if (btree_node_fake(b))
                        continue;
 
@@ -883,7 +888,7 @@ static int bch2_gc_btree(struct btree_trans *trans, enum btree_id btree_id,
                return ret;
 
        mutex_lock(&c->btree_root_lock);
-       b = c->btree_roots[btree_id].b;
+       b = bch2_btree_id_root(c, btree_id)->b;
        if (!btree_node_fake(b)) {
                struct bkey_s_c k = bkey_i_to_s_c(&b->key);
 
@@ -1006,7 +1011,7 @@ static int bch2_gc_btree_init(struct btree_trans *trans,
        struct printbuf buf = PRINTBUF;
        int ret = 0;
 
-       b = c->btree_roots[btree_id].b;
+       b = bch2_btree_id_root(c, btree_id)->b;
 
        if (btree_node_fake(b))
                return 0;
@@ -1075,6 +1080,15 @@ static int bch2_gc_btrees(struct bch_fs *c, bool initial, bool metadata_only)
                        ? bch2_gc_btree_init(&trans, ids[i], metadata_only)
                        : bch2_gc_btree(&trans, ids[i], initial, metadata_only);
 
+       for (i = BTREE_ID_NR; i < btree_id_nr_alive(c) && !ret; i++) {
+               if (!bch2_btree_id_root(c, i)->alive)
+                       continue;
+
+               ret = initial
+                       ? bch2_gc_btree_init(&trans, i, metadata_only)
+                       : bch2_gc_btree(&trans, i, initial, metadata_only);
+       }
+
        if (ret < 0)
                bch_err_fn(c, ret);
 
@@ -1218,7 +1232,7 @@ static int bch2_gc_done(struct bch_fs *c,
        for_each_member_device(ca, c, dev) {
                struct bch_dev_usage *dst = ca->usage_base;
                struct bch_dev_usage *src = (void *)
-                       bch2_acc_percpu_u64s((void *) ca->usage_gc,
+                       bch2_acc_percpu_u64s((u64 __percpu *) ca->usage_gc,
                                             dev_usage_u64s());
 
                copy_dev_field(buckets_ec,              "buckets_ec");
@@ -1234,7 +1248,7 @@ static int bch2_gc_done(struct bch_fs *c,
                unsigned nr = fs_usage_u64s(c);
                struct bch_fs_usage *dst = c->usage_base;
                struct bch_fs_usage *src = (void *)
-                       bch2_acc_percpu_u64s((void *) c->usage_gc, nr);
+                       bch2_acc_percpu_u64s((u64 __percpu *) c->usage_gc, nr);
 
                copy_fs_field(hidden,           "hidden");
                copy_fs_field(btree,            "btree");
index 27a2a7b31f379ed93f41380a67c38aee3907f349..a8197c500894fdeee7a00d80e6e4272706ab1608 100644 (file)
@@ -517,7 +517,7 @@ static void btree_pos_to_text(struct printbuf *out, struct bch_fs *c,
        prt_printf(out, "%s level %u/%u\n  ",
               bch2_btree_ids[b->c.btree_id],
               b->c.level,
-              c->btree_roots[b->c.btree_id].level);
+              bch2_btree_id_root(c, b->c.btree_id)->level);
        bch2_bkey_val_to_text(out, c, bkey_i_to_s_c(&b->key));
 }
 
@@ -699,11 +699,9 @@ static int validate_bset(struct bch_fs *c, struct bch_dev *ca,
        struct printbuf buf2 = PRINTBUF;
        int ret = 0;
 
-       btree_err_on((version != BCH_BSET_VERSION_OLD &&
-                     version < bcachefs_metadata_version_min) ||
-                    version >= bcachefs_metadata_version_max,
+       btree_err_on(!bch2_version_compatible(version),
                     BTREE_ERR_INCOMPATIBLE, c, ca, b, i,
-                    "unsupported bset version");
+                    "unsupported bset version %u", version);
 
        if (btree_err_on(version < c->sb.version_min,
                         BTREE_ERR_FIXABLE, c, NULL, b, i,
@@ -1283,7 +1281,7 @@ struct btree_node_read_all {
        unsigned                nr;
        void                    *buf[BCH_REPLICAS_MAX];
        struct bio              *bio[BCH_REPLICAS_MAX];
-       int                     err[BCH_REPLICAS_MAX];
+       blk_status_t            err[BCH_REPLICAS_MAX];
 };
 
 static unsigned btree_node_sectors_written(struct bch_fs *c, void *data)
@@ -1766,7 +1764,11 @@ static void btree_node_write_work(struct work_struct *work)
        } else {
                ret = bch2_trans_do(c, NULL, NULL, 0,
                        bch2_btree_node_update_key_get_iter(&trans, b, &wbio->key,
-                                                           !wbio->wbio.failed.nr));
+                                       BCH_WATERMARK_reclaim|
+                                       BTREE_INSERT_JOURNAL_RECLAIM|
+                                       BTREE_INSERT_NOFAIL|
+                                       BTREE_INSERT_NOCHECK_RW,
+                                       !wbio->wbio.failed.nr));
                if (ret)
                        goto err;
        }
@@ -1777,7 +1779,7 @@ out:
 err:
        set_btree_node_noevict(b);
        if (!bch2_err_matches(ret, EROFS))
-               bch2_fs_fatal_error(c, "fatal error writing btree node");
+               bch2_fs_fatal_error(c, "fatal error writing btree node: %s", bch2_err_str(ret));
        goto out;
 }
 
@@ -2015,9 +2017,7 @@ do_write:
        BUG_ON(BSET_BIG_ENDIAN(i) != CPU_BIG_ENDIAN);
        BUG_ON(i->seq != b->data->keys.seq);
 
-       i->version = c->sb.version < bcachefs_metadata_version_bkey_renumber
-               ? cpu_to_le16(BCH_BSET_VERSION_OLD)
-               : cpu_to_le16(c->sb.version);
+       i->version = cpu_to_le16(c->sb.version);
        SET_BSET_OFFSET(i, b->written);
        SET_BSET_CSUM_TYPE(i, bch2_meta_checksum_type(c));
 
@@ -2230,7 +2230,7 @@ bool bch2_btree_flush_all_writes(struct bch_fs *c)
        return __bch2_btree_flush_all(c, BTREE_NODE_write_in_flight);
 }
 
-const char * const bch2_btree_write_types[] = {
+static const char * const bch2_btree_write_types[] = {
 #define x(t, n) [n] = #t,
        BCH_BTREE_WRITE_TYPES()
        NULL
index c43fb60b8c82c2ec4f066ec0ff752e4a4baf7401..0cadf651e7cfde8122dc1632a47e80bd7140c427 100644 (file)
@@ -178,7 +178,7 @@ static inline void compat_bformat(unsigned level, enum btree_id btree_id,
 
                f->field_offset[BKEY_FIELD_SNAPSHOT] = write
                        ? 0
-                       : U32_MAX - max_packed;
+                       : cpu_to_le64(U32_MAX - max_packed);
        }
 }
 
@@ -200,7 +200,7 @@ static inline void compat_btree_node(unsigned level, enum btree_id btree_id,
                                     struct btree_node *bn)
 {
        if (version < bcachefs_metadata_version_inode_btree_change &&
-           btree_node_type_is_extents(btree_id) &&
+           btree_id_is_extents(btree_id) &&
            !bpos_eq(bn->min_key, POS_MIN) &&
            write)
                bn->min_key = bpos_nosnap_predecessor(bn->min_key);
@@ -217,7 +217,7 @@ static inline void compat_btree_node(unsigned level, enum btree_id btree_id,
                bn->max_key.snapshot = U32_MAX;
 
        if (version < bcachefs_metadata_version_inode_btree_change &&
-           btree_node_type_is_extents(btree_id) &&
+           btree_id_is_extents(btree_id) &&
            !bpos_eq(bn->min_key, POS_MIN) &&
            !write)
                bn->min_key = bpos_nosnap_successor(bn->min_key);
index 3c6ea6a235fc4941ecb46069aae0ced7ed5a0005..e292c5a2a895e5db8ce42af10813a95dc8710661 100644 (file)
@@ -238,7 +238,7 @@ static void bch2_btree_path_verify(struct btree_trans *trans,
        for (i = 0; i < (!path->cached ? BTREE_MAX_DEPTH : 1); i++) {
                if (!path->l[i].b) {
                        BUG_ON(!path->cached &&
-                              c->btree_roots[path->btree_id].b->c.level > i);
+                              bch2_btree_id_root(c, path->btree_id)->b->c.level > i);
                        break;
                }
 
@@ -700,8 +700,8 @@ void bch2_trans_node_add(struct btree_trans *trans, struct btree *b)
 
                        if (t != BTREE_NODE_UNLOCKED) {
                                btree_node_unlock(trans, path, b->c.level);
-                               six_lock_increment(&b->c.lock, t);
-                               mark_btree_node_locked(trans, path, b->c.level, t);
+                               six_lock_increment(&b->c.lock, (enum six_lock_type) t);
+                               mark_btree_node_locked(trans, path, b->c.level, (enum six_lock_type) t);
                        }
 
                        bch2_btree_path_level_init(trans, path, b);
@@ -732,7 +732,7 @@ static inline int btree_path_lock_root(struct btree_trans *trans,
                                       unsigned long trace_ip)
 {
        struct bch_fs *c = trans->c;
-       struct btree *b, **rootp = &c->btree_roots[path->btree_id].b;
+       struct btree *b, **rootp = &bch2_btree_id_root(c, path->btree_id)->b;
        enum six_lock_type lock_type;
        unsigned i;
        int ret;
@@ -1438,7 +1438,7 @@ void bch2_btree_path_to_text(struct printbuf *out, struct btree_path *path)
        prt_newline(out);
 }
 
-noinline __cold
+static noinline __cold
 void __bch2_trans_paths_to_text(struct printbuf *out, struct btree_trans *trans,
                                bool nosort)
 {
@@ -1458,7 +1458,7 @@ void bch2_trans_paths_to_text(struct printbuf *out, struct btree_trans *trans)
        __bch2_trans_paths_to_text(out, trans, false);
 }
 
-noinline __cold
+static noinline __cold
 void __bch2_dump_trans_paths_updates(struct btree_trans *trans, bool nosort)
 {
        struct printbuf buf = PRINTBUF;
@@ -1867,9 +1867,9 @@ static inline struct bkey_i *btree_trans_peek_updates(struct btree_iter *iter)
                : NULL;
 }
 
-struct bkey_i *bch2_btree_journal_peek(struct btree_trans *trans,
-                                      struct btree_iter *iter,
-                                      struct bpos end_pos)
+static struct bkey_i *bch2_btree_journal_peek(struct btree_trans *trans,
+                                             struct btree_iter *iter,
+                                             struct bpos end_pos)
 {
        struct bkey_i *k;
 
index 13d4e9aac493720e50707839257602e1e0e1e518..0e9c1cb98a130d0ceef875cfac1d65fa251b1433 100644 (file)
@@ -283,7 +283,7 @@ static inline void bch2_trans_verify_not_in_restart(struct btree_trans *trans)
 }
 
 __always_inline
-static inline int btree_trans_restart_nounlock(struct btree_trans *trans, int err)
+static int btree_trans_restart_nounlock(struct btree_trans *trans, int err)
 {
        BUG_ON(err <= 0);
        BUG_ON(!bch2_err_matches(-err, BCH_ERR_transaction_restart));
@@ -294,7 +294,7 @@ static inline int btree_trans_restart_nounlock(struct btree_trans *trans, int er
 }
 
 __always_inline
-static inline int btree_trans_restart(struct btree_trans *trans, int err)
+static int btree_trans_restart(struct btree_trans *trans, int err)
 {
        btree_trans_restart_nounlock(trans, err);
        return -err;
index 9627b945884df292db7b99d55d36fd3929ecfb5f..a71db7ab715ca18bea90adb2aacbbd642866e7d5 100644 (file)
@@ -651,9 +651,8 @@ static int btree_key_cache_flush_pos(struct btree_trans *trans,
                bch2_trans_commit(trans, NULL, NULL,
                                  BTREE_INSERT_NOCHECK_RW|
                                  BTREE_INSERT_NOFAIL|
-                                 BTREE_INSERT_USE_RESERVE|
                                  (ck->journal.seq == journal_last_seq(j)
-                                  ? JOURNAL_WATERMARK_reserved
+                                  ? BCH_WATERMARK_reclaim
                                   : 0)|
                                  commit_flags);
 
index 70d25ce35fcd429019b91aa4dae6007b5bc7405a..d7fd87149c6325fc36c53f1b2c137d5124a65799 100644 (file)
@@ -597,13 +597,6 @@ int __bch2_btree_path_relock(struct btree_trans *trans,
        return 0;
 }
 
-__flatten
-bool bch2_btree_path_upgrade_norestart(struct btree_trans *trans,
-                       struct btree_path *path, unsigned long trace_ip)
-{
-       return btree_path_get_locks(trans, path, true);
-}
-
 bool bch2_btree_path_upgrade_noupgrade_sibs(struct btree_trans *trans,
                               struct btree_path *path,
                               unsigned new_locks_want)
index 0ad8fd44aba7a79985f002b5bf6b3ca3c502cb52..f3e58aa2774d7d91c1537af99e3ffda83fb43c38 100644 (file)
@@ -94,7 +94,7 @@ static inline void mark_btree_node_locked(struct btree_trans *trans,
                                          unsigned level,
                                          enum six_lock_type type)
 {
-       mark_btree_node_locked_noreset(path, level, type);
+       mark_btree_node_locked_noreset(path, level, (enum btree_node_locked_type) type);
 #ifdef CONFIG_BCACHEFS_LOCK_TIME_STATS
        path->l[level].lock_taken_time = local_clock();
 #endif
@@ -247,7 +247,7 @@ static inline bool btree_node_lock_increment(struct btree_trans *trans,
        trans_for_each_path(trans, path)
                if (&path->l[level].b->c == b &&
                    btree_node_locked_type(path, level) >= want) {
-                       six_lock_increment(&b->lock, want);
+                       six_lock_increment(&b->lock, (enum six_lock_type) want);
                        return true;
                }
 
@@ -267,7 +267,7 @@ static inline int btree_node_lock(struct btree_trans *trans,
        EBUG_ON(!(trans->paths_allocated & (1ULL << path->idx)));
 
        if (likely(six_trylock_type(&b->lock, type)) ||
-           btree_node_lock_increment(trans, b, level, type) ||
+           btree_node_lock_increment(trans, b, level, (enum btree_node_locked_type) type) ||
            !(ret = btree_node_lock_nopath(trans, b, type, btree_path_ip_allocated(path)))) {
 #ifdef CONFIG_BCACHEFS_LOCK_TIME_STATS
                path->l[b->level].lock_taken_time = local_clock();
index d4ff72128ad3d2a3e06a8a2e3daf2868c8836943..4efc69492612edac9e82d867fdc2900ba0bc6e68 100644 (file)
@@ -688,6 +688,11 @@ static inline bool btree_node_type_is_extents(enum btree_node_type type)
        return (1U << type) & BTREE_ID_IS_EXTENTS;
 }
 
+static inline bool btree_id_is_extents(enum btree_id btree)
+{
+       return btree_node_type_is_extents((enum btree_node_type) btree);
+}
+
 #define BTREE_ID_HAS_SNAPSHOTS                         \
        ((1U << BTREE_ID_extents)|                      \
         (1U << BTREE_ID_inodes)|                       \
index dbb0ae13ca70007c20dfad4cfd720ab125a97b14..93d2e54aab40e61a345bd821417ef49a26db095a 100644 (file)
@@ -23,11 +23,10 @@ void bch2_btree_insert_key_leaf(struct btree_trans *, struct btree_path *,
                                struct bkey_i *, u64);
 
 enum btree_insert_flags {
-       /* First two bits for journal watermark: */
-       __BTREE_INSERT_NOFAIL = 2,
+       /* First bits for bch_watermark: */
+       __BTREE_INSERT_NOFAIL = BCH_WATERMARK_BITS,
        __BTREE_INSERT_NOCHECK_RW,
        __BTREE_INSERT_LAZY_RW,
-       __BTREE_INSERT_USE_RESERVE,
        __BTREE_INSERT_JOURNAL_REPLAY,
        __BTREE_INSERT_JOURNAL_RECLAIM,
        __BTREE_INSERT_NOWAIT,
@@ -37,26 +36,23 @@ enum btree_insert_flags {
 };
 
 /* Don't check for -ENOSPC: */
-#define BTREE_INSERT_NOFAIL            (1 << __BTREE_INSERT_NOFAIL)
+#define BTREE_INSERT_NOFAIL            BIT(__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 << __BTREE_INSERT_USE_RESERVE)
+#define BTREE_INSERT_NOCHECK_RW                BIT(__BTREE_INSERT_NOCHECK_RW)
+#define BTREE_INSERT_LAZY_RW           BIT(__BTREE_INSERT_LAZY_RW)
 
 /* Insert is for journal replay - don't get journal reservations: */
-#define BTREE_INSERT_JOURNAL_REPLAY    (1 << __BTREE_INSERT_JOURNAL_REPLAY)
+#define BTREE_INSERT_JOURNAL_REPLAY    BIT(__BTREE_INSERT_JOURNAL_REPLAY)
 
 /* Insert is being called from journal reclaim path: */
-#define BTREE_INSERT_JOURNAL_RECLAIM (1 << __BTREE_INSERT_JOURNAL_RECLAIM)
+#define BTREE_INSERT_JOURNAL_RECLAIM   BIT(__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)
+#define BTREE_INSERT_NOWAIT            BIT(__BTREE_INSERT_NOWAIT)
+#define BTREE_INSERT_GC_LOCK_HELD      BIT(__BTREE_INSERT_GC_LOCK_HELD)
 
-#define BCH_HASH_SET_MUST_CREATE       (1 << __BCH_HASH_SET_MUST_CREATE)
-#define BCH_HASH_SET_MUST_REPLACE      (1 << __BCH_HASH_SET_MUST_REPLACE)
+#define BCH_HASH_SET_MUST_CREATE       BIT(__BCH_HASH_SET_MUST_CREATE)
+#define BCH_HASH_SET_MUST_REPLACE      BIT(__BCH_HASH_SET_MUST_REPLACE)
 
 int bch2_btree_delete_extent_at(struct btree_trans *, struct btree_iter *,
                                unsigned, unsigned);
@@ -80,9 +76,10 @@ int bch2_btree_node_rewrite(struct btree_trans *, struct btree_iter *,
                            struct btree *, unsigned);
 void bch2_btree_node_rewrite_async(struct bch_fs *, struct btree *);
 int bch2_btree_node_update_key(struct btree_trans *, struct btree_iter *,
-                              struct btree *, struct bkey_i *, bool);
-int bch2_btree_node_update_key_get_iter(struct btree_trans *,
-                               struct btree *, struct bkey_i *, bool);
+                              struct btree *, struct bkey_i *,
+                              unsigned, bool);
+int bch2_btree_node_update_key_get_iter(struct btree_trans *, struct btree *,
+                                       struct bkey_i *, unsigned, bool);
 
 int __bch2_insert_snapshot_whiteouts(struct btree_trans *, enum btree_id,
                                     struct bpos, struct bpos);
index eb3319f97296aa4bc28e4c0285671a2f28e5fc26..5592feff79d17760dc504155b7ca39c111c5fd39 100644 (file)
@@ -246,18 +246,12 @@ static struct btree *__bch2_btree_node_alloc(struct btree_trans *trans,
        BKEY_PADDED_ONSTACK(k, BKEY_BTREE_PTR_VAL_U64s_MAX) tmp;
        struct open_buckets ob = { .nr = 0 };
        struct bch_devs_list devs_have = (struct bch_devs_list) { 0 };
-       unsigned nr_reserve;
-       enum bch_watermark alloc_reserve;
+       enum bch_watermark watermark = flags & BCH_WATERMARK_MASK;
+       unsigned nr_reserve = watermark > BCH_WATERMARK_reclaim
+               ? BTREE_NODE_RESERVE
+               : 0;
        int ret;
 
-       if (flags & BTREE_INSERT_USE_RESERVE) {
-               nr_reserve      = 0;
-               alloc_reserve   = BCH_WATERMARK_btree_copygc;
-       } else {
-               nr_reserve      = BTREE_NODE_RESERVE;
-               alloc_reserve   = BCH_WATERMARK_btree;
-       }
-
        mutex_lock(&c->btree_reserve_cache_lock);
        if (c->btree_reserve_cache_nr > nr_reserve) {
                struct btree_alloc *a =
@@ -279,7 +273,7 @@ retry:
                                      &devs_have,
                                      res->nr_replicas,
                                      c->opts.metadata_replicas_required,
-                                     alloc_reserve, 0, cl, &wp);
+                                     watermark, 0, cl, &wp);
        if (unlikely(ret))
                return ERR_PTR(ret);
 
@@ -647,11 +641,10 @@ static void btree_update_nodes_written(struct btree_update *as)
         * which may require allocations as well.
         */
        ret = commit_do(&trans, &as->disk_res, &journal_seq,
+                       BCH_WATERMARK_reclaim|
                        BTREE_INSERT_NOFAIL|
                        BTREE_INSERT_NOCHECK_RW|
-                       BTREE_INSERT_USE_RESERVE|
-                       BTREE_INSERT_JOURNAL_RECLAIM|
-                       JOURNAL_WATERMARK_reserved,
+                       BTREE_INSERT_JOURNAL_RECLAIM,
                        btree_update_nodes_written_trans(&trans, as));
        bch2_trans_unlock(&trans);
 
@@ -1049,14 +1042,24 @@ bch2_btree_update_start(struct btree_trans *trans, struct btree_path *path,
                ? BCH_DISK_RESERVATION_NOFAIL : 0;
        unsigned nr_nodes[2] = { 0, 0 };
        unsigned update_level = level;
-       int journal_flags = flags & JOURNAL_WATERMARK_MASK;
+       enum bch_watermark watermark = flags & BCH_WATERMARK_MASK;
+       unsigned journal_flags = 0;
        int ret = 0;
        u32 restart_count = trans->restart_count;
 
        BUG_ON(!path->should_be_locked);
 
+       if (watermark == BCH_WATERMARK_copygc)
+               watermark = BCH_WATERMARK_btree_copygc;
+       if (watermark < BCH_WATERMARK_btree)
+               watermark = BCH_WATERMARK_btree;
+
+       flags &= ~BCH_WATERMARK_MASK;
+       flags |= watermark;
+
        if (flags & BTREE_INSERT_JOURNAL_RECLAIM)
                journal_flags |= JOURNAL_RES_GET_NONBLOCK;
+       journal_flags |= watermark;
 
        while (1) {
                nr_nodes[!!update_level] += 1 + split;
@@ -1196,7 +1199,7 @@ static void bch2_btree_set_root_inmem(struct bch_fs *c, struct btree *b)
               (b->c.level < btree_node_root(c, b)->c.level ||
                !btree_node_dying(btree_node_root(c, b))));
 
-       btree_node_root(c, b) = b;
+       bch2_btree_id_root(c, b->c.btree_id)->b = b;
        mutex_unlock(&c->btree_root_lock);
 
        bch2_recalc_btree_reserve(c);
@@ -1845,9 +1848,7 @@ int __bch2_foreground_maybe_merge(struct btree_trans *trans,
 
        parent = btree_node_parent(path, b);
        as = bch2_btree_update_start(trans, path, level, false,
-                        BTREE_INSERT_NOFAIL|
-                        BTREE_INSERT_USE_RESERVE|
-                        flags);
+                                    BTREE_INSERT_NOFAIL|flags);
        ret = PTR_ERR_OR_ZERO(as);
        if (ret)
                goto err;
@@ -2035,7 +2036,7 @@ out:
        return ret;
 }
 
-void async_btree_node_rewrite_work(struct work_struct *work)
+static void async_btree_node_rewrite_work(struct work_struct *work)
 {
        struct async_btree_rewrite *a =
                container_of(work, struct async_btree_rewrite, work);
@@ -2127,6 +2128,7 @@ static int __bch2_btree_node_update_key(struct btree_trans *trans,
                                        struct btree_iter *iter,
                                        struct btree *b, struct btree *new_hash,
                                        struct bkey_i *new_key,
+                                       unsigned commit_flags,
                                        bool skip_triggers)
 {
        struct bch_fs *c = trans->c;
@@ -2187,12 +2189,7 @@ static int __bch2_btree_node_update_key(struct btree_trans *trans,
                trans->extra_journal_entries.nr += jset_u64s(new_key->k.u64s);
        }
 
-       ret = bch2_trans_commit(trans, NULL, NULL,
-                               BTREE_INSERT_NOFAIL|
-                               BTREE_INSERT_NOCHECK_RW|
-                               BTREE_INSERT_USE_RESERVE|
-                               BTREE_INSERT_JOURNAL_RECLAIM|
-                               JOURNAL_WATERMARK_reserved);
+       ret = bch2_trans_commit(trans, NULL, NULL, commit_flags);
        if (ret)
                goto err;
 
@@ -2226,7 +2223,7 @@ err:
 
 int bch2_btree_node_update_key(struct btree_trans *trans, struct btree_iter *iter,
                               struct btree *b, struct bkey_i *new_key,
-                              bool skip_triggers)
+                              unsigned commit_flags, bool skip_triggers)
 {
        struct bch_fs *c = trans->c;
        struct btree *new_hash = NULL;
@@ -2256,8 +2253,8 @@ int bch2_btree_node_update_key(struct btree_trans *trans, struct btree_iter *ite
        }
 
        path->intent_ref++;
-       ret = __bch2_btree_node_update_key(trans, iter, b, new_hash,
-                                          new_key, skip_triggers);
+       ret = __bch2_btree_node_update_key(trans, iter, b, new_hash, new_key,
+                                          commit_flags, skip_triggers);
        --path->intent_ref;
 
        if (new_hash) {
@@ -2275,7 +2272,7 @@ int bch2_btree_node_update_key(struct btree_trans *trans, struct btree_iter *ite
 
 int bch2_btree_node_update_key_get_iter(struct btree_trans *trans,
                                        struct btree *b, struct bkey_i *new_key,
-                                       bool skip_triggers)
+                                       unsigned commit_flags, bool skip_triggers)
 {
        struct btree_iter iter;
        int ret;
@@ -2296,7 +2293,8 @@ int bch2_btree_node_update_key_get_iter(struct btree_trans *trans,
 
        BUG_ON(!btree_node_hashed(b));
 
-       ret = bch2_btree_node_update_key(trans, &iter, b, new_key, skip_triggers);
+       ret = bch2_btree_node_update_key(trans, &iter, b, new_key,
+                                        commit_flags, skip_triggers);
 out:
        bch2_trans_iter_exit(trans, &iter);
        return ret;
@@ -2404,7 +2402,7 @@ bool bch2_btree_interior_updates_flush(struct bch_fs *c)
 
 void bch2_journal_entry_to_btree_root(struct bch_fs *c, struct jset_entry *entry)
 {
-       struct btree_root *r = &c->btree_roots[entry->btree_id];
+       struct btree_root *r = bch2_btree_id_root(c, entry->btree_id);
 
        mutex_lock(&c->btree_root_lock);
 
@@ -2430,15 +2428,15 @@ bch2_btree_roots_to_journal_entries(struct bch_fs *c,
 
        mutex_lock(&c->btree_root_lock);
 
-       for (i = 0; i < BTREE_ID_NR; i++)
-               if (c->btree_roots[i].alive && !test_bit(i, &have)) {
-                       journal_entry_set(end,
-                                         BCH_JSET_ENTRY_btree_root,
-                                         i, c->btree_roots[i].level,
-                                         &c->btree_roots[i].key,
-                                         c->btree_roots[i].key.k.u64s);
+       for (i = 0; i < btree_id_nr_alive(c); i++) {
+               struct btree_root *r = bch2_btree_id_root(c, i);
+
+               if (r->alive && !test_bit(i, &have)) {
+                       journal_entry_set(end, BCH_JSET_ENTRY_btree_root,
+                                         i, r->level, &r->key, r->key.k.u64s);
                        end = vstruct_next(end);
                }
+       }
 
        mutex_unlock(&c->btree_root_lock);
 
@@ -2452,7 +2450,7 @@ void bch2_fs_btree_interior_update_exit(struct bch_fs *c)
        mempool_exit(&c->btree_interior_update_pool);
 }
 
-int bch2_fs_btree_interior_update_init(struct bch_fs *c)
+void bch2_fs_btree_interior_update_init_early(struct bch_fs *c)
 {
        mutex_init(&c->btree_reserve_cache_lock);
        INIT_LIST_HEAD(&c->btree_interior_update_list);
@@ -2462,7 +2460,10 @@ int bch2_fs_btree_interior_update_init(struct bch_fs *c)
 
        INIT_LIST_HEAD(&c->pending_node_rewrites);
        mutex_init(&c->pending_node_rewrites_lock);
+}
 
+int bch2_fs_btree_interior_update_init(struct bch_fs *c)
+{
        c->btree_interior_update_worker =
                alloc_workqueue("btree_update", WQ_UNBOUND|WQ_MEM_RECLAIM, 1);
        if (!c->btree_interior_update_worker)
index dcfd7ceacc5926da051a11d72b1bdc12ec59b106..221b7ad5d053399f5b72e1c8952f1ef54538d295 100644 (file)
@@ -322,6 +322,7 @@ void bch2_do_pending_node_rewrites(struct bch_fs *);
 void bch2_free_pending_node_rewrites(struct bch_fs *);
 
 void bch2_fs_btree_interior_update_exit(struct bch_fs *);
+void bch2_fs_btree_interior_update_init_early(struct bch_fs *);
 int bch2_fs_btree_interior_update_init(struct bch_fs *);
 
 #endif /* _BCACHEFS_BTREE_UPDATE_INTERIOR_H */
index 8976a21f0cb65e196b82459b14bd7f97f9804a36..f7ffd68f5617252dd8072023947479277b3c683c 100644 (file)
@@ -29,7 +29,7 @@
  * bch2_btree_path_peek_slot() for a cached iterator might return a key in a
  * different snapshot:
  */
-struct bkey_s_c bch2_btree_path_peek_slot_exact(struct btree_path *path, struct bkey *u)
+static struct bkey_s_c bch2_btree_path_peek_slot_exact(struct btree_path *path, struct bkey *u)
 {
        struct bkey_s_c k = bch2_btree_path_peek_slot(path, u);
 
@@ -320,7 +320,7 @@ bch2_trans_journal_preres_get_cold(struct btree_trans *trans, unsigned flags,
                bch2_journal_preres_get(&trans->c->journal,
                        &trans->journal_preres,
                        trans->journal_preres_u64s,
-                       (flags & JOURNAL_WATERMARK_MASK)));
+                       (flags & BCH_WATERMARK_MASK)));
 }
 
 static __always_inline int bch2_trans_journal_res_get(struct btree_trans *trans,
@@ -407,6 +407,8 @@ static int run_one_mem_trigger(struct btree_trans *trans,
 {
        struct bkey_s_c old = { &i->old_k, i->old_v };
        struct bkey_i *new = i->k;
+       const struct bkey_ops *old_ops = bch2_bkey_type_ops(old.k->type);
+       const struct bkey_ops *new_ops = bch2_bkey_type_ops(i->k->k.type);
        int ret;
 
        verify_update_old_key(trans, i);
@@ -417,8 +419,7 @@ static int run_one_mem_trigger(struct btree_trans *trans,
        if (!btree_node_type_needs_gc(i->btree_id))
                return 0;
 
-       if (bch2_bkey_ops[old.k->type].atomic_trigger ==
-           bch2_bkey_ops[i->k->k.type].atomic_trigger) {
+       if (old_ops->atomic_trigger == new_ops->atomic_trigger) {
                ret   = bch2_mark_key(trans, i->btree_id, i->level,
                                old, bkey_i_to_s_c(new),
                                BTREE_TRIGGER_INSERT|BTREE_TRIGGER_OVERWRITE|flags);
@@ -449,6 +450,8 @@ static int run_one_trans_trigger(struct btree_trans *trans, struct btree_insert_
         */
        struct bkey old_k = i->old_k;
        struct bkey_s_c old = { &old_k, i->old_v };
+       const struct bkey_ops *old_ops = bch2_bkey_type_ops(old.k->type);
+       const struct bkey_ops *new_ops = bch2_bkey_type_ops(i->k->k.type);
 
        verify_update_old_key(trans, i);
 
@@ -458,8 +461,7 @@ static int run_one_trans_trigger(struct btree_trans *trans, struct btree_insert_
 
        if (!i->insert_trigger_run &&
            !i->overwrite_trigger_run &&
-           bch2_bkey_ops[old.k->type].trans_trigger ==
-           bch2_bkey_ops[i->k->k.type].trans_trigger) {
+           old_ops->trans_trigger == new_ops->trans_trigger) {
                i->overwrite_trigger_run = true;
                i->insert_trigger_run = true;
                return bch2_trans_mark_key(trans, i->btree_id, i->level, old, i->k,
@@ -634,7 +636,7 @@ bch2_trans_commit_write_locked(struct btree_trans *trans, unsigned flags,
         */
        if (likely(!(flags & BTREE_INSERT_JOURNAL_REPLAY))) {
                ret = bch2_trans_journal_res_get(trans,
-                               (flags & JOURNAL_WATERMARK_MASK)|
+                               (flags & BCH_WATERMARK_MASK)|
                                JOURNAL_RES_GET_NONBLOCK);
                if (ret)
                        return ret;
@@ -852,10 +854,13 @@ static inline int do_bch2_trans_commit(struct btree_trans *trans, unsigned flags
        struct printbuf buf = PRINTBUF;
 
        trans_for_each_update(trans, i) {
-               int rw = (flags & BTREE_INSERT_JOURNAL_REPLAY) ? READ : WRITE;
+               enum bkey_invalid_flags invalid_flags = 0;
+
+               if (!(flags & BTREE_INSERT_JOURNAL_REPLAY))
+                       invalid_flags |= BKEY_INVALID_WRITE|BKEY_INVALID_COMMIT;
 
                if (unlikely(bch2_bkey_invalid(c, bkey_i_to_s_c(i->k),
-                                              i->bkey_type, rw, &buf)))
+                                              i->bkey_type, invalid_flags, &buf)))
                        return bch2_trans_commit_bkey_invalid(trans, flags, i, &buf);
                btree_insert_entry_checks(trans, i);
        }
@@ -883,7 +888,7 @@ static inline int do_bch2_trans_commit(struct btree_trans *trans, unsigned flags
 
        ret = bch2_journal_preres_get(&c->journal,
                        &trans->journal_preres, trans->journal_preres_u64s,
-                       (flags & JOURNAL_WATERMARK_MASK)|JOURNAL_RES_GET_NONBLOCK);
+                       (flags & BCH_WATERMARK_MASK)|JOURNAL_RES_GET_NONBLOCK);
        if (unlikely(ret == -BCH_ERR_journal_preres_get_blocked))
                ret = bch2_trans_journal_preres_get_cold(trans, flags, trace_ip);
        if (unlikely(ret))
@@ -950,14 +955,14 @@ int bch2_trans_commit_error(struct btree_trans *trans, unsigned flags,
                break;
        case -BCH_ERR_journal_res_get_blocked:
                if ((flags & BTREE_INSERT_JOURNAL_RECLAIM) &&
-                   !(flags & JOURNAL_WATERMARK_reserved)) {
+                   (flags & BCH_WATERMARK_MASK) != BCH_WATERMARK_reclaim) {
                        ret = -BCH_ERR_journal_reclaim_would_deadlock;
                        break;
                }
 
                ret = drop_locks_do(trans,
                        bch2_trans_journal_res_get(trans,
-                                       (flags & JOURNAL_WATERMARK_MASK)|
+                                       (flags & BCH_WATERMARK_MASK)|
                                        JOURNAL_RES_GET_CHECK));
                break;
        case -BCH_ERR_btree_insert_need_journal_reclaim:
@@ -2044,7 +2049,7 @@ int bch2_journal_log_msg(struct bch_fs *c, const char *fmt, ...)
        int ret;
 
        va_start(args, fmt);
-       ret = __bch2_fs_log_msg(c, JOURNAL_WATERMARK_reserved, fmt, args);
+       ret = __bch2_fs_log_msg(c, BCH_WATERMARK_reclaim, fmt, args);
        va_end(args);
        return ret;
 }
index 8b7fffb2bf57e63015b54a777623733eab3de9a7..3a3e36c16bc030eae7ea5779ca69413969aa5ec8 100644 (file)
@@ -213,6 +213,9 @@ slowpath:
             btree_write_buffered_journal_cmp,
             NULL);
 
+       commit_flags &= ~BCH_WATERMARK_MASK;
+       commit_flags |= BCH_WATERMARK_reclaim;
+
        for (i = keys; i < keys + nr; i++) {
                if (!i->journal_seq)
                        continue;
@@ -231,8 +234,7 @@ slowpath:
                ret = commit_do(trans, NULL, NULL,
                                commit_flags|
                                BTREE_INSERT_NOFAIL|
-                               BTREE_INSERT_JOURNAL_RECLAIM|
-                               JOURNAL_WATERMARK_reserved,
+                               BTREE_INSERT_JOURNAL_RECLAIM,
                                __bch2_btree_insert(trans, i->btree, &i->k, 0));
                if (bch2_fs_fatal_err_on(ret, c, "%s: insert error %s", __func__, bch2_err_str(ret)))
                        break;
index ed86ad04d5a35c6a8e5aa2c1ab71a7d70c75a9ca..4aa0209e5347976f4ef8522cdbac2ebd1f10651a 100644 (file)
@@ -374,7 +374,7 @@ static inline int update_replicas(struct bch_fs *c, struct bkey_s_c k,
                        struct bch_replicas_entry *r, s64 sectors,
                        unsigned journal_seq, bool gc)
 {
-       struct bch_fs_usage __percpu *fs_usage;
+       struct bch_fs_usage *fs_usage;
        int idx, ret = 0;
        struct printbuf buf = PRINTBUF;
 
@@ -1149,7 +1149,7 @@ int bch2_mark_inode(struct btree_trans *trans,
                    unsigned flags)
 {
        struct bch_fs *c = trans->c;
-       struct bch_fs_usage __percpu *fs_usage;
+       struct bch_fs_usage *fs_usage;
        u64 journal_seq = trans->journal_res.seq;
 
        if (flags & BTREE_TRIGGER_INSERT) {
@@ -1180,7 +1180,7 @@ static int __mark_reservation(struct btree_trans *trans,
                              struct bkey_s_c k, unsigned flags)
 {
        struct bch_fs *c = trans->c;
-       struct bch_fs_usage __percpu *fs_usage;
+       struct bch_fs_usage *fs_usage;
        unsigned replicas = bkey_s_c_to_reservation(k).v->nr_replicas;
        s64 sectors = (s64) k.k->size;
 
index ef4e100aa9b6882786bf5ac1f42ca90341e62727..400d105fd09165aef446af108a619f1e4b6e2d5b 100644 (file)
@@ -170,6 +170,7 @@ static inline u64 bch2_dev_buckets_reserved(struct bch_dev *ca, enum bch_waterma
                reserved += ca->nr_btree_reserve;
                fallthrough;
        case BCH_WATERMARK_btree_copygc:
+       case BCH_WATERMARK_reclaim:
                break;
        }
 
index e5587bc5a2b73251e29dad986dd458a931c85945..442a9b806a3c164d5ae4209ea4494d45ee815230 100644 (file)
@@ -5,7 +5,7 @@
 
 /* BCH_SB_FIELD_counters */
 
-const char * const bch2_counter_names[] = {
+static const char * const bch2_counter_names[] = {
 #define x(t, n, ...) (#t),
        BCH_PERSISTENT_COUNTERS()
 #undef x
@@ -27,7 +27,7 @@ static int bch2_sb_counters_validate(struct bch_sb *sb,
        return 0;
 };
 
-void bch2_sb_counters_to_text(struct printbuf *out, struct bch_sb *sb,
+static void bch2_sb_counters_to_text(struct printbuf *out, struct bch_sb *sb,
                              struct bch_sb_field *f)
 {
        struct bch_sb_field_counters *ctrs = field_to_type(f, counters);
index 053df0c67c48c16d5bb974cc0e28fe2af41dec2c..3c918368b2ecdf9f0c3f2b2474f4029b11b95fa0 100644 (file)
@@ -381,7 +381,7 @@ void bch2_update_unwritten_extent(struct btree_trans *trans,
                                &update->op.devs_have,
                                update->op.nr_replicas,
                                update->op.nr_replicas,
-                               update->op.alloc_reserve,
+                               update->op.watermark,
                                0, &cl, &wp);
                if (bch2_err_matches(ret, BCH_ERR_operation_blocked)) {
                        bch2_trans_unlock(trans);
@@ -458,8 +458,7 @@ int bch2_data_update_init(struct btree_trans *trans,
        m->op.compression_type =
                bch2_compression_opt_to_type[io_opts.background_compression ?:
                                             io_opts.compression];
-       if (m->data_opts.btree_insert_flags & BTREE_INSERT_USE_RESERVE)
-               m->op.alloc_reserve = BCH_WATERMARK_copygc;
+       m->op.watermark         = m->data_opts.btree_insert_flags & BCH_WATERMARK_MASK;
 
        bkey_for_each_ptr(ptrs, ptr)
                percpu_ref_get(&bch_dev_bkey_exists(c, ptr->dev)->ref);
index 610dd7425fb477e2ff9cf0fba1b7f5abd4a50181..065ea59ee9fa5ecd8dcd68f12dd2ef8bd8e29497 100644 (file)
@@ -85,7 +85,8 @@ const struct bch_hash_desc bch2_dirent_hash_desc = {
 };
 
 int bch2_dirent_invalid(const struct bch_fs *c, struct bkey_s_c k,
-                       unsigned flags, struct printbuf *err)
+                       enum bkey_invalid_flags flags,
+                       struct printbuf *err)
 {
        struct bkey_s_c_dirent d = bkey_s_c_to_dirent(k);
        unsigned len;
@@ -219,7 +220,7 @@ int bch2_dirent_read_target(struct btree_trans *trans, subvol_inum dir,
        int ret = 0;
 
        if (d.v->d_type == DT_SUBVOL &&
-           d.v->d_parent_subvol != dir.subvol)
+           le32_to_cpu(d.v->d_parent_subvol) != dir.subvol)
                return 1;
 
        if (likely(d.v->d_type != DT_SUBVOL)) {
index bf9ea2e35faeb9a87c42be340e1d17e4fbb6e136..b42f4a13bc551debad140c8a6e59e39d2006a774 100644 (file)
@@ -4,9 +4,11 @@
 
 #include "str_hash.h"
 
+enum bkey_invalid_flags;
 extern const struct bch_hash_desc bch2_dirent_hash_desc;
 
-int bch2_dirent_invalid(const struct bch_fs *, struct bkey_s_c, unsigned, struct printbuf *);
+int bch2_dirent_invalid(const struct bch_fs *, struct bkey_s_c,
+                       enum bkey_invalid_flags, struct printbuf *);
 void bch2_dirent_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
 
 #define bch2_bkey_ops_dirent ((struct bkey_ops) {      \
index 8d091c4a0173732e54c6034ee953e17e2a78b033..d35a59e2d0e9cf780f8ad52aca05387f62e6a29d 100644 (file)
@@ -105,7 +105,8 @@ struct ec_bio {
 /* Stripes btree keys: */
 
 int bch2_stripe_invalid(const struct bch_fs *c, struct bkey_s_c k,
-                       unsigned flags, struct printbuf *err)
+                       enum bkey_invalid_flags flags,
+                       struct printbuf *err)
 {
        const struct bch_stripe *s = bkey_s_c_to_stripe(k).v;
 
@@ -385,7 +386,7 @@ static void ec_block_endio(struct bio *bio)
 }
 
 static void ec_block_io(struct bch_fs *c, struct ec_stripe_buf *buf,
-                       unsigned rw, unsigned idx, struct closure *cl)
+                       blk_opf_t opf, unsigned idx, struct closure *cl)
 {
        struct bch_stripe *v = &buf->key.v;
        unsigned offset = 0, bytes = buf->size << 9;
@@ -394,6 +395,7 @@ static void ec_block_io(struct bch_fs *c, struct ec_stripe_buf *buf,
        enum bch_data_type data_type = idx < buf->key.v.nr_blocks - buf->key.v.nr_redundant
                ? BCH_DATA_user
                : BCH_DATA_parity;
+       int rw = op_is_write(opf);
 
        if (ptr_stale(ca, ptr)) {
                bch_err_ratelimited(c,
@@ -419,7 +421,7 @@ static void ec_block_io(struct bch_fs *c, struct ec_stripe_buf *buf,
 
                ec_bio = container_of(bio_alloc_bioset(ca->disk_sb.bdev,
                                                       nr_iovecs,
-                                                      rw,
+                                                      opf,
                                                       GFP_KERNEL,
                                                       &c->ec_bioset),
                                      struct ec_bio, bio);
@@ -1380,11 +1382,12 @@ void bch2_ec_stripe_head_put(struct bch_fs *c, struct ec_stripe_head *h)
        mutex_unlock(&h->lock);
 }
 
-struct ec_stripe_head *__bch2_ec_stripe_head_get(struct btree_trans *trans,
-                                                unsigned target,
-                                                unsigned algo,
-                                                unsigned redundancy,
-                                                enum bch_watermark watermark)
+static struct ec_stripe_head *
+__bch2_ec_stripe_head_get(struct btree_trans *trans,
+                         unsigned target,
+                         unsigned algo,
+                         unsigned redundancy,
+                         enum bch_watermark watermark)
 {
        struct bch_fs *c = trans->c;
        struct ec_stripe_head *h;
@@ -1570,7 +1573,7 @@ static int __bch2_ec_stripe_head_reuse(struct btree_trans *trans, struct ec_stri
        }
 
        BUG_ON(h->s->existing_stripe.size != h->blocksize);
-       BUG_ON(h->s->existing_stripe.size != h->s->existing_stripe.key.v.sectors);
+       BUG_ON(h->s->existing_stripe.size != le16_to_cpu(h->s->existing_stripe.key.v.sectors));
 
        /*
         * Free buckets we initially allocated - they might conflict with
index 64ca277ca1a6dbf6606d3b724f15598c9ee96f49..1b1848e5fa5e78facd340cf194264f575c2952b0 100644 (file)
@@ -6,8 +6,10 @@
 #include "buckets_types.h"
 #include "extents_types.h"
 
+enum bkey_invalid_flags;
+
 int bch2_stripe_invalid(const struct bch_fs *, struct bkey_s_c,
-                       unsigned, struct printbuf *);
+                       enum bkey_invalid_flags, struct printbuf *);
 void bch2_stripe_to_text(struct printbuf *, struct bch_fs *,
                         struct bkey_s_c);
 
index 7e00550980de3f4c9a8c1eef3079677f8177c502..c13e0afc66eaa4430bc58b68960c22ea5fd4de5e 100644 (file)
@@ -163,7 +163,8 @@ int bch2_bkey_pick_read_device(struct bch_fs *c, struct bkey_s_c k,
 /* KEY_TYPE_btree_ptr: */
 
 int bch2_btree_ptr_invalid(const struct bch_fs *c, struct bkey_s_c k,
-                          unsigned flags, struct printbuf *err)
+                          enum bkey_invalid_flags flags,
+                          struct printbuf *err)
 {
        if (bkey_val_u64s(k.k) > BCH_REPLICAS_MAX) {
                prt_printf(err, "value too big (%zu > %u)",
@@ -181,7 +182,8 @@ void bch2_btree_ptr_to_text(struct printbuf *out, struct bch_fs *c,
 }
 
 int bch2_btree_ptr_v2_invalid(const struct bch_fs *c, struct bkey_s_c k,
-                             unsigned flags, struct printbuf *err)
+                             enum bkey_invalid_flags flags,
+                             struct printbuf *err)
 {
        if (bkey_val_u64s(k.k) > BKEY_BTREE_PTR_VAL_U64s_MAX) {
                prt_printf(err, "value too big (%zu > %zu)",
@@ -216,7 +218,7 @@ void bch2_btree_ptr_v2_compat(enum btree_id btree_id, unsigned version,
        compat_bpos(0, btree_id, version, big_endian, write, &bp.v->min_key);
 
        if (version < bcachefs_metadata_version_inode_btree_change &&
-           btree_node_type_is_extents(btree_id) &&
+           btree_id_is_extents(btree_id) &&
            !bkey_eq(bp.v->min_key, POS_MIN))
                bp.v->min_key = write
                        ? bpos_nosnap_predecessor(bp.v->min_key)
@@ -371,7 +373,8 @@ bool bch2_extent_merge(struct bch_fs *c, struct bkey_s l, struct bkey_s_c r)
 /* KEY_TYPE_reservation: */
 
 int bch2_reservation_invalid(const struct bch_fs *c, struct bkey_s_c k,
-                            unsigned flags, struct printbuf *err)
+                            enum bkey_invalid_flags flags,
+                            struct printbuf *err)
 {
        struct bkey_s_c_reservation r = bkey_s_c_to_reservation(k);
 
@@ -514,7 +517,7 @@ static void bch2_extent_crc_pack(union bch_extent_crc *dst,
        switch (type) {
        case BCH_EXTENT_ENTRY_crc32:
                set_common_fields(dst->crc32, src);
-               dst->crc32.csum  = *((__le32 *) &src.csum.lo);
+               memcpy(&dst->crc32.csum, &src.csum.lo, sizeof(dst->crc32.csum));
                break;
        case BCH_EXTENT_ENTRY_crc64:
                set_common_fields(dst->crc64, src);
@@ -1103,7 +1106,8 @@ static int extent_ptr_invalid(const struct bch_fs *c,
 }
 
 int bch2_bkey_ptrs_invalid(const struct bch_fs *c, struct bkey_s_c k,
-                          unsigned flags, struct printbuf *err)
+                          enum bkey_invalid_flags flags,
+                          struct printbuf *err)
 {
        struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k);
        const union bch_extent_entry *entry;
@@ -1202,6 +1206,8 @@ int bch2_bkey_ptrs_invalid(const struct bch_fs *c, struct bkey_s_c k,
                        }
                        have_ec = true;
                        break;
+               case BCH_EXTENT_ENTRY_rebalance:
+                       break;
                }
        }
 
@@ -1260,6 +1266,8 @@ void bch2_ptr_swab(struct bkey_s k)
                        break;
                case BCH_EXTENT_ENTRY_stripe_ptr:
                        break;
+               case BCH_EXTENT_ENTRY_rebalance:
+                       break;
                }
        }
 }
@@ -1310,6 +1318,8 @@ int bch2_cut_front_s(struct bpos where, struct bkey_s k)
                                break;
                        case BCH_EXTENT_ENTRY_stripe_ptr:
                                break;
+                       case BCH_EXTENT_ENTRY_rebalance:
+                               break;
                        }
 
                        if (extent_entry_is_crc(entry))
index 3ba41e37d8649610e94c56e26477baec8a53c7e6..d359b3fda91db3a9ce3f49520e5995b8dd9d861a 100644 (file)
@@ -8,6 +8,7 @@
 
 struct bch_fs;
 struct btree_trans;
+enum bkey_invalid_flags;
 
 /* extent entries: */
 
@@ -154,11 +155,7 @@ bch2_extent_crc_unpack(const struct bkey *k, const union bch_extent_crc *crc)
                        common_fields(crc->crc32),
                };
 
-               *((__le32 *) &ret.csum.lo) = crc->crc32.csum;
-
-               memcpy(&ret.csum.lo, &crc->crc32.csum,
-                      sizeof(crc->crc32.csum));
-
+               memcpy(&ret.csum.lo, &crc->crc32.csum, sizeof(crc->crc32.csum));
                return ret;
        }
        case BCH_EXTENT_ENTRY_crc64: {
@@ -168,8 +165,8 @@ bch2_extent_crc_unpack(const struct bkey *k, const union bch_extent_crc *crc)
                        .csum.lo                = (__force __le64) crc->crc64.csum_lo,
                };
 
-               *((__le16 *) &ret.csum.hi) = crc->crc64.csum_hi;
-
+               u16 hi = crc->crc64.csum_hi;
+               memcpy(&ret.csum.hi, &hi, sizeof(hi));
                return ret;
        }
        case BCH_EXTENT_ENTRY_crc128: {
@@ -318,6 +315,9 @@ static inline struct bkey_ptrs bch2_bkey_ptrs(struct bkey_s k)
                        (_ptr).ec = _entry->stripe_ptr;                 \
                        (_ptr).has_ec   = true;                         \
                        break;                                          \
+               default:                                                \
+                       /* nothing */                                   \
+                       break;                                          \
                }                                                       \
 out:                                                                   \
        _entry < (_end);                                                \
@@ -383,11 +383,13 @@ int bch2_bkey_pick_read_device(struct bch_fs *, struct bkey_s_c,
 
 /* KEY_TYPE_btree_ptr: */
 
-int bch2_btree_ptr_invalid(const struct bch_fs *, struct bkey_s_c, unsigned, struct printbuf *);
+int bch2_btree_ptr_invalid(const struct bch_fs *, struct bkey_s_c,
+                          enum bkey_invalid_flags, struct printbuf *);
 void bch2_btree_ptr_to_text(struct printbuf *, struct bch_fs *,
                            struct bkey_s_c);
 
-int bch2_btree_ptr_v2_invalid(const struct bch_fs *, struct bkey_s_c, unsigned, struct printbuf *);
+int bch2_btree_ptr_v2_invalid(const struct bch_fs *, struct bkey_s_c,
+                             enum bkey_invalid_flags, struct printbuf *);
 void bch2_btree_ptr_v2_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
 void bch2_btree_ptr_v2_compat(enum btree_id, unsigned, unsigned,
                              int, struct bkey_s);
@@ -427,7 +429,7 @@ bool bch2_extent_merge(struct bch_fs *, struct bkey_s, struct bkey_s_c);
 /* KEY_TYPE_reservation: */
 
 int bch2_reservation_invalid(const struct bch_fs *, struct bkey_s_c,
-                            unsigned, struct printbuf *);
+                            enum bkey_invalid_flags, struct printbuf *);
 void bch2_reservation_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
 bool bch2_reservation_merge(struct bch_fs *, struct bkey_s, struct bkey_s_c);
 
index 45858174c1f300be6b72c2ab71f46fd87b980038..36e2886427273c01749de12f721f53c57d30d029 100644 (file)
@@ -458,7 +458,7 @@ enum bch_folio_sector_state {
 #undef x
 };
 
-const char * const bch2_folio_sector_states[] = {
+static const char * const bch2_folio_sector_states[] = {
 #define x(n)   #n,
        BCH_FOLIO_SECTOR_STATE()
 #undef x
@@ -997,7 +997,7 @@ vm_fault_t bch2_page_fault(struct vm_fault *vmf)
        struct address_space *mapping = file->f_mapping;
        struct address_space *fdm = faults_disabled_mapping();
        struct bch_inode_info *inode = file_bch_inode(file);
-       int ret;
+       vm_fault_t ret;
 
        if (fdm == mapping)
                return VM_FAULT_SIGBUS;
@@ -1039,7 +1039,7 @@ vm_fault_t bch2_page_mkwrite(struct vm_fault *vmf)
        struct bch2_folio_reservation res;
        unsigned len;
        loff_t isize;
-       int ret;
+       vm_fault_t ret;
 
        bch2_folio_reservation_init(c, inode, &res);
 
index 7af65030f9d8dcc41494ca836cab8556cd610435..98fde0bf6edc8dee3823c18832300600542afca3 100644 (file)
@@ -1216,7 +1216,7 @@ static int check_overlapping_extents(struct btree_trans *trans,
                if (ret)
                        break;
 
-               if (fsck_err(c, buf.buf)) {
+               if (fsck_err(c, "%s", buf.buf)) {
                        struct bkey_i *update = bch2_trans_kmalloc(trans, bkey_bytes(k.k));
                        if ((ret = PTR_ERR_OR_ZERO(update)))
                                goto err;
@@ -1696,8 +1696,8 @@ static int check_dirent(struct btree_trans *trans, struct btree_iter *iter,
                        goto err;
 
                if (fsck_err_on(ret, c,
-                               "dirent points to missing subvolume %llu",
-                               le64_to_cpu(d.v->d_child_subvol))) {
+                               "dirent points to missing subvolume %u",
+                               le32_to_cpu(d.v->d_child_subvol))) {
                        ret = __remove_dirent(trans, d.k->p);
                        goto err;
                }
@@ -2238,7 +2238,7 @@ static int check_nlinks_find_hardlinks(struct bch_fs *c,
                 * Backpointer and directory structure checks are sufficient for
                 * directories, since they can't have hardlinks:
                 */
-               if (S_ISDIR(le16_to_cpu(u.bi_mode)))
+               if (S_ISDIR(u.bi_mode))
                        continue;
 
                if (!u.bi_nlink)
@@ -2324,7 +2324,7 @@ static int check_nlinks_update_inode(struct btree_trans *trans, struct btree_ite
 
        BUG_ON(bch2_inode_unpack(k, &u));
 
-       if (S_ISDIR(le16_to_cpu(u.bi_mode)))
+       if (S_ISDIR(u.bi_mode))
                return 0;
 
        if (!u.bi_nlink)
index 64e8d1f8a2fa791885891e071f67656f1e1774f0..fa435d8655de8e512aacd7a718c51677a384bb54 100644 (file)
@@ -432,7 +432,8 @@ static int __bch2_inode_invalid(struct bkey_s_c k, struct printbuf *err)
 }
 
 int bch2_inode_invalid(const struct bch_fs *c, struct bkey_s_c k,
-                      unsigned flags, struct printbuf *err)
+                      enum bkey_invalid_flags flags,
+                      struct printbuf *err)
 {
        struct bkey_s_c_inode inode = bkey_s_c_to_inode(k);
 
@@ -446,7 +447,8 @@ int bch2_inode_invalid(const struct bch_fs *c, struct bkey_s_c k,
 }
 
 int bch2_inode_v2_invalid(const struct bch_fs *c, struct bkey_s_c k,
-                         unsigned flags, struct printbuf *err)
+                         enum bkey_invalid_flags flags,
+                         struct printbuf *err)
 {
        struct bkey_s_c_inode_v2 inode = bkey_s_c_to_inode_v2(k);
 
@@ -460,7 +462,8 @@ int bch2_inode_v2_invalid(const struct bch_fs *c, struct bkey_s_c k,
 }
 
 int bch2_inode_v3_invalid(const struct bch_fs *c, struct bkey_s_c k,
-                         unsigned flags, struct printbuf *err)
+                         enum bkey_invalid_flags flags,
+                         struct printbuf *err)
 {
        struct bkey_s_c_inode_v3 inode = bkey_s_c_to_inode_v3(k);
 
@@ -517,7 +520,8 @@ void bch2_inode_to_text(struct printbuf *out, struct bch_fs *c, struct bkey_s_c
 }
 
 int bch2_inode_generation_invalid(const struct bch_fs *c, struct bkey_s_c k,
-                                 unsigned flags, struct printbuf *err)
+                                 enum bkey_invalid_flags flags,
+                                 struct printbuf *err)
 {
        if (k.k->p.inode) {
                prt_printf(err, "nonzero k.p.inode");
index 0c3022d3f995f00ef0bfe99de85a6f50877e9032..8f9be5e58381994ff8adaff7399e92585a761c3e 100644 (file)
@@ -5,11 +5,15 @@
 #include "bkey.h"
 #include "opts.h"
 
+enum bkey_invalid_flags;
 extern const char * const bch2_inode_opts[];
 
-int bch2_inode_invalid(const struct bch_fs *, struct bkey_s_c, unsigned, struct printbuf *);
-int bch2_inode_v2_invalid(const struct bch_fs *, struct bkey_s_c, unsigned, struct printbuf *);
-int bch2_inode_v3_invalid(const struct bch_fs *, struct bkey_s_c, unsigned, struct printbuf *);
+int bch2_inode_invalid(const struct bch_fs *, struct bkey_s_c,
+                      enum bkey_invalid_flags, struct printbuf *);
+int bch2_inode_v2_invalid(const struct bch_fs *, struct bkey_s_c,
+                         enum bkey_invalid_flags, struct printbuf *);
+int bch2_inode_v3_invalid(const struct bch_fs *, struct bkey_s_c,
+                         enum bkey_invalid_flags, struct printbuf *);
 void bch2_inode_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
 
 #define bch2_bkey_ops_inode ((struct bkey_ops) {       \
@@ -44,7 +48,7 @@ static inline bool bkey_is_inode(const struct bkey *k)
 }
 
 int bch2_inode_generation_invalid(const struct bch_fs *, struct bkey_s_c,
-                                 unsigned, struct printbuf *);
+                                 enum bkey_invalid_flags, struct printbuf *);
 void bch2_inode_generation_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
 
 #define bch2_bkey_ops_inode_generation ((struct bkey_ops) {    \
index e87c0a7f2c43ac01406b845736266dbf564c9f43..0e9c23be80aa66e6a22942f46f7122917cb96e87 100644 (file)
@@ -1696,7 +1696,7 @@ again:
                                &op->devs_have,
                                op->nr_replicas,
                                op->nr_replicas_required,
-                               op->alloc_reserve,
+                               op->watermark,
                                op->flags,
                                (op->flags & (BCH_WRITE_ALLOC_NOWAIT|
                                              BCH_WRITE_ONLY_SPECIFIED_DEVS))
@@ -1878,7 +1878,7 @@ err:
                op->end_io(op);
 }
 
-const char * const bch2_write_flags[] = {
+static const char * const bch2_write_flags[] = {
 #define x(f)   #f,
        BCH_WRITE_FLAGS()
 #undef x
index 87e1305d17755599d756e1bb03d105a568d306a7..7a243a5f3f89e9c47ef2f420065cddb62a95ec34 100644 (file)
@@ -59,7 +59,7 @@ enum bch_write_flags {
 
 static inline struct workqueue_struct *index_update_wq(struct bch_write_op *op)
 {
-       return op->alloc_reserve == BCH_WATERMARK_copygc
+       return op->watermark == BCH_WATERMARK_copygc
                ? op->c->copygc_wq
                : op->c->btree_update_wq;
 }
@@ -89,7 +89,7 @@ static inline void bch2_write_op_init(struct bch_write_op *op, struct bch_fs *c,
        op->compression_type    = bch2_compression_opt_to_type[opts.compression];
        op->nr_replicas         = 0;
        op->nr_replicas_required = c->opts.data_replicas_required;
-       op->alloc_reserve       = BCH_WATERMARK_normal;
+       op->watermark           = BCH_WATERMARK_normal;
        op->incompressible      = 0;
        op->open_buckets.nr     = 0;
        op->devs_have.nr        = 0;
index 4149291c0df6f153f8f7a147eed75487767efd18..0fbdfbf90ad836282eab3d55761c0f6aa0b2e821 100644 (file)
@@ -119,7 +119,7 @@ struct bch_write_op {
        unsigned                compression_type:4;
        unsigned                nr_replicas:4;
        unsigned                nr_replicas_required:4;
-       unsigned                alloc_reserve:3;
+       unsigned                watermark:3;
        unsigned                incompressible:1;
        unsigned                stripe_waited:1;
 
index dc34aba2d259be9b53ee81f4ae5b2f98f6da1891..f33ab45b7944290b38b7f24f9c34f485666c8f00 100644 (file)
 #include "journal_seq_blacklist.h"
 #include "trace.h"
 
-#define x(n)   #n,
-static const char * const bch2_journal_watermarks[] = {
-       JOURNAL_WATERMARKS()
-       NULL
-};
-
 static const char * const bch2_journal_errors[] = {
+#define x(n)   #n,
        JOURNAL_ERRORS()
+#undef x
        NULL
 };
-#undef x
 
 static inline bool journal_seq_unwritten(struct journal *j, u64 seq)
 {
@@ -96,7 +91,7 @@ journal_error_check_stuck(struct journal *j, int error, unsigned flags)
        if (!(error == JOURNAL_ERR_journal_full ||
              error == JOURNAL_ERR_journal_pin_full) ||
            nr_unwritten_journal_entries(j) ||
-           (flags & JOURNAL_WATERMARK_MASK) != JOURNAL_WATERMARK_reserved)
+           (flags & BCH_WATERMARK_MASK) != BCH_WATERMARK_reclaim)
                return stuck;
 
        spin_lock(&j->lock);
@@ -440,7 +435,7 @@ retry:
                return 0;
        }
 
-       if ((flags & JOURNAL_WATERMARK_MASK) < j->watermark) {
+       if ((flags & BCH_WATERMARK_MASK) < j->watermark) {
                /*
                 * Don't want to close current journal entry, just need to
                 * invoke reclaim:
@@ -1292,7 +1287,7 @@ void __bch2_journal_debug_to_text(struct printbuf *out, struct journal *j)
        prt_printf(out, "last_seq_ondisk:\t%llu\n",             j->last_seq_ondisk);
        prt_printf(out, "flushed_seq_ondisk:\t%llu\n",  j->flushed_seq_ondisk);
        prt_printf(out, "prereserved:\t\t%u/%u\n",              j->prereserved.reserved, j->prereserved.remaining);
-       prt_printf(out, "watermark:\t\t%s\n",           bch2_journal_watermarks[j->watermark]);
+       prt_printf(out, "watermark:\t\t%s\n",           bch2_watermarks[j->watermark]);
        prt_printf(out, "each entry reserved:\t%u\n",   j->entry_u64s_reserved);
        prt_printf(out, "nr flush writes:\t%llu\n",             j->nr_flush_writes);
        prt_printf(out, "nr noflush writes:\t%llu\n",   j->nr_noflush_writes);
index 024cea9f5902e7b0be7475d9b73b48d9b8b76956..008a2e25a4fac93df681233b679c9fc6eaca95d0 100644 (file)
@@ -294,9 +294,14 @@ static inline void bch2_journal_res_put(struct journal *j,
 int bch2_journal_res_get_slowpath(struct journal *, struct journal_res *,
                                  unsigned);
 
-/* First two bits for JOURNAL_WATERMARK: */
-#define JOURNAL_RES_GET_NONBLOCK       (1 << 2)
-#define JOURNAL_RES_GET_CHECK          (1 << 3)
+/* First bits for BCH_WATERMARK: */
+enum journal_res_flags {
+       __JOURNAL_RES_GET_NONBLOCK      = BCH_WATERMARK_BITS,
+       __JOURNAL_RES_GET_CHECK,
+};
+
+#define JOURNAL_RES_GET_NONBLOCK       (1 << __JOURNAL_RES_GET_NONBLOCK)
+#define JOURNAL_RES_GET_CHECK          (1 << __JOURNAL_RES_GET_CHECK)
 
 static inline int journal_res_get_fast(struct journal *j,
                                       struct journal_res *res,
@@ -317,7 +322,7 @@ static inline int journal_res_get_fast(struct journal *j,
 
                EBUG_ON(!journal_state_count(new, new.idx));
 
-               if ((flags & JOURNAL_WATERMARK_MASK) < j->watermark)
+               if ((flags & BCH_WATERMARK_MASK) < j->watermark)
                        return 0;
 
                new.cur_entry_offset += res->u64s;
@@ -373,17 +378,17 @@ out:
 static inline void journal_set_watermark(struct journal *j)
 {
        union journal_preres_state s = READ_ONCE(j->prereserved);
-       unsigned watermark = JOURNAL_WATERMARK_any;
+       unsigned watermark = BCH_WATERMARK_stripe;
 
        if (fifo_free(&j->pin) < j->pin.size / 4)
-               watermark = max_t(unsigned, watermark, JOURNAL_WATERMARK_copygc);
+               watermark = max_t(unsigned, watermark, BCH_WATERMARK_copygc);
        if (fifo_free(&j->pin) < j->pin.size / 8)
-               watermark = max_t(unsigned, watermark, JOURNAL_WATERMARK_reserved);
+               watermark = max_t(unsigned, watermark, BCH_WATERMARK_reclaim);
 
        if (s.reserved > s.remaining)
-               watermark = max_t(unsigned, watermark, JOURNAL_WATERMARK_copygc);
+               watermark = max_t(unsigned, watermark, BCH_WATERMARK_copygc);
        if (!s.remaining)
-               watermark = max_t(unsigned, watermark, JOURNAL_WATERMARK_reserved);
+               watermark = max_t(unsigned, watermark, BCH_WATERMARK_reclaim);
 
        if (watermark == j->watermark)
                return;
@@ -426,13 +431,14 @@ static inline int bch2_journal_preres_get_fast(struct journal *j,
        int d = new_u64s - res->u64s;
        union journal_preres_state old, new;
        u64 v = atomic64_read(&j->prereserved.counter);
+       enum bch_watermark watermark = flags & BCH_WATERMARK_MASK;
        int ret;
 
        do {
                old.v = new.v = v;
                ret = 0;
 
-               if ((flags & JOURNAL_WATERMARK_reserved) ||
+               if (watermark == BCH_WATERMARK_reclaim ||
                    new.reserved + d < new.remaining) {
                        new.reserved += d;
                        ret = 1;
index 8dc37867491908b6e933fdba3d0d869757d92988..c7c2ae326ff7920c7699126b99a1d108ee872acc 100644 (file)
@@ -340,7 +340,8 @@ static int journal_entry_btree_keys_validate(struct bch_fs *c,
                int ret = journal_validate_key(c, jset, entry,
                                               entry->level,
                                               entry->btree_id,
-                                              k, version, big_endian, write|BKEY_INVALID_FROM_JOURNAL);
+                                              k, version, big_endian,
+                                              write|BKEY_INVALID_JOURNAL);
                if (ret == FSCK_DELETED_KEY)
                        continue;
 
@@ -745,14 +746,10 @@ static int jset_validate(struct bch_fs *c,
                return JOURNAL_ENTRY_NONE;
 
        version = le32_to_cpu(jset->version);
-       if (journal_entry_err_on((version != BCH_JSET_VERSION_OLD &&
-                                 version < bcachefs_metadata_version_min) ||
-                                version >= bcachefs_metadata_version_max,
-                                c, jset, NULL,
-                       "%s sector %llu seq %llu: unknown journal entry version %u",
+       if (journal_entry_err_on(!bch2_version_compatible(version), c, jset, NULL,
+                       "%s sector %llu seq %llu: incompatible journal entry version %u",
                        ca ? ca->name : c->name,
-                       sector, le64_to_cpu(jset->seq),
-                       version)) {
+                       sector, le64_to_cpu(jset->seq), version)) {
                /* don't try to continue: */
                return -EINVAL;
        }
@@ -796,14 +793,10 @@ static int jset_validate_early(struct bch_fs *c,
                return JOURNAL_ENTRY_NONE;
 
        version = le32_to_cpu(jset->version);
-       if (journal_entry_err_on((version != BCH_JSET_VERSION_OLD &&
-                                 version < bcachefs_metadata_version_min) ||
-                                version >= bcachefs_metadata_version_max,
-                                c, jset, NULL,
+       if (journal_entry_err_on(!bch2_version_compatible(version), c, jset, NULL,
                        "%s sector %llu seq %llu: unknown journal entry version %u",
                        ca ? ca->name : c->name,
-                       sector, le64_to_cpu(jset->seq),
-                       version)) {
+                       sector, le64_to_cpu(jset->seq), version)) {
                /* don't try to continue: */
                return -EINVAL;
        }
@@ -1505,7 +1498,7 @@ static void journal_write_done(struct closure *cl)
         * Must come before signaling write completion, for
         * bch2_fs_journal_stop():
         */
-       if (j->watermark)
+       if (j->watermark != BCH_WATERMARK_stripe)
                journal_reclaim_kick(&c->journal);
 
        /* also must come before signalling write completion: */
@@ -1755,9 +1748,7 @@ void bch2_journal_write(struct closure *cl)
        }
 
        jset->magic             = cpu_to_le64(jset_magic(c));
-       jset->version           = c->sb.version < bcachefs_metadata_version_bkey_renumber
-               ? cpu_to_le32(BCH_JSET_VERSION_OLD)
-               : cpu_to_le32(c->sb.version);
+       jset->version           = cpu_to_le32(c->sb.version);
 
        SET_JSET_BIG_ENDIAN(jset, CPU_BIG_ENDIAN);
        SET_JSET_CSUM_TYPE(jset, bch2_meta_checksum_type(c));
index 2c7f8aca9319df668b5779a7cf8dae2d9aa587cc..72486f1f8a8e28fe6af9bede873e3a669ba912b6 100644 (file)
@@ -361,7 +361,7 @@ void bch2_journal_pin_drop(struct journal *j,
        spin_unlock(&j->lock);
 }
 
-enum journal_pin_type journal_pin_type(journal_pin_flush_fn fn)
+static enum journal_pin_type journal_pin_type(journal_pin_flush_fn fn)
 {
        if (fn == bch2_btree_node_flush0 ||
            fn == bch2_btree_node_flush1)
@@ -837,8 +837,20 @@ int bch2_journal_flush_device_pins(struct journal *j, int dev_idx)
        mutex_lock(&c->replicas_gc_lock);
        bch2_replicas_gc_start(c, 1 << BCH_DATA_journal);
 
-       seq = 0;
+       /*
+        * Now that we've populated replicas_gc, write to the journal to mark
+        * active journal devices. This handles the case where the journal might
+        * be empty. Otherwise we could clear all journal replicas and
+        * temporarily put the fs into an unrecoverable state. Journal recovery
+        * expects to find devices marked for journal data on unclean mount.
+        */
+       ret = bch2_journal_meta(&c->journal);
+       if (ret) {
+               mutex_unlock(&c->replicas_gc_lock);
+               return ret;
+       }
 
+       seq = 0;
        spin_lock(&j->lock);
        while (!ret) {
                struct bch_replicas_padded replicas;
index fcefbbe7eda8de8fce336380fb7e97cc4eefd50b..cc41bff86d6bbc049be49f3f05e751af9dd528d5 100644 (file)
@@ -201,16 +201,16 @@ int bch2_journal_buckets_to_sb(struct bch_fs *c, struct bch_dev *ca,
 
        bch2_sb_field_delete(&ca->disk_sb, BCH_SB_FIELD_journal);
 
-       j->d[dst].start = le64_to_cpu(buckets[0]);
-       j->d[dst].nr    = le64_to_cpu(1);
+       j->d[dst].start = cpu_to_le64(buckets[0]);
+       j->d[dst].nr    = cpu_to_le64(1);
 
        for (i = 1; i < nr; i++) {
                if (buckets[i] == buckets[i - 1] + 1) {
                        le64_add_cpu(&j->d[dst].nr, 1);
                } else {
                        dst++;
-                       j->d[dst].start = le64_to_cpu(buckets[i]);
-                       j->d[dst].nr    = le64_to_cpu(1);
+                       j->d[dst].start = cpu_to_le64(buckets[i]);
+                       j->d[dst].nr    = cpu_to_le64(1);
                }
        }
 
index 8d8c0b3d5a30e7e86dbef1f26db55f3b9a3fd5f1..42504e16acb6ccf261a6699b6d468cba7d26a776 100644 (file)
@@ -154,19 +154,6 @@ enum journal_flags {
        JOURNAL_NEED_FLUSH_WRITE,
 };
 
-#define JOURNAL_WATERMARKS()           \
-       x(any)                          \
-       x(copygc)                       \
-       x(reserved)
-
-enum journal_watermark {
-#define x(n)   JOURNAL_WATERMARK_##n,
-       JOURNAL_WATERMARKS()
-#undef x
-};
-
-#define JOURNAL_WATERMARK_MASK 3
-
 /* Reasons we may fail to get a journal reservation: */
 #define JOURNAL_ERRORS()               \
        x(ok)                           \
@@ -191,7 +178,7 @@ struct journal {
        struct {
 
        union journal_res_state reservations;
-       enum journal_watermark  watermark;
+       enum bch_watermark      watermark;
 
        union journal_preres_state prereserved;
 
index d3242511605de8757e905bd5882542c39044e55e..2387e08440d3f166534bdf1b396a0547dabe049f 100644 (file)
@@ -11,7 +11,8 @@
 
 /* KEY_TYPE_lru is obsolete: */
 int bch2_lru_invalid(const struct bch_fs *c, struct bkey_s_c k,
-                    unsigned flags, struct printbuf *err)
+                    enum bkey_invalid_flags flags,
+                    struct printbuf *err)
 {
        if (!lru_pos_time(k.k->p)) {
                prt_printf(err, "lru entry at time=0");
index adb98429248ef3ceee4b34f34d05417fbe3a1ce8..7a3be20a8523e423b7c03222ebef679893e65f10 100644 (file)
@@ -43,7 +43,8 @@ static inline enum bch_lru_type lru_type(struct bkey_s_c l)
        return BCH_LRU_read;
 }
 
-int bch2_lru_invalid(const struct bch_fs *, struct bkey_s_c, unsigned, struct printbuf *);
+int bch2_lru_invalid(const struct bch_fs *, struct bkey_s_c,
+                    enum bkey_invalid_flags, struct printbuf *);
 void bch2_lru_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
 
 void bch2_lru_pos_to_text(struct printbuf *, struct bpos);
index 783e9442b302876a8533f0c734d73f371e5f3e75..81c8cdbac28597c9b88e140f47f357fd07b4ac83 100644 (file)
@@ -141,7 +141,7 @@ retry:
                                break;
                        }
 
-                       ret = bch2_btree_node_update_key(&trans, &iter, b, k.k, false);
+                       ret = bch2_btree_node_update_key(&trans, &iter, b, k.k, 0, false);
                        if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) {
                                ret = 0;
                                continue;
index 37fb3784a2f97fa6e18ac72ab7211cc2341b5adc..05272673901d2ba93cccd69c0b1e9febf4042803 100644 (file)
@@ -632,7 +632,7 @@ int bch2_move_data(struct bch_fs *c,
        bch2_moving_ctxt_init(&ctxt, c, rate, stats, wp, wait_on_copygc);
 
        for (id = start_btree_id;
-            id <= min_t(unsigned, end_btree_id, BTREE_ID_NR - 1);
+            id <= min_t(unsigned, end_btree_id, btree_id_nr_alive(c) - 1);
             id++) {
                stats->btree_id = id;
 
@@ -640,6 +640,9 @@ int bch2_move_data(struct bch_fs *c,
                    id != BTREE_ID_reflink)
                        continue;
 
+               if (!bch2_btree_id_root(c, id)->b)
+                       continue;
+
                ret = __bch2_move_data(&ctxt,
                                       id == start_btree_id ? start_pos : POS_MIN,
                                       id == end_btree_id   ? end_pos   : POS_MAX,
@@ -861,10 +864,13 @@ static int bch2_move_btree(struct bch_fs *c,
        stats->data_type = BCH_DATA_btree;
 
        for (id = start_btree_id;
-            id <= min_t(unsigned, end_btree_id, BTREE_ID_NR - 1);
+            id <= min_t(unsigned, end_btree_id, btree_id_nr_alive(c) - 1);
             id++) {
                stats->btree_id = id;
 
+               if (!bch2_btree_id_root(c, id)->b)
+                       continue;
+
                bch2_trans_node_iter_init(&trans, &iter, id, POS_MIN, 0, 0,
                                          BTREE_ITER_PREFETCH);
 retry:
index 5ea512968f4d0f299b592308d14a1db64d0bc60c..5242f20bb680fc2c0d9fc8ebd54188db87dfa8ab 100644 (file)
@@ -202,7 +202,7 @@ static int bch2_copygc(struct btree_trans *trans,
 {
        struct bch_fs *c = trans->c;
        struct data_update_opts data_opts = {
-               .btree_insert_flags = BTREE_INSERT_USE_RESERVE|JOURNAL_WATERMARK_copygc,
+               .btree_insert_flags = BCH_WATERMARK_copygc,
        };
        move_buckets buckets = { 0 };
        struct move_bucket_in_flight *f;
index 04e2989cd6b392703592c134b211eefce3d26220..a05c389830dc066e53038d23061b660075146ead 100644 (file)
 
 #define x(t, n) [n] = #t,
 
-const char * const bch2_metadata_versions[] = {
-       BCH_METADATA_VERSIONS()
-       NULL
-};
-
 const char * const bch2_error_actions[] = {
        BCH_ERROR_ACTIONS()
        NULL
index 719693b333da231577d0fe09c38809954cbdfca2..e7cf7e92f3dba40144cea48b3d8a3b6322522765 100644 (file)
@@ -8,7 +8,6 @@
 #include <linux/sysfs.h>
 #include "bcachefs_format.h"
 
-extern const char * const bch2_metadata_versions[];
 extern const char * const bch2_error_actions[];
 extern const char * const bch2_sb_features[];
 extern const char * const bch2_sb_compat[];
index 7e1f1828ab2074d503f3ce9b3d464e4e710d3c88..d90db3fb823ed42fc89c9a47b8b0dc6179721b6a 100644 (file)
@@ -60,7 +60,8 @@ const struct bch_sb_field_ops bch_sb_field_ops_quota = {
 };
 
 int bch2_quota_invalid(const struct bch_fs *c, struct bkey_s_c k,
-                      unsigned flags, struct printbuf *err)
+                      enum bkey_invalid_flags flags,
+                      struct printbuf *err)
 {
        if (k.k->p.inode >= QTYP_NR) {
                prt_printf(err, "invalid quota type (%llu >= %u)",
@@ -480,13 +481,13 @@ static int __bch2_quota_set(struct bch_fs *c, struct bkey_s_c k,
                }
 
                if (qdq && qdq->d_fieldmask & QC_SPC_TIMER)
-                       mq->c[Q_SPC].timer      = cpu_to_le64(qdq->d_spc_timer);
+                       mq->c[Q_SPC].timer      = qdq->d_spc_timer;
                if (qdq && qdq->d_fieldmask & QC_SPC_WARNS)
-                       mq->c[Q_SPC].warns      = cpu_to_le64(qdq->d_spc_warns);
+                       mq->c[Q_SPC].warns      = qdq->d_spc_warns;
                if (qdq && qdq->d_fieldmask & QC_INO_TIMER)
-                       mq->c[Q_INO].timer      = cpu_to_le64(qdq->d_ino_timer);
+                       mq->c[Q_INO].timer      = qdq->d_ino_timer;
                if (qdq && qdq->d_fieldmask & QC_INO_WARNS)
-                       mq->c[Q_INO].warns      = cpu_to_le64(qdq->d_ino_warns);
+                       mq->c[Q_INO].warns      = qdq->d_ino_warns;
 
                mutex_unlock(&q->lock);
        }
index b0f7d4ee775e17ae15e0177652c49d8006086558..2f463874a3628238fb62c17f341d698f4fc3f3e6 100644 (file)
@@ -5,9 +5,11 @@
 #include "inode.h"
 #include "quota_types.h"
 
+enum bkey_invalid_flags;
 extern const struct bch_sb_field_ops bch_sb_field_ops_quota;
 
-int bch2_quota_invalid(const struct bch_fs *, struct bkey_s_c, unsigned, struct printbuf *);
+int bch2_quota_invalid(const struct bch_fs *, struct bkey_s_c,
+                      enum bkey_invalid_flags, struct printbuf *);
 void bch2_quota_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
 
 #define bch2_bkey_ops_quota ((struct bkey_ops) {       \
index 09c9d4058f829d4e7395712146074ebd7cab7f3c..9b49a6bc67022ef6faa1b9d7d469350324e5088e 100644 (file)
@@ -308,7 +308,7 @@ static void bch2_journal_iter_advance(struct journal_iter *iter)
        }
 }
 
-struct bkey_s_c bch2_journal_iter_peek(struct journal_iter *iter)
+static struct bkey_s_c bch2_journal_iter_peek(struct journal_iter *iter)
 {
        struct journal_key *k = iter->keys->d + iter->idx;
 
@@ -664,7 +664,7 @@ static int bch2_journal_replay(struct bch_fs *c, u64 start_seq, u64 end_seq)
                                    BTREE_INSERT_LAZY_RW|
                                    BTREE_INSERT_NOFAIL|
                                    (!k->allocated
-                                    ? BTREE_INSERT_JOURNAL_REPLAY|JOURNAL_WATERMARK_reserved
+                                    ? BTREE_INSERT_JOURNAL_REPLAY|BCH_WATERMARK_reclaim
                                     : 0),
                             bch2_journal_replay_key(&trans, k));
                if (ret) {
@@ -702,13 +702,13 @@ static int journal_replay_entry_early(struct bch_fs *c,
        case BCH_JSET_ENTRY_btree_root: {
                struct btree_root *r;
 
-               if (entry->btree_id >= BTREE_ID_NR) {
-                       bch_err(c, "filesystem has unknown btree type %u",
-                               entry->btree_id);
-                       return -EINVAL;
+               while (entry->btree_id >= c->btree_roots_extra.nr + BTREE_ID_NR) {
+                       ret = darray_push(&c->btree_roots_extra, (struct btree_root) { NULL });
+                       if (ret)
+                               return ret;
                }
 
-               r = &c->btree_roots[entry->btree_id];
+               r = bch2_btree_id_root(c, entry->btree_id);
 
                if (entry->u64s) {
                        r->level = entry->level;
@@ -980,8 +980,8 @@ static int read_btree_roots(struct bch_fs *c)
        unsigned i;
        int ret = 0;
 
-       for (i = 0; i < BTREE_ID_NR; i++) {
-               struct btree_root *r = &c->btree_roots[i];
+       for (i = 0; i < btree_id_nr_alive(c); i++) {
+               struct btree_root *r = bch2_btree_id_root(c, i);
 
                if (!r->alive)
                        continue;
@@ -1014,7 +1014,7 @@ static int read_btree_roots(struct bch_fs *c)
        }
 
        for (i = 0; i < BTREE_ID_NR; i++) {
-               struct btree_root *r = &c->btree_roots[i];
+               struct btree_root *r = bch2_btree_id_root(c, i);
 
                if (!r->b) {
                        r->alive = false;
@@ -1042,7 +1042,7 @@ static int bch2_fs_initialize_subvolumes(struct bch_fs *c)
        root_snapshot.k.p.offset = U32_MAX;
        root_snapshot.v.flags   = 0;
        root_snapshot.v.parent  = 0;
-       root_snapshot.v.subvol  = BCACHEFS_ROOT_SUBVOL;
+       root_snapshot.v.subvol  = cpu_to_le32(BCACHEFS_ROOT_SUBVOL);
        root_snapshot.v.tree    = cpu_to_le32(1);
        SET_BCH_SNAPSHOT_SUBVOL(&root_snapshot.v, true);
 
@@ -1146,17 +1146,22 @@ int bch2_fs_recovery(struct bch_fs *c)
                goto err;
        }
 
-       if (!c->opts.nochanges) {
-               if (c->sb.version < bcachefs_metadata_required_upgrade_below) {
-                       bch_info(c, "version %s (%u) prior to %s (%u), upgrade and fsck required",
-                                bch2_metadata_versions[c->sb.version],
-                                c->sb.version,
-                                bch2_metadata_versions[bcachefs_metadata_required_upgrade_below],
-                                bcachefs_metadata_required_upgrade_below);
-                       c->opts.version_upgrade = true;
-                       c->opts.fsck            = true;
-                       c->opts.fix_errors      = FSCK_OPT_YES;
-               }
+       if (!c->opts.nochanges &&
+           c->sb.version < bcachefs_metadata_required_upgrade_below) {
+               struct printbuf buf = PRINTBUF;
+
+               prt_str(&buf, "version ");
+               bch2_version_to_text(&buf, c->sb.version);
+               prt_str(&buf, " prior to ");
+               bch2_version_to_text(&buf, bcachefs_metadata_required_upgrade_below);
+               prt_str(&buf, ", upgrade and fsck required");
+
+               bch_info(c, "%s", buf.buf);
+               printbuf_exit(&buf);
+
+               c->opts.version_upgrade = true;
+               c->opts.fsck            = true;
+               c->opts.fix_errors      = FSCK_OPT_YES;
        }
 
        if (c->opts.fsck && c->opts.norecovery) {
@@ -1463,7 +1468,7 @@ use_clean:
 
        if (!(c->sb.compat & (1ULL << BCH_COMPAT_extents_above_btree_updates_done)) ||
            !(c->sb.compat & (1ULL << BCH_COMPAT_bformat_overflow_done)) ||
-           le16_to_cpu(c->sb.version_min) < bcachefs_metadata_version_btree_ptr_sectors_written) {
+           c->sb.version_min < bcachefs_metadata_version_btree_ptr_sectors_written) {
                struct bch_move_stats stats;
 
                bch2_move_stats_init(&stats, "recovery");
index 537d84b61ac49bdff23227f59d2ae14f415771ac..08a05cc10675ad116557933d6347abdd3a6fc98f 100644 (file)
@@ -26,7 +26,8 @@ static inline unsigned bkey_type_to_indirect(const struct bkey *k)
 /* reflink pointers */
 
 int bch2_reflink_p_invalid(const struct bch_fs *c, struct bkey_s_c k,
-                          unsigned flags, struct printbuf *err)
+                          enum bkey_invalid_flags flags,
+                          struct printbuf *err)
 {
        struct bkey_s_c_reflink_p p = bkey_s_c_to_reflink_p(k);
 
@@ -72,7 +73,8 @@ bool bch2_reflink_p_merge(struct bch_fs *c, struct bkey_s _l, struct bkey_s_c _r
 /* indirect extents */
 
 int bch2_reflink_v_invalid(const struct bch_fs *c, struct bkey_s_c k,
-                          unsigned flags, struct printbuf *err)
+                          enum bkey_invalid_flags flags,
+                          struct printbuf *err)
 {
        return bch2_bkey_ptrs_invalid(c, k, flags, err);
 }
@@ -118,7 +120,8 @@ int bch2_trans_mark_reflink_v(struct btree_trans *trans,
 /* indirect inline data */
 
 int bch2_indirect_inline_data_invalid(const struct bch_fs *c, struct bkey_s_c k,
-                                     unsigned flags, struct printbuf *err)
+                                     enum bkey_invalid_flags flags,
+                                     struct printbuf *err)
 {
        return 0;
 }
index ba400188f5befeea949f69a95cefc5c876309e44..fe52538efb522940cd6cf7b853bc6d5d4afe3c94 100644 (file)
@@ -2,8 +2,10 @@
 #ifndef _BCACHEFS_REFLINK_H
 #define _BCACHEFS_REFLINK_H
 
+enum bkey_invalid_flags;
+
 int bch2_reflink_p_invalid(const struct bch_fs *, struct bkey_s_c,
-                          unsigned, struct printbuf *);
+                          enum bkey_invalid_flags, struct printbuf *);
 void bch2_reflink_p_to_text(struct printbuf *, struct bch_fs *,
                            struct bkey_s_c);
 bool bch2_reflink_p_merge(struct bch_fs *, struct bkey_s, struct bkey_s_c);
@@ -18,7 +20,7 @@ bool bch2_reflink_p_merge(struct bch_fs *, struct bkey_s, struct bkey_s_c);
 })
 
 int bch2_reflink_v_invalid(const struct bch_fs *, struct bkey_s_c,
-                          unsigned, struct printbuf *);
+                          enum bkey_invalid_flags, struct printbuf *);
 void bch2_reflink_v_to_text(struct printbuf *, struct bch_fs *,
                            struct bkey_s_c);
 int bch2_trans_mark_reflink_v(struct btree_trans *, enum btree_id, unsigned,
@@ -34,7 +36,7 @@ int bch2_trans_mark_reflink_v(struct btree_trans *, enum btree_id, unsigned,
 })
 
 int bch2_indirect_inline_data_invalid(const struct bch_fs *, struct bkey_s_c,
-                                     unsigned, struct printbuf *);
+                                     enum bkey_invalid_flags, struct printbuf *);
 void bch2_indirect_inline_data_to_text(struct printbuf *,
                                struct bch_fs *, struct bkey_s_c);
 int bch2_trans_mark_indirect_inline_data(struct btree_trans *,
index 76efbfce7683bca0c30dc53accd0049ba170810b..d4c1d43e8c418c8224387b22a9ddb1396d2ffceb 100644 (file)
@@ -36,8 +36,8 @@ static void bch2_cpu_replicas_sort(struct bch_replicas_cpu *r)
        eytzinger0_sort(r->entries, r->nr, r->entry_size, memcmp, NULL);
 }
 
-void bch2_replicas_entry_v0_to_text(struct printbuf *out,
-                                   struct bch_replicas_entry_v0 *e)
+static void bch2_replicas_entry_v0_to_text(struct printbuf *out,
+                                          struct bch_replicas_entry_v0 *e)
 {
        unsigned i;
 
@@ -272,7 +272,7 @@ static void __replicas_table_update_pcpu(struct bch_fs_usage __percpu *dst_p,
 {
        unsigned src_nr = sizeof(struct bch_fs_usage) / sizeof(u64) + src_r->nr;
        struct bch_fs_usage *dst, *src = (void *)
-               bch2_acc_percpu_u64s((void *) src_p, src_nr);
+               bch2_acc_percpu_u64s((u64 __percpu *) src_p, src_nr);
 
        preempt_disable();
        dst = this_cpu_ptr(dst_p);
index 89c7c83c50e8b704422c65c344e6bd1540bbfb81..f26397aa2b31546e68e3da0e629fcb211c46092e 100644 (file)
@@ -23,7 +23,8 @@ void bch2_snapshot_tree_to_text(struct printbuf *out, struct bch_fs *c,
 }
 
 int bch2_snapshot_tree_invalid(const struct bch_fs *c, struct bkey_s_c k,
-                              unsigned flags, struct printbuf *err)
+                              enum bkey_invalid_flags flags,
+                              struct printbuf *err)
 {
        if (bkey_gt(k.k->p, POS(0, U32_MAX)) ||
            bkey_lt(k.k->p, POS(0, 1))) {
@@ -97,7 +98,8 @@ void bch2_snapshot_to_text(struct printbuf *out, struct bch_fs *c,
 }
 
 int bch2_snapshot_invalid(const struct bch_fs *c, struct bkey_s_c k,
-                         unsigned flags, struct printbuf *err)
+                         enum bkey_invalid_flags flags,
+                         struct printbuf *err)
 {
        struct bkey_s_c_snapshot s;
        u32 i, id;
@@ -825,7 +827,7 @@ static int bch2_snapshot_node_delete(struct btree_trans *trans, u32 id)
                        goto err;
 
                if (s.v->children[0]) {
-                       s_t->v.root_snapshot = cpu_to_le32(s.v->children[0]);
+                       s_t->v.root_snapshot = s.v->children[0];
                } else {
                        s_t->k.type = KEY_TYPE_deleted;
                        set_bkey_val_u64s(&s_t->k, 0);
@@ -1328,7 +1330,7 @@ static int bch2_subvolume_delete(struct btree_trans *trans, u32 subvolid)
                          __bch2_subvolume_delete(trans, subvolid));
 }
 
-void bch2_subvolume_wait_for_pagecache_and_delete(struct work_struct *work)
+static void bch2_subvolume_wait_for_pagecache_and_delete(struct work_struct *work)
 {
        struct bch_fs *c = container_of(work, struct bch_fs,
                                snapshot_wait_for_pagecache_and_delete_work);
@@ -1366,7 +1368,7 @@ struct subvolume_unlink_hook {
        u32                             subvol;
 };
 
-int bch2_subvolume_wait_for_pagecache_and_delete_hook(struct btree_trans *trans,
+static int bch2_subvolume_wait_for_pagecache_and_delete_hook(struct btree_trans *trans,
                                                      struct btree_trans_commit_hook *_h)
 {
        struct subvolume_unlink_hook *h = container_of(_h, struct subvolume_unlink_hook, h);
index 1a39f713db87c8731778d297f045a946c6835904..105410e080e059ee73328ad9bc849f3a1973ea6b 100644 (file)
@@ -5,9 +5,11 @@
 #include "darray.h"
 #include "subvolume_types.h"
 
+enum bkey_invalid_flags;
+
 void bch2_snapshot_tree_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
 int bch2_snapshot_tree_invalid(const struct bch_fs *, struct bkey_s_c,
-                              unsigned, struct printbuf *);
+                              enum bkey_invalid_flags, struct printbuf *);
 
 #define bch2_bkey_ops_snapshot_tree ((struct bkey_ops) {       \
        .key_invalid    = bch2_snapshot_tree_invalid,           \
@@ -19,7 +21,7 @@ int bch2_snapshot_tree_lookup(struct btree_trans *, u32, struct bch_snapshot_tre
 
 void bch2_snapshot_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
 int bch2_snapshot_invalid(const struct bch_fs *, struct bkey_s_c,
-                         unsigned, struct printbuf *);
+                         enum bkey_invalid_flags, struct printbuf *);
 int bch2_mark_snapshot(struct btree_trans *, enum btree_id, unsigned,
                       struct bkey_s_c, struct bkey_s_c, unsigned);
 
index e5636c32f2058cae918a8981f38f831611621dba..472f5b216c654c184922aafba5f786145ca44170 100644 (file)
 #include <linux/backing-dev.h>
 #include <linux/sort.h>
 
+static const char * const bch2_metadata_versions[] = {
+#define x(t, n) [n] = #t,
+       BCH_METADATA_VERSIONS()
+#undef x
+};
+
+void bch2_version_to_text(struct printbuf *out, unsigned v)
+{
+       const char *str = v < ARRAY_SIZE(bch2_metadata_versions)
+               ? bch2_metadata_versions[v]
+               : "(unknown version)";
+
+       prt_printf(out, "%u: %s", v, str);
+}
+
 const char * const bch2_sb_fields[] = {
 #define x(name, nr)    #name,
        BCH_SB_FIELDS()
@@ -250,40 +265,58 @@ static int validate_sb_layout(struct bch_sb_layout *layout, struct printbuf *out
        return 0;
 }
 
-static int bch2_sb_validate(struct bch_sb_handle *disk_sb, struct printbuf *out,
-                           int rw)
+static int bch2_sb_compatible(struct bch_sb *sb, struct printbuf *out)
 {
-       struct bch_sb *sb = disk_sb->sb;
-       struct bch_sb_field *f;
-       struct bch_sb_field_members *mi;
-       enum bch_opt_id opt_id;
-       u32 version, version_min;
-       u16 block_size;
-       int ret;
-
-       version         = le16_to_cpu(sb->version);
-       version_min     = version >= bcachefs_metadata_version_bkey_renumber
-               ? le16_to_cpu(sb->version_min)
-               : version;
-
-       if (version    >= bcachefs_metadata_version_max) {
-               prt_printf(out, "Unsupported superblock version %u (min %u, max %u)",
-                      version, bcachefs_metadata_version_min, bcachefs_metadata_version_max);
+       u16 version             = le16_to_cpu(sb->version);
+       u16 version_min         = le16_to_cpu(sb->version_min);
+
+       if (!bch2_version_compatible(version)) {
+               prt_str(out, "Unsupported superblock version ");
+               bch2_version_to_text(out, version);
+               prt_str(out, " (min ");
+               bch2_version_to_text(out, bcachefs_metadata_version_min);
+               prt_str(out, ", max ");
+               bch2_version_to_text(out, bcachefs_metadata_version_current);
+               prt_str(out, ")");
                return -BCH_ERR_invalid_sb_version;
        }
 
-       if (version_min < bcachefs_metadata_version_min) {
-               prt_printf(out, "Unsupported superblock version %u (min %u, max %u)",
-                      version_min, bcachefs_metadata_version_min, bcachefs_metadata_version_max);
+       if (!bch2_version_compatible(version_min)) {
+               prt_str(out, "Unsupported superblock version_min ");
+               bch2_version_to_text(out, version_min);
+               prt_str(out, " (min ");
+               bch2_version_to_text(out, bcachefs_metadata_version_min);
+               prt_str(out, ", max ");
+               bch2_version_to_text(out, bcachefs_metadata_version_current);
+               prt_str(out, ")");
                return -BCH_ERR_invalid_sb_version;
        }
 
        if (version_min > version) {
-               prt_printf(out, "Bad minimum version %u, greater than version field %u",
-                      version_min, version);
+               prt_str(out, "Bad minimum version ");
+               bch2_version_to_text(out, version_min);
+               prt_str(out, ", greater than version field ");
+               bch2_version_to_text(out, version);
                return -BCH_ERR_invalid_sb_version;
        }
 
+       return 0;
+}
+
+static int bch2_sb_validate(struct bch_sb_handle *disk_sb, struct printbuf *out,
+                           int rw)
+{
+       struct bch_sb *sb = disk_sb->sb;
+       struct bch_sb_field *f;
+       struct bch_sb_field_members *mi;
+       enum bch_opt_id opt_id;
+       u16 block_size;
+       int ret;
+
+       ret = bch2_sb_compatible(sb, out);
+       if (ret)
+               return ret;
+
        if (sb->features[1] ||
            (le64_to_cpu(sb->features[0]) & (~0ULL << BCH_FEATURE_NR))) {
                prt_printf(out, "Filesystem has incompatible features");
@@ -331,7 +364,7 @@ static int bch2_sb_validate(struct bch_sb_handle *disk_sb, struct printbuf *out,
        if (rw == READ) {
                /*
                 * Been seeing a bug where these are getting inexplicably
-                * zeroed, so we'r now validating them, but we have to be
+                * zeroed, so we're now validating them, but we have to be
                 * careful not to preven people's filesystems from mounting:
                 */
                if (!BCH_SB_JOURNAL_FLUSH_DELAY(sb))
@@ -512,7 +545,6 @@ int bch2_sb_from_fs(struct bch_fs *c, struct bch_dev *ca)
 static int read_one_super(struct bch_sb_handle *sb, u64 offset, struct printbuf *err)
 {
        struct bch_csum csum;
-       u32 version, version_min;
        size_t bytes;
        int ret;
 reread:
@@ -532,22 +564,9 @@ reread:
                return -BCH_ERR_invalid_sb_magic;
        }
 
-       version         = le16_to_cpu(sb->sb->version);
-       version_min     = version >= bcachefs_metadata_version_bkey_renumber
-               ? le16_to_cpu(sb->sb->version_min)
-               : version;
-
-       if (version    >= bcachefs_metadata_version_max) {
-               prt_printf(err, "Unsupported superblock version %u (min %u, max %u)",
-                      version, bcachefs_metadata_version_min, bcachefs_metadata_version_max);
-               return -BCH_ERR_invalid_sb_version;
-       }
-
-       if (version_min < bcachefs_metadata_version_min) {
-               prt_printf(err, "Unsupported superblock version %u (min %u, max %u)",
-                      version_min, bcachefs_metadata_version_min, bcachefs_metadata_version_max);
-               return -BCH_ERR_invalid_sb_version;
-       }
+       ret = bch2_sb_compatible(sb->sb, err);
+       if (ret)
+               return ret;
 
        bytes = vstruct_bytes(sb->sb);
 
@@ -1389,21 +1408,29 @@ static const struct bch_sb_field_ops *bch2_sb_field_ops[] = {
 #undef x
 };
 
+static const struct bch_sb_field_ops bch2_sb_field_null_ops = {
+       NULL
+};
+
+static const struct bch_sb_field_ops *bch2_sb_field_type_ops(unsigned type)
+{
+       return likely(type < ARRAY_SIZE(bch2_sb_field_ops))
+               ? bch2_sb_field_ops[type]
+               : &bch2_sb_field_null_ops;
+}
+
 static int bch2_sb_field_validate(struct bch_sb *sb, struct bch_sb_field *f,
                                  struct printbuf *err)
 {
        unsigned type = le32_to_cpu(f->type);
        struct printbuf field_err = PRINTBUF;
+       const struct bch_sb_field_ops *ops = bch2_sb_field_type_ops(type);
        int ret;
 
-       if (type >= BCH_SB_FIELD_NR)
-               return 0;
-
-       ret = bch2_sb_field_ops[type]->validate(sb, f, &field_err);
+       ret = ops->validate ? ops->validate(sb, f, &field_err) : 0;
        if (ret) {
                prt_printf(err, "Invalid superblock section %s: %s",
-                      bch2_sb_fields[type],
-                      field_err.buf);
+                          bch2_sb_fields[type], field_err.buf);
                prt_newline(err);
                bch2_sb_field_to_text(err, sb, f);
        }
@@ -1416,13 +1443,12 @@ void bch2_sb_field_to_text(struct printbuf *out, struct bch_sb *sb,
                           struct bch_sb_field *f)
 {
        unsigned type = le32_to_cpu(f->type);
-       const struct bch_sb_field_ops *ops = type < BCH_SB_FIELD_NR
-               ? bch2_sb_field_ops[type] : NULL;
+       const struct bch_sb_field_ops *ops = bch2_sb_field_type_ops(type);
 
        if (!out->nr_tabstops)
                printbuf_tabstop_push(out, 32);
 
-       if (ops)
+       if (type < BCH_SB_FIELD_NR)
                prt_printf(out, "%s", bch2_sb_fields[type]);
        else
                prt_printf(out, "(unknown field %u)", type);
@@ -1430,9 +1456,9 @@ void bch2_sb_field_to_text(struct printbuf *out, struct bch_sb *sb,
        prt_printf(out, " (size %zu):", vstruct_bytes(f));
        prt_newline(out);
 
-       if (ops && ops->to_text) {
+       if (ops->to_text) {
                printbuf_indent_add(out, 2);
-               bch2_sb_field_ops[type]->to_text(out, sb, f);
+               ops->to_text(out, sb, f);
                printbuf_indent_sub(out, 2);
        }
 }
@@ -1503,12 +1529,12 @@ void bch2_sb_to_text(struct printbuf *out, struct bch_sb *sb,
 
        prt_str(out, "Version:");
        prt_tab(out);
-       prt_printf(out, "%s", bch2_metadata_versions[le16_to_cpu(sb->version)]);
+       bch2_version_to_text(out, le16_to_cpu(sb->version));
        prt_newline(out);
 
        prt_printf(out, "Oldest version on disk:");
        prt_tab(out);
-       prt_printf(out, "%s", bch2_metadata_versions[le16_to_cpu(sb->version_min)]);
+       bch2_version_to_text(out, le16_to_cpu(sb->version_min));
        prt_newline(out);
 
        prt_printf(out, "Created:");
index ab0ad3248e8fad4bbd63bc1ff811814b0d01bd9d..cda71ec845a526132a08d0d03894b1c3e31ccb94 100644 (file)
@@ -9,6 +9,14 @@
 
 #include <asm/byteorder.h>
 
+static inline bool bch2_version_compatible(u16 version)
+{
+       return version <= bcachefs_metadata_version_current &&
+               version >= bcachefs_metadata_version_min;
+}
+
+void bch2_version_to_text(struct printbuf *, unsigned);
+
 struct bch_sb_field *bch2_sb_field_get(struct bch_sb *, enum bch_sb_field_type);
 struct bch_sb_field *bch2_sb_field_resize(struct bch_sb_handle *,
                                          enum bch_sb_field_type, unsigned);
index 99b7670511c44ad00dc51aeddebd3c12bb46fc7c..6fa805cb4bc51cb08147fd90d477e54e9b30d53f 100644 (file)
@@ -485,6 +485,7 @@ static void __bch2_fs_free(struct bch_fs *c)
                for_each_possible_cpu(cpu)
                        kfree(per_cpu_ptr(c->btree_paths_bufs, cpu)->path);
 
+       darray_exit(&c->btree_roots_extra);
        free_percpu(c->btree_paths_bufs);
        free_percpu(c->pcpu);
        mempool_exit(&c->large_bkey_pool);
@@ -560,9 +561,12 @@ void __bch2_fs_stop(struct bch_fs *c)
 
        cancel_work_sync(&c->read_only_work);
 
-       for (i = 0; i < c->sb.nr_devices; i++)
-               if (c->devs[i])
-                       bch2_free_super(&c->devs[i]->disk_sb);
+       for (i = 0; i < c->sb.nr_devices; i++) {
+               struct bch_dev *ca = rcu_dereference_protected(c->devs[i], true);
+
+               if (ca)
+                       bch2_free_super(&ca->disk_sb);
+       }
 }
 
 void bch2_fs_free(struct bch_fs *c)
@@ -685,6 +689,7 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts)
 
        bch2_fs_copygc_init(c);
        bch2_fs_btree_key_cache_init_early(&c->btree_key_cache);
+       bch2_fs_btree_interior_update_init_early(c);
        bch2_fs_allocator_background_init(c);
        bch2_fs_allocator_foreground_init(c);
        bch2_fs_rebalance_init(c);
@@ -751,11 +756,11 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts)
                goto err;
 
        /* Compat: */
-       if (sb->version <= bcachefs_metadata_version_inode_v2 &&
+       if (le16_to_cpu(sb->version) <= bcachefs_metadata_version_inode_v2 &&
            !BCH_SB_JOURNAL_FLUSH_DELAY(sb))
                SET_BCH_SB_JOURNAL_FLUSH_DELAY(sb, 1000);
 
-       if (sb->version <= bcachefs_metadata_version_inode_v2 &&
+       if (le16_to_cpu(sb->version) <= bcachefs_metadata_version_inode_v2 &&
            !BCH_SB_JOURNAL_RECLAIM_DELAY(sb))
                SET_BCH_SB_JOURNAL_RECLAIM_DELAY(sb, 100);
 
@@ -875,7 +880,8 @@ static void print_mount_opts(struct bch_fs *c)
        struct printbuf p = PRINTBUF;
        bool first = true;
 
-       prt_printf(&p, "mounted version=%s", bch2_metadata_versions[c->sb.version]);
+       prt_str(&p, "mounted version ");
+       bch2_version_to_text(&p, c->sb.version);
 
        if (c->opts.read_only) {
                prt_str(&p, " opts=");
@@ -1520,6 +1526,17 @@ int bch2_dev_remove(struct bch_fs *c, struct bch_dev *ca, int flags)
 
        bch2_dev_free(ca);
 
+       /*
+        * At this point the device object has been removed in-core, but the
+        * on-disk journal might still refer to the device index via sb device
+        * usage entries. Recovery fails if it sees usage information for an
+        * invalid device. Flush journal pins to push the back of the journal
+        * past now invalid device index references before we update the
+        * superblock, but after the device object has been removed so any
+        * further journal writes elide usage info for the device.
+        */
+       bch2_journal_flush_all_pins(&c->journal);
+
        /*
         * Free this device's slot in the bch_member array - all pointers to
         * this device must be gone:
@@ -1986,7 +2003,7 @@ err:
 BCH_DEBUG_PARAMS()
 #undef BCH_DEBUG_PARAM
 
-unsigned bch2_metadata_version = bcachefs_metadata_version_current;
+static unsigned bch2_metadata_version = bcachefs_metadata_version_current;
 module_param_named(version, bch2_metadata_version, uint, 0400);
 
 module_exit(bcachefs_exit);
index 3145a0ad63bbd025fb907cec12a51b3fda05dc45..740305e67bdb30291cddb6c61df3687bd618f608 100644 (file)
@@ -202,7 +202,7 @@ read_attribute(nocow_lock_table);
 #ifdef BCH_WRITE_REF_DEBUG
 read_attribute(write_refs);
 
-const char * const bch2_write_refs[] = {
+static const char * const bch2_write_refs[] = {
 #define x(n)   #n,
        BCH_WRITE_REFS()
 #undef x
index 50d69a5634bd4c42ff2bcdaffccddc24680f2736..cef23d2ccc5ffec62b9e711679644228ff7cdbc0 100644 (file)
@@ -444,7 +444,7 @@ static int test_peek_end_extents(struct bch_fs *c, u64 nr)
 
 /* extent unit tests */
 
-u64 test_version;
+static u64 test_version;
 
 static int insert_test_extent(struct bch_fs *c,
                              u64 start, u64 end)
index 5143b603bf67ff397181e70a9705cfa100237fbf..ef030fc0244807ee10064a9dab5d83fd9791f45f 100644 (file)
@@ -22,12 +22,13 @@ int bch2_varint_encode(u8 *out, u64 v)
 {
        unsigned bits = fls64(v|1);
        unsigned bytes = DIV_ROUND_UP(bits, 7);
+       __le64 v_le;
 
        if (likely(bytes < 9)) {
                v <<= bytes;
                v |= ~(~0 << (bytes - 1));
-               v = cpu_to_le64(v);
-               memcpy(out, &v, bytes);
+               v_le = cpu_to_le64(v);
+               memcpy(out, &v_le, bytes);
        } else {
                *out++ = 255;
                bytes = 9;
@@ -57,9 +58,9 @@ int bch2_varint_decode(const u8 *in, const u8 *end, u64 *out)
                return -1;
 
        if (likely(bytes < 9)) {
-               v = 0;
-               memcpy(&v, in, bytes);
-               v = le64_to_cpu(v);
+               __le64 v_le = 0;
+               memcpy(&v_le, in, bytes);
+               v = le64_to_cpu(v_le);
                v >>= bytes;
        } else {
                v = get_unaligned_le64(++in);
index 05c65d94c00fc03090520290037689cff83f0d86..867cc68782483c86d0b6e9a578903f529ce6dd4e 100644 (file)
@@ -70,7 +70,8 @@ const struct bch_hash_desc bch2_xattr_hash_desc = {
 };
 
 int bch2_xattr_invalid(const struct bch_fs *c, struct bkey_s_c k,
-                      unsigned flags, struct printbuf *err)
+                      enum bkey_invalid_flags flags,
+                      struct printbuf *err)
 {
        const struct xattr_handler *handler;
        struct bkey_s_c_xattr xattr = bkey_s_c_to_xattr(k);
@@ -135,15 +136,14 @@ static int bch2_xattr_get_trans(struct btree_trans *trans, struct bch_inode_info
                                const char *name, void *buffer, size_t size, int type)
 {
        struct bch_hash_info hash = bch2_hash_info_init(trans->c, &inode->ei_inode);
+       struct xattr_search_key search = X_SEARCH(type, name, strlen(name));
        struct btree_iter iter;
        struct bkey_s_c_xattr xattr;
        struct bkey_s_c k;
        int ret;
 
        ret = bch2_hash_lookup(trans, &iter, bch2_xattr_hash_desc, &hash,
-                              inode_inum(inode),
-                              &X_SEARCH(type, name, strlen(name)),
-                              0);
+                              inode_inum(inode), &search, 0);
        if (ret)
                goto err1;
 
index b3e16729bcbba472f15302a3c3bb0b560330c8ce..214cbbaac3045d92da690d7fa18c6489183a702c 100644 (file)
@@ -6,7 +6,8 @@
 
 extern const struct bch_hash_desc bch2_xattr_hash_desc;
 
-int bch2_xattr_invalid(const struct bch_fs *, struct bkey_s_c, unsigned, struct printbuf *);
+int bch2_xattr_invalid(const struct bch_fs *, struct bkey_s_c,
+                      enum bkey_invalid_flags, struct printbuf *);
 void bch2_xattr_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
 
 #define bch2_bkey_ops_xattr ((struct bkey_ops) {       \