BUG_ON(get_order(__vstruct_bytes(struct bch_sb, sb_u64s)) >
sb->page_order);
- if (!f) {
+ if (!f && !u64s) {
+ /* nothing to do: */
+ } else if (!f) {
f = vstruct_last(sb->sb);
memset(f, 0, sizeof(u64) * u64s);
f->u64s = cpu_to_le32(u64s);
return ret;
}
+void __bch2_check_set_feature(struct bch_fs *c, unsigned feat)
+{
+ mutex_lock(&c->sb_lock);
+ if (!(c->sb.features & (1ULL << feat))) {
+ c->disk_sb.sb->features[0] |= cpu_to_le64(1ULL << feat);
+
+ bch2_write_super(c);
+ }
+ mutex_unlock(&c->sb_lock);
+}
+
/* BCH_SB_FIELD_journal: */
static int u64_cmp(const void *_l, const void *_r)
mutex_lock(&c->sb_lock);
SET_BCH_SB_CLEAN(c->disk_sb.sb, false);
c->disk_sb.sb->compat[0] &= ~(1ULL << BCH_COMPAT_FEAT_ALLOC_METADATA);
+ c->disk_sb.sb->features[0] |= 1ULL << BCH_FEATURE_new_extent_overwrite;
+ c->disk_sb.sb->features[0] |= 1ULL << BCH_FEATURE_extents_above_btree_updates;
ret = bch2_write_super(c);
mutex_unlock(&c->sb_lock);
return ret;
}
+static void
+entry_init_u64s(struct jset_entry *entry, unsigned u64s)
+{
+ memset(entry, 0, u64s * sizeof(u64));
+
+ /*
+ * The u64s field counts from the start of data, ignoring the shared
+ * fields.
+ */
+ entry->u64s = u64s - 1;
+}
+
+static void
+entry_init_size(struct jset_entry *entry, size_t size)
+{
+ unsigned u64s = DIV_ROUND_UP(size, sizeof(u64));
+ entry_init_u64s(entry, u64s);
+}
+
struct jset_entry *
bch2_journal_super_entries_add_common(struct bch_fs *c,
struct jset_entry *entry,
r < c->btree_roots + BTREE_ID_NR;
r++)
if (r->alive) {
- entry->u64s = r->key.u64s;
+ entry_init_u64s(entry, r->key.u64s + 1);
entry->btree_id = r - c->btree_roots;
entry->level = r->level;
entry->type = BCH_JSET_ENTRY_btree_root;
struct jset_entry_usage *u =
container_of(entry, struct jset_entry_usage, entry);
- memset(u, 0, sizeof(*u));
- u->entry.u64s = DIV_ROUND_UP(sizeof(*u), sizeof(u64)) - 1;
+ entry_init_size(entry, sizeof(*u));
u->entry.type = BCH_JSET_ENTRY_usage;
u->entry.btree_id = FS_USAGE_INODES;
u->v = cpu_to_le64(c->usage_base->nr_inodes);
struct jset_entry_usage *u =
container_of(entry, struct jset_entry_usage, entry);
- memset(u, 0, sizeof(*u));
- u->entry.u64s = DIV_ROUND_UP(sizeof(*u), sizeof(u64)) - 1;
+ entry_init_size(entry, sizeof(*u));
u->entry.type = BCH_JSET_ENTRY_usage;
u->entry.btree_id = FS_USAGE_KEY_VERSION;
u->v = cpu_to_le64(atomic64_read(&c->key_version));
struct jset_entry_usage *u =
container_of(entry, struct jset_entry_usage, entry);
- memset(u, 0, sizeof(*u));
- u->entry.u64s = DIV_ROUND_UP(sizeof(*u), sizeof(u64)) - 1;
+ entry_init_size(entry, sizeof(*u));
u->entry.type = BCH_JSET_ENTRY_usage;
u->entry.btree_id = FS_USAGE_RESERVED;
u->entry.level = i;
struct jset_entry_data_usage *u =
container_of(entry, struct jset_entry_data_usage, entry);
- memset(u, 0, sizeof(*u));
- u->entry.u64s = DIV_ROUND_UP(sizeof(*u) + e->nr_devs,
- sizeof(u64)) - 1;
+ entry_init_size(entry, sizeof(*u) + e->nr_devs);
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));
c->disk_sb.sb->compat[0] |= 1ULL << BCH_COMPAT_FEAT_ALLOC_INFO;
c->disk_sb.sb->compat[0] |= 1ULL << BCH_COMPAT_FEAT_ALLOC_METADATA;
+ c->disk_sb.sb->features[0] &= ~(1ULL << BCH_FEATURE_extents_above_btree_updates);
u64s = sizeof(*sb_clean) / sizeof(u64) + c->journal.entry_u64s_reserved;