]> git.sesse.net Git - bcachefs-tools-debian/blobdiff - libbcachefs/super-io.c
Update bcachefs sources to 400f275d46 bcachefs: Fix check_overlapping_extents()
[bcachefs-tools-debian] / libbcachefs / super-io.c
index 6d99a5814392ed366fea6dcef4fb7313c395c301..5a15d649d3575d35d7f7a9ec9d1fac08774adb46 100644 (file)
 #include "quota.h"
 #include "super-io.h"
 #include "super.h"
+#include "trace.h"
 #include "vstructs.h"
 #include "counters.h"
 
 #include <linux/backing-dev.h>
-#include <linux/pretty-printers.h>
 #include <linux/sort.h>
 
-#include <trace/events/bcachefs.h>
-
 const char * const bch2_sb_fields[] = {
 #define x(name, nr)    #name,
        BCH_SB_FIELDS()
@@ -137,14 +135,14 @@ int bch2_sb_realloc(struct bch_sb_handle *sb, unsigned u64s)
                return 0;
 
        if (dynamic_fault("bcachefs:add:super_realloc"))
-               return -ENOMEM;
+               return -BCH_ERR_ENOMEM_sb_realloc_injected;
 
        if (sb->have_bio) {
                unsigned nr_bvecs = DIV_ROUND_UP(new_buffer_size, PAGE_SIZE);
 
                bio = bio_kmalloc(nr_bvecs, GFP_KERNEL);
                if (!bio)
-                       return -ENOMEM;
+                       return -BCH_ERR_ENOMEM_sb_bio_realloc;
 
                bio_init(bio, NULL, bio->bi_inline_vecs, nr_bvecs, 0);
 
@@ -154,7 +152,7 @@ int bch2_sb_realloc(struct bch_sb_handle *sb, unsigned u64s)
 
        new_sb = krealloc(sb->sb, new_buffer_size, GFP_NOFS|__GFP_ZERO);
        if (!new_sb)
-               return -ENOMEM;
+               return -BCH_ERR_ENOMEM_sb_buf_realloc;
 
        sb->sb = new_sb;
        sb->buffer_size = new_buffer_size;
@@ -211,7 +209,8 @@ static int validate_sb_layout(struct bch_sb_layout *layout, struct printbuf *out
        u64 offset, prev_offset, max_sectors;
        unsigned i;
 
-       if (uuid_le_cmp(layout->magic, BCACHE_MAGIC)) {
+       if (uuid_le_cmp(layout->magic, BCACHE_MAGIC) &&
+           uuid_le_cmp(layout->magic, BCHFS_MAGIC)) {
                prt_printf(out, "Not a bcachefs superblock layout");
                return -BCH_ERR_invalid_sb_layout;
        }
@@ -432,7 +431,7 @@ static void bch2_sb_update(struct bch_fs *c)
                ca->mi = bch2_mi_to_cpu(mi->members + i);
 }
 
-static void __copy_super(struct bch_sb_handle *dst_handle, struct bch_sb *src)
+static int __copy_super(struct bch_sb_handle *dst_handle, struct bch_sb *src)
 {
        struct bch_sb_field *src_f, *dst_f;
        struct bch_sb *dst = dst_handle->sb;
@@ -457,42 +456,45 @@ static void __copy_super(struct bch_sb_handle *dst_handle, struct bch_sb *src)
        memcpy(dst->compat,     src->compat,    sizeof(dst->compat));
 
        for (i = 0; i < BCH_SB_FIELD_NR; i++) {
+               int d;
+
                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);
+
+               d = (src_f ? le32_to_cpu(src_f->u64s) : 0) -
+                   (dst_f ? le32_to_cpu(dst_f->u64s) : 0);
+               if (d > 0) {
+                       int ret = bch2_sb_realloc(dst_handle, le32_to_cpu(dst_handle->sb->u64s) + d);
+                       if (ret)
+                               return ret;
+
+                       dst = dst_handle->sb;
+                       dst_f = bch2_sb_field_get(dst, i);
+               }
+
                dst_f = __bch2_sb_field_resize(dst_handle, dst_f,
                                src_f ? le32_to_cpu(src_f->u64s) : 0);
 
                if (src_f)
                        memcpy(dst_f, src_f, vstruct_bytes(src_f));
        }
+
+       return 0;
 }
 
 int bch2_sb_to_fs(struct bch_fs *c, struct bch_sb *src)
 {
-       struct bch_sb_field_journal *journal_buckets =
-               bch2_sb_get_journal(src);
-       unsigned journal_u64s = journal_buckets
-               ? le32_to_cpu(journal_buckets->field.u64s)
-               : 0;
        int ret;
 
        lockdep_assert_held(&c->sb_lock);
 
-       ret = bch2_sb_realloc(&c->disk_sb,
-                             le32_to_cpu(src->u64s) - journal_u64s);
-       if (ret)
-               return ret;
-
-       __copy_super(&c->disk_sb, src);
-
-       ret = bch2_sb_replicas_to_cpu_replicas(c);
-       if (ret)
-               return ret;
-
-       ret = bch2_sb_disk_groups_to_cpu(c);
+       ret =   bch2_sb_realloc(&c->disk_sb, 0) ?:
+               __copy_super(&c->disk_sb, src) ?:
+               bch2_sb_replicas_to_cpu_replicas(c) ?:
+               bch2_sb_disk_groups_to_cpu(c);
        if (ret)
                return ret;
 
@@ -502,21 +504,7 @@ int bch2_sb_to_fs(struct bch_fs *c, struct bch_sb *src)
 
 int bch2_sb_from_fs(struct bch_fs *c, struct bch_dev *ca)
 {
-       struct bch_sb *src = c->disk_sb.sb, *dst = ca->disk_sb.sb;
-       struct bch_sb_field_journal *journal_buckets =
-               bch2_sb_get_journal(dst);
-       unsigned journal_u64s = journal_buckets
-               ? le32_to_cpu(journal_buckets->field.u64s)
-               : 0;
-       unsigned u64s = le32_to_cpu(src->u64s) + journal_u64s;
-       int ret;
-
-       ret = bch2_sb_realloc(&ca->disk_sb, u64s);
-       if (ret)
-               return ret;
-
-       __copy_super(&ca->disk_sb, src);
-       return 0;
+       return __copy_super(&ca->disk_sb, c->disk_sb.sb);
 }
 
 /* read superblock: */
@@ -538,7 +526,8 @@ reread:
                return ret;
        }
 
-       if (uuid_le_cmp(sb->sb->magic, BCACHE_MAGIC)) {
+       if (uuid_le_cmp(sb->sb->magic, BCACHE_MAGIC) &&
+           uuid_le_cmp(sb->sb->magic, BCHFS_MAGIC)) {
                prt_printf(err, "Not a bcachefs superblock");
                return -BCH_ERR_invalid_sb_magic;
        }
@@ -569,8 +558,9 @@ reread:
        }
 
        if (bytes > sb->buffer_size) {
-               if (bch2_sb_realloc(sb, le32_to_cpu(sb->sb->u64s)))
-                       return -ENOMEM;
+               ret = bch2_sb_realloc(sb, le32_to_cpu(sb->sb->u64s));
+               if (ret)
+                       return ret;
                goto reread;
        }
 
@@ -802,6 +792,11 @@ int bch2_write_super(struct bch_fs *c)
        closure_init_stack(cl);
        memset(&sb_written, 0, sizeof(sb_written));
 
+       if (c->opts.version_upgrade) {
+               c->disk_sb.sb->magic = BCHFS_MAGIC;
+               c->disk_sb.sb->layout.magic = BCHFS_MAGIC;
+       }
+
        le64_add_cpu(&c->disk_sb.sb->seq, 1);
 
        if (test_bit(BCH_FS_ERROR, &c->flags))
@@ -856,7 +851,7 @@ int bch2_write_super(struct bch_fs *c)
                                le64_to_cpu(ca->sb_read_scratch->seq),
                                ca->disk_sb.seq);
                        percpu_ref_put(&ca->io_ref);
-                       ret = -EROFS;
+                       ret = -BCH_ERR_erofs_sb_err;
                        goto out;
                }
 
@@ -866,7 +861,7 @@ int bch2_write_super(struct bch_fs *c)
                                le64_to_cpu(ca->sb_read_scratch->seq),
                                ca->disk_sb.seq);
                        percpu_ref_put(&ca->io_ref);
-                       ret = -EROFS;
+                       ret = -BCH_ERR_erofs_sb_err;
                        goto out;
                }
        }
@@ -1254,7 +1249,8 @@ void bch2_journal_super_entries_add_common(struct bch_fs *c,
 
                u->entry.type   = BCH_JSET_ENTRY_data_usage;
                u->v            = cpu_to_le64(c->usage_base->replicas[i]);
-               memcpy(&u->r, e, replicas_entry_bytes(e));
+               unsafe_memcpy(&u->r, e, replicas_entry_bytes(e),
+                             "embedded variable length struct");
        }
 
        for_each_member_device(ca, c, dev) {