]> git.sesse.net Git - bcachefs-tools-debian/commitdiff
Update bcachefs sources to a180af9dd349 bcachefs: Refactor memcpy into direct assignment
authorKent Overstreet <kent.overstreet@linux.dev>
Thu, 19 Oct 2023 01:57:11 +0000 (21:57 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Thu, 19 Oct 2023 02:14:53 +0000 (22:14 -0400)
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
30 files changed:
.bcachefs_revision
cmd_format.c
cmd_key.c
crypto.c
include/linux/compiler.h
libbcachefs.c
libbcachefs/alloc_background.c
libbcachefs/bcachefs.h
libbcachefs/bkey_methods.c
libbcachefs/buckets.c
libbcachefs/checksum.c
libbcachefs/counters.c
libbcachefs/disk_groups.c
libbcachefs/extents.h
libbcachefs/fs-ioctl.c
libbcachefs/io_misc.c
libbcachefs/journal.c
libbcachefs/journal_sb.c
libbcachefs/journal_seq_blacklist.c
libbcachefs/quota.c
libbcachefs/recovery.c
libbcachefs/replicas.c
libbcachefs/sb-clean.c
libbcachefs/sb-members.c
libbcachefs/snapshot.c
libbcachefs/super-io.c
libbcachefs/super-io.h
libbcachefs/super.c
libbcachefs/super_types.h
rust-src/bch_bindgen/src/bcachefs.rs

index 48318a75845f5c80befb6910a8aa87e65d2b00fb..6f98bb843d8120802ddd579fa0efe74731a343cf 100644 (file)
@@ -1 +1 @@
-7bf1ac0d46ebede68561e0476f7af9c07ac21de8
+a180af9dd349d9819b13af43f877bea4f94c1c79
index 42f3fc6ca4ac822422906a1505a20ff7c6a571ce..954d40fec72e370c395b533019db84f52c64a656 100644 (file)
@@ -348,7 +348,7 @@ int cmd_show_super(int argc, char *argv[])
                die("Error opening %s: %s", dev, bch2_err_str(ret));
 
        if (print_default_fields)
-               fields = bch2_sb_get_members_v2(sb.sb)
+               fields = bch2_sb_field_get(sb.sb, members_v2)
                        ? 1 << BCH_SB_FIELD_members_v2
                        : 1 << BCH_SB_FIELD_members_v1;
 
index d3e5d7bdb7b2a5bbd9aeca78710f799158adcbf3..96206c4c36b5a62cce4cc27fd445a383bdfa87df 100644 (file)
--- a/cmd_key.c
+++ b/cmd_key.c
@@ -92,7 +92,7 @@ int cmd_set_passphrase(int argc, char *argv[])
        if (IS_ERR(c))
                die("Error opening %s: %s", argv[1], bch2_err_str(PTR_ERR(c)));
 
-       struct bch_sb_field_crypt *crypt = bch2_sb_get_crypt(c->disk_sb.sb);
+       struct bch_sb_field_crypt *crypt = bch2_sb_field_get(c->disk_sb.sb, crypt);
        if (!crypt)
                die("Filesystem does not have encryption enabled");
 
@@ -130,7 +130,7 @@ int cmd_remove_passphrase(int argc, char *argv[])
        if (IS_ERR(c))
                die("Error opening %s: %s", argv[1], bch2_err_str(PTR_ERR(c)));
 
-       struct bch_sb_field_crypt *crypt = bch2_sb_get_crypt(c->disk_sb.sb);
+       struct bch_sb_field_crypt *crypt = bch2_sb_field_get(c->disk_sb.sb, crypt);
        if (!crypt)
                die("Filesystem does not have encryption enabled");
 
index 4e4d15a90fe90d7fdbf051cd122c85353c162f69..32671bd84c332e90deb0510743443faf41df6c45 100644 (file)
--- a/crypto.c
+++ b/crypto.c
@@ -105,7 +105,7 @@ bool bch2_sb_is_encrypted(struct bch_sb *sb)
 {
        struct bch_sb_field_crypt *crypt;
 
-       return (crypt = bch2_sb_get_crypt(sb)) &&
+       return (crypt = bch2_sb_field_get(sb, crypt)) &&
                bch2_key_is_encrypted(&crypt->key);
 }
 
@@ -113,7 +113,7 @@ void bch2_passphrase_check(struct bch_sb *sb, const char *passphrase,
                           struct bch_key *passphrase_key,
                           struct bch_encrypted_key *sb_key)
 {
-       struct bch_sb_field_crypt *crypt = bch2_sb_get_crypt(sb);
+       struct bch_sb_field_crypt *crypt = bch2_sb_field_get(sb, crypt);
        if (!crypt)
                die("filesystem is not encrypted");
 
index b9486dbe38a24708eeb4159b0cf61c3f1f76ccd6..61beee94871f065bef3157ab36bd668508a8c290 100644 (file)
@@ -66,6 +66,7 @@
 #define __same_type(a, b)      __builtin_types_compatible_p(typeof(a), typeof(b))
 #define fallthrough            __attribute__((__fallthrough__))
 #define __noreturn             __attribute__((__noreturn__))
+#define __counted_by(nr)
 
 #define ___PASTE(a,b) a##b
 #define __PASTE(a,b) ___PASTE(a,b)
index 499badb1429c997922df27ab3849839edc0c0062..577ccac170a78c4a13fdcef7b07920af18c1dbf8 100644 (file)
@@ -221,7 +221,7 @@ struct bch_sb *bch2_format(struct bch_opt_strs      fs_opt_strs,
 
        /* Member info: */
        struct bch_sb_field_members_v2 *mi =
-               bch2_sb_resize_members_v2(&sb,
+               bch2_sb_field_resize(&sb, members_v2,
                        (sizeof(*mi) + sizeof(struct bch_member) *
                        nr_devs) / sizeof(u64));
        mi->member_bytes = cpu_to_le16(sizeof(struct bch_member));
@@ -270,7 +270,7 @@ struct bch_sb *bch2_format(struct bch_opt_strs      fs_opt_strs,
        /* Crypt: */
        if (opts.encrypted) {
                struct bch_sb_field_crypt *crypt =
-                       bch2_sb_resize_crypt(&sb, sizeof(*crypt) / sizeof(u64));
+                       bch2_sb_field_resize(&sb, crypt, sizeof(*crypt) / sizeof(u64));
 
                bch_sb_crypt_init(sb.sb, crypt, opts.passphrase);
                SET_BCH_SB_ENCRYPTION_TYPE(sb.sb, 1);
index d1c323fd3f0bb619bc40d7c8696be2257f790d59..2d516207e223f097d75c056288620297bfcbedb6 100644 (file)
@@ -1839,7 +1839,7 @@ int bch2_dev_freespace_init(struct bch_fs *c, struct bch_dev *ca,
        struct bkey_s_c k;
        struct bkey hole;
        struct bpos end = POS(ca->dev_idx, bucket_end);
-       struct bch_member m;
+       struct bch_member *m;
        unsigned long last_updated = jiffies;
        int ret;
 
@@ -1926,8 +1926,8 @@ bkey_err:
        }
 
        mutex_lock(&c->sb_lock);
-       m = bch2_sb_member_get(c->disk_sb.sb, ca->dev_idx);
-       SET_BCH_MEMBER_FREESPACE_INITIALIZED(&m, true);
+       m = bch2_members_v2_get_mut(c->disk_sb.sb, ca->dev_idx);
+       SET_BCH_MEMBER_FREESPACE_INITIALIZED(m, true);
        mutex_unlock(&c->sb_lock);
 
        return 0;
index e9d07f9fa1c0e8f8a1e624fdd42e4ab2a0e2cd19..53ffa88cae16cab4e883459dae1fb61424b3b7ec 100644 (file)
@@ -746,6 +746,7 @@ struct bch_fs {
        struct snapshot_table __rcu *snapshots;
        size_t                  snapshot_table_size;
        struct mutex            snapshot_table_lock;
+       struct rw_semaphore     snapshot_create_lock;
 
        struct work_struct      snapshot_delete_work;
        struct work_struct      snapshot_wait_for_pagecache_and_delete_work;
index be9f012fc7be5fc5898de53b4466eb55c6de1cd2..d9fb1fc81f1e17fb45dedf76349177a0abc9f22a 100644 (file)
@@ -121,7 +121,6 @@ const struct bkey_ops bch2_bkey_ops[] = {
 };
 
 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,
index 46b6406d772b2216e686b6df1a7c772aab0bebdf..a1a4b5feadaa2cf36fc3b0657241efc464b6faab 100644 (file)
@@ -473,8 +473,9 @@ static inline int update_replicas_list(struct btree_trans *trans,
        d = trans->fs_usage_deltas;
        n = (void *) d->d + d->used;
        n->delta = sectors;
-       memcpy((void *) n + offsetof(struct replicas_delta, r),
-              r, replicas_entry_bytes(r));
+       unsafe_memcpy((void *) n + offsetof(struct replicas_delta, r),
+                     r, replicas_entry_bytes(r),
+                     "flexible array member embedded in strcuct with padding");
        bch2_replicas_entry_sort(&n->r);
        d->used += b;
        return 0;
index 839f00dce50f61bcbb1803a66fc594e620de1437..3c761ad6b1c8ef1fef8781dc10f393ccfee9997e 100644 (file)
@@ -678,7 +678,7 @@ int bch2_disable_encryption(struct bch_fs *c)
 
        mutex_lock(&c->sb_lock);
 
-       crypt = bch2_sb_get_crypt(c->disk_sb.sb);
+       crypt = bch2_sb_field_get(c->disk_sb.sb, crypt);
        if (!crypt)
                goto out;
 
@@ -712,7 +712,7 @@ int bch2_enable_encryption(struct bch_fs *c, bool keyed)
        mutex_lock(&c->sb_lock);
 
        /* Do we already have an encryption key? */
-       if (bch2_sb_get_crypt(c->disk_sb.sb))
+       if (bch2_sb_field_get(c->disk_sb.sb, crypt))
                goto err;
 
        ret = bch2_alloc_ciphers(c);
@@ -740,7 +740,8 @@ int bch2_enable_encryption(struct bch_fs *c, bool keyed)
        if (ret)
                goto err;
 
-       crypt = bch2_sb_resize_crypt(&c->disk_sb, sizeof(*crypt) / sizeof(u64));
+       crypt = bch2_sb_field_resize(&c->disk_sb, crypt,
+                                    sizeof(*crypt) / sizeof(u64));
        if (!crypt) {
                ret = -BCH_ERR_ENOSPC_sb_crypt;
                goto err;
@@ -781,7 +782,7 @@ int bch2_fs_encryption_init(struct bch_fs *c)
                goto out;
        }
 
-       crypt = bch2_sb_get_crypt(c->disk_sb.sb);
+       crypt = bch2_sb_field_get(c->disk_sb.sb, crypt);
        if (!crypt)
                goto out;
 
index 26eb3d82b1cb98977224ca67d24b4f213360796b..02a996e06a64e3d10483f7fcbffc0de66428f9ed 100644 (file)
@@ -48,7 +48,7 @@ static void bch2_sb_counters_to_text(struct printbuf *out, struct bch_sb *sb,
 
 int bch2_sb_counters_to_cpu(struct bch_fs *c)
 {
-       struct bch_sb_field_counters *ctrs = bch2_sb_get_counters(c->disk_sb.sb);
+       struct bch_sb_field_counters *ctrs = bch2_sb_field_get(c->disk_sb.sb, counters);
        unsigned int i;
        unsigned int nr = bch2_sb_counter_nr_entries(ctrs);
        u64 val = 0;
@@ -66,13 +66,13 @@ int bch2_sb_counters_to_cpu(struct bch_fs *c)
 
 int bch2_sb_counters_from_cpu(struct bch_fs *c)
 {
-       struct bch_sb_field_counters *ctrs = bch2_sb_get_counters(c->disk_sb.sb);
+       struct bch_sb_field_counters *ctrs = bch2_sb_field_get(c->disk_sb.sb, counters);
        struct bch_sb_field_counters *ret;
        unsigned int i;
        unsigned int nr = bch2_sb_counter_nr_entries(ctrs);
 
        if (nr < BCH_COUNTER_NR) {
-               ret = bch2_sb_resize_counters(&c->disk_sb,
+               ret = bch2_sb_field_resize(&c->disk_sb, counters,
                                               sizeof(*ctrs) / sizeof(u64) + BCH_COUNTER_NR);
 
                if (ret) {
index 43aad8ba8cc970794dc57a2b548b279667923615..e00133b6ea517be6a6544973532e0c299e7371b5 100644 (file)
@@ -157,14 +157,13 @@ int bch2_sb_disk_groups_to_cpu(struct bch_fs *c)
 
        lockdep_assert_held(&c->sb_lock);
 
-       groups          = bch2_sb_get_disk_groups(c->disk_sb.sb);
+       groups          = bch2_sb_field_get(c->disk_sb.sb, disk_groups);
        nr_groups       = disk_groups_nr(groups);
 
        if (!groups)
                return 0;
 
-       cpu_g = kzalloc(sizeof(*cpu_g) +
-                       sizeof(cpu_g->entries[0]) * nr_groups, GFP_KERNEL);
+       cpu_g = kzalloc(struct_size(cpu_g, entries, nr_groups), GFP_KERNEL);
        if (!cpu_g)
                return -BCH_ERR_ENOMEM_disk_groups_to_cpu;
 
@@ -296,7 +295,7 @@ static int __bch2_disk_group_add(struct bch_sb_handle *sb, unsigned parent,
                                 const char *name, unsigned namelen)
 {
        struct bch_sb_field_disk_groups *groups =
-               bch2_sb_get_disk_groups(sb->sb);
+               bch2_sb_field_get(sb->sb, disk_groups);
        unsigned i, nr_groups = disk_groups_nr(groups);
        struct bch_disk_group *g;
 
@@ -314,7 +313,7 @@ static int __bch2_disk_group_add(struct bch_sb_handle *sb, unsigned parent,
                         sizeof(struct bch_disk_group) * (nr_groups + 1)) /
                        sizeof(u64);
 
-               groups = bch2_sb_resize_disk_groups(sb, u64s);
+               groups = bch2_sb_field_resize(sb, disk_groups, u64s);
                if (!groups)
                        return -BCH_ERR_ENOSPC_disk_label_add;
 
@@ -338,7 +337,7 @@ static int __bch2_disk_group_add(struct bch_sb_handle *sb, unsigned parent,
 int bch2_disk_path_find(struct bch_sb_handle *sb, const char *name)
 {
        struct bch_sb_field_disk_groups *groups =
-               bch2_sb_get_disk_groups(sb->sb);
+               bch2_sb_field_get(sb->sb, disk_groups);
        int v = -1;
 
        do {
@@ -368,7 +367,7 @@ int bch2_disk_path_find_or_create(struct bch_sb_handle *sb, const char *name)
                if (*next == '.')
                        next++;
 
-               groups = bch2_sb_get_disk_groups(sb->sb);
+               groups = bch2_sb_field_get(sb->sb, disk_groups);
 
                v = __bch2_disk_group_find(groups, parent, name, len);
                if (v < 0)
@@ -386,7 +385,7 @@ int bch2_disk_path_find_or_create(struct bch_sb_handle *sb, const char *name)
 void bch2_disk_path_to_text(struct printbuf *out, struct bch_sb *sb, unsigned v)
 {
        struct bch_sb_field_disk_groups *groups =
-               bch2_sb_get_disk_groups(sb);
+               bch2_sb_field_get(sb, disk_groups);
        struct bch_disk_group *g;
        unsigned nr = 0;
        u16 path[32];
index 7ee8d031bb6c50c809114107dbf79c7aadc17bf7..879e7d218b6a4baf58b7a567266d1941f72de1fe 100644 (file)
@@ -520,6 +520,7 @@ static inline bool bkey_extent_is_allocation(const struct bkey *k)
        case KEY_TYPE_reflink_v:
        case KEY_TYPE_inline_data:
        case KEY_TYPE_indirect_inline_data:
+       case KEY_TYPE_error:
                return true;
        default:
                return false;
@@ -632,6 +633,8 @@ void bch2_bkey_extent_entry_drop(struct bkey_i *, union bch_extent_entry *);
 
 static inline void bch2_bkey_append_ptr(struct bkey_i *k, struct bch_extent_ptr ptr)
 {
+       struct bch_extent_ptr *dest;
+
        EBUG_ON(bch2_bkey_has_device(bkey_i_to_s(k), ptr.dev));
 
        switch (k->k.type) {
@@ -641,10 +644,8 @@ static inline void bch2_bkey_append_ptr(struct bkey_i *k, struct bch_extent_ptr
                EBUG_ON(bkey_val_u64s(&k->k) >= BKEY_EXTENT_VAL_U64s_MAX);
 
                ptr.type = 1 << BCH_EXTENT_ENTRY_ptr;
-
-               memcpy((void *) &k->v + bkey_val_bytes(&k->k),
-                      &ptr,
-                      sizeof(ptr));
+               dest = (struct bch_extent_ptr *)((void *) &k->v + bkey_val_bytes(&k->k));
+               *dest = ptr;
                k->k.u64s++;
                break;
        default:
index 0679b2f79fd6fdca71b820bac339f4bb4ffe2b3a..6040bd3f077819b41accbc08ac37fa5928d0592d 100644 (file)
@@ -318,8 +318,8 @@ err:
        return ret;
 }
 
-static long bch2_ioctl_subvolume_create(struct bch_fs *c, struct file *filp,
-                               struct bch_ioctl_subvolume arg)
+static long __bch2_ioctl_subvolume_create(struct bch_fs *c, struct file *filp,
+                                         struct bch_ioctl_subvolume arg)
 {
        struct inode *dir;
        struct bch_inode_info *inode;
@@ -440,6 +440,16 @@ err1:
        return error;
 }
 
+static long bch2_ioctl_subvolume_create(struct bch_fs *c, struct file *filp,
+                                       struct bch_ioctl_subvolume arg)
+{
+       down_write(&c->snapshot_create_lock);
+       long ret = __bch2_ioctl_subvolume_create(c, filp, arg);
+       up_write(&c->snapshot_create_lock);
+
+       return ret;
+}
+
 static long bch2_ioctl_subvolume_destroy(struct bch_fs *c, struct file *filp,
                                struct bch_ioctl_subvolume arg)
 {
index 32432bdddac46ab18ab04172c2fded5e0bccb148..119834cb8f9ee7f80c10b504ca8602ae5614ac37 100644 (file)
@@ -287,9 +287,18 @@ int bch2_truncate(struct bch_fs *c, subvol_inum inum, u64 new_i_size, u64 *i_sec
        op.v.inum       = cpu_to_le64(inum.inum);
        op.v.new_i_size = cpu_to_le64(new_i_size);
 
-       return bch2_trans_run(c,
+       /*
+        * Logged ops aren't atomic w.r.t. snapshot creation: creating a
+        * snapshot while they're in progress, then crashing, will result in the
+        * resume only proceeding in one of the snapshots
+        */
+       down_read(&c->snapshot_create_lock);
+       int ret = bch2_trans_run(c,
                bch2_logged_op_start(trans, &op.k_i) ?:
                __bch2_resume_logged_op_truncate(trans, &op.k_i, i_sectors_delta));
+       up_read(&c->snapshot_create_lock);
+
+       return ret;
 }
 
 /* finsert/fcollapse: */
@@ -491,7 +500,16 @@ int bch2_fcollapse_finsert(struct bch_fs *c, subvol_inum inum,
        op.v.src_offset = cpu_to_le64(offset);
        op.v.pos        = cpu_to_le64(insert ? U64_MAX : offset);
 
-       return bch2_trans_run(c,
+       /*
+        * Logged ops aren't atomic w.r.t. snapshot creation: creating a
+        * snapshot while they're in progress, then crashing, will result in the
+        * resume only proceeding in one of the snapshots
+        */
+       down_read(&c->snapshot_create_lock);
+       int ret = bch2_trans_run(c,
                bch2_logged_op_start(trans, &op.k_i) ?:
                __bch2_resume_logged_op_finsert(trans, &op.k_i, i_sectors_delta));
+       up_read(&c->snapshot_create_lock);
+
+       return ret;
 }
index fc3dd5bef386abbd59b1c240240a43d6fd4a871b..0e7a9ffa3671f729459a3f1a6032021e09937925 100644 (file)
@@ -1170,9 +1170,9 @@ int bch2_dev_journal_init(struct bch_dev *ca, struct bch_sb *sb)
 {
        struct journal_device *ja = &ca->journal;
        struct bch_sb_field_journal *journal_buckets =
-               bch2_sb_get_journal(sb);
+               bch2_sb_field_get(sb, journal);
        struct bch_sb_field_journal_v2 *journal_buckets_v2 =
-               bch2_sb_get_journal_v2(sb);
+               bch2_sb_field_get(sb, journal_v2);
        unsigned i, nr_bvecs;
 
        ja->nr = 0;
index 3c5a95e29463367db9fbbbffedad49a68e74f2e8..ae4fb8c3a2bc26fe937c5bc88f8b5b78143e91b0 100644 (file)
@@ -194,7 +194,7 @@ int bch2_journal_buckets_to_sb(struct bch_fs *c, struct bch_dev *ca,
                if (buckets[i] + 1 != buckets[i + 1])
                        nr_compacted++;
 
-       j = bch2_sb_resize_journal_v2(&ca->disk_sb,
+       j = bch2_sb_field_resize(&ca->disk_sb, journal_v2,
                         (sizeof(*j) + sizeof(j->d[0]) * nr_compacted) / sizeof(u64));
        if (!j)
                return -BCH_ERR_ENOSPC_sb_journal;
index 1e1a79405693610a8781a6ef1ed6da49bf831b4a..f9d9aa95bf3a64640d3d1e6012fc319ca7aad05e 100644 (file)
@@ -58,8 +58,8 @@ blacklist_entry_try_merge(struct bch_fs *c,
                        &bl->start[i + 1],
                        sizeof(bl->start[0]) * (nr - i));
 
-               bl = bch2_sb_resize_journal_seq_blacklist(&c->disk_sb,
-                                                       sb_blacklist_u64s(nr));
+               bl = bch2_sb_field_resize(&c->disk_sb, journal_seq_blacklist,
+                                         sb_blacklist_u64s(nr));
                BUG_ON(!bl);
        }
 
@@ -79,7 +79,7 @@ int bch2_journal_seq_blacklist_add(struct bch_fs *c, u64 start, u64 end)
        int ret = 0;
 
        mutex_lock(&c->sb_lock);
-       bl = bch2_sb_get_journal_seq_blacklist(c->disk_sb.sb);
+       bl = bch2_sb_field_get(c->disk_sb.sb, journal_seq_blacklist);
        nr = blacklist_nr_entries(bl);
 
        for (i = 0; i < nr; i++) {
@@ -100,8 +100,8 @@ int bch2_journal_seq_blacklist_add(struct bch_fs *c, u64 start, u64 end)
                }
        }
 
-       bl = bch2_sb_resize_journal_seq_blacklist(&c->disk_sb,
-                                       sb_blacklist_u64s(nr + 1));
+       bl = bch2_sb_field_resize(&c->disk_sb, journal_seq_blacklist,
+                                 sb_blacklist_u64s(nr + 1));
        if (!bl) {
                ret = -BCH_ERR_ENOSPC_sb_journal_seq_blacklist;
                goto out;
@@ -158,7 +158,7 @@ bool bch2_journal_seq_is_blacklisted(struct bch_fs *c, u64 seq,
 int bch2_blacklist_table_initialize(struct bch_fs *c)
 {
        struct bch_sb_field_journal_seq_blacklist *bl =
-               bch2_sb_get_journal_seq_blacklist(c->disk_sb.sb);
+               bch2_sb_field_get(c->disk_sb.sb, journal_seq_blacklist);
        struct journal_seq_blacklist_table *t;
        unsigned i, nr = blacklist_nr_entries(bl);
 
@@ -281,7 +281,7 @@ retry:
                return;
 
        mutex_lock(&c->sb_lock);
-       bl = bch2_sb_get_journal_seq_blacklist(c->disk_sb.sb);
+       bl = bch2_sb_field_get(c->disk_sb.sb, journal_seq_blacklist);
        if (!bl)
                goto out;
 
@@ -306,7 +306,7 @@ retry:
        bch_info(c, "nr blacklist entries was %u, now %u", nr, new_nr);
 
        if (new_nr != nr) {
-               bl = bch2_sb_resize_journal_seq_blacklist(&c->disk_sb,
+               bl = bch2_sb_field_resize(&c->disk_sb, journal_seq_blacklist,
                                new_nr ? sb_blacklist_u64s(new_nr) : 0);
                BUG_ON(new_nr && !bl);
 
index 36de2f071d8000e8218745f8d7c926cfc0c778a5..cb68ae44d597a6a97babfc0540a55035a692a12a 100644 (file)
@@ -513,12 +513,12 @@ void bch2_fs_quota_init(struct bch_fs *c)
 
 static struct bch_sb_field_quota *bch2_sb_get_or_create_quota(struct bch_sb_handle *sb)
 {
-       struct bch_sb_field_quota *sb_quota = bch2_sb_get_quota(sb->sb);
+       struct bch_sb_field_quota *sb_quota = bch2_sb_field_get(sb->sb, quota);
 
        if (sb_quota)
                return sb_quota;
 
-       sb_quota = bch2_sb_resize_quota(sb, sizeof(*sb_quota) / sizeof(u64));
+       sb_quota = bch2_sb_field_resize(sb, quota, sizeof(*sb_quota) / sizeof(u64));
        if (sb_quota) {
                unsigned qtype, qc;
 
@@ -536,7 +536,7 @@ static void bch2_sb_quota_read(struct bch_fs *c)
        struct bch_sb_field_quota *sb_quota;
        unsigned i, j;
 
-       sb_quota = bch2_sb_get_quota(c->disk_sb.sb);
+       sb_quota = bch2_sb_field_get(c->disk_sb.sb, quota);
        if (!sb_quota)
                return;
 
index cd037f2e423558868e89067d934396adcd550711..4cd660650e5bda264283f10624b52a3f02910b37 100644 (file)
 
 #define QSTR(n) { { { .len = strlen(n) } }, .name = n }
 
+static bool btree_id_is_alloc(enum btree_id id)
+{
+       switch (id) {
+       case BTREE_ID_alloc:
+       case BTREE_ID_backpointers:
+       case BTREE_ID_need_discard:
+       case BTREE_ID_freespace:
+       case BTREE_ID_bucket_gens:
+               return true;
+       default:
+               return false;
+       }
+}
+
 /* for -o reconstruct_alloc: */
 static void drop_alloc_keys(struct journal_keys *keys)
 {
        size_t src, dst;
 
        for (src = 0, dst = 0; src < keys->nr; src++)
-               if (keys->d[src].btree_id != BTREE_ID_alloc)
+               if (!btree_id_is_alloc(keys->d[src].btree_id))
                        keys->d[dst++] = keys->d[src];
 
        keys->nr = dst;
@@ -332,20 +346,6 @@ static int journal_replay_early(struct bch_fs *c,
 
 /* sb clean section: */
 
-static bool btree_id_is_alloc(enum btree_id id)
-{
-       switch (id) {
-       case BTREE_ID_alloc:
-       case BTREE_ID_backpointers:
-       case BTREE_ID_need_discard:
-       case BTREE_ID_freespace:
-       case BTREE_ID_bucket_gens:
-               return true;
-       default:
-               return false;
-       }
-}
-
 static int read_btree_roots(struct bch_fs *c)
 {
        unsigned i;
index a9a694fb0b18e7e588351820cddecc83b43f6d38..cef2a0447b8601a191ac39852ae4a7e0d9fc317d 100644 (file)
@@ -700,9 +700,9 @@ int bch2_sb_replicas_to_cpu_replicas(struct bch_fs *c)
        struct bch_replicas_cpu new_r = { 0, 0, NULL };
        int ret = 0;
 
-       if ((sb_v1 = bch2_sb_get_replicas(c->disk_sb.sb)))
+       if ((sb_v1 = bch2_sb_field_get(c->disk_sb.sb, replicas)))
                ret = __bch2_sb_replicas_to_cpu_replicas(sb_v1, &new_r);
-       else if ((sb_v0 = bch2_sb_get_replicas_v0(c->disk_sb.sb)))
+       else if ((sb_v0 = bch2_sb_field_get(c->disk_sb.sb, replicas_v0)))
                ret = __bch2_sb_replicas_v0_to_cpu_replicas(sb_v0, &new_r);
        if (ret)
                return ret;
@@ -732,13 +732,13 @@ static int bch2_cpu_replicas_to_sb_replicas_v0(struct bch_fs *c,
        for_each_cpu_replicas_entry(r, src)
                bytes += replicas_entry_bytes(src) - 1;
 
-       sb_r = bch2_sb_resize_replicas_v0(&c->disk_sb,
+       sb_r = bch2_sb_field_resize(&c->disk_sb, replicas_v0,
                        DIV_ROUND_UP(bytes, sizeof(u64)));
        if (!sb_r)
                return -BCH_ERR_ENOSPC_sb_replicas;
 
        bch2_sb_field_delete(&c->disk_sb, BCH_SB_FIELD_replicas);
-       sb_r = bch2_sb_get_replicas_v0(c->disk_sb.sb);
+       sb_r = bch2_sb_field_get(c->disk_sb.sb, replicas_v0);
 
        memset(&sb_r->entries, 0,
               vstruct_end(&sb_r->field) -
@@ -777,13 +777,13 @@ static int bch2_cpu_replicas_to_sb_replicas(struct bch_fs *c,
        if (!need_v1)
                return bch2_cpu_replicas_to_sb_replicas_v0(c, r);
 
-       sb_r = bch2_sb_resize_replicas(&c->disk_sb,
+       sb_r = bch2_sb_field_resize(&c->disk_sb, replicas,
                        DIV_ROUND_UP(bytes, sizeof(u64)));
        if (!sb_r)
                return -BCH_ERR_ENOSPC_sb_replicas;
 
        bch2_sb_field_delete(&c->disk_sb, BCH_SB_FIELD_replicas_v0);
-       sb_r = bch2_sb_get_replicas(c->disk_sb.sb);
+       sb_r = bch2_sb_field_get(c->disk_sb.sb, replicas);
 
        memset(&sb_r->entries, 0,
               vstruct_end(&sb_r->field) -
@@ -998,8 +998,8 @@ unsigned bch2_sb_dev_has_data(struct bch_sb *sb, unsigned dev)
        struct bch_sb_field_replicas_v0 *replicas_v0;
        unsigned i, data_has = 0;
 
-       replicas = bch2_sb_get_replicas(sb);
-       replicas_v0 = bch2_sb_get_replicas_v0(sb);
+       replicas = bch2_sb_field_get(sb, replicas);
+       replicas_v0 = bch2_sb_field_get(sb, replicas_v0);
 
        if (replicas) {
                struct bch_replicas_entry *r;
index a3695e56a155a8487d2ab42104c954ca2e57cd24..61203d7c8d36054400ff0d1ee2e1838966168a73 100644 (file)
@@ -137,7 +137,7 @@ struct bch_sb_field_clean *bch2_read_superblock_clean(struct bch_fs *c)
        int ret;
 
        mutex_lock(&c->sb_lock);
-       sb_clean = bch2_sb_get_clean(c->disk_sb.sb);
+       sb_clean = bch2_sb_field_get(c->disk_sb.sb, clean);
 
        if (fsck_err_on(!sb_clean, c,
                        "superblock marked clean but clean section not present")) {
@@ -359,7 +359,7 @@ void bch2_fs_mark_clean(struct bch_fs *c)
 
        u64s = sizeof(*sb_clean) / sizeof(u64) + c->journal.entry_u64s_reserved;
 
-       sb_clean = bch2_sb_resize_clean(&c->disk_sb, u64s);
+       sb_clean = bch2_sb_field_resize(&c->disk_sb, clean, u64s);
        if (!sb_clean) {
                bch_err(c, "error resizing superblock while setting filesystem clean");
                goto out;
index 04bde1aaff9f45de7fc5b3cd37af448bca0076d2..6dd85bb996feed0c318595215d4d72f2c63b0371 100644 (file)
@@ -16,7 +16,7 @@ static struct bch_member *members_v2_get_mut(struct bch_sb_field_members_v2 *mi,
 
 struct bch_member *bch2_members_v2_get_mut(struct bch_sb *sb, int i)
 {
-       return members_v2_get_mut(bch2_sb_get_members_v2(sb), i);
+       return members_v2_get_mut(bch2_sb_field_get(sb, members_v2), i);
 }
 
 static struct bch_member members_v2_get(struct bch_sb_field_members_v2 *mi, int i)
@@ -41,22 +41,22 @@ static struct bch_member members_v1_get(struct bch_sb_field_members_v1 *mi, int
 
 struct bch_member bch2_sb_member_get(struct bch_sb *sb, int i)
 {
-       struct bch_sb_field_members_v2 *mi2 = bch2_sb_get_members_v2(sb);
+       struct bch_sb_field_members_v2 *mi2 = bch2_sb_field_get(sb, members_v2);
        if (mi2)
                return members_v2_get(mi2, i);
-       struct bch_sb_field_members_v1 *mi1 = bch2_sb_get_members_v1(sb);
+       struct bch_sb_field_members_v1 *mi1 = bch2_sb_field_get(sb, members_v1);
        return members_v1_get(mi1, i);
 }
 
 static int sb_members_v2_resize_entries(struct bch_fs *c)
 {
-       struct bch_sb_field_members_v2 *mi = bch2_sb_get_members_v2(c->disk_sb.sb);
+       struct bch_sb_field_members_v2 *mi = bch2_sb_field_get(c->disk_sb.sb, members_v2);
 
        if (le16_to_cpu(mi->member_bytes) < sizeof(struct bch_member)) {
                unsigned u64s = DIV_ROUND_UP((sizeof(*mi) + sizeof(mi->_members[0]) *
                                              c->disk_sb.sb->nr_devices), 8);
 
-               mi = bch2_sb_resize_members_v2(&c->disk_sb, u64s);
+               mi = bch2_sb_field_resize(&c->disk_sb, members_v2, u64s);
                if (!mi)
                        return -BCH_ERR_ENOSPC_sb_members_v2;
 
@@ -76,12 +76,12 @@ int bch2_members_v2_init(struct bch_fs *c)
        struct bch_sb_field_members_v1 *mi1;
        struct bch_sb_field_members_v2 *mi2;
 
-       if (!bch2_sb_get_members_v2(c->disk_sb.sb)) {
-               mi2 = bch2_sb_resize_members_v2(&c->disk_sb,
+       if (!bch2_sb_field_get(c->disk_sb.sb, members_v2)) {
+               mi2 = bch2_sb_field_resize(&c->disk_sb, members_v2,
                                DIV_ROUND_UP(sizeof(*mi2) +
                                             sizeof(struct bch_member) * c->sb.nr_devices,
                                             sizeof(u64)));
-               mi1 = bch2_sb_get_members_v1(c->disk_sb.sb);
+               mi1 = bch2_sb_field_get(c->disk_sb.sb, members_v1);
                memcpy(&mi2->_members[0], &mi1->_members[0],
                       BCH_MEMBER_V1_BYTES * c->sb.nr_devices);
                memset(&mi2->pad[0], 0, sizeof(mi2->pad));
@@ -96,13 +96,13 @@ int bch_members_cpy_v2_v1(struct bch_sb_handle *disk_sb)
        struct bch_sb_field_members_v1 *mi1;
        struct bch_sb_field_members_v2 *mi2;
 
-       mi1 = bch2_sb_resize_members_v1(disk_sb,
+       mi1 = bch2_sb_field_resize(disk_sb, members_v1,
                        DIV_ROUND_UP(sizeof(*mi1) + BCH_MEMBER_V1_BYTES *
                                     disk_sb->sb->nr_devices, sizeof(u64)));
        if (!mi1)
                return -BCH_ERR_ENOSPC_sb_members;
 
-       mi2 = bch2_sb_get_members_v2(disk_sb->sb);
+       mi2 = bch2_sb_field_get(disk_sb->sb, members_v2);
 
        for (unsigned i = 0; i < disk_sb->sb->nr_devices; i++)
                memcpy(members_v1_get_mut(mi1, i), members_v2_get_mut(mi2, i), BCH_MEMBER_V1_BYTES);
@@ -283,7 +283,7 @@ static void bch2_sb_members_v1_to_text(struct printbuf *out, struct bch_sb *sb,
                                       struct bch_sb_field *f)
 {
        struct bch_sb_field_members_v1 *mi = field_to_type(f, members_v1);
-       struct bch_sb_field_disk_groups *gi = bch2_sb_get_disk_groups(sb);
+       struct bch_sb_field_disk_groups *gi = bch2_sb_field_get(sb, disk_groups);
        unsigned i;
 
        for (i = 0; i < sb->nr_devices; i++) {
@@ -301,7 +301,7 @@ static void bch2_sb_members_v2_to_text(struct printbuf *out, struct bch_sb *sb,
                                       struct bch_sb_field *f)
 {
        struct bch_sb_field_members_v2 *mi = field_to_type(f, members_v2);
-       struct bch_sb_field_disk_groups *gi = bch2_sb_get_disk_groups(sb);
+       struct bch_sb_field_disk_groups *gi = bch2_sb_field_get(sb, disk_groups);
        unsigned i;
 
        for (i = 0; i < sb->nr_devices; i++) {
index 3ecc17b8d6fcaea206cb166d5ed58a5cad889f9c..4982468bfe1182910fa6a03e3b691bf7ce8be758 100644 (file)
@@ -1288,6 +1288,9 @@ static inline u32 bch2_snapshot_nth_parent_skip(struct bch_fs *c, u32 id, u32 n,
                                                snapshot_id_list *skip)
 {
        rcu_read_lock();
+       while (snapshot_list_has_id(skip, id))
+               id = __bch2_snapshot_parent(c, id);
+
        while (n--) {
                do {
                        id = __bch2_snapshot_parent(c, id);
@@ -1444,6 +1447,8 @@ int bch2_delete_dead_snapshots(struct bch_fs *c)
                }
        }
 
+       down_write(&c->snapshot_create_lock);
+
        for_each_btree_key(trans, iter, BTREE_ID_snapshots,
                           POS_MIN, 0, k, ret) {
                u32 snapshot = k.k->p.offset;
@@ -1454,6 +1459,9 @@ int bch2_delete_dead_snapshots(struct bch_fs *c)
        }
        bch2_trans_iter_exit(trans, &iter);
 
+       if (ret)
+               goto err_create_lock;
+
        /*
         * Fixing children of deleted snapshots can't be done completely
         * atomically, if we crash between here and when we delete the interior
@@ -1464,14 +1472,14 @@ int bch2_delete_dead_snapshots(struct bch_fs *c)
                                  NULL, NULL, BTREE_INSERT_NOFAIL,
                bch2_fix_child_of_deleted_snapshot(trans, &iter, k, &deleted_interior));
        if (ret)
-               goto err;
+               goto err_create_lock;
 
        darray_for_each(deleted, i) {
                ret = commit_do(trans, NULL, NULL, 0,
                        bch2_snapshot_node_delete(trans, *i));
                if (ret) {
                        bch_err_msg(c, ret, "deleting snapshot %u", *i);
-                       goto err;
+                       goto err_create_lock;
                }
        }
 
@@ -1480,11 +1488,13 @@ int bch2_delete_dead_snapshots(struct bch_fs *c)
                        bch2_snapshot_node_delete(trans, *i));
                if (ret) {
                        bch_err_msg(c, ret, "deleting snapshot %u", *i);
-                       goto err;
+                       goto err_create_lock;
                }
        }
 
        clear_bit(BCH_FS_HAVE_DELETED_SNAPSHOTS, &c->flags);
+err_create_lock:
+       up_write(&c->snapshot_create_lock);
 err:
        darray_exit(&deleted_interior);
        darray_exit(&deleted);
index 4498e24dabdbff8ca9fd6537c64cddca6f072f60..332d41e1c0a32082988f70ded38bd004b35444c0 100644 (file)
@@ -96,7 +96,7 @@ const char * const bch2_sb_fields[] = {
 static int bch2_sb_field_validate(struct bch_sb *, struct bch_sb_field *,
                                  struct printbuf *);
 
-struct bch_sb_field *bch2_sb_field_get(struct bch_sb *sb,
+struct bch_sb_field *bch2_sb_field_get_id(struct bch_sb *sb,
                                      enum bch_sb_field_type type)
 {
        struct bch_sb_field *f;
@@ -151,7 +151,7 @@ static struct bch_sb_field *__bch2_sb_field_resize(struct bch_sb_handle *sb,
 void bch2_sb_field_delete(struct bch_sb_handle *sb,
                          enum bch_sb_field_type type)
 {
-       struct bch_sb_field *f = bch2_sb_field_get(sb->sb, type);
+       struct bch_sb_field *f = bch2_sb_field_get_id(sb->sb, type);
 
        if (f)
                __bch2_sb_field_resize(sb, f, 0);
@@ -225,11 +225,11 @@ int bch2_sb_realloc(struct bch_sb_handle *sb, unsigned u64s)
        return 0;
 }
 
-struct bch_sb_field *bch2_sb_field_resize(struct bch_sb_handle *sb,
+struct bch_sb_field *bch2_sb_field_resize_id(struct bch_sb_handle *sb,
                                          enum bch_sb_field_type type,
                                          unsigned u64s)
 {
-       struct bch_sb_field *f = bch2_sb_field_get(sb->sb, type);
+       struct bch_sb_field *f = bch2_sb_field_get_id(sb->sb, type);
        ssize_t old_u64s = f ? le32_to_cpu(f->u64s) : 0;
        ssize_t d = -old_u64s + u64s;
 
@@ -255,7 +255,7 @@ struct bch_sb_field *bch2_sb_field_resize(struct bch_sb_handle *sb,
                }
        }
 
-       f = bch2_sb_field_get(sb->sb, type);
+       f = bch2_sb_field_get_id(sb->sb, type);
        f = __bch2_sb_field_resize(sb, f, u64s);
        if (f)
                f->type = cpu_to_le32(type);
@@ -458,7 +458,7 @@ static int bch2_sb_validate(struct bch_sb_handle *disk_sb, struct printbuf *out,
        }
 
        /* members must be validated first: */
-       mi = bch2_sb_get_members_v1(sb);
+       mi = bch2_sb_field_get(sb, members_v1);
        if (!mi) {
                prt_printf(out, "Invalid superblock: member info area missing");
                return -BCH_ERR_invalid_sb_members_missing;
@@ -546,8 +546,8 @@ static int __copy_super(struct bch_sb_handle *dst_handle, struct bch_sb *src)
                if ((1U << i) & BCH_SINGLE_DEVICE_SB_FIELDS)
                        continue;
 
-               src_f = bch2_sb_field_get(src, i);
-               dst_f = bch2_sb_field_get(dst, i);
+               src_f = bch2_sb_field_get_id(src, i);
+               dst_f = bch2_sb_field_get_id(dst, i);
 
                d = (src_f ? le32_to_cpu(src_f->u64s) : 0) -
                    (dst_f ? le32_to_cpu(dst_f->u64s) : 0);
@@ -559,7 +559,7 @@ static int __copy_super(struct bch_sb_handle *dst_handle, struct bch_sb *src)
                                return ret;
 
                        dst = dst_handle->sb;
-                       dst_f = bch2_sb_field_get(dst, i);
+                       dst_f = bch2_sb_field_get_id(dst, i);
                }
 
                dst_f = __bch2_sb_field_resize(dst_handle, dst_f,
index f7e9099931a74db6e015e7af4436dd80de699dbe..b0d8584f475f1f2290b33e3120500cda726b4473 100644 (file)
@@ -23,31 +23,19 @@ u64 bch2_upgrade_recovery_passes(struct bch_fs *c,
                                 unsigned,
                                 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);
-void bch2_sb_field_delete(struct bch_sb_handle *, enum bch_sb_field_type);
-
 #define field_to_type(_f, _name)                                       \
        container_of_or_null(_f, struct bch_sb_field_##_name, field)
 
-#define x(_name, _nr)                                                  \
-static inline struct bch_sb_field_##_name *                            \
-bch2_sb_get_##_name(struct bch_sb *sb)                                 \
-{                                                                      \
-       return field_to_type(bch2_sb_field_get(sb,                      \
-                               BCH_SB_FIELD_##_name), _name);          \
-}                                                                      \
-                                                                       \
-static inline struct bch_sb_field_##_name *                            \
-bch2_sb_resize_##_name(struct bch_sb_handle *sb, unsigned u64s)        \
-{                                                                      \
-       return field_to_type(bch2_sb_field_resize(sb,                   \
-                               BCH_SB_FIELD_##_name, u64s), _name);    \
-}
+struct bch_sb_field *bch2_sb_field_get_id(struct bch_sb *, enum bch_sb_field_type);
+#define bch2_sb_field_get(_sb, _name)                                  \
+       field_to_type(bch2_sb_field_get_id(_sb, BCH_SB_FIELD_##_name), _name)
 
-BCH_SB_FIELDS()
-#undef x
+struct bch_sb_field *bch2_sb_field_resize_id(struct bch_sb_handle *,
+                                            enum bch_sb_field_type, unsigned);
+#define bch2_sb_field_resize(_sb, _name, _u64s)                                \
+       field_to_type(bch2_sb_field_resize_id(_sb, BCH_SB_FIELD_##_name, _u64s), _name)
+
+void bch2_sb_field_delete(struct bch_sb_handle *, enum bch_sb_field_type);
 
 extern const char * const bch2_sb_fields[];
 
index 2014f7816f6679fd7436b33252cdfd3686618de2..0e85c22672be85fb09a1ce51ed457d65ab1d2d5c 100644 (file)
@@ -720,6 +720,7 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts)
 
        mutex_init(&c->bio_bounce_pages_lock);
        mutex_init(&c->snapshot_table_lock);
+       init_rwsem(&c->snapshot_create_lock);
 
        spin_lock_init(&c->btree_write_error_lock);
 
@@ -1630,9 +1631,9 @@ int bch2_dev_add(struct bch_fs *c, const char *path)
                goto err_unlock;
        }
 
-       mi = bch2_sb_get_members_v2(ca->disk_sb.sb);
+       mi = bch2_sb_field_get(ca->disk_sb.sb, members_v2);
 
-       if (!bch2_sb_resize_members_v2(&ca->disk_sb,
+       if (!bch2_sb_field_resize(&ca->disk_sb, members_v2,
                                le32_to_cpu(mi->field.u64s) +
                                sizeof(dev_mi) / sizeof(u64))) {
                ret = -BCH_ERR_ENOSPC_sb_members;
@@ -1656,7 +1657,7 @@ have_slot:
        u64s = DIV_ROUND_UP(sizeof(struct bch_sb_field_members_v2) +
                            le16_to_cpu(mi->member_bytes) * nr_devices, sizeof(u64));
 
-       mi = bch2_sb_resize_members_v2(&c->disk_sb, u64s);
+       mi = bch2_sb_field_resize(&c->disk_sb, members_v2, u64s);
        if (!mi) {
                ret = -BCH_ERR_ENOSPC_sb_members;
                bch_err_msg(c, ret, "setting up new superblock");
index 597a8db73585b8ad2793c59e1fa6668dfe3f87e5..78d6138db62d7e4a1f1fe07bb043ca7ada417986 100644 (file)
@@ -46,7 +46,7 @@ struct bch_disk_group_cpu {
 struct bch_disk_groups_cpu {
        struct rcu_head                 rcu;
        unsigned                        nr;
-       struct bch_disk_group_cpu       entries[];
+       struct bch_disk_group_cpu       entries[] __counted_by(nr);
 };
 
 #endif /* _BCACHEFS_SUPER_TYPES_H */
index fa8dbdeb432965605aed3b41c9dcf991ddd85afb..8e897c08b0029d936d5f07db557ced157fc8781e 100644 (file)
@@ -43,7 +43,7 @@ impl PartialEq for bch_sb {
 impl bch_sb {
     pub fn crypt(&self) -> Option<&bch_sb_field_crypt> {
         unsafe {
-            let ptr = bch2_sb_field_get(
+            let ptr = bch2_sb_field_get_id(
                 self as *const _ as *mut _,
                 bch_sb_field_type::BCH_SB_FIELD_crypt,
             ) as *const u8;