summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2019-01-24 17:12:00 -0500
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-22 17:08:15 -0400
commit2c5af169f72c1018e83b79ac82ffe387534910e8 (patch)
tree818bbcd3317dc579323e2a2dfa75cabeb12b3104
parent24547d097a520312cf9d727d3af8da1b0c985f98 (diff)
downloadlwn-2c5af169f72c1018e83b79ac82ffe387534910e8.tar.gz
lwn-2c5af169f72c1018e83b79ac82ffe387534910e8.zip
bcachefs: reserve space in journal for fs usage entries
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
-rw-r--r--fs/bcachefs/bcachefs.h2
-rw-r--r--fs/bcachefs/bcachefs_format.h17
-rw-r--r--fs/bcachefs/journal_io.c39
-rw-r--r--fs/bcachefs/recovery.c3
-rw-r--r--fs/bcachefs/replicas.c34
-rw-r--r--fs/bcachefs/replicas.h2
-rw-r--r--fs/bcachefs/super.c1
7 files changed, 84 insertions, 14 deletions
diff --git a/fs/bcachefs/bcachefs.h b/fs/bcachefs/bcachefs.h
index 4a0e2f63e645..90c44ef0fbe0 100644
--- a/fs/bcachefs/bcachefs.h
+++ b/fs/bcachefs/bcachefs.h
@@ -545,6 +545,8 @@ struct bch_fs {
struct bch_replicas_cpu replicas_gc;
struct mutex replicas_gc_lock;
+ struct journal_entry_res replicas_journal_res;
+
struct bch_disk_groups_cpu __rcu *disk_groups;
struct bch_opts opts;
diff --git a/fs/bcachefs/bcachefs_format.h b/fs/bcachefs/bcachefs_format.h
index f6cf4ccedcb1..bd41628f2995 100644
--- a/fs/bcachefs/bcachefs_format.h
+++ b/fs/bcachefs/bcachefs_format.h
@@ -1362,7 +1362,8 @@ static inline __u64 __bset_magic(struct bch_sb *sb)
x(btree_root, 1) \
x(prio_ptrs, 2) \
x(blacklist, 3) \
- x(blacklist_v2, 4)
+ x(blacklist_v2, 4) \
+ x(usage, 5)
enum {
#define x(f, nr) BCH_JSET_ENTRY_##f = nr,
@@ -1392,6 +1393,20 @@ struct jset_entry_blacklist_v2 {
__le64 end;
};
+enum {
+ FS_USAGE_REPLICAS = 0,
+ FS_USAGE_INODES = 1,
+ FS_USAGE_KEY_VERSION = 2,
+ FS_USAGE_NR = 3
+};
+
+struct jset_entry_usage {
+ struct jset_entry entry;
+ __le64 sectors;
+ __u8 type;
+ struct bch_replicas_entry r;
+} __attribute__((packed));
+
/*
* On disk format for a journal entry:
* seq is monotonically increasing; every journal entry has its own unique
diff --git a/fs/bcachefs/journal_io.c b/fs/bcachefs/journal_io.c
index 9c794c9a1924..173aecfaebc2 100644
--- a/fs/bcachefs/journal_io.c
+++ b/fs/bcachefs/journal_io.c
@@ -284,6 +284,7 @@ static int journal_entry_validate_blacklist_v2(struct bch_fs *c,
if (journal_entry_err_on(le16_to_cpu(entry->u64s) != 2, c,
"invalid journal seq blacklist entry: bad size")) {
journal_entry_null_range(entry, vstruct_next(entry));
+ goto out;
}
bl_entry = container_of(entry, struct jset_entry_blacklist_v2, entry);
@@ -293,6 +294,28 @@ static int journal_entry_validate_blacklist_v2(struct bch_fs *c,
"invalid journal seq blacklist entry: start > end")) {
journal_entry_null_range(entry, vstruct_next(entry));
}
+out:
+fsck_err:
+ return ret;
+}
+
+static int journal_entry_validate_usage(struct bch_fs *c,
+ struct jset *jset,
+ struct jset_entry *entry,
+ int write)
+{
+ struct jset_entry_usage *u =
+ container_of(entry, struct jset_entry_usage, entry);
+ unsigned bytes = jset_u64s(le16_to_cpu(entry->u64s)) * sizeof(u64);
+ int ret = 0;
+
+ if (journal_entry_err_on(bytes < sizeof(*u) ||
+ bytes < sizeof(*u) + u->r.nr_devs,
+ c,
+ "invalid journal entry usage: bad size")) {
+ journal_entry_null_range(entry, vstruct_next(entry));
+ return ret;
+ }
fsck_err:
return ret;
@@ -315,18 +338,10 @@ static const struct jset_entry_ops bch2_jset_entry_ops[] = {
static int journal_entry_validate(struct bch_fs *c, struct jset *jset,
struct jset_entry *entry, int write)
{
- int ret = 0;
-
- if (entry->type >= BCH_JSET_ENTRY_NR) {
- journal_entry_err(c, "invalid journal entry type %u",
- entry->type);
- journal_entry_null_range(entry, vstruct_next(entry));
- return 0;
- }
-
- ret = bch2_jset_entry_ops[entry->type].validate(c, jset, entry, write);
-fsck_err:
- return ret;
+ return entry->type < BCH_JSET_ENTRY_NR
+ ? bch2_jset_entry_ops[entry->type].validate(c, jset,
+ entry, write)
+ : 0;
}
static int jset_validate_entries(struct bch_fs *c, struct jset *jset,
diff --git a/fs/bcachefs/recovery.c b/fs/bcachefs/recovery.c
index 2ff86262d41c..cb9601dfcd37 100644
--- a/fs/bcachefs/recovery.c
+++ b/fs/bcachefs/recovery.c
@@ -108,7 +108,8 @@ static bool journal_empty(struct list_head *journal)
list_for_each_entry(i, journal, list) {
vstruct_for_each(&i->j, entry) {
- if (entry->type == BCH_JSET_ENTRY_btree_root)
+ if (entry->type == BCH_JSET_ENTRY_btree_root ||
+ entry->type == BCH_JSET_ENTRY_usage)
continue;
if (entry->type == BCH_JSET_ENTRY_btree_keys &&
diff --git a/fs/bcachefs/replicas.c b/fs/bcachefs/replicas.c
index 5663441fd7ce..991d409b6a86 100644
--- a/fs/bcachefs/replicas.c
+++ b/fs/bcachefs/replicas.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
#include "bcachefs.h"
+#include "journal.h"
#include "replicas.h"
#include "super-io.h"
@@ -302,6 +303,27 @@ err:
return ret;
}
+static unsigned reserve_journal_replicas(struct bch_fs *c,
+ struct bch_replicas_cpu *r)
+{
+ struct bch_replicas_entry *e;
+ unsigned journal_res_u64s = 0;
+
+ /* nr_inodes: */
+ journal_res_u64s +=
+ DIV_ROUND_UP(sizeof(struct jset_entry_usage), sizeof(u64));
+
+ /* key_version: */
+ journal_res_u64s +=
+ DIV_ROUND_UP(sizeof(struct jset_entry_usage), sizeof(u64));
+
+ for_each_cpu_replicas_entry(r, e)
+ journal_res_u64s +=
+ DIV_ROUND_UP(sizeof(struct jset_entry_usage) +
+ e->nr_devs, sizeof(u64));
+ return journal_res_u64s;
+}
+
noinline
static int bch2_mark_replicas_slowpath(struct bch_fs *c,
struct bch_replicas_entry *new_entry)
@@ -329,6 +351,10 @@ static int bch2_mark_replicas_slowpath(struct bch_fs *c,
ret = bch2_cpu_replicas_to_sb_replicas(c, &new_r);
if (ret)
goto err;
+
+ bch2_journal_entry_res_resize(&c->journal,
+ &c->replicas_journal_res,
+ reserve_journal_replicas(c, &new_r));
}
if (!new_r.entries &&
@@ -595,6 +621,7 @@ int bch2_sb_replicas_to_cpu_replicas(struct bch_fs *c)
bch2_cpu_replicas_sort(&new_r);
percpu_down_write(&c->mark_lock);
+
ret = replicas_table_update(c, &new_r);
percpu_up_write(&c->mark_lock);
@@ -915,3 +942,10 @@ unsigned bch2_dev_has_data(struct bch_fs *c, struct bch_dev *ca)
return ret;
}
+
+int bch2_fs_replicas_init(struct bch_fs *c)
+{
+ c->journal.entry_u64s_reserved +=
+ reserve_journal_replicas(c, &c->replicas);
+ return 0;
+}
diff --git a/fs/bcachefs/replicas.h b/fs/bcachefs/replicas.h
index 923bddb21ec3..4fabe0372ec3 100644
--- a/fs/bcachefs/replicas.h
+++ b/fs/bcachefs/replicas.h
@@ -80,4 +80,6 @@ int bch2_sb_replicas_to_cpu_replicas(struct bch_fs *);
extern const struct bch_sb_field_ops bch_sb_field_ops_replicas;
extern const struct bch_sb_field_ops bch_sb_field_ops_replicas_v0;
+int bch2_fs_replicas_init(struct bch_fs *);
+
#endif /* _BCACHEFS_REPLICAS_H */
diff --git a/fs/bcachefs/super.c b/fs/bcachefs/super.c
index 9ec05410aeb4..8a5ee2835bbd 100644
--- a/fs/bcachefs/super.c
+++ b/fs/bcachefs/super.c
@@ -658,6 +658,7 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts)
bch2_io_clock_init(&c->io_clock[READ]) ||
bch2_io_clock_init(&c->io_clock[WRITE]) ||
bch2_fs_journal_init(&c->journal) ||
+ bch2_fs_replicas_init(c) ||
bch2_fs_btree_cache_init(c) ||
bch2_fs_io_init(c) ||
bch2_fs_encryption_init(c) ||