diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2019-01-24 17:12:00 -0500 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-10-22 17:08:15 -0400 |
commit | 2c5af169f72c1018e83b79ac82ffe387534910e8 (patch) | |
tree | 818bbcd3317dc579323e2a2dfa75cabeb12b3104 | |
parent | 24547d097a520312cf9d727d3af8da1b0c985f98 (diff) | |
download | lwn-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.h | 2 | ||||
-rw-r--r-- | fs/bcachefs/bcachefs_format.h | 17 | ||||
-rw-r--r-- | fs/bcachefs/journal_io.c | 39 | ||||
-rw-r--r-- | fs/bcachefs/recovery.c | 3 | ||||
-rw-r--r-- | fs/bcachefs/replicas.c | 34 | ||||
-rw-r--r-- | fs/bcachefs/replicas.h | 2 | ||||
-rw-r--r-- | fs/bcachefs/super.c | 1 |
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) || |