summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/bcachefs/journal_io.c33
-rw-r--r--fs/bcachefs/replicas.c5
-rw-r--r--fs/bcachefs/replicas.h5
-rw-r--r--fs/bcachefs/super-io.c131
-rw-r--r--fs/bcachefs/super-io.h4
5 files changed, 120 insertions, 58 deletions
diff --git a/fs/bcachefs/journal_io.c b/fs/bcachefs/journal_io.c
index 173aecfaebc2..2f04f0074ec4 100644
--- a/fs/bcachefs/journal_io.c
+++ b/fs/bcachefs/journal_io.c
@@ -863,19 +863,6 @@ err:
/* journal write: */
-static void bch2_journal_add_btree_root(struct journal_buf *buf,
- enum btree_id id, struct bkey_i *k,
- unsigned level)
-{
- struct jset_entry *entry;
-
- entry = bch2_journal_add_entry_noreservation(buf, k->k.u64s);
- entry->type = BCH_JSET_ENTRY_btree_root;
- entry->btree_id = id;
- entry->level = level;
- memcpy_u64s(entry->_data, k, k->k.u64s);
-}
-
static unsigned journal_dev_buckets_available(struct journal *j,
struct journal_device *ja)
{
@@ -1206,25 +1193,27 @@ void bch2_journal_write(struct closure *cl)
struct bch_fs *c = container_of(j, struct bch_fs, journal);
struct bch_dev *ca;
struct journal_buf *w = journal_prev_buf(j);
+ struct jset_entry *start, *end;
struct jset *jset;
struct bio *bio;
struct bch_extent_ptr *ptr;
bool validate_before_checksum = false;
- unsigned i, sectors, bytes;
+ unsigned i, sectors, bytes, u64s;
journal_buf_realloc(j, w);
jset = w->data;
j->write_start_time = local_clock();
- mutex_lock(&c->btree_root_lock);
- for (i = 0; i < BTREE_ID_NR; i++) {
- struct btree_root *r = &c->btree_roots[i];
- if (r->alive)
- bch2_journal_add_btree_root(w, i, &r->key, r->level);
- }
- c->btree_roots_dirty = false;
- mutex_unlock(&c->btree_root_lock);
+ start = vstruct_last(w->data);
+ end = bch2_journal_super_entries_add_common(c, start,
+ le64_to_cpu(jset->seq));
+ u64s = (u64 *) end - (u64 *) start;
+ BUG_ON(u64s > j->entry_u64s_reserved);
+
+ le32_add_cpu(&w->data->u64s, u64s);
+ BUG_ON(vstruct_sectors(jset, c->block_bits) >
+ w->disk_sectors);
journal_write_compact(jset);
diff --git a/fs/bcachefs/replicas.c b/fs/bcachefs/replicas.c
index 991d409b6a86..8495cac29a14 100644
--- a/fs/bcachefs/replicas.c
+++ b/fs/bcachefs/replicas.c
@@ -30,11 +30,6 @@ static void replicas_entry_sort(struct bch_replicas_entry *e)
bubble_sort(e->devs, e->nr_devs, u8_cmp);
}
-#define for_each_cpu_replicas_entry(_r, _i) \
- for (_i = (_r)->entries; \
- (void *) (_i) < (void *) (_r)->entries + (_r)->nr * (_r)->entry_size;\
- _i = (void *) (_i) + (_r)->entry_size)
-
static void bch2_cpu_replicas_sort(struct bch_replicas_cpu *r)
{
eytzinger0_sort(r->entries, r->nr, r->entry_size, memcmp, NULL);
diff --git a/fs/bcachefs/replicas.h b/fs/bcachefs/replicas.h
index 4fabe0372ec3..35164887dffb 100644
--- a/fs/bcachefs/replicas.h
+++ b/fs/bcachefs/replicas.h
@@ -57,6 +57,11 @@ unsigned bch2_dev_has_data(struct bch_fs *, struct bch_dev *);
int bch2_replicas_gc_end(struct bch_fs *, int);
int bch2_replicas_gc_start(struct bch_fs *, unsigned);
+#define for_each_cpu_replicas_entry(_r, _i) \
+ for (_i = (_r)->entries; \
+ (void *) (_i) < (void *) (_r)->entries + (_r)->nr * (_r)->entry_size;\
+ _i = (void *) (_i) + (_r)->entry_size)
+
/* iterate over superblock replicas - used by userspace tools: */
#define replicas_entry_bytes(_i) \
diff --git a/fs/bcachefs/super-io.c b/fs/bcachefs/super-io.c
index 2ad1266e167d..9e991be3d90d 100644
--- a/fs/bcachefs/super-io.c
+++ b/fs/bcachefs/super-io.c
@@ -885,29 +885,112 @@ void bch2_sb_clean_renumber(struct bch_sb_field_clean *clean, int write)
bch2_bkey_renumber(BKEY_TYPE_BTREE, bkey_to_packed(entry->start), write);
}
-void bch2_fs_mark_clean(struct bch_fs *c, bool clean)
+static void bch2_fs_mark_dirty(struct bch_fs *c)
{
- struct bch_sb_field_clean *sb_clean;
- unsigned u64s = sizeof(*sb_clean) / sizeof(u64);
- struct jset_entry *entry;
- struct btree_root *r;
-
mutex_lock(&c->sb_lock);
- if (clean == BCH_SB_CLEAN(c->disk_sb.sb))
- goto out;
-
- SET_BCH_SB_CLEAN(c->disk_sb.sb, clean);
+ if (BCH_SB_CLEAN(c->disk_sb.sb)) {
+ SET_BCH_SB_CLEAN(c->disk_sb.sb, false);
+ bch2_write_super(c);
+ }
+ mutex_unlock(&c->sb_lock);
+}
- if (!clean)
- goto write_super;
+struct jset_entry *
+bch2_journal_super_entries_add_common(struct bch_fs *c,
+ struct jset_entry *entry,
+ u64 journal_seq)
+{
+ struct jset_entry_usage *u;
+ struct btree_root *r;
+ unsigned i;
mutex_lock(&c->btree_root_lock);
for (r = c->btree_roots;
r < c->btree_roots + BTREE_ID_NR;
r++)
- if (r->alive)
- u64s += jset_u64s(r->key.u64s);
+ if (r->alive) {
+ entry->u64s = r->key.u64s;
+ entry->btree_id = r - c->btree_roots;
+ entry->level = r->level;
+ entry->type = BCH_JSET_ENTRY_btree_root;
+ bkey_copy(&entry->start[0], &r->key);
+
+ entry = vstruct_next(entry);
+ }
+ c->btree_roots_dirty = false;
+
+ mutex_unlock(&c->btree_root_lock);
+
+ if (journal_seq)
+ return entry;
+
+ percpu_down_write(&c->mark_lock);
+
+ {
+ u64 nr_inodes = percpu_u64_get(&c->usage[0]->s.nr_inodes);
+
+ 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;
+ u->entry.type = BCH_JSET_ENTRY_usage;
+ u->sectors = cpu_to_le64(nr_inodes);
+ u->type = FS_USAGE_INODES;
+
+ entry = vstruct_next(entry);
+ }
+
+ {
+ 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;
+ u->entry.type = BCH_JSET_ENTRY_usage;
+ u->sectors = cpu_to_le64(atomic64_read(&c->key_version));
+ u->type = FS_USAGE_KEY_VERSION;
+
+ entry = vstruct_next(entry);
+ }
+
+ for (i = 0; i < c->replicas.nr; i++) {
+ struct bch_replicas_entry *e =
+ cpu_replicas_entry(&c->replicas, i);
+ u64 sectors = percpu_u64_get(&c->usage[0]->data[i]);
+
+ u = container_of(entry, struct jset_entry_usage, entry);
+ u->entry.u64s = DIV_ROUND_UP(sizeof(*u) + e->nr_devs,
+ sizeof(u64)) - 1;
+ u->entry.type = BCH_JSET_ENTRY_usage;
+ u->sectors = cpu_to_le64(sectors);
+ u->type = FS_USAGE_REPLICAS;
+ unsafe_memcpy(&u->r, e, replicas_entry_bytes(e),
+ "embedded variable length struct");
+
+ entry = vstruct_next(entry);
+ }
+
+ percpu_up_write(&c->mark_lock);
+
+ return entry;
+}
+
+void bch2_fs_mark_clean(struct bch_fs *c, bool clean)
+{
+ struct bch_sb_field_clean *sb_clean;
+ struct jset_entry *entry;
+ unsigned u64s;
+
+ if (!clean) {
+ bch2_fs_mark_dirty(c);
+ return;
+ }
+
+ mutex_lock(&c->sb_lock);
+ if (BCH_SB_CLEAN(c->disk_sb.sb))
+ goto out;
+
+ SET_BCH_SB_CLEAN(c->disk_sb.sb, true);
+
+ u64s = sizeof(*sb_clean) / sizeof(u64) + c->journal.entry_u64s_reserved;
sb_clean = bch2_sb_resize_clean(&c->disk_sb, u64s);
if (!sb_clean) {
@@ -921,30 +1004,16 @@ void bch2_fs_mark_clean(struct bch_fs *c, bool clean)
sb_clean->journal_seq = journal_cur_seq(&c->journal) - 1;
entry = sb_clean->start;
+ entry = bch2_journal_super_entries_add_common(c, entry, 0);
+ BUG_ON((void *) entry > vstruct_end(&sb_clean->field));
+
memset(entry, 0,
vstruct_end(&sb_clean->field) - (void *) entry);
- for (r = c->btree_roots;
- r < c->btree_roots + BTREE_ID_NR;
- r++)
- if (r->alive) {
- entry->u64s = r->key.u64s;
- entry->btree_id = r - c->btree_roots;
- entry->level = r->level;
- entry->type = BCH_JSET_ENTRY_btree_root;
- bkey_copy(&entry->start[0], &r->key);
- entry = vstruct_next(entry);
- BUG_ON((void *) entry > vstruct_end(&sb_clean->field));
- }
-
- BUG_ON(entry != vstruct_end(&sb_clean->field));
-
if (le16_to_cpu(c->disk_sb.sb->version) <
bcachefs_metadata_version_bkey_renumber)
bch2_sb_clean_renumber(sb_clean, WRITE);
- mutex_unlock(&c->btree_root_lock);
-write_super:
bch2_write_super(c);
out:
mutex_unlock(&c->sb_lock);
diff --git a/fs/bcachefs/super-io.h b/fs/bcachefs/super-io.h
index ac3b704f0540..498a9e887d4e 100644
--- a/fs/bcachefs/super-io.h
+++ b/fs/bcachefs/super-io.h
@@ -135,6 +135,10 @@ static inline struct bch_member_cpu bch2_mi_to_cpu(struct bch_member *mi)
/* BCH_SB_FIELD_clean: */
+struct jset_entry *
+bch2_journal_super_entries_add_common(struct bch_fs *,
+ struct jset_entry *, u64);
+
void bch2_sb_clean_renumber(struct bch_sb_field_clean *, int);
void bch2_fs_mark_clean(struct bch_fs *, bool);