Compare commits

...

2 Commits

Author SHA1 Message Date
Kent Overstreet
96aa355c1d Update bcachefs sources to 2a26443359de bcachefs: btree_node_root_err() etc. now print
Some checks failed
build / bcachefs-tools-msrv (push) Has been cancelled
.deb build orchestrator / source-only (push) Has been cancelled
Nix Flake actions / nix-matrix (push) Has been cancelled
Nix Flake actions / ${{ matrix.name }} (${{ matrix.system }}) (push) Has been cancelled
.deb build orchestrator / obs (push) Has been cancelled
.deb build orchestrator / buildd (map[name:debian version:forky], map[build-arch:amd64 host-arch:amd64 machine-arch:amd64 runs-on:ubuntu-24.04]) (push) Has been cancelled
.deb build orchestrator / buildd (map[name:debian version:forky], map[build-arch:amd64 host-arch:ppc64el machine-arch:amd64 runs-on:ubuntu-24.04]) (push) Has been cancelled
.deb build orchestrator / buildd (map[name:debian version:forky], map[build-arch:arm64 host-arch:arm64 machine-arch:arm64 runs-on:ubuntu-24.04-arm]) (push) Has been cancelled
.deb build orchestrator / buildd (map[name:debian version:trixie], map[build-arch:amd64 host-arch:amd64 machine-arch:amd64 runs-on:ubuntu-24.04]) (push) Has been cancelled
.deb build orchestrator / buildd (map[name:debian version:trixie], map[build-arch:amd64 host-arch:ppc64el machine-arch:amd64 runs-on:ubuntu-24.04]) (push) Has been cancelled
.deb build orchestrator / buildd (map[name:debian version:trixie], map[build-arch:arm64 host-arch:arm64 machine-arch:arm64 runs-on:ubuntu-24.04-arm]) (push) Has been cancelled
.deb build orchestrator / buildd (map[name:debian version:unstable], map[build-arch:amd64 host-arch:amd64 machine-arch:amd64 runs-on:ubuntu-24.04]) (push) Has been cancelled
.deb build orchestrator / buildd (map[name:debian version:unstable], map[build-arch:amd64 host-arch:ppc64el machine-arch:amd64 runs-on:ubuntu-24.04]) (push) Has been cancelled
.deb build orchestrator / buildd (map[name:debian version:unstable], map[build-arch:arm64 host-arch:arm64 machine-arch:arm64 runs-on:ubuntu-24.04-arm]) (push) Has been cancelled
.deb build orchestrator / buildd (map[name:ubuntu version:plucky], map[build-arch:amd64 host-arch:amd64 machine-arch:amd64 runs-on:ubuntu-24.04]) (push) Has been cancelled
.deb build orchestrator / buildd (map[name:ubuntu version:plucky], map[build-arch:arm64 host-arch:arm64 machine-arch:arm64 runs-on:ubuntu-24.04-arm]) (push) Has been cancelled
.deb build orchestrator / buildd (map[name:ubuntu version:questing], map[build-arch:amd64 host-arch:amd64 machine-arch:amd64 runs-on:ubuntu-24.04]) (push) Has been cancelled
.deb build orchestrator / buildd (map[name:ubuntu version:questing], map[build-arch:arm64 host-arch:arm64 machine-arch:arm64 runs-on:ubuntu-24.04-arm]) (push) Has been cancelled
.deb build orchestrator / reprotest (push) Has been cancelled
.deb build orchestrator / publish (push) Has been cancelled
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2025-12-01 15:04:45 -05:00
Kent Overstreet
573dc50246 Update bcachefs sources to 452d7a3f10e4 bcachefs: data_read_fail_and_poison on by default
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2025-12-01 01:53:27 -05:00
72 changed files with 971 additions and 813 deletions

View File

@ -1 +1 @@
56d76a11ee0410a197639f978efd2b13e6968143
2a26443359de230e360b7de6531db938bfb0cbd8

View File

@ -41,6 +41,10 @@ DEFINE_LOCK_GUARD_1(spinlock, spinlock_t,
spin_lock(_T->lock),
spin_unlock(_T->lock))
DEFINE_LOCK_GUARD_1(spinlock_irqsave, spinlock_t,
spin_lock(_T->lock),
spin_unlock(_T->lock))
DEFINE_LOCK_GUARD_1_COND(spinlock, _try, spin_trylock(_T->lock))
DEFINE_LOCK_GUARD_1(spinlock_irq, spinlock_t,
spin_lock_irq(_T->lock),

View File

@ -23,6 +23,7 @@ bcachefs-y := \
btree/cache.o \
btree/check.o \
btree/commit.o \
btree/init.o \
btree/interior.o \
btree/iter.o \
btree/journal_overlay.o \

View File

@ -495,6 +495,27 @@ void __bch2_accounting_maybe_kill(struct bch_fs *c, struct bpos pos)
bch2_write_super(c);
}
void bch2_accounting_mem_gc(struct bch_fs *c)
{
struct bch_accounting_mem *acc = &c->accounting;
guard(percpu_write)(&c->capacity.mark_lock);
struct accounting_mem_entry *dst = acc->k.data;
darray_for_each(acc->k, src) {
if (accounting_mem_entry_is_zero(src)) {
free_percpu(src->v[0]);
free_percpu(src->v[1]);
} else {
*dst++ = *src;
}
}
acc->k.nr = dst - acc->k.data;
eytzinger0_sort(acc->k.data, acc->k.nr, sizeof(acc->k.data[0]),
accounting_pos_cmp, NULL);
}
/*
* Read out accounting keys for replicas entries, as an array of
* bch_replicas_usage entries.

View File

@ -146,6 +146,7 @@ enum bch_accounting_mode {
int bch2_accounting_mem_insert(struct bch_fs *, struct bkey_s_c_accounting, enum bch_accounting_mode);
int bch2_accounting_mem_insert_locked(struct bch_fs *, struct bkey_s_c_accounting, enum bch_accounting_mode);
void bch2_accounting_mem_gc(struct bch_fs *);
static inline bool bch2_accounting_is_mem(struct disk_accounting_pos *acc)
{

View File

@ -411,7 +411,7 @@ static int bch2_check_backpointer_has_valid_bucket(struct btree_trans *trans, st
int bch2_check_btree_backpointers(struct bch_fs *c)
{
struct progress_indicator progress;
bch2_progress_init(&progress, c, BIT_ULL(BTREE_ID_backpointers));
bch2_progress_init(&progress, __func__, c, BIT_ULL(BTREE_ID_backpointers), 0);
struct wb_maybe_flush last_flushed __cleanup(wb_maybe_flush_exit);
wb_maybe_flush_init(&last_flushed);
@ -420,7 +420,7 @@ int bch2_check_btree_backpointers(struct bch_fs *c)
return for_each_btree_key_commit(trans, iter,
BTREE_ID_backpointers, POS_MIN, 0, k,
NULL, NULL, BCH_TRANS_COMMIT_no_enospc, ({
progress_update_iter(trans, &progress, &iter) ?:
bch2_progress_update_iter(trans, &progress, &iter) ?:
bch2_check_backpointer_has_valid_bucket(trans, k, &last_flushed);
}));
}
@ -729,10 +729,10 @@ static int bch2_get_btree_in_memory_pos(struct btree_trans *trans,
btree_interior_mask |= btree_leaf_mask;
c->btree_cache.pinned_nodes_mask[0] = btree_leaf_mask;
c->btree_cache.pinned_nodes_mask[1] = btree_interior_mask;
c->btree_cache.pinned_nodes_start = start;
c->btree_cache.pinned_nodes_end = *end = BBPOS_MAX;
c->btree.cache.pinned_nodes_mask[0] = btree_leaf_mask;
c->btree.cache.pinned_nodes_mask[1] = btree_interior_mask;
c->btree.cache.pinned_nodes_start = start;
c->btree.cache.pinned_nodes_end = *end = BBPOS_MAX;
for (enum btree_id btree = start.btree;
btree < BTREE_ID_NR && !ret;
@ -748,7 +748,7 @@ static int bch2_get_btree_in_memory_pos(struct btree_trans *trans,
0, depth, BTREE_ITER_prefetch, b, ({
mem_may_pin -= btree_buf_bytes(b);
if (mem_may_pin <= 0) {
c->btree_cache.pinned_nodes_end = *end =
c->btree.cache.pinned_nodes_end = *end =
BBPOS(btree, b->key.k.p);
break;
}
@ -766,7 +766,7 @@ static int bch2_check_extents_to_backpointers_pass(struct btree_trans *trans,
struct bch_fs *c = trans->c;
struct progress_indicator progress;
bch2_progress_init_inner(&progress, trans->c,
bch2_progress_init(&progress, "extents_to_backpointers", trans->c,
btree_has_data_ptrs_mask,
~0ULL);
@ -783,7 +783,7 @@ static int bch2_check_extents_to_backpointers_pass(struct btree_trans *trans,
CLASS(btree_node_iter, iter)(trans, btree_id, POS_MIN, 0, level, BTREE_ITER_prefetch);
try(for_each_btree_key_continue(trans, iter, 0, k, ({
bch2_progress_update_iter(trans, &progress, &iter, "extents_to_backpointers") ?:
bch2_progress_update_iter(trans, &progress, &iter) ?:
wb_maybe_flush_inc(&s->last_flushed) ?:
check_extent_to_backpointers(trans, s, btree_id, level, k) ?:
bch2_trans_commit(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc);
@ -1263,11 +1263,12 @@ static int bch2_check_backpointers_to_extents_pass(struct btree_trans *trans,
wb_maybe_flush_init(&last_flushed);
struct progress_indicator progress;
bch2_progress_init(&progress, trans->c, BIT_ULL(BTREE_ID_backpointers));
bch2_progress_init(&progress, "backpointers_to_extents", trans->c,
BIT_ULL(BTREE_ID_backpointers), 0);
return for_each_btree_key(trans, iter, BTREE_ID_backpointers,
POS_MIN, BTREE_ITER_prefetch, k, ({
bch2_progress_update_iter(trans, &progress, &iter, "backpointers_to_extents") ?:
bch2_progress_update_iter(trans, &progress, &iter);
check_one_backpointer(trans, start, end, k, &last_flushed);
}));
}

View File

@ -504,7 +504,7 @@ static int check_btree_alloc_iter(struct btree_trans *trans,
if (!k.k)
return 1;
try(progress_update_iter(trans, progress, iter));
try(bch2_progress_update_iter(trans, progress, iter));
struct bpos next;
if (k.k->type) {
@ -536,7 +536,7 @@ static int check_btree_alloc_iter(struct btree_trans *trans,
static int check_btree_alloc(struct btree_trans *trans)
{
struct progress_indicator progress;
bch2_progress_init(&progress, trans->c, BIT_ULL(BTREE_ID_alloc));
bch2_progress_init(&progress, __func__, trans->c, BIT_ULL(BTREE_ID_alloc), 0);
CLASS(btree_iter, iter)(trans, BTREE_ID_alloc, POS_MIN, BTREE_ITER_prefetch);
CLASS(btree_iter, discard_iter)(trans, BTREE_ID_need_discard, POS_MIN, BTREE_ITER_prefetch);
@ -663,13 +663,13 @@ int bch2_check_alloc_to_lru_refs(struct bch_fs *c)
wb_maybe_flush_init(&last_flushed);
struct progress_indicator progress;
bch2_progress_init(&progress, c, BIT_ULL(BTREE_ID_alloc));
bch2_progress_init(&progress, __func__, c, BIT_ULL(BTREE_ID_alloc), 0);
CLASS(btree_trans, trans)(c);
return for_each_btree_key_commit(trans, iter, BTREE_ID_alloc,
POS_MIN, BTREE_ITER_prefetch, k,
NULL, NULL, BCH_TRANS_COMMIT_no_enospc, ({
progress_update_iter(trans, &progress, &iter) ?:
bch2_progress_update_iter(trans, &progress, &iter) ?:
wb_maybe_flush_inc(&last_flushed) ?:
bch2_check_alloc_to_lru_ref(trans, &iter, &last_flushed);
}))?: bch2_check_stripe_to_lru_refs(trans);

View File

@ -1008,10 +1008,10 @@ void bch2_open_buckets_stop(struct bch_fs *c, struct bch_dev *ca,
bch2_writepoint_stop(c, ca, ec, &a->reconcile_write_point);
bch2_writepoint_stop(c, ca, ec, &a->btree_write_point);
scoped_guard(mutex, &c->btree_reserve_cache.lock)
while (c->btree_reserve_cache.nr) {
scoped_guard(mutex, &c->btree.reserve_cache.lock)
while (c->btree.reserve_cache.nr) {
struct btree_alloc *a =
&c->btree_reserve_cache.data[--c->btree_reserve_cache.nr];
&c->btree.reserve_cache.data[--c->btree.reserve_cache.nr];
bch2_open_buckets_put(c, &a->ob);
}
@ -1528,7 +1528,7 @@ void bch2_fs_alloc_debug_to_text(struct printbuf *out, struct bch_fs *c)
prt_printf(out, "open_buckets_wait\t%s\n", a->open_buckets_wait.list.first ? "waiting" : "empty");
prt_printf(out, "open_buckets_btree\t%u\n", nr[BCH_DATA_btree]);
prt_printf(out, "open_buckets_user\t%u\n", nr[BCH_DATA_user]);
prt_printf(out, "btree reserve cache\t%u\n", c->btree_reserve_cache.nr);
prt_printf(out, "btree reserve cache\t%u\n", c->btree.reserve_cache.nr);
}
void bch2_dev_alloc_debug_to_text(struct printbuf *out, struct bch_dev *ca)

View File

@ -204,13 +204,13 @@ int bch2_check_lrus(struct bch_fs *c)
wb_maybe_flush_init(&last_flushed);
struct progress_indicator progress;
bch2_progress_init(&progress, c, BIT_ULL(BTREE_ID_lru));
bch2_progress_init(&progress, __func__, c, BIT_ULL(BTREE_ID_lru), 0);
CLASS(btree_trans, trans)(c);
return for_each_btree_key_commit(trans, iter,
BTREE_ID_lru, POS_MIN, BTREE_ITER_prefetch, k,
NULL, NULL, BCH_TRANS_COMMIT_no_enospc, ({
progress_update_iter(trans, &progress, &iter) ?:
bch2_progress_update_iter(trans, &progress, &iter) ?:
wb_maybe_flush_inc(&last_flushed) ?:
bch2_check_lru_key(trans, &iter, k, &last_flushed);
}));

View File

@ -484,6 +484,60 @@ int bch2_replicas_gc_reffed(struct bch_fs *c)
return 0;
}
int bch2_replicas_gc_accounted(struct bch_fs *c)
{
int ret = 0;
bch2_accounting_mem_gc(c);
guard(mutex)(&c->sb_lock);
scoped_guard(percpu_write, &c->capacity.mark_lock) {
struct bch_replicas_cpu new = {
.entry_size = c->replicas.entry_size,
.entries = kcalloc(c->replicas.nr, c->replicas.entry_size, GFP_KERNEL),
};
if (!new.entries) {
bch_err(c, "error allocating c->replicas_gc");
return bch_err_throw(c, ENOMEM_replicas_gc);
}
for (unsigned i = 0; i < c->replicas.nr; i++) {
struct bch_replicas_entry_cpu *e =
cpu_replicas_entry(&c->replicas, i);
struct disk_accounting_pos k = {
.type = BCH_DISK_ACCOUNTING_replicas,
};
unsafe_memcpy(&k.replicas, &e->e, replicas_entry_bytes(&e->e),
"embedded variable length struct");
struct bpos p = disk_accounting_pos_to_bpos(&k);
struct bch_accounting_mem *acc = &c->accounting;
bool kill = eytzinger0_find(acc->k.data, acc->k.nr, sizeof(acc->k.data[0]),
accounting_pos_cmp, &p) >= acc->k.nr;
if (e->e.data_type == BCH_DATA_journal || !kill)
memcpy(cpu_replicas_entry(&new, new.nr++),
e, new.entry_size);
}
bch2_cpu_replicas_sort(&new);
ret = bch2_cpu_replicas_to_sb_replicas(c, &new);
if (!ret)
swap(c->replicas, new);
kfree(new.entries);
}
if (!ret)
bch2_write_super(c);
return ret;
}
/* Replicas tracking - superblock: */
static int

View File

@ -54,6 +54,7 @@ int bch2_replicas_entry_get(struct bch_fs *, struct bch_replicas_entry_v1 *);
void bch2_replicas_entry_kill(struct bch_fs *, struct bch_replicas_entry_v1 *);
int bch2_replicas_gc_reffed(struct bch_fs *);
int bch2_replicas_gc_accounted(struct bch_fs *);
static inline bool bch2_replicas_entry_has_dev(struct bch_replicas_entry_v1 *r, unsigned dev)
{

View File

@ -241,12 +241,10 @@
#include "alloc/types.h"
#include "btree/check_types.h"
#include "btree/interior_types.h"
#include "btree/journal_overlay_types.h"
#include "btree/types.h"
#include "btree/node_scan_types.h"
#include "btree/write_buffer_types.h"
#include "data/compress_types.h"
#include "data/copygc_types.h"
#include "data/ec_types.h"
#include "data/keylist_types.h"
@ -271,6 +269,8 @@
#include "snapshots/snapshot_types.h"
#include "snapshots/subvolume_types.h"
#include "vfs/types.h"
#define bch2_fs_init_fault(name) \
dynamic_fault("bcachefs:bch_fs_init:" name)
#define bch2_meta_read_fault(name) \
@ -318,23 +318,24 @@ void __bch2_print(struct bch_fs *c, const char *fmt, ...);
#define bch2_print(_c, ...) __bch2_print(maybe_dev_to_fs(_c), __VA_ARGS__)
#define bch2_print_ratelimited(_c, ...) \
do { \
static DEFINE_RATELIMIT_STATE(_rs, \
#define bch2_ratelimit() \
({ \
static DEFINE_RATELIMIT_STATE(rs, \
DEFAULT_RATELIMIT_INTERVAL, \
DEFAULT_RATELIMIT_BURST); \
\
if (__ratelimit(&_rs)) \
!__ratelimit(&rs); \
})
#define bch2_print_ratelimited(_c, ...) \
do { \
if (!bch2_ratelimit()) \
bch2_print(_c, __VA_ARGS__); \
} while (0)
#define bch2_print_str_ratelimited(_c, ...) \
do { \
static DEFINE_RATELIMIT_STATE(_rs, \
DEFAULT_RATELIMIT_INTERVAL, \
DEFAULT_RATELIMIT_BURST); \
\
if (__ratelimit(&_rs)) \
if (!bch2_ratelimit()) \
bch2_print_str(_c, __VA_ARGS__); \
} while (0)
@ -813,7 +814,6 @@ struct bch_fs {
struct unicode_map *cf_encoding;
unsigned short block_bits; /* ilog2(block_size) */
u16 btree_foreground_merge_threshold;
struct delayed_work maybe_schedule_btree_bitmap_gc;
@ -836,27 +836,7 @@ struct bch_fs {
struct bch_fs_recovery recovery;
/* BTREE CACHE */
/*
* A btree node on disk could have too many bsets for an iterator to fit
* on the stack - have to dynamically allocate them
*/
mempool_t fill_iter;
mempool_t btree_bounce_pool;
struct bio_set btree_bio;
struct workqueue_struct *btree_read_complete_wq;
struct workqueue_struct *btree_write_submit_wq;
struct journal_entry_res btree_root_journal_res;
struct workqueue_struct *btree_write_complete_wq;
struct bch_fs_btree_cache btree_cache;
struct bch_fs_btree_key_cache btree_key_cache;
struct bch_fs_btree_write_buffer btree_write_buffer;
struct bch_fs_btree_trans btree_trans;
struct bch_fs_btree_reserve_cache btree_reserve_cache;
struct bch_fs_btree_interior_updates btree_interior_updates;
struct bch_fs_btree_node_rewrites btree_node_rewrites;
struct find_btree_nodes found_btree_nodes;
struct bch_fs_btree btree;
struct bch_fs_gc gc;
struct bch_fs_gc_gens gc_gens;
@ -870,12 +850,7 @@ struct bch_fs {
struct bch_fs_snapshots snapshots;
/* btree_io.c: */
spinlock_t btree_write_error_lock;
struct btree_write_stats {
atomic64_t nr;
atomic64_t bytes;
} btree_write_stats[BTREE_WRITE_TYPE_NR];
spinlock_t write_error_lock;
/*
* Use a dedicated wq for write ref holder tasks. Required to avoid
* dependency problems with other wq tasks that can block on ref
@ -901,10 +876,6 @@ struct bch_fs {
nocow_locks;
struct rhashtable promote_table;
mempool_t compression_bounce[2];
mempool_t compress_workspace[BCH_COMPRESSION_OPT_NR];
size_t zstd_workspace_size;
struct bch_key chacha20_key;
bool chacha20_key_set;
@ -914,6 +885,7 @@ struct bch_fs {
struct list_head moving_context_list;
struct mutex moving_context_lock;
struct bch_fs_compress compress;
struct bch_fs_reconcile reconcile;
struct bch_fs_copygc copygc;
struct bch_fs_ec ec;
@ -922,18 +894,7 @@ struct bch_fs {
reflink_gc_table reflink_gc_table;
size_t reflink_gc_nr;
/* fs.c */
struct list_head vfs_inodes_list;
struct mutex vfs_inodes_lock;
struct rhashtable vfs_inodes_table;
struct rhltable vfs_inodes_by_inum_table;
struct workqueue_struct *vfs_writeback_wq;
/* VFS IO PATH - fs-io.c */
struct bio_set writepage_bioset;
struct bio_set dio_write_bioset;
struct bio_set dio_read_bioset;
struct bio_set nocow_flush_bioset;
struct bch_fs_vfs vfs;
/* QUOTAS */
struct bch_memquota_type quotas[QTYP_NR];

View File

@ -36,7 +36,7 @@ void bch2_recalc_btree_reserve(struct bch_fs *c)
{
unsigned reserve = 16;
if (!c->btree_cache.roots_known[0].b)
if (!c->btree.cache.roots_known[0].b)
reserve += 8;
for (unsigned i = 0; i < btree_id_nr_alive(c); i++) {
@ -46,7 +46,7 @@ void bch2_recalc_btree_reserve(struct bch_fs *c)
reserve += min_t(unsigned, 1, r->b->c.level) * 8;
}
c->btree_cache.nr_reserve = reserve;
c->btree.cache.nr_reserve = reserve;
}
static inline size_t btree_cache_can_free(struct btree_cache_list *list)
@ -81,7 +81,7 @@ static void __bch2_btree_node_to_freelist(struct bch_fs_btree_cache *bc, struct
void bch2_btree_node_to_freelist(struct bch_fs *c, struct btree *b)
{
struct bch_fs_btree_cache *bc = &c->btree_cache;
struct bch_fs_btree_cache *bc = &c->btree.cache;
scoped_guard(mutex, &bc->lock)
__bch2_btree_node_to_freelist(bc, b);
@ -217,7 +217,7 @@ static inline bool __btree_node_pinned(struct bch_fs_btree_cache *bc, struct btr
void bch2_node_pin(struct bch_fs *c, struct btree *b)
{
struct bch_fs_btree_cache *bc = &c->btree_cache;
struct bch_fs_btree_cache *bc = &c->btree.cache;
guard(mutex)(&bc->lock);
if (!btree_node_is_root(c, b) && !btree_node_pinned(b)) {
@ -230,7 +230,7 @@ void bch2_node_pin(struct bch_fs *c, struct btree *b)
void bch2_btree_cache_unpin(struct bch_fs *c)
{
struct bch_fs_btree_cache *bc = &c->btree_cache;
struct bch_fs_btree_cache *bc = &c->btree.cache;
struct btree *b, *n;
guard(mutex)(&bc->lock);
@ -304,7 +304,7 @@ void bch2_btree_node_update_key_early(struct btree_trans *trans,
enum btree_id btree, unsigned level,
struct bkey_s_c old, struct bkey_i *new)
{
struct bch_fs *c = trans->c;
struct bch_fs_btree_cache *bc = &trans->c->btree.cache;
struct btree *b;
struct bkey_buf tmp __cleanup(bch2_bkey_buf_exit);
int ret;
@ -314,12 +314,12 @@ void bch2_btree_node_update_key_early(struct btree_trans *trans,
b = bch2_btree_node_get_noiter(trans, tmp.k, btree, level, true);
if (!IS_ERR_OR_NULL(b)) {
guard(mutex)(&c->btree_cache.lock);
guard(mutex)(&bc->lock);
__bch2_btree_node_hash_remove(&c->btree_cache, b);
__bch2_btree_node_hash_remove(bc, b);
bkey_copy(&b->key, new);
ret = __bch2_btree_node_hash_insert(&c->btree_cache, b);
ret = __bch2_btree_node_hash_insert(bc, b);
BUG_ON(ret);
six_unlock_read(&b->c.lock);
@ -338,7 +338,7 @@ static inline struct btree *btree_cache_find(struct bch_fs_btree_cache *bc,
static int __btree_node_reclaim_checks(struct bch_fs *c, struct btree *b,
bool flush, bool locked)
{
struct bch_fs_btree_cache *bc = &c->btree_cache;
struct bch_fs_btree_cache *bc = &c->btree.cache;
lockdep_assert_held(&bc->lock);
@ -404,7 +404,7 @@ static int __btree_node_reclaim_checks(struct bch_fs *c, struct btree *b,
*/
static int __btree_node_reclaim(struct bch_fs *c, struct btree *b, bool flush)
{
struct bch_fs_btree_cache *bc = &c->btree_cache;
struct bch_fs_btree_cache *bc = &c->btree.cache;
int ret = 0;
lockdep_assert_held(&bc->lock);
@ -458,7 +458,7 @@ static unsigned long bch2_btree_cache_scan(struct shrinker *shrink,
struct btree_cache_list *list = shrink->private_data;
struct bch_fs_btree_cache *bc =
container_of(list, struct bch_fs_btree_cache, live[list->idx]);
struct bch_fs *c = container_of(bc, struct bch_fs, btree_cache);
struct bch_fs *c = container_of(bc, struct bch_fs, btree.cache);
struct btree *b, *t;
unsigned long nr = sc->nr_to_scan;
unsigned long can_free = 0;
@ -575,7 +575,7 @@ static unsigned long bch2_btree_cache_count(struct shrinker *shrink,
void bch2_fs_btree_cache_exit(struct bch_fs *c)
{
struct bch_fs_btree_cache *bc = &c->btree_cache;
struct bch_fs_btree_cache *bc = &c->btree.cache;
struct btree *b, *t;
shrinker_free(bc->live[1].shrink);
@ -634,7 +634,7 @@ void bch2_fs_btree_cache_exit(struct bch_fs *c)
int bch2_fs_btree_cache_init(struct bch_fs *c)
{
struct bch_fs_btree_cache *bc = &c->btree_cache;
struct bch_fs_btree_cache *bc = &c->btree.cache;
struct shrinker *shrink;
if (rhashtable_init(&bc->table, &bch_btree_cache_params))
@ -699,7 +699,7 @@ void bch2_fs_btree_cache_init_early(struct bch_fs_btree_cache *bc)
*/
void bch2_btree_cache_cannibalize_unlock(struct btree_trans *trans)
{
struct bch_fs_btree_cache *bc = &trans->c->btree_cache;
struct bch_fs_btree_cache *bc = &trans->c->btree.cache;
if (bc->alloc_lock == current) {
event_inc_trace(trans->c, btree_cache_cannibalize_unlock, buf,
@ -711,7 +711,7 @@ void bch2_btree_cache_cannibalize_unlock(struct btree_trans *trans)
static int __btree_cache_cannibalize_lock(struct bch_fs *c, struct closure *cl)
{
struct bch_fs_btree_cache *bc = &c->btree_cache;
struct bch_fs_btree_cache *bc = &c->btree.cache;
struct task_struct *old;
old = NULL;
@ -747,7 +747,7 @@ int bch2_btree_cache_cannibalize_lock(struct btree_trans *trans, struct closure
static struct btree *btree_node_cannibalize(struct bch_fs *c)
{
struct bch_fs_btree_cache *bc = &c->btree_cache;
struct bch_fs_btree_cache *bc = &c->btree.cache;
struct btree *b;
for (unsigned i = 0; i < ARRAY_SIZE(bc->live); i++)
@ -773,7 +773,7 @@ static struct btree *btree_node_cannibalize(struct bch_fs *c)
struct btree *bch2_btree_node_mem_alloc(struct btree_trans *trans, bool pcpu_read_locks)
{
struct bch_fs *c = trans->c;
struct bch_fs_btree_cache *bc = &c->btree_cache;
struct bch_fs_btree_cache *bc = &c->btree.cache;
struct list_head *freed = pcpu_read_locks
? &bc->freed_pcpu
: &bc->freed_nonpcpu;
@ -899,7 +899,7 @@ static noinline struct btree *bch2_btree_node_fill(struct btree_trans *trans,
bool sync)
{
struct bch_fs *c = trans->c;
struct bch_fs_btree_cache *bc = &c->btree_cache;
struct bch_fs_btree_cache *bc = &c->btree.cache;
struct btree *b;
EBUG_ON(path && level + 1 != path->level);
@ -1041,7 +1041,7 @@ static struct btree *__bch2_btree_node_get(struct btree_trans *trans, struct btr
unsigned long trace_ip)
{
struct bch_fs *c = trans->c;
struct bch_fs_btree_cache *bc = &c->btree_cache;
struct bch_fs_btree_cache *bc = &c->btree.cache;
struct btree *b;
int ret;
@ -1236,7 +1236,7 @@ struct btree *bch2_btree_node_get_noiter(struct btree_trans *trans,
bool nofill)
{
struct bch_fs *c = trans->c;
struct bch_fs_btree_cache *bc = &c->btree_cache;
struct bch_fs_btree_cache *bc = &c->btree.cache;
struct btree *b;
int ret;
@ -1319,7 +1319,7 @@ int bch2_btree_node_prefetch(struct btree_trans *trans,
enum btree_id btree_id, unsigned level)
{
struct bch_fs *c = trans->c;
struct bch_fs_btree_cache *bc = &c->btree_cache;
struct bch_fs_btree_cache *bc = &c->btree.cache;
BUG_ON(path && !btree_node_locked(path, level + 1));
BUG_ON(level >= BTREE_MAX_DEPTH);
@ -1338,7 +1338,7 @@ int bch2_btree_node_prefetch(struct btree_trans *trans,
void bch2_btree_node_evict(struct btree_trans *trans, const struct bkey_i *k)
{
struct bch_fs *c = trans->c;
struct bch_fs_btree_cache *bc = &c->btree_cache;
struct bch_fs_btree_cache *bc = &c->btree.cache;
struct btree *b;
b = btree_cache_find(bc, k);
@ -1453,7 +1453,7 @@ void bch2_btree_node_to_text(struct printbuf *out, struct bch_fs *c, const struc
b->nr.live_u64s * 100 / btree_max_u64s(c),
b->sib_u64s[0],
b->sib_u64s[1],
c->btree_foreground_merge_threshold,
c->btree.foreground_merge_threshold,
b->nr.packed_keys,
b->nr.unpacked_keys,
stats.floats,
@ -1477,7 +1477,7 @@ static const char * const bch2_btree_cache_not_freed_reasons_strs[] = {
void bch2_btree_cache_to_text(struct printbuf *out, const struct bch_fs_btree_cache *bc)
{
struct bch_fs *c = container_of(bc, struct bch_fs, btree_cache);
struct bch_fs *c = container_of(bc, struct bch_fs, btree.cache);
if (!out->nr_tabstops)
printbuf_tabstop_push(out, 32);

View File

@ -80,8 +80,8 @@ static inline bool btree_node_hashed(struct btree *b)
}
#define for_each_cached_btree(_b, _c, _tbl, _iter, _pos) \
for ((_tbl) = rht_dereference_rcu((_c)->btree_cache.table.tbl, \
&(_c)->btree_cache.table), \
for ((_tbl) = rht_dereference_rcu((_c)->btree.cache.table.tbl, \
&(_c)->btree.cache.table), \
_iter = 0; _iter < (_tbl)->size; _iter++) \
rht_for_each_entry_rcu((_b), (_pos), _tbl, _iter, hash)
@ -119,21 +119,21 @@ static inline unsigned btree_blocks(const struct bch_fs *c)
static inline unsigned btree_id_nr_alive(struct bch_fs *c)
{
return BTREE_ID_NR + c->btree_cache.roots_extra.nr;
return BTREE_ID_NR + c->btree.cache.roots_extra.nr;
}
static inline struct btree_root *bch2_btree_id_root(struct bch_fs *c, unsigned id)
{
if (likely(id < BTREE_ID_NR)) {
return &c->btree_cache.roots_known[id];
return &c->btree.cache.roots_known[id];
} else {
unsigned idx = id - BTREE_ID_NR;
/* This can happen when we're called from btree_node_scan */
if (idx >= c->btree_cache.roots_extra.nr)
if (idx >= c->btree.cache.roots_extra.nr)
return NULL;
return &c->btree_cache.roots_extra.data[idx];
return &c->btree.cache.roots_extra.data[idx];
}
}

View File

@ -179,11 +179,11 @@ static int set_node_max(struct bch_fs *c, struct btree *b, struct bpos new_max)
bch2_btree_node_drop_keys_outside_node(b);
guard(mutex)(&c->btree_cache.lock);
__bch2_btree_node_hash_remove(&c->btree_cache, b);
guard(mutex)(&c->btree.cache.lock);
__bch2_btree_node_hash_remove(&c->btree.cache, b);
bkey_copy(&b->key, &new->k_i);
ret = __bch2_btree_node_hash_insert(&c->btree_cache, b);
ret = __bch2_btree_node_hash_insert(&c->btree.cache, b);
BUG_ON(ret);
return 0;
}
@ -616,8 +616,8 @@ recover:
six_unlock_read(&b->c.lock);
if (bch2_err_matches(ret, BCH_ERR_topology_repair_drop_this_node)) {
scoped_guard(mutex, &c->btree_cache.lock)
bch2_btree_node_hash_remove(&c->btree_cache, b);
scoped_guard(mutex, &c->btree.cache.lock)
bch2_btree_node_hash_remove(&c->btree.cache, b);
r->b = NULL;
@ -697,7 +697,7 @@ static int bch2_gc_mark_key(struct btree_trans *trans, enum btree_id btree_id,
if (bch2_trans_has_updates(trans)) {
CLASS(disk_reservation, res)(c);
return bch2_trans_commit(trans, &res.r, NULL, BCH_TRANS_COMMIT_no_enospc) ?:
-BCH_ERR_transaction_restart_nested;
bch_err_throw(c, transaction_restart_commit);
}
try(bch2_key_trigger(trans, btree_id, level, old, unsafe_bkey_s_c_to_s(k),
@ -732,7 +732,7 @@ static int bch2_gc_btree(struct btree_trans *trans,
try(for_each_btree_key_continue(trans, iter, 0, k, ({
gc_pos_set(trans->c, gc_pos_btree(btree, level, k.k->p));
bch2_progress_update_iter(trans, progress, &iter, "check_allocations") ?:
bch2_progress_update_iter(trans, progress, &iter) ?:
bch2_gc_mark_key(trans, btree, level, &prev, &iter, k, initial);
})));
}
@ -752,7 +752,7 @@ static int bch2_gc_btrees(struct bch_fs *c)
int ret = 0;
struct progress_indicator progress;
bch2_progress_init_inner(&progress, c, ~0ULL, ~0ULL);
bch2_progress_init(&progress, "check_allocations", c, ~0ULL, ~0ULL);
enum btree_id ids[BTREE_ID_NR];
for (unsigned i = 0; i < BTREE_ID_NR; i++)
@ -1219,7 +1219,7 @@ static int merge_btree_node_one(struct btree_trans *trans,
if (!b)
return 1;
try(bch2_progress_update_iter(trans, progress, iter, "merge_btree_nodes"));
try(bch2_progress_update_iter(trans, progress, iter));
if (!btree_node_needs_merge(trans, b, 0)) {
if (bpos_eq(b->key.k.p, SPOS_MAX))
@ -1238,7 +1238,7 @@ static int merge_btree_node_one(struct btree_trans *trans,
int bch2_merge_btree_nodes(struct bch_fs *c)
{
struct progress_indicator progress;
bch2_progress_init_inner(&progress, c, ~0ULL, ~0ULL);
bch2_progress_init(&progress, __func__, c, ~0ULL, ~0ULL);
CLASS(btree_trans, trans)(c);

View File

@ -918,8 +918,8 @@ static int __bch2_trans_commit_error(struct btree_trans *trans, unsigned flags,
event_inc_trace(c, trans_blocked_journal_reclaim, buf, ({
prt_printf(&buf, "%s\n", trans->fn);
prt_printf(&buf, "key cache dirty %lu/%lu must_wait %zu\n",
atomic_long_read(&c->btree_key_cache.nr_keys),
atomic_long_read(&c->btree_key_cache.nr_dirty),
atomic_long_read(&c->btree.key_cache.nr_keys),
atomic_long_read(&c->btree.key_cache.nr_dirty),
__bch2_btree_key_cache_must_wait(c));
}));
track_event_change(&c->times[BCH_TIME_blocked_key_cache_flush], true);
@ -1008,7 +1008,7 @@ retry:
}
if (i->type == BCH_JSET_ENTRY_btree_root) {
guard(mutex)(&c->btree_cache.root_lock);
guard(mutex)(&c->btree.cache.root_lock);
struct btree_root *r = bch2_btree_id_root(c, i->btree_id);
@ -1026,6 +1026,8 @@ retry:
goto fatal_err;
}
event_inc_trace(c, transaction_commit, buf, prt_str(&buf, trans->fn));
return 0;
fatal_err:
bch2_fs_fatal_error(c, "fatal error in transaction commit: %s", bch2_err_str(ret));

82
libbcachefs/btree/init.c Normal file
View File

@ -0,0 +1,82 @@
// SPDX-License-Identifier: GPL-2.0
#include "bcachefs.h"
#include "btree/cache.h"
#include "btree/init.h"
#include "btree/interior.h"
#include "btree/key_cache.h"
#include "btree/node_scan.h"
#include "btree/read.h"
#include "btree/sort.h"
#include "btree/write.h"
#include "btree/write_buffer.h"
void bch2_fs_btree_exit(struct bch_fs *c)
{
bch2_find_btree_nodes_exit(&c->btree.node_scan);
bch2_fs_btree_write_buffer_exit(c);
bch2_fs_btree_key_cache_exit(&c->btree.key_cache);
bch2_fs_btree_iter_exit(c);
bch2_fs_btree_interior_update_exit(c);
bch2_fs_btree_cache_exit(c);
if (c->btree.read_complete_wq)
destroy_workqueue(c->btree.read_complete_wq);
if (c->btree.write_submit_wq)
destroy_workqueue(c->btree.write_submit_wq);
if (c->btree.write_complete_wq)
destroy_workqueue(c->btree.write_complete_wq);
mempool_exit(&c->btree.bounce_pool);
bioset_exit(&c->btree.bio);
mempool_exit(&c->btree.fill_iter);
}
void bch2_fs_btree_init_early(struct bch_fs *c)
{
bch2_fs_btree_cache_init_early(&c->btree.cache);
bch2_fs_btree_interior_update_init_early(c);
bch2_fs_btree_iter_init_early(c);
bch2_fs_btree_write_buffer_init_early(c);
bch2_find_btree_nodes_init(&c->btree.node_scan);
}
int bch2_fs_btree_init(struct bch_fs *c)
{
c->btree.foreground_merge_threshold = BTREE_FOREGROUND_MERGE_THRESHOLD(c);
unsigned iter_size = sizeof(struct sort_iter) +
(btree_blocks(c) + 1) * 2 *
sizeof(struct sort_iter_set);
if (!(c->btree.read_complete_wq = alloc_workqueue("bcachefs_btree_read_complete",
WQ_HIGHPRI|WQ_FREEZABLE|WQ_MEM_RECLAIM, 512)) ||
mempool_init_kmalloc_pool(&c->btree.fill_iter, 1, iter_size) ||
bioset_init(&c->btree.bio, 1,
max(offsetof(struct btree_read_bio, bio),
offsetof(struct btree_write_bio, wbio.bio)),
BIOSET_NEED_BVECS) ||
mempool_init_kvmalloc_pool(&c->btree.bounce_pool, 1,
c->opts.btree_node_size))
return bch_err_throw(c, ENOMEM_fs_other_alloc);
try(bch2_fs_btree_cache_init(c));
try(bch2_fs_btree_iter_init(c));
try(bch2_fs_btree_key_cache_init(&c->btree.key_cache));
return 0;
}
int bch2_fs_btree_init_rw(struct bch_fs *c)
{
if (!(c->btree.write_submit_wq = alloc_workqueue("bcachefs_btree_write_sumit",
WQ_HIGHPRI|WQ_FREEZABLE|WQ_MEM_RECLAIM, 1)) ||
!(c->btree.write_complete_wq = alloc_workqueue("bcachefs_btree_write_complete",
WQ_HIGHPRI|WQ_FREEZABLE|WQ_MEM_RECLAIM, 1)))
return bch_err_throw(c, ENOMEM_fs_other_alloc);
try(bch2_fs_btree_interior_update_init(c));
try(bch2_fs_btree_write_buffer_init(c));
return 0;
}

10
libbcachefs/btree/init.h Normal file
View File

@ -0,0 +1,10 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _BCACHEFS_BTREE_INIT_H
#define _BCACHEFS_BTREE_INIT_H
void bch2_fs_btree_exit(struct bch_fs *);
void bch2_fs_btree_init_early(struct bch_fs *);
int bch2_fs_btree_init(struct bch_fs *);
int bch2_fs_btree_init_rw(struct bch_fs *);
#endif /* _BCACHEFS_BTREE_INIT_H */

View File

@ -252,8 +252,8 @@ static void bch2_btree_node_free_inmem(struct btree_trans *trans,
__btree_node_free(trans, b);
scoped_guard(mutex, &c->btree_cache.lock)
bch2_btree_node_hash_remove(&c->btree_cache, b);
scoped_guard(mutex, &c->btree.cache.lock)
bch2_btree_node_hash_remove(&c->btree.cache, b);
six_unlock_write(&b->c.lock);
mark_btree_node_locked_noreset(path, b->c.level, BTREE_NODE_INTENT_LOCKED);
@ -279,8 +279,8 @@ static void bch2_btree_node_free_never_used(struct btree_update *as,
clear_btree_node_dirty_acct(c, b);
clear_btree_node_need_write(b);
scoped_guard(mutex, &c->btree_cache.lock)
__bch2_btree_node_hash_remove(&c->btree_cache, b);
scoped_guard(mutex, &c->btree.cache.lock)
__bch2_btree_node_hash_remove(&c->btree.cache, b);
BUG_ON(p->nr >= ARRAY_SIZE(p->b));
p->b[p->nr++] = b;
@ -357,9 +357,9 @@ retry:
goto retry;
}
mutex_lock(&c->btree_reserve_cache.lock);
while (c->btree_reserve_cache.nr) {
struct btree_alloc *a = c->btree_reserve_cache.data + --c->btree_reserve_cache.nr;
mutex_lock(&c->btree.reserve_cache.lock);
while (c->btree.reserve_cache.nr) {
struct btree_alloc *a = c->btree.reserve_cache.data + --c->btree.reserve_cache.nr;
/* check if it has sufficient durability */
@ -368,13 +368,13 @@ retry:
bkey_i_to_s_c(&a->k))) {
bkey_copy(&b->key, &a->k);
b->ob = a->ob;
mutex_unlock(&c->btree_reserve_cache.lock);
mutex_unlock(&c->btree.reserve_cache.lock);
goto out;
}
bch2_open_buckets_put(c, &a->ob);
}
mutex_unlock(&c->btree_reserve_cache.lock);
mutex_unlock(&c->btree.reserve_cache.lock);
bkey_btree_ptr_v2_init(&b->key);
bch2_alloc_sectors_append_ptrs(c, wp, &b->key, btree_sectors(c), false);
@ -436,7 +436,7 @@ static struct btree *bch2_btree_node_alloc(struct btree_update *as,
bch2_btree_build_aux_trees(b);
ret = bch2_btree_node_hash_insert(&c->btree_cache, b, level, as->btree_id);
ret = bch2_btree_node_hash_insert(&c->btree.cache, b, level, as->btree_id);
BUG_ON(ret);
trace_btree_node(c, b, btree_node_alloc);
@ -511,12 +511,12 @@ static void bch2_btree_reserve_put(struct btree_update *as, struct btree_trans *
while (p->nr) {
struct btree *b = p->b[--p->nr];
mutex_lock(&c->btree_reserve_cache.lock);
mutex_lock(&c->btree.reserve_cache.lock);
if (c->btree_reserve_cache.nr <
ARRAY_SIZE(c->btree_reserve_cache.data)) {
if (c->btree.reserve_cache.nr <
ARRAY_SIZE(c->btree.reserve_cache.data)) {
struct btree_alloc *a =
&c->btree_reserve_cache.data[c->btree_reserve_cache.nr++];
&c->btree.reserve_cache.data[c->btree.reserve_cache.nr++];
a->ob = b->ob;
b->ob.nr = 0;
@ -525,7 +525,7 @@ static void bch2_btree_reserve_put(struct btree_update *as, struct btree_trans *
bch2_open_buckets_put(c, &b->ob);
}
mutex_unlock(&c->btree_reserve_cache.lock);
mutex_unlock(&c->btree.reserve_cache.lock);
btree_node_lock_nopath_nofail(trans, &b->c, SIX_LOCK_intent);
btree_node_lock_nopath_nofail(trans, &b->c, SIX_LOCK_write);
@ -586,19 +586,19 @@ static void bch2_btree_update_free(struct btree_update *as, struct btree_trans *
bch2_time_stats_update(&c->times[BCH_TIME_btree_interior_update_total],
as->start_time);
guard(mutex)(&c->btree_interior_updates.lock);
guard(mutex)(&c->btree.interior_updates.lock);
list_del(&as->unwritten_list);
list_del(&as->list);
closure_debug_destroy(&as->cl);
mempool_free(as, &c->btree_interior_updates.pool);
mempool_free(as, &c->btree.interior_updates.pool);
/*
* Have to do the wakeup with btree_interior_update_lock still held,
* since being on btree_interior_update_list is our ref on @c:
*/
closure_wake_up(&c->btree_interior_updates.wait);
closure_wake_up(&c->btree.interior_updates.wait);
}
static void bch2_btree_update_add_key(btree_update_nodes *nodes,
@ -835,7 +835,7 @@ static void btree_update_nodes_written(struct btree_update *as)
* btree_node_update_key(): having the lock be at the filesystem level
* sucks, we'll need to watch for contention
*/
scoped_guard(mutex, &c->btree_interior_updates.commit_lock) {
scoped_guard(mutex, &c->btree.interior_updates.commit_lock) {
ret = commit_do(trans, &as->disk_res, &journal_seq,
BCH_WATERMARK_interior_updates|
BCH_TRANS_COMMIT_no_enospc|
@ -902,7 +902,7 @@ static void btree_update_nodes_written(struct btree_update *as)
bch2_btree_node_lock_write_nofail(trans, path, &b->c);
mutex_lock(&c->btree_interior_updates.lock);
mutex_lock(&c->btree.interior_updates.lock);
list_del(&as->write_blocked_list);
if (list_empty(&b->write_blocked))
@ -934,7 +934,7 @@ static void btree_update_nodes_written(struct btree_update *as)
}
}
mutex_unlock(&c->btree_interior_updates.lock);
mutex_unlock(&c->btree.interior_updates.lock);
mark_btree_node_locked_noreset(path, b->c.level, BTREE_NODE_INTENT_LOCKED);
six_unlock_write(&b->c.lock);
@ -962,12 +962,12 @@ static void btree_update_nodes_written(struct btree_update *as)
static void btree_interior_update_work(struct work_struct *work)
{
struct bch_fs *c =
container_of(work, struct bch_fs, btree_interior_updates.work);
container_of(work, struct bch_fs, btree.interior_updates.work);
struct btree_update *as;
while (1) {
scoped_guard(mutex, &c->btree_interior_updates.lock) {
as = list_first_entry_or_null(&c->btree_interior_updates.unwritten,
scoped_guard(mutex, &c->btree.interior_updates.lock) {
as = list_first_entry_or_null(&c->btree.interior_updates.unwritten,
struct btree_update, unwritten_list);
if (as && !as->nodes_written)
as = NULL;
@ -985,10 +985,10 @@ static CLOSURE_CALLBACK(btree_update_set_nodes_written)
closure_type(as, struct btree_update, cl);
struct bch_fs *c = as->c;
scoped_guard(mutex, &c->btree_interior_updates.lock)
scoped_guard(mutex, &c->btree.interior_updates.lock)
as->nodes_written = true;
queue_work(c->btree_interior_updates.worker, &c->btree_interior_updates.work);
queue_work(c->btree.interior_updates.worker, &c->btree.interior_updates.work);
}
/*
@ -1004,8 +1004,8 @@ static void btree_update_updated_node(struct btree_update *as, struct btree *b)
BUG_ON(!btree_node_dirty(b));
BUG_ON(!b->c.level);
guard(mutex)(&c->btree_interior_updates.lock);
list_add_tail(&as->unwritten_list, &c->btree_interior_updates.unwritten);
guard(mutex)(&c->btree.interior_updates.lock);
list_add_tail(&as->unwritten_list, &c->btree.interior_updates.unwritten);
as->mode = BTREE_UPDATE_node;
as->b = b;
@ -1026,7 +1026,7 @@ static void btree_update_reparent(struct btree_update *as,
{
struct bch_fs *c = as->c;
lockdep_assert_held(&c->btree_interior_updates.lock);
lockdep_assert_held(&c->btree.interior_updates.lock);
child->b = NULL;
child->mode = BTREE_UPDATE_update;
@ -1042,8 +1042,8 @@ static void btree_update_updated_root(struct btree_update *as, struct btree *b)
BUG_ON(as->mode != BTREE_UPDATE_none);
as->mode = BTREE_UPDATE_root;
scoped_guard(mutex, &c->btree_interior_updates.lock)
list_add_tail(&as->unwritten_list, &c->btree_interior_updates.unwritten);
scoped_guard(mutex, &c->btree.interior_updates.lock)
list_add_tail(&as->unwritten_list, &c->btree.interior_updates.unwritten);
}
/*
@ -1064,7 +1064,7 @@ static void bch2_btree_update_add_new_node(struct btree_update *as, struct btree
closure_get(&as->cl);
guard(mutex)(&c->btree_interior_updates.lock);
guard(mutex)(&c->btree.interior_updates.lock);
BUG_ON(b->will_make_reachable);
@ -1110,7 +1110,7 @@ static void bch2_btree_interior_update_will_free_node(struct btree_update *as,
if (btree_node_fake(b))
return;
mutex_lock(&c->btree_interior_updates.lock);
mutex_lock(&c->btree.interior_updates.lock);
/*
* Does this node have any btree_update operations preventing
@ -1128,7 +1128,7 @@ static void bch2_btree_interior_update_will_free_node(struct btree_update *as,
* for flush_held_btree_writes() waiting on updates to flush or
* nodes to be writeable:
*/
closure_wake_up(&c->btree_interior_updates.wait);
closure_wake_up(&c->btree.interior_updates.wait);
}
clear_btree_node_dirty_acct(c, b);
@ -1153,7 +1153,7 @@ static void bch2_btree_interior_update_will_free_node(struct btree_update *as,
bch2_btree_update_will_free_node_journal_pin_flush);
bch2_journal_pin_drop(&c->journal, &w->journal);
mutex_unlock(&c->btree_interior_updates.lock);
mutex_unlock(&c->btree.interior_updates.lock);
bch2_btree_update_add_node(c, &as->old_nodes, b);
}
@ -1172,7 +1172,7 @@ static void bch2_btree_update_done(struct btree_update *as, struct btree_trans *
bch2_btree_reserve_put(as, trans);
continue_at(&as->cl, btree_update_set_nodes_written,
as->c->btree_interior_updates.worker);
as->c->btree.interior_updates.worker);
bch2_time_stats_update(&c->times[BCH_TIME_btree_interior_update_foreground],
start_time);
@ -1258,7 +1258,7 @@ bch2_btree_update_start(struct btree_trans *trans, struct btree_path *path,
}
}
as = mempool_alloc(&c->btree_interior_updates.pool, GFP_NOFS);
as = mempool_alloc(&c->btree.interior_updates.pool, GFP_NOFS);
memset(as, 0, sizeof(*as));
closure_init(&as->cl, NULL);
as->c = c;
@ -1277,8 +1277,8 @@ bch2_btree_update_start(struct btree_trans *trans, struct btree_path *path,
darray_init(&as->new_nodes);
bch2_keylist_init(&as->parent_keys, as->inline_keys);
scoped_guard(mutex, &c->btree_interior_updates.lock)
list_add_tail(&as->list, &c->btree_interior_updates.list);
scoped_guard(mutex, &c->btree.interior_updates.lock)
list_add_tail(&as->list, &c->btree.interior_updates.list);
struct btree *b = btree_path_node(path, path->level);
as->node_start = b->data->min_key;
@ -1377,10 +1377,10 @@ err:
static void bch2_btree_set_root_inmem(struct bch_fs *c, struct btree *b)
{
/* Root nodes cannot be reaped */
scoped_guard(mutex, &c->btree_cache.lock)
scoped_guard(mutex, &c->btree.cache.lock)
list_del_init(&b->list);
scoped_guard(mutex, &c->btree_cache.root_lock)
scoped_guard(mutex, &c->btree.cache.root_lock)
bch2_btree_id_root(c, b->c.btree_id)->b = b;
bch2_recalc_btree_reserve(c);
@ -2019,8 +2019,8 @@ static void __btree_increase_depth(struct btree_update *as, struct btree_trans *
bch2_trans_node_add(trans, path, n);
six_unlock_intent(&n->c.lock);
scoped_guard(mutex, &c->btree_cache.lock)
list_add_tail(&b->list, &c->btree_cache.live[btree_node_pinned(b)].list);
scoped_guard(mutex, &c->btree.cache.lock)
list_add_tail(&b->list, &c->btree.cache.live[btree_node_pinned(b)].list);
bch2_trans_verify_locks(trans);
}
@ -2122,8 +2122,8 @@ int __bch2_foreground_maybe_merge(struct btree_trans *trans,
if (!bpos_eq(bpos_successor(prev->data->max_key), next->data->min_key)) {
CLASS(printbuf, buf)();
bch2_log_msg_start(c, &buf);
printbuf_indent_add_nextline(&buf, 2);
prt_printf(&buf, "%s(): ", __func__);
ret = __bch2_topology_error(c, &buf);
prt_newline(&buf);
@ -2135,7 +2135,7 @@ int __bch2_foreground_maybe_merge(struct btree_trans *trans,
prt_printf(&buf, "next starts at ");
bch2_bpos_to_text(&buf, next->data->min_key);
bch_err(c, "%s", buf.buf);
bch2_print_str(c, KERN_ERR, buf.buf);
goto err;
}
@ -2161,10 +2161,10 @@ int __bch2_foreground_maybe_merge(struct btree_trans *trans,
next->nr.live_u64s * 100 / btree_max_u64s(c));
prt_printf(&buf, "merged would have %zu threshold %u\n",
sib_u64s, c->btree_foreground_merge_threshold);
sib_u64s, c->btree.foreground_merge_threshold);
}));
if (sib_u64s > c->btree_foreground_merge_threshold) {
if (sib_u64s > c->btree.foreground_merge_threshold) {
if (sib_u64s > BTREE_FOREGROUND_MERGE_HYSTERESIS(c))
sib_u64s -= (sib_u64s - BTREE_FOREGROUND_MERGE_HYSTERESIS(c)) / 2;
@ -2419,10 +2419,10 @@ static void async_btree_node_rewrite_work(struct work_struct *work)
!bch2_err_matches(ret, EROFS))
bch_err_fn_ratelimited(c, ret);
scoped_guard(spinlock, &c->btree_node_rewrites.lock)
scoped_guard(spinlock, &c->btree.node_rewrites.lock)
list_del(&a->list);
closure_wake_up(&c->btree_node_rewrites.wait);
closure_wake_up(&c->btree.node_rewrites.wait);
bch2_bkey_buf_exit(&a->key);
enumerated_ref_put(&c->writes, BCH_WRITE_REF_node_rewrite);
@ -2446,19 +2446,19 @@ static void __bch2_btree_node_rewrite_async(struct bch_fs *c, struct btree *b, b
bool now = false, pending = false;
scoped_guard(spinlock, &c->btree_node_rewrites.lock) {
scoped_guard(spinlock, &c->btree.node_rewrites.lock) {
if (c->recovery.passes_complete & BIT_ULL(BCH_RECOVERY_PASS_journal_replay) &&
enumerated_ref_tryget(&c->writes, BCH_WRITE_REF_node_rewrite)) {
list_add(&a->list, &c->btree_node_rewrites.list);
list_add(&a->list, &c->btree.node_rewrites.list);
now = true;
} else if (!test_bit(BCH_FS_may_go_rw, &c->flags) && !merge) {
list_add(&a->list, &c->btree_node_rewrites.pending);
list_add(&a->list, &c->btree.node_rewrites.pending);
pending = true;
}
}
if (now) {
queue_work(c->btree_node_rewrites.worker, &a->work);
queue_work(c->btree.node_rewrites.worker, &a->work);
} else if (pending) {
/* bch2_do_pending_node_rewrites will execute */
} else {
@ -2479,8 +2479,8 @@ void bch2_btree_node_merge_async(struct bch_fs *c, struct btree *b)
void bch2_async_btree_node_rewrites_flush(struct bch_fs *c)
{
closure_wait_event(&c->btree_node_rewrites.wait,
list_empty(&c->btree_node_rewrites.list));
closure_wait_event(&c->btree.node_rewrites.wait,
list_empty(&c->btree.node_rewrites.list));
}
void bch2_do_pending_node_rewrites(struct bch_fs *c)
@ -2488,18 +2488,18 @@ void bch2_do_pending_node_rewrites(struct bch_fs *c)
while (1) {
struct async_btree_rewrite *a;
scoped_guard(spinlock, &c->btree_node_rewrites.lock) {
a = list_pop_entry(&c->btree_node_rewrites.pending,
scoped_guard(spinlock, &c->btree.node_rewrites.lock) {
a = list_pop_entry(&c->btree.node_rewrites.pending,
struct async_btree_rewrite, list);
if (a)
list_add(&a->list, &c->btree_node_rewrites.list);
list_add(&a->list, &c->btree.node_rewrites.list);
}
if (!a)
break;
enumerated_ref_get(&c->writes, BCH_WRITE_REF_node_rewrite);
queue_work(c->btree_node_rewrites.worker, &a->work);
queue_work(c->btree.node_rewrites.worker, &a->work);
}
}
@ -2508,8 +2508,8 @@ void bch2_free_pending_node_rewrites(struct bch_fs *c)
while (1) {
struct async_btree_rewrite *a;
scoped_guard(spinlock, &c->btree_node_rewrites.lock)
a = list_pop_entry(&c->btree_node_rewrites.pending,
scoped_guard(spinlock, &c->btree.node_rewrites.lock)
a = list_pop_entry(&c->btree.node_rewrites.pending,
struct async_btree_rewrite, list);
if (!a)
@ -2567,7 +2567,7 @@ static int __bch2_btree_node_update_key(struct btree_trans *trans,
new_key, new_key->k.u64s);
/*
* propagated back to c->btree_roots[].key by
* propagated back to c->btree.roots[].key by
* bch2_journal_entry_to_btree_root() incorrect for
*/
}
@ -2590,10 +2590,10 @@ static int __bch2_btree_node_update_key(struct btree_trans *trans,
bkey_copy(&b->key, new_key);
bch2_btree_node_unlock_write(trans, btree_iter_path(trans, iter), b);
} else {
try(bch2_trans_mutex_lock(trans, &c->btree_interior_updates.commit_lock));
try(bch2_trans_mutex_lock(trans, &c->btree.interior_updates.commit_lock));
if (!btree_node_will_make_reachable(b)) {
mutex_unlock(&c->btree_interior_updates.commit_lock);
mutex_unlock(&c->btree.interior_updates.commit_lock);
return bch_err_throw(c, transaction_restart_nested);
}
@ -2605,7 +2605,7 @@ static int __bch2_btree_node_update_key(struct btree_trans *trans,
bch2_btree_node_unlock_write(trans, btree_iter_path(trans, iter), b);
bkey_copy(&n->key, new_key);
mutex_unlock(&c->btree_interior_updates.commit_lock);
mutex_unlock(&c->btree.interior_updates.commit_lock);
}
return 0;
}
@ -2683,7 +2683,7 @@ int bch2_btree_root_alloc_fake_trans(struct btree_trans *trans, enum btree_id id
b->data->format = bch2_btree_calc_format(b);
btree_node_set_format(b, b->data->format);
ret = bch2_btree_node_hash_insert(&c->btree_cache, b,
ret = bch2_btree_node_hash_insert(&c->btree.cache, b,
b->c.level, b->c.btree_id);
BUG_ON(ret);
@ -2730,15 +2730,15 @@ void bch2_btree_updates_to_text(struct printbuf *out, struct bch_fs *c)
{
struct btree_update *as;
guard(mutex)(&c->btree_interior_updates.lock);
list_for_each_entry(as, &c->btree_interior_updates.list, list)
guard(mutex)(&c->btree.interior_updates.lock);
list_for_each_entry(as, &c->btree.interior_updates.list, list)
bch2_btree_update_to_text(out, as);
}
static bool bch2_btree_interior_updates_pending(struct bch_fs *c)
{
guard(mutex)(&c->btree_interior_updates.lock);
return !list_empty(&c->btree_interior_updates.list);
guard(mutex)(&c->btree.interior_updates.lock);
return !list_empty(&c->btree.interior_updates.list);
}
bool bch2_btree_interior_updates_flush(struct bch_fs *c)
@ -2746,7 +2746,7 @@ bool bch2_btree_interior_updates_flush(struct bch_fs *c)
bool ret = bch2_btree_interior_updates_pending(c);
if (ret)
closure_wait_event(&c->btree_interior_updates.wait,
closure_wait_event(&c->btree.interior_updates.wait,
!bch2_btree_interior_updates_pending(c));
return ret;
}
@ -2755,7 +2755,7 @@ void bch2_journal_entry_to_btree_root(struct bch_fs *c, struct jset_entry *entry
{
struct btree_root *r = bch2_btree_id_root(c, entry->btree_id);
guard(mutex)(&c->btree_interior_updates.lock);
guard(mutex)(&c->btree.interior_updates.lock);
r->level = entry->level;
r->alive = true;
@ -2767,7 +2767,7 @@ bch2_btree_roots_to_journal_entries(struct bch_fs *c,
struct jset_entry *end,
unsigned long skip)
{
guard(mutex)(&c->btree_interior_updates.lock);
guard(mutex)(&c->btree.interior_updates.lock);
for (unsigned i = 0; i < btree_id_nr_alive(c); i++) {
struct btree_root *r = bch2_btree_id_root(c, i);
@ -2798,49 +2798,49 @@ static void bch2_btree_alloc_to_text(struct printbuf *out,
void bch2_btree_reserve_cache_to_text(struct printbuf *out, struct bch_fs *c)
{
for (unsigned i = 0; i < c->btree_reserve_cache.nr; i++)
bch2_btree_alloc_to_text(out, c, &c->btree_reserve_cache.data[i]);
for (unsigned i = 0; i < c->btree.reserve_cache.nr; i++)
bch2_btree_alloc_to_text(out, c, &c->btree.reserve_cache.data[i]);
}
void bch2_fs_btree_interior_update_exit(struct bch_fs *c)
{
WARN_ON(!list_empty(&c->btree_node_rewrites.list));
WARN_ON(!list_empty(&c->btree_node_rewrites.pending));
WARN_ON(!list_empty(&c->btree.node_rewrites.list));
WARN_ON(!list_empty(&c->btree.node_rewrites.pending));
if (c->btree_node_rewrites.worker)
destroy_workqueue(c->btree_node_rewrites.worker);
if (c->btree_interior_updates.worker)
destroy_workqueue(c->btree_interior_updates.worker);
mempool_exit(&c->btree_interior_updates.pool);
if (c->btree.node_rewrites.worker)
destroy_workqueue(c->btree.node_rewrites.worker);
if (c->btree.interior_updates.worker)
destroy_workqueue(c->btree.interior_updates.worker);
mempool_exit(&c->btree.interior_updates.pool);
}
void bch2_fs_btree_interior_update_init_early(struct bch_fs *c)
{
mutex_init(&c->btree_reserve_cache.lock);
INIT_LIST_HEAD(&c->btree_interior_updates.list);
INIT_LIST_HEAD(&c->btree_interior_updates.unwritten);
mutex_init(&c->btree_interior_updates.lock);
mutex_init(&c->btree_interior_updates.commit_lock);
INIT_WORK(&c->btree_interior_updates.work, btree_interior_update_work);
mutex_init(&c->btree.reserve_cache.lock);
INIT_LIST_HEAD(&c->btree.interior_updates.list);
INIT_LIST_HEAD(&c->btree.interior_updates.unwritten);
mutex_init(&c->btree.interior_updates.lock);
mutex_init(&c->btree.interior_updates.commit_lock);
INIT_WORK(&c->btree.interior_updates.work, btree_interior_update_work);
INIT_LIST_HEAD(&c->btree_node_rewrites.list);
INIT_LIST_HEAD(&c->btree_node_rewrites.pending);
spin_lock_init(&c->btree_node_rewrites.lock);
INIT_LIST_HEAD(&c->btree.node_rewrites.list);
INIT_LIST_HEAD(&c->btree.node_rewrites.pending);
spin_lock_init(&c->btree.node_rewrites.lock);
}
int bch2_fs_btree_interior_update_init(struct bch_fs *c)
{
c->btree_interior_updates.worker =
c->btree.interior_updates.worker =
alloc_workqueue("btree_update", WQ_UNBOUND|WQ_MEM_RECLAIM, 8);
if (!c->btree_interior_updates.worker)
if (!c->btree.interior_updates.worker)
return bch_err_throw(c, ENOMEM_btree_interior_update_worker_init);
c->btree_node_rewrites.worker =
c->btree.node_rewrites.worker =
alloc_ordered_workqueue("btree_node_rewrite", WQ_UNBOUND);
if (!c->btree_node_rewrites.worker)
if (!c->btree.node_rewrites.worker)
return bch_err_throw(c, ENOMEM_btree_interior_update_worker_init);
if (mempool_init_kmalloc_pool(&c->btree_interior_updates.pool, 1,
if (mempool_init_kmalloc_pool(&c->btree.interior_updates.pool, 1,
sizeof(struct btree_update)))
return bch_err_throw(c, ENOMEM_btree_interior_update_pool_init);

View File

@ -139,7 +139,7 @@ static inline bool btree_node_needs_merge(struct btree_trans *trans, struct btre
return false;
return (int) min(b->sib_u64s[0], b->sib_u64s[1]) + d <=
(int) trans->c->btree_foreground_merge_threshold;
(int) trans->c->btree.foreground_merge_threshold;
}
static inline int bch2_foreground_maybe_merge(struct btree_trans *trans,

View File

@ -1,5 +1,4 @@
// SPDX-License-Identifier: GPL-2.0
#include "bcachefs.h"
#include "alloc/replicas.h"
@ -743,7 +742,9 @@ static noinline_for_stack int btree_node_root_err(struct btree_trans *trans, str
bch2_btree_pos_to_text(&buf, c, b);
prt_newline(&buf);
return __bch2_topology_error(c, &buf);
int ret = __bch2_topology_error(c, &buf);
bch2_print_str(trans->c, KERN_ERR, buf.buf);
return ret;
}
static inline int btree_path_lock_root(struct btree_trans *trans,
@ -917,7 +918,9 @@ static noinline_for_stack int btree_node_missing_err(struct btree_trans *trans,
bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(&path_l(path)->b->key));
prt_newline(&buf);
return __bch2_topology_error(c, &buf);
int ret = __bch2_topology_error(c, &buf);
bch2_print_str(trans->c, KERN_ERR, buf.buf);
return ret;
}
static noinline_for_stack int btree_node_gap_err(struct btree_trans *trans,
@ -935,7 +938,9 @@ static noinline_for_stack int btree_node_gap_err(struct btree_trans *trans,
bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(k));
prt_newline(&buf);
return __bch2_topology_error(c, &buf);
int ret = __bch2_topology_error(c, &buf);
bch2_print_str(trans->c, KERN_ERR, buf.buf);
return ret;
}
static noinline int btree_node_iter_and_journal_peek(struct btree_trans *trans,
@ -3344,7 +3349,7 @@ void *__bch2_trans_kmalloc(struct btree_trans *trans, size_t size, unsigned long
new_mem = allocate_dropping_locks_norelock(trans, lock_dropped,
kmalloc(new_bytes, _gfp|__GFP_NOWARN));
if (!new_mem) {
new_mem = mempool_alloc(&c->btree_trans.malloc_pool, GFP_KERNEL);
new_mem = mempool_alloc(&c->btree.trans.malloc_pool, GFP_KERNEL);
new_bytes = BTREE_TRANS_MEM_MAX;
trans->used_mempool = true;
}
@ -3391,7 +3396,7 @@ void bch2_trans_srcu_unlock(struct btree_trans *trans)
path->l[0].b = ERR_PTR(-BCH_ERR_no_btree_node_srcu_reset);
check_srcu_held_too_long(trans);
srcu_read_unlock(&c->btree_trans.barrier, trans->srcu_idx);
srcu_read_unlock(&c->btree.trans.barrier, trans->srcu_idx);
trans->srcu_held = false;
}
}
@ -3399,7 +3404,7 @@ void bch2_trans_srcu_unlock(struct btree_trans *trans)
static void bch2_trans_srcu_lock(struct btree_trans *trans)
{
if (!trans->srcu_held) {
trans->srcu_idx = srcu_read_lock(&trans->c->btree_trans.barrier);
trans->srcu_idx = srcu_read_lock(&trans->c->btree.trans.barrier);
trans->srcu_lock_time = jiffies;
trans->srcu_held = true;
}
@ -3438,7 +3443,7 @@ u32 bch2_trans_begin(struct btree_trans *trans)
(void)lock_dropped;
if (!new_mem) {
new_mem = mempool_alloc(&trans->c->btree_trans.malloc_pool, GFP_KERNEL);
new_mem = mempool_alloc(&trans->c->btree.trans.malloc_pool, GFP_KERNEL);
new_bytes = BTREE_TRANS_MEM_MAX;
trans->used_mempool = true;
kfree(trans->mem);
@ -3535,24 +3540,24 @@ unsigned bch2_trans_get_fn_idx(const char *fn)
static inline struct btree_trans *bch2_trans_alloc(struct bch_fs *c)
{
if (IS_ENABLED(__KERNEL__)) {
struct btree_trans *trans = this_cpu_xchg(c->btree_trans.bufs->trans, NULL);
struct btree_trans *trans = this_cpu_xchg(c->btree.trans.bufs->trans, NULL);
if (trans) {
memset(trans, 0, offsetof(struct btree_trans, list));
return trans;
}
}
struct btree_trans *trans = mempool_alloc(&c->btree_trans.pool, GFP_NOFS);
struct btree_trans *trans = mempool_alloc(&c->btree.trans.pool, GFP_NOFS);
memset(trans, 0, sizeof(*trans));
seqmutex_lock(&c->btree_trans.lock);
seqmutex_lock(&c->btree.trans.lock);
if (IS_ENABLED(CONFIG_BCACHEFS_DEBUG)) {
struct btree_trans *pos;
pid_t pid = current->pid;
trans->locking_wait.task = current;
list_for_each_entry(pos, &c->btree_trans.list, list) {
list_for_each_entry(pos, &c->btree.trans.list, list) {
struct task_struct *pos_task = READ_ONCE(pos->locking_wait.task);
/*
* We'd much prefer to be stricter here and completely
@ -3566,14 +3571,14 @@ static inline struct btree_trans *bch2_trans_alloc(struct bch_fs *c)
}
}
list_add(&trans->list, &c->btree_trans.list);
seqmutex_unlock(&c->btree_trans.lock);
list_add(&trans->list, &c->btree.trans.list);
seqmutex_unlock(&c->btree.trans.lock);
return trans;
}
struct btree_trans *__bch2_trans_get(struct bch_fs *c, unsigned fn_idx)
__acquires(&c->btree_trans.barrier)
__acquires(&c->btree.trans.barrier)
{
/*
* No multithreaded btree access until we've gone RW and are no longer
@ -3608,7 +3613,7 @@ struct btree_trans *__bch2_trans_get(struct bch_fs *c, unsigned fn_idx)
if (fn_idx < BCH_TRANSACTIONS_NR) {
trans->fn = bch2_btree_transaction_fns[fn_idx];
struct btree_transaction_stats *s = &c->btree_trans.stats[fn_idx];
struct btree_transaction_stats *s = &c->btree.trans.stats[fn_idx];
if (s->max_mem) {
unsigned expected_mem_bytes = roundup_pow_of_two(s->max_mem);
@ -3621,7 +3626,7 @@ struct btree_trans *__bch2_trans_get(struct bch_fs *c, unsigned fn_idx)
trans->nr_paths_max = s->nr_max_paths;
}
trans->srcu_idx = srcu_read_lock(&c->btree_trans.barrier);
trans->srcu_idx = srcu_read_lock(&c->btree.trans.barrier);
trans->srcu_lock_time = jiffies;
trans->srcu_held = true;
trans_set_locked(trans, false);
@ -3669,7 +3674,7 @@ static inline void check_btree_paths_leaked(struct btree_trans *trans) {}
#endif
void bch2_trans_put(struct btree_trans *trans)
__releases(&c->btree_trans.barrier)
__releases(&c->btree.trans.barrier)
{
struct bch_fs *c = trans->c;
@ -3686,7 +3691,7 @@ void bch2_trans_put(struct btree_trans *trans)
if (trans->srcu_held) {
check_srcu_held_too_long(trans);
srcu_read_unlock(&c->btree_trans.barrier, trans->srcu_idx);
srcu_read_unlock(&c->btree.trans.barrier, trans->srcu_idx);
}
if (unlikely(trans->journal_replay_not_finished))
@ -3714,35 +3719,35 @@ void bch2_trans_put(struct btree_trans *trans)
kvfree_rcu_mightsleep(paths_allocated);
if (trans->used_mempool)
mempool_free(trans->mem, &c->btree_trans.malloc_pool);
mempool_free(trans->mem, &c->btree.trans.malloc_pool);
else
kfree(trans->mem);
/* Userspace doesn't have a real percpu implementation: */
if (IS_ENABLED(__KERNEL__))
trans = this_cpu_xchg(c->btree_trans.bufs->trans, trans);
trans = this_cpu_xchg(c->btree.trans.bufs->trans, trans);
if (trans) {
seqmutex_lock(&c->btree_trans.lock);
seqmutex_lock(&c->btree.trans.lock);
list_del(&trans->list);
seqmutex_unlock(&c->btree_trans.lock);
seqmutex_unlock(&c->btree.trans.lock);
mempool_free(trans, &c->btree_trans.pool);
mempool_free(trans, &c->btree.trans.pool);
}
}
bool bch2_current_has_btree_trans(struct bch_fs *c)
{
seqmutex_lock(&c->btree_trans.lock);
seqmutex_lock(&c->btree.trans.lock);
struct btree_trans *trans;
bool ret = false;
list_for_each_entry(trans, &c->btree_trans.list, list)
list_for_each_entry(trans, &c->btree.trans.list, list)
if (trans->locking_wait.task == current &&
trans->locked) {
ret = true;
break;
}
seqmutex_unlock(&c->btree_trans.lock);
seqmutex_unlock(&c->btree.trans.lock);
return ret;
}
@ -3837,26 +3842,26 @@ void bch2_fs_btree_iter_exit(struct bch_fs *c)
struct btree_trans *trans;
int cpu;
if (c->btree_trans.bufs)
if (c->btree.trans.bufs)
for_each_possible_cpu(cpu) {
struct btree_trans *trans =
per_cpu_ptr(c->btree_trans.bufs, cpu)->trans;
per_cpu_ptr(c->btree.trans.bufs, cpu)->trans;
if (trans) {
seqmutex_lock(&c->btree_trans.lock);
seqmutex_lock(&c->btree.trans.lock);
list_del(&trans->list);
seqmutex_unlock(&c->btree_trans.lock);
seqmutex_unlock(&c->btree.trans.lock);
}
kfree(trans);
}
free_percpu(c->btree_trans.bufs);
free_percpu(c->btree.trans.bufs);
trans = list_first_entry_or_null(&c->btree_trans.list, struct btree_trans, list);
trans = list_first_entry_or_null(&c->btree.trans.list, struct btree_trans, list);
if (trans)
panic("%s leaked btree_trans\n", trans->fn);
for (s = c->btree_trans.stats;
s < c->btree_trans.stats + ARRAY_SIZE(c->btree_trans.stats);
for (s = c->btree.trans.stats;
s < c->btree.trans.stats + ARRAY_SIZE(c->btree.trans.stats);
s++) {
#ifdef CONFIG_BCACHEFS_TRANS_KMALLOC_TRACE
darray_exit(&s->trans_kmalloc_trace);
@ -3865,39 +3870,39 @@ void bch2_fs_btree_iter_exit(struct bch_fs *c)
bch2_time_stats_exit(&s->lock_hold_times);
}
if (c->btree_trans.barrier_initialized) {
synchronize_srcu_expedited(&c->btree_trans.barrier);
cleanup_srcu_struct(&c->btree_trans.barrier);
if (c->btree.trans.barrier_initialized) {
synchronize_srcu_expedited(&c->btree.trans.barrier);
cleanup_srcu_struct(&c->btree.trans.barrier);
}
mempool_exit(&c->btree_trans.malloc_pool);
mempool_exit(&c->btree_trans.pool);
mempool_exit(&c->btree.trans.malloc_pool);
mempool_exit(&c->btree.trans.pool);
}
void bch2_fs_btree_iter_init_early(struct bch_fs *c)
{
struct btree_transaction_stats *s;
for (s = c->btree_trans.stats;
s < c->btree_trans.stats + ARRAY_SIZE(c->btree_trans.stats);
for (s = c->btree.trans.stats;
s < c->btree.trans.stats + ARRAY_SIZE(c->btree.trans.stats);
s++) {
bch2_time_stats_init(&s->duration);
bch2_time_stats_init(&s->lock_hold_times);
mutex_init(&s->lock);
}
INIT_LIST_HEAD(&c->btree_trans.list);
seqmutex_init(&c->btree_trans.lock);
INIT_LIST_HEAD(&c->btree.trans.list);
seqmutex_init(&c->btree.trans.lock);
}
int bch2_fs_btree_iter_init(struct bch_fs *c)
{
c->btree_trans.bufs = alloc_percpu(struct btree_trans_buf);
if (!c->btree_trans.bufs)
c->btree.trans.bufs = alloc_percpu(struct btree_trans_buf);
if (!c->btree.trans.bufs)
return -ENOMEM;
try(mempool_init_kmalloc_pool(&c->btree_trans.pool, 1, sizeof(struct btree_trans)));
try(mempool_init_kmalloc_pool(&c->btree_trans.malloc_pool, 1, BTREE_TRANS_MEM_MAX));
try(init_srcu_struct(&c->btree_trans.barrier));
try(mempool_init_kmalloc_pool(&c->btree.trans.pool, 1, sizeof(struct btree_trans)));
try(mempool_init_kmalloc_pool(&c->btree.trans.malloc_pool, 1, BTREE_TRANS_MEM_MAX));
try(init_srcu_struct(&c->btree.trans.barrier));
/*
* static annotation (hackily done) for lock ordering of reclaim vs.
@ -3911,7 +3916,7 @@ int bch2_fs_btree_iter_init(struct bch_fs *c)
fs_reclaim_release(GFP_KERNEL);
#endif
c->btree_trans.barrier_initialized = true;
c->btree.trans.barrier_initialized = true;
return 0;
}

View File

@ -59,7 +59,7 @@ bch2_btree_key_cache_find(struct bch_fs *c, enum btree_id btree_id, struct bpos
.pos = pos,
};
return rhashtable_lookup_fast(&c->btree_key_cache.table, &key,
return rhashtable_lookup_fast(&c->btree.key_cache.table, &key,
bch2_btree_key_cache_params);
}
@ -96,10 +96,10 @@ static bool bkey_cached_evict(struct bch_fs_btree_key_cache *c,
static void __bkey_cached_free(struct rcu_pending *pending, struct rcu_head *rcu)
{
struct bch_fs *c = container_of(pending->srcu, struct bch_fs, btree_trans.barrier);
struct bch_fs *c = container_of(pending->srcu, struct bch_fs, btree.trans.barrier);
struct bkey_cached *ck = container_of(rcu, struct bkey_cached, rcu);
this_cpu_dec(*c->btree_key_cache.nr_pending);
this_cpu_dec(*c->btree.key_cache.nr_pending);
six_lock_exit(&ck->c.lock);
kmem_cache_free(bch2_key_cache, ck);
}
@ -152,7 +152,7 @@ static struct bkey_cached *
bkey_cached_alloc(struct btree_trans *trans, struct btree_path *path, unsigned key_u64s)
{
struct bch_fs *c = trans->c;
struct bch_fs_btree_key_cache *bc = &c->btree_key_cache;
struct bch_fs_btree_key_cache *bc = &c->btree.key_cache;
bool pcpu_readers = btree_uses_pcpu_readers(path->btree_id);
int ret;
@ -209,7 +209,7 @@ static int btree_key_cache_create(struct btree_trans *trans,
struct bkey_s_c k)
{
struct bch_fs *c = trans->c;
struct bch_fs_btree_key_cache *bc = &c->btree_key_cache;
struct bch_fs_btree_key_cache *bc = &c->btree.key_cache;
int ret = 0;
/*
@ -479,7 +479,7 @@ static int btree_key_cache_flush_pos(struct btree_trans *trans,
if (!evict) {
if (test_bit(BKEY_CACHED_DIRTY, &ck->flags)) {
clear_bit(BKEY_CACHED_DIRTY, &ck->flags);
atomic_long_dec(&c->btree_key_cache.nr_dirty);
atomic_long_dec(&c->btree.key_cache.nr_dirty);
}
} else {
struct btree_path *path = btree_iter_path(trans, &c_iter);
@ -494,12 +494,12 @@ static int btree_key_cache_flush_pos(struct btree_trans *trans,
if (test_bit(BKEY_CACHED_DIRTY, &ck->flags)) {
clear_bit(BKEY_CACHED_DIRTY, &ck->flags);
atomic_long_dec(&c->btree_key_cache.nr_dirty);
atomic_long_dec(&c->btree.key_cache.nr_dirty);
}
mark_btree_node_locked_noreset(path, 0, BTREE_NODE_UNLOCKED);
if (bkey_cached_evict(&c->btree_key_cache, ck)) {
bkey_cached_free(trans, &c->btree_key_cache, ck);
if (bkey_cached_evict(&c->btree.key_cache, ck)) {
bkey_cached_free(trans, &c->btree.key_cache, ck);
} else {
six_unlock_write(&ck->c.lock);
six_unlock_intent(&ck->c.lock);
@ -516,7 +516,7 @@ int bch2_btree_key_cache_journal_flush(struct journal *j,
struct bkey_cached *ck =
container_of(pin, struct bkey_cached, journal);
struct bkey_cached_key key;
int srcu_idx = srcu_read_lock(&c->btree_trans.barrier);
int srcu_idx = srcu_read_lock(&c->btree.trans.barrier);
int ret = 0;
CLASS(btree_trans, trans)(c);
@ -545,7 +545,7 @@ int bch2_btree_key_cache_journal_flush(struct journal *j,
!bch2_journal_error(j), c,
"flushing key cache: %s", bch2_err_str(ret));
unlock:
srcu_read_unlock(&c->btree_trans.barrier, srcu_idx);
srcu_read_unlock(&c->btree.trans.barrier, srcu_idx);
return ret;
}
@ -566,7 +566,7 @@ bool bch2_btree_insert_key_cached(struct btree_trans *trans,
if (!test_bit(BKEY_CACHED_DIRTY, &ck->flags)) {
EBUG_ON(test_bit(BCH_FS_clean_shutdown, &c->flags));
set_bit(BKEY_CACHED_DIRTY, &ck->flags);
atomic_long_inc(&c->btree_key_cache.nr_dirty);
atomic_long_inc(&c->btree.key_cache.nr_dirty);
if (bch2_nr_btree_keys_need_flush(c))
kick_reclaim = true;
@ -600,7 +600,7 @@ void bch2_btree_key_cache_drop(struct btree_trans *trans,
struct btree_path *path)
{
struct bch_fs *c = trans->c;
struct bch_fs_btree_key_cache *bc = &c->btree_key_cache;
struct bch_fs_btree_key_cache *bc = &c->btree.key_cache;
struct bkey_cached *ck = (void *) path->l[0].b;
/*
@ -609,7 +609,7 @@ void bch2_btree_key_cache_drop(struct btree_trans *trans,
*/
if (test_bit(BKEY_CACHED_DIRTY, &ck->flags)) {
clear_bit(BKEY_CACHED_DIRTY, &ck->flags);
atomic_long_dec(&c->btree_key_cache.nr_dirty);
atomic_long_dec(&c->btree.key_cache.nr_dirty);
bch2_journal_pin_drop(&c->journal, &ck->journal);
}
@ -642,14 +642,14 @@ static unsigned long bch2_btree_key_cache_scan(struct shrinker *shrink,
struct shrink_control *sc)
{
struct bch_fs *c = shrink->private_data;
struct bch_fs_btree_key_cache *bc = &c->btree_key_cache;
struct bch_fs_btree_key_cache *bc = &c->btree.key_cache;
struct bucket_table *tbl;
struct bkey_cached *ck;
size_t scanned = 0, freed = 0, nr = sc->nr_to_scan;
unsigned iter, start;
int srcu_idx;
srcu_idx = srcu_read_lock(&c->btree_trans.barrier);
srcu_idx = srcu_read_lock(&c->btree.trans.barrier);
rcu_read_lock();
tbl = rht_dereference_rcu(bc->table.tbl, &bc->table);
@ -663,7 +663,7 @@ static unsigned long bch2_btree_key_cache_scan(struct shrinker *shrink,
*/
if (unlikely(tbl->nest)) {
rcu_read_unlock();
srcu_read_unlock(&c->btree_trans.barrier, srcu_idx);
srcu_read_unlock(&c->btree.trans.barrier, srcu_idx);
return SHRINK_STOP;
}
@ -712,7 +712,7 @@ out:
bc->shrink_iter = iter;
rcu_read_unlock();
srcu_read_unlock(&c->btree_trans.barrier, srcu_idx);
srcu_read_unlock(&c->btree.trans.barrier, srcu_idx);
return freed;
}
@ -721,7 +721,7 @@ static unsigned long bch2_btree_key_cache_count(struct shrinker *shrink,
struct shrink_control *sc)
{
struct bch_fs *c = shrink->private_data;
struct bch_fs_btree_key_cache *bc = &c->btree_key_cache;
struct bch_fs_btree_key_cache *bc = &c->btree.key_cache;
long nr = atomic_long_read(&bc->nr_keys) -
atomic_long_read(&bc->nr_dirty);
@ -738,7 +738,7 @@ static unsigned long bch2_btree_key_cache_count(struct shrinker *shrink,
void bch2_fs_btree_key_cache_exit(struct bch_fs_btree_key_cache *bc)
{
struct bch_fs *c = container_of(bc, struct bch_fs, btree_key_cache);
struct bch_fs *c = container_of(bc, struct bch_fs, btree.key_cache);
struct bucket_table *tbl;
struct bkey_cached *ck;
struct rhash_head *pos;
@ -792,21 +792,17 @@ void bch2_fs_btree_key_cache_exit(struct bch_fs_btree_key_cache *bc)
free_percpu(bc->nr_pending);
}
void bch2_fs_btree_key_cache_init_early(struct bch_fs_btree_key_cache *c)
{
}
int bch2_fs_btree_key_cache_init(struct bch_fs_btree_key_cache *bc)
{
struct bch_fs *c = container_of(bc, struct bch_fs, btree_key_cache);
struct bch_fs *c = container_of(bc, struct bch_fs, btree.key_cache);
struct shrinker *shrink;
bc->nr_pending = alloc_percpu(size_t);
if (!bc->nr_pending)
return bch_err_throw(c, ENOMEM_fs_btree_cache_init);
if (rcu_pending_init(&bc->pending[0], &c->btree_trans.barrier, __bkey_cached_free) ||
rcu_pending_init(&bc->pending[1], &c->btree_trans.barrier, __bkey_cached_free))
if (rcu_pending_init(&bc->pending[0], &c->btree.trans.barrier, __bkey_cached_free) ||
rcu_pending_init(&bc->pending[1], &c->btree.trans.barrier, __bkey_cached_free))
return bch_err_throw(c, ENOMEM_fs_btree_cache_init);
if (rhashtable_init(&bc->table, &bch2_btree_key_cache_params))

View File

@ -4,8 +4,8 @@
static inline size_t bch2_nr_btree_keys_need_flush(struct bch_fs *c)
{
size_t nr_dirty = atomic_long_read(&c->btree_key_cache.nr_dirty);
size_t nr_keys = atomic_long_read(&c->btree_key_cache.nr_keys);
size_t nr_dirty = atomic_long_read(&c->btree.key_cache.nr_dirty);
size_t nr_keys = atomic_long_read(&c->btree.key_cache.nr_keys);
size_t max_dirty = 1024 + nr_keys / 2;
return max_t(ssize_t, 0, nr_dirty - max_dirty);
@ -13,8 +13,8 @@ static inline size_t bch2_nr_btree_keys_need_flush(struct bch_fs *c)
static inline ssize_t __bch2_btree_key_cache_must_wait(struct bch_fs *c)
{
size_t nr_dirty = atomic_long_read(&c->btree_key_cache.nr_dirty);
size_t nr_keys = atomic_long_read(&c->btree_key_cache.nr_keys);
size_t nr_dirty = atomic_long_read(&c->btree.key_cache.nr_dirty);
size_t nr_keys = atomic_long_read(&c->btree.key_cache.nr_keys);
size_t max_dirty = 4096 + (nr_keys * 3) / 4;
return nr_dirty - max_dirty;
@ -27,8 +27,8 @@ static inline bool bch2_btree_key_cache_must_wait(struct bch_fs *c)
static inline bool bch2_btree_key_cache_wait_done(struct bch_fs *c)
{
size_t nr_dirty = atomic_long_read(&c->btree_key_cache.nr_dirty);
size_t nr_keys = atomic_long_read(&c->btree_key_cache.nr_keys);
size_t nr_dirty = atomic_long_read(&c->btree.key_cache.nr_dirty);
size_t nr_keys = atomic_long_read(&c->btree.key_cache.nr_keys);
size_t max_dirty = 2048 + (nr_keys * 5) / 8;
return nr_dirty <= max_dirty;
@ -48,7 +48,6 @@ void bch2_btree_key_cache_drop(struct btree_trans *,
struct btree_path *);
void bch2_fs_btree_key_cache_exit(struct bch_fs_btree_key_cache *);
void bch2_fs_btree_key_cache_init_early(struct bch_fs_btree_key_cache *);
int bch2_fs_btree_key_cache_init(struct bch_fs_btree_key_cache *);
void bch2_btree_key_cache_to_text(struct printbuf *, struct bch_fs_btree_key_cache *);

View File

@ -25,8 +25,8 @@ static inline bool is_btree_node(struct btree_path *path, unsigned l)
static inline struct btree_transaction_stats *btree_trans_stats(struct btree_trans *trans)
{
return trans->fn_idx < ARRAY_SIZE(trans->c->btree_trans.stats)
? &trans->c->btree_trans.stats[trans->fn_idx]
return trans->fn_idx < ARRAY_SIZE(trans->c->btree.trans.stats)
? &trans->c->btree.trans.stats[trans->fn_idx]
: NULL;
}

View File

@ -122,7 +122,7 @@ static const struct min_heap_callbacks found_btree_node_heap_cbs = {
static void try_read_btree_node(struct find_btree_nodes *f, struct bch_dev *ca,
struct btree *b, struct bio *bio, u64 offset)
{
struct bch_fs *c = container_of(f, struct bch_fs, found_btree_nodes);
struct bch_fs *c = container_of(f, struct bch_fs, btree.node_scan);
struct btree_node *bn = b->data;
bio_reset(bio, ca->disk_sb.bdev, REQ_OP_READ);
@ -215,7 +215,7 @@ static void try_read_btree_node(struct find_btree_nodes *f, struct bch_dev *ca,
static int read_btree_nodes_worker(void *p)
{
struct find_btree_nodes_worker *w = p;
struct bch_fs *c = container_of(w->f, struct bch_fs, found_btree_nodes);
struct bch_fs *c = container_of(w->f, struct bch_fs, btree.node_scan);
struct bch_dev *ca = w->ca;
unsigned long last_print = jiffies;
struct btree *b = NULL;
@ -272,7 +272,7 @@ err:
static int read_btree_nodes(struct find_btree_nodes *f)
{
struct bch_fs *c = container_of(f, struct bch_fs, found_btree_nodes);
struct bch_fs *c = container_of(f, struct bch_fs, btree.node_scan);
int ret = 0;
CLASS(closure_stack, cl)();
@ -371,7 +371,7 @@ static int handle_overwrites(struct bch_fs *c,
int bch2_scan_for_btree_nodes(struct bch_fs *c)
{
struct find_btree_nodes *f = &c->found_btree_nodes;
struct find_btree_nodes *f = &c->btree.node_scan;
CLASS(printbuf, buf)();
CLASS(darray_found_btree_node, nodes_heap)();
size_t dst;
@ -491,7 +491,7 @@ static int found_btree_node_range_start_cmp(const void *_l, const void *_r)
bool bch2_btree_node_is_stale(struct bch_fs *c, struct btree *b)
{
struct find_btree_nodes *f = &c->found_btree_nodes;
struct find_btree_nodes *f = &c->btree.node_scan;
struct found_btree_node search = {
.btree_id = b->c.btree_id,
@ -517,7 +517,7 @@ int bch2_btree_has_scanned_nodes(struct bch_fs *c, enum btree_id btree, struct p
.max_key = SPOS_MAX,
};
for_each_found_btree_node_in_range(&c->found_btree_nodes, search, idx)
for_each_found_btree_node_in_range(&c->btree.node_scan, search, idx)
return true;
return false;
}
@ -551,7 +551,7 @@ int bch2_get_scanned_nodes(struct bch_fs *c, enum btree_id btree,
.max_key = node_max,
};
struct find_btree_nodes *f = &c->found_btree_nodes;
struct find_btree_nodes *f = &c->btree.node_scan;
for_each_found_btree_node_in_range(f, search, idx) {
struct found_btree_node n = f->nodes.data[idx];

View File

@ -661,7 +661,7 @@ int bch2_btree_node_read_done(struct bch_fs *c, struct bch_dev *ca,
/* We might get called multiple times on read retry: */
b->written = 0;
iter = mempool_alloc(&c->fill_iter, GFP_NOFS);
iter = mempool_alloc(&c->btree.fill_iter, GFP_NOFS);
sort_iter_init(iter, b, (btree_blocks(c) + 1) * 2);
if (bch2_meta_read_fault("btree"))
@ -932,7 +932,7 @@ int bch2_btree_node_read_done(struct bch_fs *c, struct bch_dev *ca,
set_btree_node_need_rewrite_ptr_written_zero(b);
}
fsck_err:
mempool_free(iter, &c->fill_iter);
mempool_free(iter, &c->btree.fill_iter);
bch2_time_stats_update(&c->times[BCH_TIME_btree_node_read_done], start_time);
return ret;
}
@ -1062,7 +1062,7 @@ static void btree_node_read_endio(struct bio *bio)
bch2_account_io_completion(ca, BCH_MEMBER_ERROR_read,
rb->start_time, !bio->bi_status);
queue_work(c->btree_read_complete_wq, &rb->work);
queue_work(c->btree.read_complete_wq, &rb->work);
}
void bch2_btree_read_bio_to_text(struct printbuf *out, struct btree_read_bio *rbio)
@ -1086,7 +1086,7 @@ void bch2_btree_node_read(struct btree_trans *trans, struct btree *b,
NULL, &pick, -1);
if (ret <= 0) {
bool ratelimit = true;
bool print = !bch2_ratelimit();
CLASS(printbuf, buf)();
bch2_log_msg_start(c, &buf);
@ -1097,12 +1097,9 @@ void bch2_btree_node_read(struct btree_trans *trans, struct btree *b,
if (c->recovery.passes_complete & BIT_ULL(BCH_RECOVERY_PASS_check_topology) &&
bch2_fs_emergency_read_only2(c, &buf))
ratelimit = false;
print = true;
static DEFINE_RATELIMIT_STATE(rs,
DEFAULT_RATELIMIT_INTERVAL,
DEFAULT_RATELIMIT_BURST);
if (!ratelimit || __ratelimit(&rs))
if (print)
bch2_print_str(c, KERN_ERR, buf.buf);
set_btree_node_read_error(b);
@ -1118,7 +1115,7 @@ void bch2_btree_node_read(struct btree_trans *trans, struct btree *b,
buf_pages(b->data, btree_buf_bytes(b)),
REQ_OP_READ|REQ_SYNC|REQ_META,
GFP_NOFS,
&c->btree_bio);
&c->btree.bio);
rb = container_of(bio, struct btree_read_bio, bio);
rb->c = c;
rb->b = b;
@ -1150,7 +1147,7 @@ void bch2_btree_node_read(struct btree_trans *trans, struct btree *b,
if (sync)
btree_node_read_work(&rb->work);
else
queue_work(c->btree_read_complete_wq, &rb->work);
queue_work(c->btree.read_complete_wq, &rb->work);
}
}
@ -1174,7 +1171,7 @@ static int __bch2_btree_root_read(struct btree_trans *trans, enum btree_id id,
BUG_ON(IS_ERR(b));
bkey_copy(&b->key, k);
BUG_ON(bch2_btree_node_hash_insert(&c->btree_cache, b, level, id));
BUG_ON(bch2_btree_node_hash_insert(&c->btree.cache, b, level, id));
set_btree_node_read_in_flight(b);
@ -1183,8 +1180,8 @@ static int __bch2_btree_root_read(struct btree_trans *trans, enum btree_id id,
bch2_btree_node_read(trans, b, true);
if (btree_node_read_error(b)) {
scoped_guard(mutex, &c->btree_cache.lock)
bch2_btree_node_hash_remove(&c->btree_cache, b);
scoped_guard(mutex, &c->btree.cache.lock)
bch2_btree_node_hash_remove(&c->btree.cache, b);
ret = bch_err_throw(c, btree_node_read_error);
goto err;
@ -1308,7 +1305,7 @@ static void btree_node_scrub_endio(struct bio *bio)
{
struct btree_node_scrub *scrub = container_of(bio, struct btree_node_scrub, bio);
queue_work(scrub->c->btree_read_complete_wq, &scrub->work);
queue_work(scrub->c->btree.read_complete_wq, &scrub->work);
}
int bch2_btree_node_scrub(struct btree_trans *trans,

View File

@ -100,7 +100,6 @@ int bch2_btree_node_scrub(struct btree_trans *, enum btree_id, unsigned,
struct bkey_s_c, unsigned);
bool bch2_btree_flush_all_reads(struct bch_fs *);
bool bch2_btree_flush_all_writes(struct bch_fs *);
static inline void compat_bformat(unsigned level, enum btree_id btree_id,
unsigned version, unsigned big_endian,

View File

@ -240,7 +240,7 @@ static void verify_no_dups(struct btree *b,
void bch2_btree_bounce_free(struct bch_fs *c, size_t size, bool used_mempool, void *p)
{
if (used_mempool)
mempool_free(p, &c->btree_bounce_pool);
mempool_free(p, &c->btree.bounce_pool);
else
kvfree(p);
}
@ -255,7 +255,7 @@ void *bch2_btree_bounce_alloc(struct bch_fs *c, size_t size, bool *used_mempool)
void *p = kvmalloc(size, GFP_NOWAIT|__GFP_ACCOUNT|__GFP_RECLAIMABLE);
if (!p) {
*used_mempool = true;
p = mempool_alloc(&c->btree_bounce_pool, GFP_NOFS|__GFP_ACCOUNT|__GFP_RECLAIMABLE);
p = mempool_alloc(&c->btree.bounce_pool, GFP_NOFS|__GFP_ACCOUNT|__GFP_RECLAIMABLE);
}
return p;
}

View File

@ -9,7 +9,10 @@
#include "alloc/replicas_types.h"
#include "btree/bbpos_types.h"
#include "btree/interior_types.h"
#include "btree/key_cache_types.h"
#include "btree/node_scan_types.h"
#include "btree/write_buffer_types.h"
#include "journal/types.h"
@ -705,6 +708,35 @@ enum btree_node_rewrite_reason {
#undef x
};
struct bch_fs_btree {
u16 foreground_merge_threshold;
mempool_t bounce_pool;
struct btree_write_stats {
atomic64_t nr;
atomic64_t bytes;
} write_stats[BTREE_WRITE_TYPE_NR];
struct bio_set bio;
mempool_t fill_iter;
struct workqueue_struct *read_complete_wq;
struct workqueue_struct *write_submit_wq;
struct workqueue_struct *write_complete_wq;
struct journal_entry_res root_journal_res;
struct bch_fs_btree_cache cache;
struct bch_fs_btree_key_cache key_cache;
struct bch_fs_btree_write_buffer write_buffer;
struct bch_fs_btree_trans trans;
struct bch_fs_btree_reserve_cache reserve_cache;
struct bch_fs_btree_interior_updates interior_updates;
struct bch_fs_btree_node_rewrites node_rewrites;
struct find_btree_nodes node_scan;
};
static inline enum btree_node_rewrite_reason btree_node_rewrite_reason(struct btree *b)
{
if (btree_node_need_rewrite_ptr_written_zero(b))

View File

@ -12,7 +12,9 @@
#include "debug/async_objs.h"
#include "debug/debug.h"
#include "init/dev.h"
#include "init/error.h"
#include "init/fs.h"
#include "sb/counters.h"
@ -112,7 +114,7 @@ static int btree_node_write_update_key(struct btree_trans *trans,
bkey_i_to_btree_ptr_v2(&wbio->key)->v.sectors_written;
bch2_bkey_drop_ptrs(bkey_i_to_s(n), p, entry,
bch2_dev_list_has_dev(wbio->wbio.failed, p.ptr.dev));
bch2_dev_io_failures(&wbio->wbio.failed, p.ptr.dev));
if (!bch2_bkey_nr_dirty_ptrs(c, bkey_i_to_s_c(n)))
return bch_err_throw(c, btree_node_write_all_failed);
@ -147,15 +149,33 @@ static void btree_node_write_work(struct work_struct *work)
if (!wbio->wbio.first_btree_write || wbio->wbio.failed.nr) {
int ret = bch2_trans_do(c, btree_node_write_update_key(trans, wbio, b));
if (ret) {
if (ret)
set_btree_node_noevict(b);
if (!bch2_err_matches(ret, EROFS)) {
CLASS(printbuf, buf)();
prt_printf(&buf, "writing btree node: %s\n ", bch2_err_str(ret));
bch2_btree_pos_to_text(&buf, c, b);
bch2_fs_fatal_error(c, "%s", buf.buf);
if ((ret && !bch2_err_matches(ret, EROFS)) ||
wbio->wbio.failed.nr) {
bool print = !bch2_ratelimit();
CLASS(printbuf, buf)();
bch2_log_msg_start(c, &buf);
prt_printf(&buf, "error writing btree node at ");
bch2_btree_pos_to_text(&buf, c, b);
prt_newline(&buf);
bch2_io_failures_to_text(&buf, c, &wbio->wbio.failed);
if (!ret) {
prt_printf(&buf, "wrote degraded to ");
struct bch_devs_list d = bch2_bkey_devs(c, bkey_i_to_s_c(&b->key));
bch2_devs_list_to_text(&buf, c, &d);
prt_newline(&buf);
} else {
prt_printf(&buf, "%s\n", bch2_err_str(ret));
print = bch2_fs_emergency_read_only2(c, &buf);
}
if (print)
bch2_print_str(c, KERN_ERR, buf.buf);
}
}
@ -174,25 +194,15 @@ static void btree_node_write_endio(struct bio *bio)
struct btree *b = wbio->bio.bi_private;
struct bch_dev *ca = wbio->have_ioref ? bch2_dev_have_ref(c, wbio->dev) : NULL;
/* XXX: ca can be null, stash dev_idx */
bch2_account_io_completion(ca, BCH_MEMBER_ERROR_write,
wbio->submit_time, !bio->bi_status);
if (ca && bio->bi_status) {
CLASS(printbuf, buf)();
guard(printbuf_atomic)(&buf);
__bch2_log_msg_start(ca->name, &buf);
prt_printf(&buf, "btree write error: %s\n",
bch2_blk_status_to_str(bio->bi_status));
bch2_btree_pos_to_text(&buf, c, b);
bch2_print_str_ratelimited(c, KERN_ERR, buf.buf);
}
if (bio->bi_status) {
unsigned long flags;
spin_lock_irqsave(&c->btree_write_error_lock, flags);
bch2_dev_list_add_dev(&orig->failed, wbio->dev);
spin_unlock_irqrestore(&c->btree_write_error_lock, flags);
if (unlikely(bio->bi_status)) {
guard(spinlock_irqsave)(&c->write_error_lock);
bch2_dev_io_failures_mut(&orig->failed, wbio->dev)->errcode =
__bch2_err_throw(c, -blk_status_to_bch_err(bio->bi_status));
}
/*
@ -213,7 +223,7 @@ static void btree_node_write_endio(struct bio *bio)
smp_mb__after_atomic();
wake_up_bit(&b->flags, BTREE_NODE_write_in_flight_inner);
INIT_WORK(&wb->work, btree_node_write_work);
queue_work(c->btree_write_complete_wq, &wb->work);
queue_work(c->btree.write_complete_wq, &wb->work);
}
static int validate_bset_for_write(struct bch_fs *c, struct btree *b,
@ -324,7 +334,7 @@ void __bch2_btree_node_write(struct bch_fs *c, struct btree *b, unsigned flags)
do_write:
BUG_ON((type == BTREE_WRITE_initial) != (b->written == 0));
atomic_long_dec(&c->btree_cache.nr_dirty);
atomic_long_dec(&c->btree.cache.nr_dirty);
BUG_ON(btree_node_fake(b));
BUG_ON((b->will_make_reachable != 0) != !b->written);
@ -485,7 +495,7 @@ do_write:
buf_pages(data, sectors_to_write << 9),
REQ_OP_WRITE|REQ_META|REQ_SYNC|REQ_IDLE,
GFP_NOFS,
&c->btree_bio),
&c->btree.bio),
struct btree_write_bio, wbio.bio);
wbio_init(&wbio->wbio.bio);
wbio->data = data;
@ -508,13 +518,13 @@ do_write:
bkey_i_to_btree_ptr_v2(&wbio->key)->v.sectors_written =
cpu_to_le16(b->written);
atomic64_inc(&c->btree_write_stats[type].nr);
atomic64_add(bytes_to_write, &c->btree_write_stats[type].bytes);
atomic64_inc(&c->btree.write_stats[type].nr);
atomic64_add(bytes_to_write, &c->btree.write_stats[type].bytes);
async_object_list_add(c, btree_write_bio, wbio, &wbio->list_idx);
INIT_WORK(&wbio->work, btree_write_submit);
queue_work(c->btree_write_submit_wq, &wbio->work);
queue_work(c->btree.write_submit_wq, &wbio->work);
return;
err:
set_btree_node_noevict(b);
@ -724,8 +734,8 @@ void bch2_btree_write_stats_to_text(struct printbuf *out, struct bch_fs *c)
prt_printf(out, "\tnr\tsize\n");
for (unsigned i = 0; i < BTREE_WRITE_TYPE_NR; i++) {
u64 nr = atomic64_read(&c->btree_write_stats[i].nr);
u64 bytes = atomic64_read(&c->btree_write_stats[i].bytes);
u64 nr = atomic64_read(&c->btree.write_stats[i].nr);
u64 bytes = atomic64_read(&c->btree.write_stats[i].bytes);
prt_printf(out, "%s:\t%llu\t", bch2_btree_write_types[i], nr);
prt_human_readable_u64(out, nr ? div64_u64(bytes, nr) : 0);

View File

@ -20,13 +20,13 @@ struct btree_write_bio {
static inline void set_btree_node_dirty_acct(struct bch_fs *c, struct btree *b)
{
if (!test_and_set_bit(BTREE_NODE_dirty, &b->flags))
atomic_long_inc(&c->btree_cache.nr_dirty);
atomic_long_inc(&c->btree.cache.nr_dirty);
}
static inline void clear_btree_node_dirty_acct(struct bch_fs *c, struct btree *b)
{
if (test_and_clear_bit(BTREE_NODE_dirty, &b->flags))
atomic_long_dec(&c->btree_cache.nr_dirty);
atomic_long_dec(&c->btree.cache.nr_dirty);
}
bool bch2_btree_post_write_cleanup(struct bch_fs *, struct btree *);
@ -52,5 +52,6 @@ static inline void btree_node_write_if_need(struct btree_trans *trans, struct bt
}
void bch2_btree_write_stats_to_text(struct printbuf *, struct bch_fs *);
bool bch2_btree_flush_all_writes(struct bch_fs *);
#endif /* _BCACHEFS_BTREE_WRITE_H */

View File

@ -152,8 +152,8 @@ static inline int wb_flush_one(struct btree_trans *trans, struct btree_iter *ite
struct btree_path *path;
EBUG_ON(!wb->journal_seq);
EBUG_ON(!trans->c->btree_write_buffer.flushing.pin.seq);
EBUG_ON(trans->c->btree_write_buffer.flushing.pin.seq > wb->journal_seq);
EBUG_ON(!trans->c->btree.write_buffer.flushing.pin.seq);
EBUG_ON(trans->c->btree.write_buffer.flushing.pin.seq > wb->journal_seq);
try(bch2_btree_iter_traverse(iter));
@ -243,7 +243,7 @@ btree_write_buffered_insert(struct btree_trans *trans,
static void move_keys_from_inc_to_flushing(struct bch_fs_btree_write_buffer *wb)
{
struct bch_fs *c = container_of(wb, struct bch_fs, btree_write_buffer);
struct bch_fs *c = container_of(wb, struct bch_fs, btree.write_buffer);
struct journal *j = &c->journal;
if (!wb->inc.keys.nr)
@ -307,7 +307,7 @@ static int bch2_btree_write_buffer_flush_locked(struct btree_trans *trans)
{
struct bch_fs *c = trans->c;
struct journal *j = &c->journal;
struct bch_fs_btree_write_buffer *wb = &c->btree_write_buffer;
struct bch_fs_btree_write_buffer *wb = &c->btree.write_buffer;
struct btree_iter iter = { NULL };
size_t overwritten = 0, fast = 0, noop = 0, slowpath = 0, could_not_insert = 0;
bool write_locked = false;
@ -577,7 +577,7 @@ static int btree_write_buffer_flush_seq(struct btree_trans *trans, u64 max_seq,
bool *did_work)
{
struct bch_fs *c = trans->c;
struct bch_fs_btree_write_buffer *wb = &c->btree_write_buffer;
struct bch_fs_btree_write_buffer *wb = &c->btree.write_buffer;
int ret = 0, fetch_from_journal_err;
do {
@ -639,7 +639,7 @@ bool bch2_btree_write_buffer_flush_going_ro(struct bch_fs *c)
int bch2_btree_write_buffer_flush_nocheck_rw(struct btree_trans *trans)
{
struct bch_fs *c = trans->c;
struct bch_fs_btree_write_buffer *wb = &c->btree_write_buffer;
struct bch_fs_btree_write_buffer *wb = &c->btree.write_buffer;
int ret = 0;
if (mutex_trylock(&wb->flushing.lock)) {
@ -710,8 +710,8 @@ int bch2_btree_write_buffer_maybe_flush(struct btree_trans *trans,
static void bch2_btree_write_buffer_flush_work(struct work_struct *work)
{
struct bch_fs *c = container_of(work, struct bch_fs, btree_write_buffer.flush_work);
struct bch_fs_btree_write_buffer *wb = &c->btree_write_buffer;
struct bch_fs *c = container_of(work, struct bch_fs, btree.write_buffer.flush_work);
struct bch_fs_btree_write_buffer *wb = &c->btree.write_buffer;
int ret;
scoped_guard(mutex, &wb->flushing.lock) {
@ -734,7 +734,7 @@ static void wb_accounting_sort(struct bch_fs_btree_write_buffer *wb)
int bch2_accounting_key_to_wb_slowpath(struct bch_fs *c, enum btree_id btree,
struct bkey_i_accounting *k)
{
struct bch_fs_btree_write_buffer *wb = &c->btree_write_buffer;
struct bch_fs_btree_write_buffer *wb = &c->btree.write_buffer;
event_inc_trace(c, accounting_key_to_wb_slowpath, buf, ({
prt_printf(&buf, "have: %zu\n", wb->accounting.nr);
@ -754,7 +754,7 @@ int bch2_journal_key_to_wb_slowpath(struct bch_fs *c,
struct journal_keys_to_wb *dst,
enum btree_id btree, struct bkey_i *k)
{
struct bch_fs_btree_write_buffer *wb = &c->btree_write_buffer;
struct bch_fs_btree_write_buffer *wb = &c->btree.write_buffer;
unsigned u64s = wb_key_u64s(k);
int ret;
retry:
@ -763,9 +763,9 @@ retry:
ret = darray_resize(&wb->sorted, wb->flushing.keys.size);
if (unlikely(ret)) {
if (dst->wb == &c->btree_write_buffer.flushing) {
if (dst->wb == &c->btree.write_buffer.flushing) {
mutex_unlock(&dst->wb->lock);
dst->wb = &c->btree_write_buffer.inc;
dst->wb = &c->btree.write_buffer.inc;
bch2_journal_pin_add(&c->journal, dst->seq, &dst->wb->pin,
bch2_btree_write_buffer_journal_flush);
goto retry;
@ -786,7 +786,7 @@ retry:
void bch2_journal_keys_to_write_buffer_start(struct bch_fs *c, struct journal_keys_to_wb *dst, u64 seq)
{
struct bch_fs_btree_write_buffer *wb = &c->btree_write_buffer;
struct bch_fs_btree_write_buffer *wb = &c->btree.write_buffer;
if (mutex_trylock(&wb->flushing.lock)) {
mutex_lock(&wb->inc.lock);
@ -822,7 +822,7 @@ void bch2_journal_keys_to_write_buffer_start(struct bch_fs *c, struct journal_ke
int bch2_journal_keys_to_write_buffer_end(struct bch_fs *c, struct journal_keys_to_wb *dst)
{
struct bch_fs_btree_write_buffer *wb = &c->btree_write_buffer;
struct bch_fs_btree_write_buffer *wb = &c->btree.write_buffer;
unsigned live_accounting_keys = 0;
int ret = 0;
@ -850,7 +850,7 @@ int bch2_journal_keys_to_write_buffer_end(struct bch_fs *c, struct journal_keys_
if (bch2_btree_write_buffer_should_flush(c) &&
__enumerated_ref_tryget(&c->writes, BCH_WRITE_REF_btree_write_buffer) &&
!queue_work(system_unbound_wq, &c->btree_write_buffer.flush_work))
!queue_work(system_unbound_wq, &c->btree.write_buffer.flush_work))
enumerated_ref_put(&c->writes, BCH_WRITE_REF_btree_write_buffer);
if (dst->wb == &wb->flushing)
@ -875,7 +875,7 @@ static int wb_keys_resize(struct btree_write_buffer_keys *wb, size_t new_size)
int bch2_btree_write_buffer_resize(struct bch_fs *c, size_t new_size)
{
struct bch_fs_btree_write_buffer *wb = &c->btree_write_buffer;
struct bch_fs_btree_write_buffer *wb = &c->btree.write_buffer;
return wb_keys_resize(&wb->flushing, new_size) ?:
wb_keys_resize(&wb->inc, new_size);
@ -883,7 +883,7 @@ int bch2_btree_write_buffer_resize(struct bch_fs *c, size_t new_size)
void bch2_fs_btree_write_buffer_exit(struct bch_fs *c)
{
struct bch_fs_btree_write_buffer *wb = &c->btree_write_buffer;
struct bch_fs_btree_write_buffer *wb = &c->btree.write_buffer;
BUG_ON((wb->inc.keys.nr || wb->flushing.keys.nr) &&
!bch2_journal_error(&c->journal));
@ -896,7 +896,7 @@ void bch2_fs_btree_write_buffer_exit(struct bch_fs *c)
void bch2_fs_btree_write_buffer_init_early(struct bch_fs *c)
{
struct bch_fs_btree_write_buffer *wb = &c->btree_write_buffer;
struct bch_fs_btree_write_buffer *wb = &c->btree.write_buffer;
mutex_init(&wb->inc.lock);
mutex_init(&wb->flushing.lock);
@ -905,7 +905,7 @@ void bch2_fs_btree_write_buffer_init_early(struct bch_fs *c)
int bch2_fs_btree_write_buffer_init(struct bch_fs *c)
{
struct bch_fs_btree_write_buffer *wb = &c->btree_write_buffer;
struct bch_fs_btree_write_buffer *wb = &c->btree.write_buffer;
/* Will be resized by journal as needed: */
unsigned initial_size = 1 << 16;

View File

@ -8,14 +8,14 @@
static inline bool bch2_btree_write_buffer_should_flush(struct bch_fs *c)
{
struct bch_fs_btree_write_buffer *wb = &c->btree_write_buffer;
struct bch_fs_btree_write_buffer *wb = &c->btree.write_buffer;
return wb->inc.keys.nr + wb->flushing.keys.nr > wb->inc.keys.size / 4;
}
static inline bool bch2_btree_write_buffer_must_wait(struct bch_fs *c)
{
struct bch_fs_btree_write_buffer *wb = &c->btree_write_buffer;
struct bch_fs_btree_write_buffer *wb = &c->btree.write_buffer;
return wb->inc.keys.nr > wb->inc.keys.size * 3 / 4;
}
@ -72,7 +72,7 @@ int bch2_accounting_key_to_wb_slowpath(struct bch_fs *,
static inline int bch2_accounting_key_to_wb(struct bch_fs *c,
enum btree_id btree, struct bkey_i_accounting *k)
{
struct bch_fs_btree_write_buffer *wb = &c->btree_write_buffer;
struct bch_fs_btree_write_buffer *wb = &c->btree.write_buffer;
struct btree_write_buffered_key search;
search.btree = btree;
search.k.k.p = k->k.p;

View File

@ -57,7 +57,7 @@ static void bbuf_exit(struct bbuf *buf)
kfree(buf->b);
break;
case BB_mempool:
mempool_free(buf->b, &buf->c->compression_bounce[buf->rw]);
mempool_free(buf->b, &buf->c->compress.bounce[buf->rw]);
break;
}
}
@ -72,7 +72,7 @@ static struct bbuf __bounce_alloc(struct bch_fs *c, unsigned size, int rw)
if (b)
return (struct bbuf) { .c = c, .b = b, .type = BB_kmalloc, .rw = rw };
b = mempool_alloc(&c->compression_bounce[rw], GFP_NOFS);
b = mempool_alloc(&c->compress.bounce[rw], GFP_NOFS);
if (b)
return (struct bbuf) { .c = c, .b = b, .type = BB_mempool, .rw = rw };
@ -191,7 +191,7 @@ static int __bio_uncompress(struct bch_fs *c, struct bio *src,
int ret2;
enum bch_compression_opts opt = bch2_compression_type_to_opt(crc.compression_type);
mempool_t *workspace_pool = &c->compress_workspace[opt];
mempool_t *workspace_pool = &c->compress.workspace[opt];
if (unlikely(!mempool_initialized(workspace_pool))) {
if (ret_fsck_err(c, compression_type_not_marked_in_sb,
"compression type %s set but not marked in superblock",
@ -388,7 +388,7 @@ static int attempt_compress(struct bch_fs *c,
*/
unsigned level = min((compression.level * 3) / 2, zstd_max_clevel());
ZSTD_parameters params = zstd_get_params(level, c->opts.encoded_extent_max);
ZSTD_CCtx *ctx = zstd_init_cctx(workspace, c->zstd_workspace_size);
ZSTD_CCtx *ctx = zstd_init_cctx(workspace, c->compress.zstd_workspace_size);
/*
* ZSTD requires that when we decompress we pass in the exact
@ -428,7 +428,7 @@ static unsigned __bio_compress(struct bch_fs *c,
/* bch2_compression_decode catches unknown compression types: */
BUG_ON(compression.type >= BCH_COMPRESSION_OPT_NR);
mempool_t *workspace_pool = &c->compress_workspace[compression.type];
mempool_t *workspace_pool = &c->compress.workspace[compression.type];
if (unlikely(!mempool_initialized(workspace_pool))) {
if (ret_fsck_err(c, compression_opt_not_marked_in_sb,
"compression opt %s set but not marked in superblock",
@ -587,10 +587,10 @@ void bch2_fs_compress_exit(struct bch_fs *c)
{
unsigned i;
for (i = 0; i < ARRAY_SIZE(c->compress_workspace); i++)
mempool_exit(&c->compress_workspace[i]);
mempool_exit(&c->compression_bounce[WRITE]);
mempool_exit(&c->compression_bounce[READ]);
for (i = 0; i < ARRAY_SIZE(c->compress.workspace); i++)
mempool_exit(&c->compress.workspace[i]);
mempool_exit(&c->compress.bounce[WRITE]);
mempool_exit(&c->compress.bounce[READ]);
}
static int __bch2_fs_compress_init(struct bch_fs *c, u64 features)
@ -598,7 +598,7 @@ static int __bch2_fs_compress_init(struct bch_fs *c, u64 features)
ZSTD_parameters params = zstd_get_params(zstd_max_clevel(),
c->opts.encoded_extent_max);
c->zstd_workspace_size = zstd_cctx_workspace_bound(&params.cParams);
c->compress.zstd_workspace_size = zstd_cctx_workspace_bound(&params.cParams);
struct {
unsigned feature;
@ -611,7 +611,7 @@ static int __bch2_fs_compress_init(struct bch_fs *c, u64 features)
max(zlib_deflate_workspacesize(MAX_WBITS, DEF_MEM_LEVEL),
zlib_inflate_workspacesize()) },
{ BCH_FEATURE_zstd, BCH_COMPRESSION_OPT_zstd,
max(c->zstd_workspace_size,
max(c->compress.zstd_workspace_size,
zstd_dctx_workspace_bound()) },
}, *i;
bool have_compressed = false;
@ -624,13 +624,13 @@ static int __bch2_fs_compress_init(struct bch_fs *c, u64 features)
if (!have_compressed)
return 0;
if (!mempool_initialized(&c->compression_bounce[READ]) &&
mempool_init_kvmalloc_pool(&c->compression_bounce[READ],
if (!mempool_initialized(&c->compress.bounce[READ]) &&
mempool_init_kvmalloc_pool(&c->compress.bounce[READ],
1, c->opts.encoded_extent_max))
return bch_err_throw(c, ENOMEM_compression_bounce_read_init);
if (!mempool_initialized(&c->compression_bounce[WRITE]) &&
mempool_init_kvmalloc_pool(&c->compression_bounce[WRITE],
if (!mempool_initialized(&c->compress.bounce[WRITE]) &&
mempool_init_kvmalloc_pool(&c->compress.bounce[WRITE],
1, c->opts.encoded_extent_max))
return bch_err_throw(c, ENOMEM_compression_bounce_write_init);
@ -640,11 +640,11 @@ static int __bch2_fs_compress_init(struct bch_fs *c, u64 features)
if (!(features & (1 << i->feature)))
continue;
if (mempool_initialized(&c->compress_workspace[i->type]))
if (mempool_initialized(&c->compress.workspace[i->type]))
continue;
if (mempool_init_kvmalloc_pool(
&c->compress_workspace[i->type],
&c->compress.workspace[i->type],
1, i->compress_workspace))
return bch_err_throw(c, ENOMEM_compression_workspace_init);
}

View File

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _BCACHEFS_COMPRESS_H
#define _BCACHEFS_COMPRESS_H
#ifndef _BCACHEFS_DATA_COMPRESS_H
#define _BCACHEFS_DATA_COMPRESS_H
#include "extents_types.h"
@ -56,4 +56,4 @@ int bch2_opt_compression_validate(u64, struct printbuf *);
.validate = bch2_opt_compression_validate, \
}
#endif /* _BCACHEFS_COMPRESS_H */
#endif /* _BCACHEFS_DATA_COMPRESS_H */

View File

@ -0,0 +1,11 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _BCACHEFS_DATA_COMPRESS_TYPES_H
#define _BCACHEFS_DATA_COMPRESS_TYPES_H
struct bch_fs_compress {
mempool_t bounce[2];
mempool_t workspace[BCH_COMPRESSION_OPT_NR];
size_t zstd_workspace_size;
};
#endif /* _BCACHEFS_DATA_COMPRESS_TYPES_H */

View File

@ -141,7 +141,7 @@ static int bch2_dev_usrdata_drop(struct bch_fs *c,
BTREE_ITER_prefetch|BTREE_ITER_all_snapshots, k,
&res.r, NULL, BCH_TRANS_COMMIT_no_enospc, ({
bch2_disk_reservation_put(c, &res.r);
bch2_progress_update_iter(trans, progress, &iter, "dropping user data") ?:
bch2_progress_update_iter(trans, progress, &iter) ?:
bch2_dev_usrdata_drop_key(trans, &iter, k, dev_idx, flags, err);
})));
}
@ -159,7 +159,7 @@ static int dev_metadata_drop_one(struct btree_trans *trans,
if (!b)
return 1;
try(bch2_progress_update_iter(trans, progress, iter, "dropping metadata"));
try(bch2_progress_update_iter(trans, progress, iter));
try(drop_btree_ptrs(trans, iter, b, dev_idx, flags, err));
return 0;
}
@ -251,11 +251,12 @@ int bch2_dev_data_drop(struct bch_fs *c, unsigned dev_idx,
unsigned flags, struct printbuf *err)
{
struct progress_indicator progress;
bch2_progress_init(&progress, c, btree_has_data_ptrs_mask & ~BIT_ULL(BTREE_ID_stripes));
bch2_progress_init(&progress, "dropping user data", c,
btree_has_data_ptrs_mask & ~BIT_ULL(BTREE_ID_stripes), 0);
try(bch2_dev_usrdata_drop(c, &progress, dev_idx, flags, err));
bch2_progress_init_inner(&progress, c, 0, ~0ULL);
bch2_progress_init(&progress, "dropping metadata", c, 0, ~0ULL);
return bch2_dev_metadata_drop(c, &progress, dev_idx, flags, err);
}

View File

@ -50,7 +50,7 @@ module_param_named(read_corrupt_device, bch2_read_corrupt_device, int, 0644);
MODULE_PARM_DESC(read_corrupt_device, "");
#endif
static bool bch2_poison_extents_on_checksum_error;
static bool bch2_poison_extents_on_checksum_error = true;
module_param_named(poison_extents_on_checksum_error,
bch2_poison_extents_on_checksum_error, bool, 0644);
MODULE_PARM_DESC(poison_extents_on_checksum_error,
@ -567,7 +567,6 @@ static noinline int maybe_poison_extent(struct btree_trans *trans, struct bch_re
return 0;
struct bch_fs *c = trans->c;
struct data_update *u = rbio_data_update(rbio);
if (u)
read_k = bkey_i_to_s_c(u->k.k);
@ -597,6 +596,12 @@ static noinline int maybe_poison_extent(struct btree_trans *trans, struct bch_re
*/
if (u)
bch2_bkey_buf_copy(&u->k, new);
event_inc_trace(c, data_read_fail_and_poison, buf, ({
bch2_bkey_val_to_text(&buf, c, k);
prt_newline(&buf);
bch2_read_bio_to_text_atomic(&buf, rbio);
}));
return 0;
}
@ -1294,12 +1299,6 @@ static noinline int read_extent_pick_err(struct btree_trans *trans,
BUG_ON(!(flags & BCH_READ_in_retry));
try(maybe_poison_extent(trans, rbio, data_btree, k));
event_inc_trace(c, data_read_fail_and_poison, buf, ({
bch2_bkey_val_to_text(&buf, c, k);
prt_newline(&buf);
bch2_read_bio_to_text_atomic(&buf, rbio);
}));
}
if (!(flags & BCH_READ_in_retry)) {

View File

@ -2284,7 +2284,7 @@ static int check_reconcile_work_data_btree(struct btree_trans *trans,
while (true) {
bch2_disk_reservation_put(c, &res.r);
try(bch2_progress_update_iter(trans, progress, &data_iter, "check_reconcile_work"));
try(bch2_progress_update_iter(trans, progress, &data_iter));
try(commit_do(trans, &res.r, NULL, BCH_TRANS_COMMIT_no_enospc,
check_reconcile_work_one(trans, &data_iter, rb_w, rb_h, rb_p,
snapshot_io_opts, last_flushed, &cur_pos)));
@ -2371,7 +2371,7 @@ static int check_reconcile_work_phys(struct btree_trans *trans)
struct bch_fs *c = trans->c;
struct progress_indicator progress;
bch2_progress_init(&progress, c, BIT_ULL(BTREE_ID_backpointers));
bch2_progress_init(&progress, __func__, c, BIT_ULL(BTREE_ID_backpointers), 0);
struct bpos cur_pos = POS_MIN;
CLASS(btree_iter, bp)(trans, BTREE_ID_backpointers, POS_MIN, BTREE_ITER_prefetch);
@ -2382,7 +2382,7 @@ static int check_reconcile_work_phys(struct btree_trans *trans)
wb_maybe_flush_init(&last_flushed);
while (true) {
try(bch2_progress_update_iter(trans, &progress, &bp, "check_reconcile_work_phys"));
try(bch2_progress_update_iter(trans, &progress, &bp));
try(commit_do(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc,
check_reconcile_work_phys_one(trans, &bp, &r_w, &r_h,
@ -2477,7 +2477,7 @@ static int check_reconcile_work_btrees(struct btree_trans *trans)
CLASS(disk_reservation, res)(c);
struct progress_indicator progress;
bch2_progress_init_inner(&progress, c, 0, ~0ULL);
bch2_progress_init(&progress, __func__, c, 0, ~0ULL);
for (enum btree_id btree = 0; btree < btree_id_nr_alive(c); btree++) {
if (!bch2_btree_id_root(c, btree)->b)
@ -2491,7 +2491,7 @@ static int check_reconcile_work_btrees(struct btree_trans *trans)
try(for_each_btree_key_continue(trans, iter, 0, k, ({
bch2_disk_reservation_put(c, &res.r);
progress_update_iter(trans, &progress, &iter) ?:
bch2_progress_update_iter(trans, &progress, &iter) ?:
check_reconcile_work_btree_key(trans, &iter, k) ?:
bch2_trans_commit(trans, &res.r, NULL, BCH_TRANS_COMMIT_no_enospc);
})));
@ -2515,12 +2515,12 @@ noinline_for_stack
static int check_reconcile_btree_bps(struct btree_trans *trans)
{
struct progress_indicator progress;
bch2_progress_init(&progress, trans->c, BIT_ULL(BTREE_ID_reconcile_scan));
bch2_progress_init(&progress, __func__, trans->c, BIT_ULL(BTREE_ID_reconcile_scan), 0);
return for_each_btree_key_max(trans, iter, BTREE_ID_reconcile_scan,
POS(1, 0), POS(1, U64_MAX),
BTREE_ITER_prefetch, k, ({
progress_update_iter(trans, &progress, &iter) ?:
bch2_progress_update_iter(trans, &progress, &iter) ?:
check_reconcile_btree_bp(trans, k);
}));
}
@ -2542,9 +2542,10 @@ int bch2_check_reconcile_work(struct bch_fs *c)
wb_maybe_flush_init(&last_flushed);
struct progress_indicator progress;
bch2_progress_init(&progress, c,
bch2_progress_init(&progress, __func__, c,
BIT_ULL(BTREE_ID_extents)|
BIT_ULL(BTREE_ID_reflink));
BIT_ULL(BTREE_ID_reflink),
0);
static const enum btree_id data_btrees[] = {
BTREE_ID_stripes,

View File

@ -349,6 +349,7 @@ void bch2_data_update_read_done(struct data_update *u)
}
if (unlikely(rbio->ret)) {
u->op.error = rbio->ret;
u->op.end_io(&u->op);
return;
}

View File

@ -422,19 +422,31 @@ static int bch2_write_index_default(struct bch_write_op *op)
/* Writes */
void bch2_write_op_error(struct bch_write_op *op, u64 offset, const char *fmt, ...)
static void bch2_log_write_error_start(struct printbuf *out, struct bch_write_op *op, u64 offset)
{
CLASS(btree_trans, trans)(op->c);
CLASS(printbuf, buf)();
bch2_log_msg_start(op->c, &buf);
bch2_log_msg_start(op->c, out);
prt_printf(out, "error writing data at ");
struct bpos pos = op->pos;
pos.offset = offset;
bch2_inum_offset_err_msg_trans(trans, &buf, op->subvol, pos);
CLASS(btree_trans, trans)(op->c);
bch2_inum_offset_err_msg_trans(trans, out, op->subvol, pos);
prt_newline(out);
prt_str(&buf, "write error: ");
if (op->flags & BCH_WRITE_move) {
struct data_update *u = container_of(op, struct data_update, op);
prt_printf(out, "from internal move ");
bch2_bkey_val_to_text(out, op->c, bkey_i_to_s_c(u->k.k));
prt_newline(out);
}
}
void bch2_write_op_error(struct bch_write_op *op, u64 offset, const char *fmt, ...)
{
CLASS(printbuf, buf)();
bch2_log_write_error_start(&buf, op, offset);
va_list args;
va_start(args, fmt);
@ -442,14 +454,6 @@ void bch2_write_op_error(struct bch_write_op *op, u64 offset, const char *fmt, .
va_end(args);
prt_newline(&buf);
if (op->flags & BCH_WRITE_move) {
struct data_update *u = container_of(op, struct data_update, op);
prt_printf(&buf, "from internal move ");
bch2_bkey_val_to_text(&buf, op->c, bkey_i_to_s_c(u->k.k));
prt_newline(&buf);
}
bch2_print_str_ratelimited(op->c, KERN_ERR, buf.buf);
}
@ -469,9 +473,15 @@ void bch2_submit_wbio_replicas(struct bch_write_bio *wbio, struct bch_fs *c,
const struct bch_extent_ptr *last = NULL;
bkey_for_each_ptr(ptrs, ptr)
last = ptr;
if (ptr->dev != BCH_SB_MEMBER_INVALID)
last = ptr;
BUG_ON(!last);
bkey_for_each_ptr(ptrs, ptr) {
if (ptr->dev == BCH_SB_MEMBER_INVALID)
continue;
/*
* XXX: btree writes should be using io_ref[WRITE], but we
* aren't retrying failed btree writes yet (due to device
@ -560,7 +570,7 @@ static noinline int bch2_write_drop_io_error_ptrs(struct bch_write_op *op)
if (bkey_extent_is_direct_data(&src->k)) {
bch2_bkey_drop_ptrs(bkey_i_to_s(src), p, entry,
test_bit(p.ptr.dev, op->failed.d));
bch2_dev_io_failures(&op->wbio.failed, p.ptr.dev));
if (!bch2_bkey_nr_dirty_ptrs(c, bkey_i_to_s_c(src)))
return bch_err_throw(c, data_write_io);
@ -583,11 +593,30 @@ static void __bch2_write_index(struct bch_write_op *op)
{
struct bch_fs *c = op->c;
struct keylist *keys = &op->insert_keys;
unsigned dev;
int ret = 0;
if (unlikely(op->io_error)) {
struct bkey_i *k = bch2_keylist_front(&op->insert_keys);
bool print;
CLASS(printbuf, buf)();
bch2_log_write_error_start(&buf, op, bkey_start_offset(&k->k));
bch2_io_failures_to_text(&buf, c, &op->wbio.failed);
ret = bch2_write_drop_io_error_ptrs(op);
if (!ret) {
prt_printf(&buf, "wrote degraded to ");
struct bch_devs_list d = bch2_bkey_devs(c, bkey_i_to_s_c(k));
bch2_devs_list_to_text(&buf, c, &d);
prt_newline(&buf);
print = !bch2_ratelimit(); /* Different ratelimits for hard and soft errors */
} else {
prt_printf(&buf, "all replicated writes failed\n");
print = !bch2_ratelimit();
}
if (print)
bch2_print_str(c, KERN_ERR, buf.buf);
if (ret)
goto err;
}
@ -616,8 +645,9 @@ static void __bch2_write_index(struct bch_write_op *op)
}
out:
/* If some a bucket wasn't written, we can't erasure code it: */
for_each_set_bit(dev, op->failed.d, BCH_SB_MEMBERS_MAX)
bch2_open_bucket_write_error(c, &op->open_buckets, dev, -BCH_ERR_data_write_io);
darray_for_each(op->wbio.failed, i)
bch2_open_bucket_write_error(c, &op->open_buckets, i->dev,
i->errcode ?: -BCH_ERR_data_write_io);
bch2_open_buckets_put(c, &op->open_buckets);
return;
@ -732,19 +762,9 @@ static void bch2_write_endio(struct bio *bio)
wbio->submit_time, !bio->bi_status);
if (unlikely(bio->bi_status)) {
if (ca)
bch_err_inum_offset_ratelimited(ca,
op->pos.inode,
wbio->inode_offset << 9,
"data write error: %s",
bch2_blk_status_to_str(bio->bi_status));
else
bch_err_inum_offset_ratelimited(c,
op->pos.inode,
wbio->inode_offset << 9,
"data write error: %s",
bch2_blk_status_to_str(bio->bi_status));
set_bit(wbio->dev, op->failed.d);
guard(spinlock_irqsave)(&c->write_error_lock);
bch2_dev_io_failures_mut(&op->wbio.failed, wbio->dev)->errcode =
__bch2_err_throw(c, -blk_status_to_bch_err(bio->bi_status));
op->io_error = true;
}
@ -1513,7 +1533,7 @@ static void __bch2_write(struct bch_write_op *op)
return;
}
again:
memset(&op->failed, 0, sizeof(op->failed));
op->wbio.failed.nr = 0;
do {
struct bkey_i *key_to_write;
@ -1617,7 +1637,7 @@ static void bch2_write_data_inline(struct bch_write_op *op, unsigned data_len)
unsigned sectors;
int ret;
memset(&op->failed, 0, sizeof(op->failed));
op->wbio.failed.nr = 0;
op->flags |= BCH_WRITE_wrote_data_inline;
op->flags |= BCH_WRITE_submitted;
@ -1768,7 +1788,7 @@ void __bch2_write_op_to_text(struct printbuf *out, struct bch_write_op *op)
prt_printf(out, "nr_replicas:\t%u\n", op->nr_replicas);
prt_printf(out, "nr_replicas_required:\t%u\n", op->nr_replicas_required);
prt_printf(out, "devs_have:\t");
bch2_devs_list_to_text(out, &op->devs_have);
bch2_devs_list_to_text(out, op->c, &op->devs_have);
prt_newline(out);
prt_printf(out, "opts:\t");

View File

@ -49,7 +49,7 @@ struct bch_write_bio {
u64 inode_offset;
u64 nocow_bucket;
struct bch_devs_list failed;
struct bch_io_failures failed;
u8 dev;
unsigned split:1,
@ -111,8 +111,6 @@ struct bch_write_op {
u64 new_i_size;
s64 i_sectors_delta;
struct bch_devs_mask failed;
struct keylist insert_keys;
u64 inline_keys[BKEY_EXTENT_U64s_MAX * 2];

View File

@ -60,7 +60,7 @@ static bool bch2_btree_verify_replica(struct bch_fs *c, struct btree *b,
buf_pages(n_sorted, btree_buf_bytes(b)),
REQ_OP_READ|REQ_META,
GFP_NOFS,
&c->btree_bio);
&c->btree.bio);
bio->bi_iter.bi_sector = pick.ptr.offset;
bch2_bio_map(bio, n_sorted, btree_buf_bytes(b));
@ -217,7 +217,7 @@ void bch2_btree_node_ondisk_to_text(struct printbuf *out, struct bch_fs *c,
buf_pages(n_ondisk, btree_buf_bytes(b)),
REQ_OP_READ|REQ_META,
GFP_NOFS,
&c->btree_bio);
&c->btree.bio);
bio->bi_iter.bi_sector = pick.ptr.offset;
bch2_bio_map(bio, n_ondisk, btree_buf_bytes(b));
@ -521,8 +521,8 @@ static ssize_t bch2_cached_btree_nodes_read(struct file *file, char __user *buf,
scoped_guard(rcu) {
guard(printbuf_atomic)(&i->buf);
struct bucket_table *tbl =
rht_dereference_rcu(c->btree_cache.table.tbl,
&c->btree_cache.table);
rht_dereference_rcu(c->btree.cache.table.tbl,
&c->btree.cache.table);
if (i->iter < tbl->size) {
struct rhash_head *pos;
struct btree *b;
@ -590,12 +590,12 @@ static ssize_t bch2_btree_transactions_read(struct file *file, char __user *buf,
i->size = size;
i->ret = 0;
int srcu_idx = srcu_read_lock(&c->btree_trans.barrier);
int srcu_idx = srcu_read_lock(&c->btree.trans.barrier);
restart:
seqmutex_lock(&c->btree_trans.lock);
list_sort(&c->btree_trans.list, list_ptr_order_cmp);
seqmutex_lock(&c->btree.trans.lock);
list_sort(&c->btree.trans.list, list_ptr_order_cmp);
list_for_each_entry(trans, &c->btree_trans.list, list) {
list_for_each_entry(trans, &c->btree.trans.list, list) {
if ((ulong) trans <= i->iter)
continue;
@ -609,7 +609,7 @@ restart:
continue;
}
u32 seq = seqmutex_unlock(&c->btree_trans.lock);
u32 seq = seqmutex_unlock(&c->btree.trans.lock);
bch2_btree_trans_to_text(&i->buf, trans);
@ -624,12 +624,12 @@ restart:
if (ret)
goto unlocked;
if (!seqmutex_relock(&c->btree_trans.lock, seq))
if (!seqmutex_relock(&c->btree.trans.lock, seq))
goto restart;
}
seqmutex_unlock(&c->btree_trans.lock);
seqmutex_unlock(&c->btree.trans.lock);
unlocked:
srcu_read_unlock(&c->btree_trans.barrier, srcu_idx);
srcu_read_unlock(&c->btree.trans.barrier, srcu_idx);
if (i->buf.allocation_failure)
ret = -ENOMEM;
@ -759,7 +759,7 @@ static ssize_t btree_transaction_stats_read(struct file *file, char __user *buf,
i->ret = 0;
while (1) {
struct btree_transaction_stats *s = &c->btree_trans.stats[i->iter];
struct btree_transaction_stats *s = &c->btree.trans.stats[i->iter];
err = bch2_debugfs_flush_buf(i);
if (err)
@ -825,10 +825,10 @@ static void btree_deadlock_to_text(struct printbuf *out, struct bch_fs *c)
struct btree_trans *trans;
ulong iter = 0;
restart:
seqmutex_lock(&c->btree_trans.lock);
list_sort(&c->btree_trans.list, list_ptr_order_cmp);
seqmutex_lock(&c->btree.trans.lock);
list_sort(&c->btree.trans.list, list_ptr_order_cmp);
list_for_each_entry(trans, &c->btree_trans.list, list) {
list_for_each_entry(trans, &c->btree.trans.list, list) {
if ((ulong) trans <= iter)
continue;
@ -837,7 +837,7 @@ restart:
if (!closure_get_not_zero(&trans->ref))
continue;
u32 seq = seqmutex_unlock(&c->btree_trans.lock);
u32 seq = seqmutex_unlock(&c->btree.trans.lock);
bool found = bch2_check_for_deadlock(trans, out) != 0;
@ -846,10 +846,10 @@ restart:
if (found)
return;
if (!seqmutex_relock(&c->btree_trans.lock, seq))
if (!seqmutex_relock(&c->btree.trans.lock, seq))
goto restart;
}
seqmutex_unlock(&c->btree_trans.lock);
seqmutex_unlock(&c->btree.trans.lock);
}
typedef void (*fs_to_text_fn)(struct printbuf *, struct bch_fs *);
@ -908,7 +908,7 @@ static const struct file_operations write_points_ops = {
static bool print_next_node_scan_node(struct dump_iter *i)
{
struct find_btree_nodes *f = &i->c->found_btree_nodes;
struct find_btree_nodes *f = &i->c->btree.node_scan;
guard(mutex)(&f->lock);
if (i->iter >= f->nodes.nr)

View File

@ -246,7 +246,7 @@ write_attribute(perf_test);
static size_t bch2_btree_cache_size(struct bch_fs *c)
{
struct bch_fs_btree_cache *bc = &c->btree_cache;
struct bch_fs_btree_cache *bc = &c->btree.cache;
size_t ret = 0;
struct btree *b;
@ -357,10 +357,10 @@ SHOW(bch2_fs)
bch2_journal_debug_to_text(out, &c->journal);
if (attr == &sysfs_btree_cache)
bch2_btree_cache_to_text(out, &c->btree_cache);
bch2_btree_cache_to_text(out, &c->btree.cache);
if (attr == &sysfs_btree_key_cache)
bch2_btree_key_cache_to_text(out, &c->btree_key_cache);
bch2_btree_key_cache_to_text(out, &c->btree.key_cache);
if (attr == &sysfs_btree_reserve_cache)
bch2_btree_reserve_cache_to_text(out, c);
@ -425,13 +425,13 @@ STORE(bch2_fs)
/* Debugging: */
if (attr == &sysfs_trigger_btree_updates)
queue_work(c->btree_interior_updates.worker, &c->btree_interior_updates.work);
queue_work(c->btree.interior_updates.worker, &c->btree.interior_updates.work);
if (!enumerated_ref_tryget(&c->writes, BCH_WRITE_REF_sysfs))
return -EROFS;
if (attr == &sysfs_trigger_btree_cache_shrink) {
struct bch_fs_btree_cache *bc = &c->btree_cache;
struct bch_fs_btree_cache *bc = &c->btree.cache;
struct shrink_control sc;
sc.gfp_mask = GFP_KERNEL;
@ -444,7 +444,7 @@ STORE(bch2_fs)
sc.gfp_mask = GFP_KERNEL;
sc.nr_to_scan = strtoul_or_return(buf);
c->btree_key_cache.shrink->scan_objects(c->btree_key_cache.shrink, &sc);
c->btree.key_cache.shrink->scan_objects(c->btree.key_cache.shrink, &sc);
}
if (attr == &sysfs_trigger_btree_write_buffer_flush)

View File

@ -1095,13 +1095,13 @@ int bch2_check_inodes(struct bch_fs *c)
CLASS(snapshots_seen, s)();
struct progress_indicator progress;
bch2_progress_init(&progress, c, BIT_ULL(BTREE_ID_inodes));
bch2_progress_init(&progress, __func__, c, BIT_ULL(BTREE_ID_inodes), 0);
return for_each_btree_key_commit(trans, iter, BTREE_ID_inodes,
POS_MIN,
BTREE_ITER_prefetch|BTREE_ITER_all_snapshots, k,
NULL, NULL, BCH_TRANS_COMMIT_no_enospc, ({
progress_update_iter(trans, &progress, &iter) ?:
bch2_progress_update_iter(trans, &progress, &iter) ?:
check_inode(trans, &iter, k, &snapshot_root, &s);
}));
}
@ -1183,14 +1183,14 @@ fsck_err:
int bch2_check_unreachable_inodes(struct bch_fs *c)
{
struct progress_indicator progress;
bch2_progress_init(&progress, c, BIT_ULL(BTREE_ID_inodes));
bch2_progress_init(&progress, __func__, c, BIT_ULL(BTREE_ID_inodes), 0);
CLASS(btree_trans, trans)(c);
return for_each_btree_key_commit(trans, iter, BTREE_ID_inodes,
POS_MIN,
BTREE_ITER_prefetch|BTREE_ITER_all_snapshots, k,
NULL, NULL, BCH_TRANS_COMMIT_no_enospc, ({
progress_update_iter(trans, &progress, &iter) ?:
bch2_progress_update_iter(trans, &progress, &iter) ?:
check_unreachable_inode(trans, &iter, k);
}));
}
@ -1678,13 +1678,13 @@ int bch2_check_dirents(struct bch_fs *c)
bool need_second_pass = false, did_second_pass = false;
int ret;
again:
bch2_progress_init(&progress, c, BIT_ULL(BTREE_ID_dirents));
bch2_progress_init(&progress, __func__, c, BIT_ULL(BTREE_ID_dirents), 0);
ret = for_each_btree_key_commit(trans, iter, BTREE_ID_dirents,
POS(BCACHEFS_ROOT_INO, 0),
BTREE_ITER_prefetch|BTREE_ITER_all_snapshots, k,
NULL, NULL, BCH_TRANS_COMMIT_no_enospc, ({
progress_update_iter(trans, &progress, &iter) ?:
bch2_progress_update_iter(trans, &progress, &iter) ?:
check_dirent(trans, &iter, k, &hash_info, &dir, &target, &s,
&need_second_pass);
})) ?:
@ -1743,7 +1743,7 @@ int bch2_check_xattrs(struct bch_fs *c)
CLASS(inode_walker, inode)();
struct progress_indicator progress;
bch2_progress_init(&progress, c, BIT_ULL(BTREE_ID_xattrs));
bch2_progress_init(&progress, __func__, c, BIT_ULL(BTREE_ID_xattrs), 0);
int ret = for_each_btree_key_commit(trans, iter, BTREE_ID_xattrs,
POS(BCACHEFS_ROOT_INO, 0),
@ -1751,7 +1751,7 @@ int bch2_check_xattrs(struct bch_fs *c)
k,
NULL, NULL,
BCH_TRANS_COMMIT_no_enospc, ({
progress_update_iter(trans, &progress, &iter) ?:
bch2_progress_update_iter(trans, &progress, &iter) ?:
check_xattr(trans, &iter, k, &hash_info, &inode);
}));
return ret;

View File

@ -123,12 +123,12 @@ int bch2_check_subvolume_structure(struct bch_fs *c)
CLASS(btree_trans, trans)(c);
struct progress_indicator progress;
bch2_progress_init(&progress, c, BIT_ULL(BTREE_ID_subvolumes));
bch2_progress_init(&progress, __func__, c, BIT_ULL(BTREE_ID_subvolumes), 0);
return for_each_btree_key_commit(trans, iter,
BTREE_ID_subvolumes, POS_MIN, BTREE_ITER_prefetch, k,
NULL, NULL, BCH_TRANS_COMMIT_no_enospc, ({
progress_update_iter(trans, &progress, &iter) ?:
bch2_progress_update_iter(trans, &progress, &iter) ?:
check_subvol_path(trans, &iter, k);
}));
}

View File

@ -416,13 +416,13 @@ int bch2_check_extents(struct bch_fs *c)
CLASS(extent_ends, extent_ends)();
struct progress_indicator progress;
bch2_progress_init(&progress, c, BIT_ULL(BTREE_ID_extents));
bch2_progress_init(&progress, __func__, c, BIT_ULL(BTREE_ID_extents), 0);
return for_each_btree_key(trans, iter, BTREE_ID_extents,
POS(BCACHEFS_ROOT_INO, 0),
BTREE_ITER_prefetch|BTREE_ITER_all_snapshots, k, ({
bch2_disk_reservation_put(c, &res.r);
progress_update_iter(trans, &progress, &iter) ?:
bch2_progress_update_iter(trans, &progress, &iter) ?:
check_extent(trans, &iter, k, &w, &s, &extent_ends, &res.r);
})) ?:
check_i_sectors_notnested(trans, &w);
@ -434,7 +434,7 @@ int bch2_check_indirect_extents(struct bch_fs *c)
CLASS(btree_trans, trans)(c);
struct progress_indicator progress;
bch2_progress_init(&progress, c, BIT_ULL(BTREE_ID_reflink));
bch2_progress_init(&progress, __func__, c, BIT_ULL(BTREE_ID_reflink), 0);
return for_each_btree_key_commit(trans, iter, BTREE_ID_reflink,
POS_MIN,
@ -442,7 +442,7 @@ int bch2_check_indirect_extents(struct bch_fs *c)
&res.r, NULL,
BCH_TRANS_COMMIT_no_enospc, ({
bch2_disk_reservation_put(c, &res.r);
progress_update_iter(trans, &progress, &iter) ?:
bch2_progress_update_iter(trans, &progress, &iter) ?:
check_extent_overbig(trans, &iter, k) ?:
bch2_bkey_drop_stale_ptrs(trans, &iter, k);
}));

View File

@ -35,15 +35,23 @@ const char * const bch2_dev_write_refs[] = {
};
#undef x
void bch2_devs_list_to_text(struct printbuf *out, struct bch_devs_list *d)
void bch2_devs_list_to_text(struct printbuf *out,
struct bch_fs *c,
struct bch_devs_list *d)
{
prt_char(out, '[');
bch2_printbuf_make_room(out, 1024);
guard(rcu)();
darray_for_each(*d, i) {
if (i != d->data)
prt_char(out, ' ');
prt_printf(out, "%u", *i);
struct bch_dev *ca = bch2_dev_rcu_noerror(c, *i);
if (ca)
prt_str(out, ca->name);
else
prt_printf(out, "(invalid device %u)", *i);
}
prt_char(out, ']');
}
static int bch2_dev_may_add(struct bch_sb *sb, struct bch_fs *c)
@ -676,6 +684,11 @@ int bch2_dev_remove(struct bch_fs *c, struct bch_dev *ca, int flags,
goto err;
}
ret = bch2_replicas_gc_accounted(c);
if (ret) {
prt_printf(err, "bch2_replicas_gc2() error: %s\n", bch2_err_str(ret));
goto err;
}
/*
* flushing the journal should be sufficient, but it's the write buffer
* flush that kills superblock replicas entries after they've gone to 0

View File

@ -2,7 +2,7 @@
#ifndef _BCACHEFS_INIT_DEV_H
#define _BCACHEFS_INIT_DEV_H
void bch2_devs_list_to_text(struct printbuf *, struct bch_devs_list *);
void bch2_devs_list_to_text(struct printbuf *, struct bch_fs *, struct bch_devs_list *);
struct bch_fs *bch2_dev_to_fs(dev_t);
int bch2_dev_in_fs(struct bch_sb_handle *,

View File

@ -15,14 +15,12 @@
#include "alloc/foreground.h"
#include "alloc/replicas.h"
#include "btree/cache.h"
#include "btree/check.h"
#include "btree/journal_overlay.h"
#include "btree/init.h"
#include "btree/interior.h"
#include "btree/key_cache.h"
#include "btree/node_scan.h"
#include "btree/read.h"
#include "btree/sort.h"
#include "btree/write.h"
#include "btree/write_buffer.h"
@ -377,10 +375,10 @@ void bch2_fs_read_only(struct bch_fs *c)
c->recovery.pass_done >= BCH_RECOVERY_PASS_journal_replay) {
BUG_ON(c->journal.last_empty_seq != journal_cur_seq(&c->journal));
BUG_ON(!c->sb.clean);
BUG_ON(atomic_long_read(&c->btree_cache.nr_dirty));
BUG_ON(atomic_long_read(&c->btree_key_cache.nr_dirty));
BUG_ON(c->btree_write_buffer.inc.keys.nr);
BUG_ON(c->btree_write_buffer.flushing.keys.nr);
BUG_ON(atomic_long_read(&c->btree.cache.nr_dirty));
BUG_ON(atomic_long_read(&c->btree.key_cache.nr_dirty));
BUG_ON(c->btree.write_buffer.inc.keys.nr);
BUG_ON(c->btree.write_buffer.flushing.keys.nr);
bch2_verify_replicas_refs_clean(c);
bch2_verify_accounting_clean(c);
} else {
@ -417,8 +415,7 @@ bool bch2_fs_emergency_read_only(struct bch_fs *c)
return ret;
}
static bool __bch2_fs_emergency_read_only2(struct bch_fs *c, struct printbuf *out,
bool locked)
static bool __bch2_fs_emergency_read_only2(struct bch_fs *c, struct printbuf *out, bool locked)
{
bool ret = !test_and_set_bit(BCH_FS_emergency_ro, &c->flags);
@ -429,11 +426,9 @@ static bool __bch2_fs_emergency_read_only2(struct bch_fs *c, struct printbuf *ou
bch2_fs_read_only_async(c);
wake_up(&bch2_read_only_wait);
if (ret) {
if (ret)
prt_printf(out, "emergency read only at seq %llu\n",
journal_cur_seq(&c->journal));
bch2_prt_task_backtrace(out, current, 2, out->atomic ? GFP_ATOMIC : GFP_KERNEL);
}
return ret;
}
@ -568,7 +563,6 @@ static void __bch2_fs_free(struct bch_fs *c)
bch2_reconcile_stop(c);
bch2_copygc_stop(c);
bch2_find_btree_nodes_exit(&c->found_btree_nodes);
bch2_free_pending_node_rewrites(c);
bch2_free_fsck_errs(c);
bch2_fs_vfs_exit(c);
@ -578,9 +572,6 @@ static void __bch2_fs_free(struct bch_fs *c)
bch2_fs_quota_exit(c);
bch2_fs_nocow_locking_exit(c);
bch2_fs_journal_exit(&c->journal);
bch2_fs_fs_io_direct_exit(c);
bch2_fs_fs_io_buffered_exit(c);
bch2_fs_fsio_exit(c);
bch2_fs_io_write_exit(c);
bch2_fs_io_read_exit(c);
bch2_fs_errors_exit(c);
@ -593,17 +584,10 @@ static void __bch2_fs_free(struct bch_fs *c)
bch2_io_clock_exit(&c->io_clock[READ]);
bch2_fs_capacity_exit(c);
bch2_fs_buckets_waiting_for_journal_exit(c);
bch2_fs_btree_write_buffer_exit(c);
bch2_fs_btree_key_cache_exit(&c->btree_key_cache);
bch2_fs_btree_iter_exit(c);
bch2_fs_btree_interior_update_exit(c);
bch2_fs_btree_cache_exit(c);
bch2_fs_btree_exit(c);
bch2_fs_accounting_exit(c);
bch2_fs_async_obj_exit(c);
mempool_exit(&c->btree_bounce_pool);
bioset_exit(&c->btree_bio);
mempool_exit(&c->fill_iter);
enumerated_ref_exit(&c->writes);
kfree(rcu_dereference_protected(c->disk_groups, 1));
kfree(c->journal_seq_blacklist_table);
@ -612,12 +596,6 @@ static void __bch2_fs_free(struct bch_fs *c)
destroy_workqueue(c->promote_wq);
if (c->write_ref_wq)
destroy_workqueue(c->write_ref_wq);
if (c->btree_write_submit_wq)
destroy_workqueue(c->btree_write_submit_wq);
if (c->btree_read_complete_wq)
destroy_workqueue(c->btree_read_complete_wq);
if (c->btree_write_complete_wq)
destroy_workqueue(c->btree_write_complete_wq);
if (c->btree_update_wq)
destroy_workqueue(c->btree_update_wq);
@ -673,7 +651,7 @@ int bch2_fs_stop(struct bch_fs *c)
cancel_work_sync(&c->read_only_work);
flush_work(&c->btree_interior_updates.work);
flush_work(&c->btree.interior_updates.work);
}
if (test_bit(BCH_FS_emergency_ro, &c->flags))
@ -758,26 +736,19 @@ int bch2_fs_init_rw(struct bch_fs *c)
if (!(c->btree_update_wq = alloc_workqueue("bcachefs",
WQ_HIGHPRI|WQ_FREEZABLE|WQ_MEM_RECLAIM|WQ_UNBOUND, 512)) ||
!(c->btree_write_complete_wq = alloc_workqueue("bcachefs_btree_write_complete",
WQ_HIGHPRI|WQ_FREEZABLE|WQ_MEM_RECLAIM, 1)) ||
!(c->btree_write_submit_wq = alloc_workqueue("bcachefs_btree_write_sumit",
WQ_HIGHPRI|WQ_FREEZABLE|WQ_MEM_RECLAIM, 1)) ||
!(c->write_ref_wq = alloc_workqueue("bcachefs_write_ref",
WQ_FREEZABLE, 0)) ||
!(c->promote_wq = alloc_workqueue("bcachefs_promotes",
WQ_FREEZABLE, 2)))
return bch_err_throw(c, ENOMEM_fs_other_alloc);
int ret = bch2_fs_btree_interior_update_init(c) ?:
bch2_fs_btree_write_buffer_init(c) ?:
bch2_fs_fs_io_buffered_init(c) ?:
bch2_fs_io_write_init(c) ?:
bch2_fs_journal_init(&c->journal) ?:
bch2_journal_reclaim_start(&c->journal) ?:
bch2_copygc_start(c) ?:
bch2_reconcile_start(c);
if (ret)
return ret;
try(bch2_fs_btree_init_rw(c));
try(bch2_fs_io_write_init(c));
try(bch2_fs_journal_init(&c->journal));
try(bch2_fs_vfs_init_rw(c));
try(bch2_journal_reclaim_start(&c->journal));
try(bch2_copygc_start(c));
try(bch2_reconcile_start(c));
set_bit(BCH_FS_rw_init_done, &c->flags);
return 0;
@ -1027,7 +998,6 @@ static int bch2_fs_init(struct bch_fs *c, struct bch_sb *sb,
struct bch_opts *opts, bch_sb_handles *sbs,
struct printbuf *out)
{
unsigned i, iter_size;
CLASS(printbuf, name)();
c->stdio = (void *)(unsigned long) opts->stdio;
@ -1054,17 +1024,13 @@ static int bch2_fs_init(struct bch_fs *c, struct bch_sb *sb,
refcount_set(&c->ro_ref, 1);
init_waitqueue_head(&c->ro_ref_wait);
for (i = 0; i < BCH_TIME_STAT_NR; i++)
for (unsigned i = 0; i < BCH_TIME_STAT_NR; i++)
bch2_time_stats_init(&c->times[i]);
bch2_fs_allocator_background_init(c);
bch2_fs_allocator_foreground_init(c);
bch2_fs_btree_cache_init_early(&c->btree_cache);
bch2_fs_btree_gc_init_early(c);
bch2_fs_btree_interior_update_init_early(c);
bch2_fs_btree_iter_init_early(c);
bch2_fs_btree_key_cache_init_early(&c->btree_key_cache);
bch2_fs_btree_write_buffer_init_early(c);
bch2_fs_btree_init_early(c);
bch2_fs_copygc_init(c);
bch2_fs_ec_init_early(c);
bch2_fs_errors_init_early(c);
@ -1076,19 +1042,15 @@ static int bch2_fs_init(struct bch_fs *c, struct bch_sb *sb,
bch2_fs_recovery_passes_init(c);
bch2_fs_snapshots_init_early(c);
bch2_fs_subvolumes_init_early(c);
bch2_find_btree_nodes_init(&c->found_btree_nodes);
INIT_LIST_HEAD(&c->list);
mutex_init(&c->bio_bounce_pages_lock);
spin_lock_init(&c->btree_write_error_lock);
spin_lock_init(&c->write_error_lock);
INIT_LIST_HEAD(&c->journal_iters);
INIT_LIST_HEAD(&c->vfs_inodes_list);
mutex_init(&c->vfs_inodes_lock);
c->journal.flush_write_time = &c->times[BCH_TIME_journal_flush_write];
c->journal.noflush_write_time = &c->times[BCH_TIME_journal_noflush_write];
c->journal.flush_seq_time = &c->times[BCH_TIME_journal_flush_seq];
@ -1121,7 +1083,6 @@ static int bch2_fs_init(struct bch_fs *c, struct bch_sb *sb,
#endif
c->block_bits = ilog2(block_sectors(c));
c->btree_foreground_merge_threshold = BTREE_FOREGROUND_MERGE_THRESHOLD(c);
if (bch2_fs_init_fault("fs_alloc")) {
prt_printf(out, "fs_alloc fault injected\n");
@ -1137,42 +1098,24 @@ static int bch2_fs_init(struct bch_fs *c, struct bch_sb *sb,
strscpy(c->name, name.buf, sizeof(c->name));
iter_size = sizeof(struct sort_iter) +
(btree_blocks(c) + 1) * 2 *
sizeof(struct sort_iter_set);
if (!(c->btree_read_complete_wq = alloc_workqueue("bcachefs_btree_read_complete",
WQ_HIGHPRI|WQ_FREEZABLE|WQ_MEM_RECLAIM, 512)) ||
enumerated_ref_init(&c->writes, BCH_WRITE_REF_NR,
bch2_writes_disabled) ||
mempool_init_kmalloc_pool(&c->fill_iter, 1, iter_size) ||
bioset_init(&c->btree_bio, 1,
max(offsetof(struct btree_read_bio, bio),
offsetof(struct btree_write_bio, wbio.bio)),
BIOSET_NEED_BVECS) ||
mempool_init_kvmalloc_pool(&c->btree_bounce_pool, 1,
c->opts.btree_node_size))
if (enumerated_ref_init(&c->writes, BCH_WRITE_REF_NR,
bch2_writes_disabled))
return bch_err_throw(c, ENOMEM_fs_other_alloc);
try(bch2_fs_async_obj_init(c));
try(bch2_blacklist_table_initialize(c));
try(bch2_fs_btree_cache_init(c));
try(bch2_fs_btree_iter_init(c));
try(bch2_fs_btree_key_cache_init(&c->btree_key_cache));
try(bch2_fs_async_obj_init(c));
try(bch2_fs_btree_init(c));
try(bch2_fs_buckets_waiting_for_journal_init(c));
try(bch2_io_clock_init(&c->io_clock[READ]));
try(bch2_io_clock_init(&c->io_clock[WRITE]));
try(bch2_fs_compress_init(c));
try(bch2_fs_counters_init(c));
try(bch2_fs_ec_init(c));
try(bch2_fs_errors_init(c));
try(bch2_fs_encryption_init(c));
try(bch2_fs_fsio_init(c));
try(bch2_fs_fs_io_direct_init(c));
try(bch2_fs_io_read_init(c));
try(bch2_fs_reconcile_init(c));
try(bch2_fs_vfs_init(c));
try(bch2_io_clock_init(&c->io_clock[READ]));
try(bch2_io_clock_init(&c->io_clock[WRITE]));
#if IS_ENABLED(CONFIG_UNICODE)
if (!bch2_fs_casefold_enabled(c)) {
@ -1200,7 +1143,7 @@ static int bch2_fs_init(struct bch_fs *c, struct bch_sb *sb,
}
bch2_journal_entry_res_resize(&c->journal,
&c->btree_root_journal_res,
&c->btree.root_journal_res,
BTREE_ID_NR * (JSET_KEYS_U64s + BKEY_BTREE_PTR_U64s_MAX));
bch2_journal_entry_res_resize(&c->journal,
&c->clock_journal_res,

View File

@ -8,13 +8,15 @@
#include "init/passes.h"
#include "init/progress.h"
void bch2_progress_init_inner(struct progress_indicator *s,
struct bch_fs *c,
u64 leaf_btree_id_mask,
u64 inner_btree_id_mask)
void bch2_progress_init(struct progress_indicator *s,
const char *msg,
struct bch_fs *c,
u64 leaf_btree_id_mask,
u64 inner_btree_id_mask)
{
memset(s, 0, sizeof(*s));
s->msg = strip_bch2(msg);
s->next_print = jiffies + HZ * 10;
/* This is only an estimation: nodes can have different replica counts */
@ -67,8 +69,7 @@ static inline bool progress_update_p(struct progress_indicator *s)
int bch2_progress_update_iter(struct btree_trans *trans,
struct progress_indicator *s,
struct btree_iter *iter,
const char *msg)
struct btree_iter *iter)
{
struct bch_fs *c = trans->c;
@ -87,7 +88,7 @@ int bch2_progress_update_iter(struct btree_trans *trans,
if (!s->silent && progress_update_p(s)) {
CLASS(printbuf, buf)();
prt_printf(&buf, "%s ", strip_bch2(msg));
prt_printf(&buf, "%s ", s->msg);
bch2_progress_to_text(&buf, s);
bch_info(c, "%s", buf.buf);
}

View File

@ -16,6 +16,7 @@
*/
struct progress_indicator {
const char *msg;
struct bbpos pos;
unsigned long next_print;
u64 nodes_seen;
@ -24,24 +25,15 @@ struct progress_indicator {
bool silent;
};
void bch2_progress_init_inner(struct progress_indicator *s,
void bch2_progress_init(struct progress_indicator *s,
const char *msg,
struct bch_fs *c,
u64 leaf_btree_id_mask,
u64 inner_btree_id_mask);
static inline void bch2_progress_init(struct progress_indicator *s,
struct bch_fs *c, u64 btree_id_mask)
{
bch2_progress_init_inner(s, c, btree_id_mask, 0);
}
int bch2_progress_update_iter(struct btree_trans *,
struct progress_indicator *,
struct btree_iter *,
const char *);
#define progress_update_iter(trans, p, iter) \
bch2_progress_update_iter(trans, p, iter, __func__)
struct btree_iter *);
void bch2_progress_to_text(struct printbuf *, struct progress_indicator *);

View File

@ -511,8 +511,8 @@ static int journal_replay_entry_early(struct bch_fs *c,
entry->btree_id, BTREE_ID_NR_MAX))
return 0;
while (entry->btree_id >= c->btree_cache.roots_extra.nr + BTREE_ID_NR)
try(darray_push(&c->btree_cache.roots_extra, (struct btree_root) { NULL }));
while (entry->btree_id >= c->btree.cache.roots_extra.nr + BTREE_ID_NR)
try(darray_push(&c->btree.cache.roots_extra, (struct btree_root) { NULL }));
struct btree_root *r = bch2_btree_id_root(c, entry->btree_id);
@ -904,6 +904,13 @@ use_clean:
bch2_fs_read_write_early(c);
bch2_delete_dead_snapshots_async(c);
}
/*
* (Hopefully unnecessary) cleanup, once per mount - we should be
* killing replicas entries when accounting entries go to 0, but - old
* filesystems, etc.:
*/
bch2_replicas_gc_accounted(c);
fsck_err:
return ret;
}

View File

@ -317,7 +317,7 @@ void bch2_journal_halt(struct journal *j)
bch2_journal_halt_locked(j);
}
static bool journal_entry_want_write(struct journal *j)
static bool journal_entry_close_locked(struct journal *j)
{
bool ret = !journal_entry_is_open(j) ||
journal_cur_seq(j) == journal_last_unwritten_seq(j);
@ -340,7 +340,7 @@ static bool journal_entry_want_write(struct journal *j)
bool bch2_journal_entry_close(struct journal *j)
{
guard(spinlock)(&j->lock);
return journal_entry_want_write(j);
return journal_entry_close_locked(j);
}
/*
@ -437,11 +437,11 @@ static int journal_entry_open(struct journal *j)
buf->must_flush = c->sb.clean;
buf->separate_flush = false;
buf->flush_time = 0;
buf->failed.nr = 0;
buf->need_flush_to_write_buffer = true;
buf->write_started = false;
buf->write_allocated = false;
buf->write_done = false;
buf->had_error = false;
buf->empty = false;
memset(buf->data, 0, sizeof(*buf->data));
@ -493,7 +493,7 @@ static bool journal_quiesced(struct journal *j)
bool ret = atomic64_read(&j->seq) == j->seq_ondisk;
if (!ret)
bch2_journal_entry_close(j);
journal_entry_close_locked(j);
return ret;
}
@ -837,7 +837,7 @@ recheck_need_open:
BUG();
want_write:
if (seq == journal_cur_seq(j))
journal_entry_want_write(j);
journal_entry_close_locked(j);
out:
spin_unlock(&j->lock);
return ret;

View File

@ -709,7 +709,7 @@ static u64 journal_seq_to_flush(struct journal *j)
static int __bch2_journal_reclaim(struct journal *j, bool direct, bool kicked)
{
struct bch_fs *c = container_of(j, struct bch_fs, journal);
struct bch_fs_btree_cache *bc = &c->btree_cache;
struct bch_fs_btree_cache *bc = &c->btree.cache;
bool kthread = (current->flags & PF_KTHREAD) != 0;
u64 seq_to_flush;
size_t min_nr, min_key_cache, nr_flushed;
@ -760,8 +760,8 @@ static int __bch2_journal_reclaim(struct journal *j, bool direct, bool kicked)
prt_printf(&buf, "btree cache %lu/%zu min %zu\n",
atomic_long_read(&bc->nr_dirty), btree_cache_live, min_nr);
prt_printf(&buf, "key cache %lu/%lu min %zu\n",
atomic_long_read(&c->btree_key_cache.nr_dirty),
atomic_long_read(&c->btree_key_cache.nr_keys),
atomic_long_read(&c->btree.key_cache.nr_dirty),
atomic_long_read(&c->btree.key_cache.nr_keys),
min_key_cache);
}));

View File

@ -7,7 +7,11 @@
#include "alloc/replicas_types.h"
#include "alloc/types.h"
#include "data/extents_types.h"
#include "init/dev_types.h"
#include "util/fifo.h"
/* btree write buffer steals 8 bits for its own purposes: */
@ -31,6 +35,7 @@ struct journal_buf {
__BKEY_PADDED(key, BCH_REPLICAS_MAX);
struct bch_devs_list devs_written;
struct bch_io_failures failed;
struct closure_waitlist wait;
u64 last_seq; /* copy of data->last_seq */
@ -49,7 +54,6 @@ struct journal_buf {
bool write_started:1;
bool write_allocated:1;
bool write_done:1;
bool had_error:1;
bool empty:1;
u8 idx;
};

View File

@ -11,6 +11,7 @@
#include "data/checksum.h"
#include "init/dev.h"
#include "init/error.h"
#include "init/fs.h"
@ -216,7 +217,8 @@ static CLOSURE_CALLBACK(journal_write_done)
: j->noflush_write_time, j->write_start_time);
struct bch_replicas_entry_v1 *r = &journal_seq_pin(j, seq_wrote)->devs.e;
if (w->had_error) {
if (unlikely(w->failed.nr)) {
bch2_replicas_entry_put(c, r);
r->nr_devs = 0;
}
@ -228,22 +230,33 @@ static CLOSURE_CALLBACK(journal_write_done)
r->nr_devs = 0;
}
if (!w->devs_written.nr)
err = bch_err_throw(c, journal_write_err);
if (unlikely(w->failed.nr || err)) {
bool print = !bch2_ratelimit();
if (err && !bch2_journal_error(j)) {
CLASS(printbuf, buf)();
bch2_log_msg_start(c, &buf);
prt_printf(&buf, "error writing journal entry %llu\n", seq_wrote);
bch2_io_failures_to_text(&buf, c, &w->failed);
if (err == -BCH_ERR_journal_write_err)
prt_printf(&buf, "unable to write journal to sufficient devices\n");
else
prt_printf(&buf, "journal write error marking replicas: %s\n",
bch2_err_str(err));
if (!w->devs_written.nr)
err = bch_err_throw(c, journal_write_err);
bch2_fs_emergency_read_only2(c, &buf);
if (!err) {
prt_printf(&buf, "wrote degraded to ");
bch2_devs_list_to_text(&buf, c, &w->devs_written);
prt_newline(&buf);
} else {
if (err == -BCH_ERR_journal_write_err)
prt_printf(&buf, "unable to write journal to sufficient devices\n");
else
prt_printf(&buf, "journal write error marking replicas: %s\n",
bch2_err_str(err));
bch2_print_str(c, KERN_ERR, buf.buf);
print = bch2_fs_emergency_read_only2(c, &buf);
}
if (print)
bch2_print_str(c, KERN_ERR, buf.buf);
}
closure_debug_destroy(cl);
@ -381,22 +394,17 @@ static void journal_write_endio(struct bio *bio)
struct journal_bio *jbio = container_of(bio, struct journal_bio, bio);
struct bch_dev *ca = jbio->ca;
struct journal *j = &ca->fs->journal;
struct bch_fs *c = container_of(j, struct bch_fs, journal);
struct journal_buf *w = j->buf + jbio->buf_idx;
bch2_account_io_completion(ca, BCH_MEMBER_ERROR_write,
jbio->submit_time, !bio->bi_status);
if (bio->bi_status) {
bch_err_dev_ratelimited(ca,
"error writing journal entry %llu: %s",
le64_to_cpu(w->data->seq),
bch2_blk_status_to_str(bio->bi_status));
unsigned long flags;
spin_lock_irqsave(&j->err_lock, flags);
guard(spinlock_irqsave)(&j->err_lock);
bch2_dev_io_failures_mut(&w->failed, ca->dev_idx)->errcode =
__bch2_err_throw(c, -blk_status_to_bch_err(bio->bi_status));
bch2_dev_list_drop_dev(&w->devs_written, ca->dev_idx);
w->had_error = true;
spin_unlock_irqrestore(&j->err_lock, flags);
}
closure_put(&w->io);

View File

@ -212,10 +212,10 @@ UPGRADE_TABLE_INCOMPAT()
static int have_stripes(struct bch_fs *c)
{
if (IS_ERR_OR_NULL(c->btree_cache.roots_known[BTREE_ID_stripes].b))
if (IS_ERR_OR_NULL(c->btree.cache.roots_known[BTREE_ID_stripes].b))
return 0;
return !btree_node_fake(c->btree_cache.roots_known[BTREE_ID_stripes].b);
return !btree_node_fake(c->btree.cache.roots_known[BTREE_ID_stripes].b);
}
int bch2_sb_set_upgrade_extra(struct bch_fs *c)

View File

@ -637,7 +637,7 @@ static int btree_bitmap_gc_btree_level(struct btree_trans *trans,
if (!bch2_dev_btree_bitmap_marked(c, k))
bch2_dev_btree_bitmap_mark(c, k);
bch2_progress_update_iter(trans, progress, &iter, "btree_bitmap_gc");
bch2_progress_update_iter(trans, progress, &iter);
})));
return 0;
@ -646,7 +646,7 @@ static int btree_bitmap_gc_btree_level(struct btree_trans *trans,
int bch2_btree_bitmap_gc(struct bch_fs *c)
{
struct progress_indicator progress;
bch2_progress_init_inner(&progress, c, 0, ~0ULL);
bch2_progress_init(&progress, __func__, c, 0, ~0ULL);
scoped_guard(mutex, &c->sb_lock) {
guard(rcu)();

View File

@ -551,7 +551,7 @@ int bch2_reconstruct_snapshots(struct bch_fs *c)
int ret = 0;
struct progress_indicator progress;
bch2_progress_init(&progress, c, btree_has_snapshots_mask);
bch2_progress_init(&progress, __func__, c, btree_has_snapshots_mask, 0);
for (unsigned btree = 0; btree < BTREE_ID_NR; btree++) {
if (btree_type_has_snapshots(btree)) {
@ -559,7 +559,7 @@ int bch2_reconstruct_snapshots(struct bch_fs *c)
try(for_each_btree_key(trans, iter, btree, POS_MIN,
BTREE_ITER_all_snapshots|BTREE_ITER_prefetch, k, ({
progress_update_iter(trans, &progress, &iter) ?:
bch2_progress_update_iter(trans, &progress, &iter) ?:
get_snapshot_trees(c, &r, k.k->p);
})));

View File

@ -771,7 +771,7 @@ static int delete_dead_snapshot_keys_v1(struct btree_trans *trans)
struct bch_fs *c = trans->c;
struct snapshot_delete *d = &c->snapshots.delete;
bch2_progress_init(&d->progress, c, btree_has_snapshots_mask);
bch2_progress_init(&d->progress, __func__, c, btree_has_snapshots_mask, 0);
d->progress.silent = true;
d->version = 1;
@ -786,7 +786,7 @@ static int delete_dead_snapshot_keys_v1(struct btree_trans *trans)
btree, POS_MIN,
BTREE_ITER_prefetch|BTREE_ITER_all_snapshots, k,
&res.r, NULL, BCH_TRANS_COMMIT_no_enospc, ({
progress_update_iter(trans, &d->progress, &iter);
bch2_progress_update_iter(trans, &d->progress, &iter);
if (skip_unrelated_snapshot_tree(trans, &iter, &prev_inum))
continue;
@ -822,7 +822,7 @@ static int delete_dead_snapshot_keys_v2(struct btree_trans *trans)
CLASS(disk_reservation, res)(c);
u64 prev_inum = 0;
bch2_progress_init(&d->progress, c, BIT_ULL(BTREE_ID_inodes));
bch2_progress_init(&d->progress, __func__, c, BIT_ULL(BTREE_ID_inodes), 0);
d->progress.silent = true;
d->version = 2;
@ -844,7 +844,7 @@ static int delete_dead_snapshot_keys_v2(struct btree_trans *trans)
if (!k.k)
break;
progress_update_iter(trans, &d->progress, &iter);
bch2_progress_update_iter(trans, &d->progress, &iter);
if (skip_unrelated_snapshot_tree(trans, &iter, &prev_inum))
continue;

View File

@ -401,13 +401,6 @@ int bch2_read_folio(struct file *file, struct folio *folio)
/* writepages: */
struct bch_writepage_io {
struct bch_inode_info *inode;
/* must be last: */
struct bch_write_op op;
};
struct bch_writepage_state {
struct bch_writepage_io *io;
struct bch_inode_opts opts;
@ -446,7 +439,7 @@ static void bch2_writepage_io_done(struct bch_write_op *op)
bio_for_each_folio_all(fi, bio) {
mapping_set_error(fi.folio->mapping, -EIO);
struct bch_folio *s = __bch2_folio(fi.folio);
struct bch_folio *s = bch2_folio(fi.folio);
guard(spinlock)(&s->lock);
for (i = 0; i < folio_sectors(fi.folio); i++)
@ -456,7 +449,7 @@ static void bch2_writepage_io_done(struct bch_write_op *op)
if (io->op.flags & BCH_WRITE_wrote_data_inline) {
bio_for_each_folio_all(fi, bio) {
struct bch_folio *s = __bch2_folio(fi.folio);
struct bch_folio *s = bch2_folio(fi.folio);
guard(spinlock)(&s->lock);
for (i = 0; i < folio_sectors(fi.folio); i++)
@ -484,7 +477,7 @@ static void bch2_writepage_io_done(struct bch_write_op *op)
bch2_i_sectors_acct(c, io->inode, NULL, io->op.i_sectors_delta);
bio_for_each_folio_all(fi, bio) {
struct bch_folio *s = __bch2_folio(fi.folio);
struct bch_folio *s = bch2_folio(fi.folio);
if (atomic_dec_and_test(&s->write_count))
folio_end_writeback(fi.folio);
@ -517,7 +510,7 @@ static void bch2_writepage_io_alloc(struct bch_fs *c,
w->io = container_of(bio_alloc_bioset(NULL, BIO_MAX_VECS,
REQ_OP_WRITE,
GFP_KERNEL,
&c->writepage_bioset),
&c->vfs.writepage_bioset),
struct bch_writepage_io, op.wbio.bio);
w->io->inode = inode;
@ -1165,19 +1158,4 @@ out:
return bch2_err_class(ret);
}
void bch2_fs_fs_io_buffered_exit(struct bch_fs *c)
{
bioset_exit(&c->writepage_bioset);
}
int bch2_fs_fs_io_buffered_init(struct bch_fs *c)
{
if (bioset_init(&c->writepage_bioset,
4, offsetof(struct bch_writepage_io, op.wbio.bio),
BIOSET_NEED_BVECS))
return -BCH_ERR_ENOMEM_writepage_bioset_init;
return 0;
}
#endif /* NO_BCACHEFS_FS */

View File

@ -6,6 +6,15 @@
#include <linux/version.h>
#include "data/write_types.h"
struct bch_writepage_io {
struct bch_inode_info *inode;
/* must be last: */
struct bch_write_op op;
};
int bch2_read_single_folio(struct folio *, struct address_space *);
int bch2_read_folio(struct file *, struct folio *);
@ -25,12 +34,6 @@ int bch2_write_end(struct file *, struct address_space *, loff_t,
#endif
ssize_t bch2_write_iter(struct kiocb *, struct iov_iter *);
void bch2_fs_fs_io_buffered_exit(struct bch_fs *);
int bch2_fs_fs_io_buffered_init(struct bch_fs *);
#else
static inline void bch2_fs_fs_io_buffered_exit(struct bch_fs *c) {}
static inline int bch2_fs_fs_io_buffered_init(struct bch_fs *c) { return 0; }
#endif
#endif /* _BCACHEFS_FS_IO_BUFFERED_H */

View File

@ -24,14 +24,6 @@
/* O_DIRECT reads */
struct dio_read {
struct closure cl;
struct kiocb *req;
long ret;
bool should_dirty;
struct bch_read_bio rbio;
};
static void bio_check_or_release(struct bio *bio, bool check_dirty)
{
if (check_dirty) {
@ -106,7 +98,7 @@ static int bch2_direct_IO_read(struct kiocb *req, struct iov_iter *iter)
bio_iov_vecs_to_alloc(iter, BIO_MAX_VECS),
REQ_OP_READ,
GFP_KERNEL,
&c->dio_read_bioset);
&c->vfs.dio_read_bioset);
dio = container_of(bio, struct dio_read, rbio.bio);
closure_init(&dio->cl, NULL);
@ -233,26 +225,6 @@ out:
/* O_DIRECT writes */
struct dio_write {
struct kiocb *req;
struct address_space *mapping;
struct bch_inode_info *inode;
struct mm_struct *mm;
const struct iovec *iov;
unsigned loop:1,
extending:1,
sync:1,
flush:1;
struct quota_res quota_res;
u64 written;
struct iov_iter iter;
struct iovec inline_vecs[2];
/* must be last: */
struct bch_write_op op;
};
static bool bch2_check_range_allocated(struct bch_fs *c, subvol_inum inum,
u64 offset, u64 size,
unsigned nr_replicas, bool compressed)
@ -639,7 +611,7 @@ ssize_t bch2_direct_write(struct kiocb *req, struct iov_iter *iter)
bio_iov_vecs_to_alloc(iter, BIO_MAX_VECS),
REQ_OP_WRITE | REQ_SYNC | REQ_IDLE,
GFP_KERNEL,
&c->dio_write_bioset);
&c->vfs.dio_write_bioset);
dio = container_of(bio, struct dio_write, op.wbio.bio);
dio->req = req;
dio->mapping = mapping;
@ -677,25 +649,4 @@ err_put_write_ref:
goto out;
}
void bch2_fs_fs_io_direct_exit(struct bch_fs *c)
{
bioset_exit(&c->dio_write_bioset);
bioset_exit(&c->dio_read_bioset);
}
int bch2_fs_fs_io_direct_init(struct bch_fs *c)
{
if (bioset_init(&c->dio_read_bioset,
4, offsetof(struct dio_read, rbio.bio),
BIOSET_NEED_BVECS))
return -BCH_ERR_ENOMEM_dio_read_bioset_init;
if (bioset_init(&c->dio_write_bioset,
4, offsetof(struct dio_write, op.wbio.bio),
BIOSET_NEED_BVECS))
return -BCH_ERR_ENOMEM_dio_write_bioset_init;
return 0;
}
#endif /* NO_BCACHEFS_FS */

View File

@ -3,14 +3,39 @@
#define _BCACHEFS_FS_IO_DIRECT_H
#ifndef NO_BCACHEFS_FS
#include "data/read.h"
#include "vfs/io.h"
struct dio_read {
struct closure cl;
struct kiocb *req;
long ret;
bool should_dirty;
struct bch_read_bio rbio;
};
struct dio_write {
struct kiocb *req;
struct address_space *mapping;
struct bch_inode_info *inode;
struct mm_struct *mm;
const struct iovec *iov;
unsigned loop:1,
extending:1,
sync:1,
flush:1;
struct quota_res quota_res;
u64 written;
struct iov_iter iter;
struct iovec inline_vecs[2];
/* must be last: */
struct bch_write_op op;
};
ssize_t bch2_direct_write(struct kiocb *, struct iov_iter *);
ssize_t bch2_read_iter(struct kiocb *, struct iov_iter *);
void bch2_fs_fs_io_direct_exit(struct bch_fs *);
int bch2_fs_fs_io_direct_init(struct bch_fs *);
#else
static inline void bch2_fs_fs_io_direct_exit(struct bch_fs *c) {}
static inline int bch2_fs_fs_io_direct_init(struct bch_fs *c) { return 0; }
#endif
#endif /* _BCACHEFS_FS_IO_DIRECT_H */

View File

@ -235,7 +235,7 @@ static const struct rhashtable_params bch2_vfs_inodes_by_inum_params = {
int bch2_inode_or_descendents_is_open(struct btree_trans *trans, struct bpos p)
{
struct bch_fs *c = trans->c;
struct rhltable *ht = &c->vfs_inodes_by_inum_table;
struct rhltable *ht = &c->vfs.inodes_by_inum_table;
u64 inum = p.offset;
CLASS(darray_u32, subvols)();
@ -302,7 +302,7 @@ restart:
static struct bch_inode_info *__bch2_inode_hash_find(struct bch_fs *c, subvol_inum inum)
{
return rhashtable_lookup_fast(&c->vfs_inodes_table, &inum, bch2_vfs_inodes_params);
return rhashtable_lookup_fast(&c->vfs.inodes_table, &inum, bch2_vfs_inodes_params);
}
static void __wait_on_freeing_inode(struct bch_fs *c,
@ -358,11 +358,11 @@ static void bch2_inode_hash_remove(struct bch_fs *c, struct bch_inode_info *inod
remove = test_and_clear_bit(EI_INODE_HASHED, &inode->ei_flags);
if (remove) {
int ret = rhltable_remove(&c->vfs_inodes_by_inum_table,
int ret = rhltable_remove(&c->vfs.inodes_by_inum_table,
&inode->by_inum_hash, bch2_vfs_inodes_by_inum_params);
BUG_ON(ret);
ret = rhashtable_remove_fast(&c->vfs_inodes_table,
ret = rhashtable_remove_fast(&c->vfs.inodes_table,
&inode->hash, bch2_vfs_inodes_params);
BUG_ON(ret);
inode->v.i_hash.pprev = NULL;
@ -382,7 +382,7 @@ static struct bch_inode_info *bch2_inode_hash_insert(struct bch_fs *c,
set_bit(EI_INODE_HASHED, &inode->ei_flags);
retry:
if (unlikely(rhashtable_lookup_insert_key(&c->vfs_inodes_table,
if (unlikely(rhashtable_lookup_insert_key(&c->vfs.inodes_table,
&inode->ei_inum,
&inode->hash,
bch2_vfs_inodes_params))) {
@ -407,7 +407,7 @@ retry:
discard_new_inode(&inode->v);
return old;
} else {
int ret = rhltable_insert(&c->vfs_inodes_by_inum_table,
int ret = rhltable_insert(&c->vfs.inodes_by_inum_table,
&inode->by_inum_hash,
bch2_vfs_inodes_by_inum_params);
BUG_ON(ret);
@ -416,8 +416,8 @@ retry:
inode_sb_list_add(&inode->v);
scoped_guard(mutex, &c->vfs_inodes_lock)
list_add(&inode->ei_vfs_inode_list, &c->vfs_inodes_list);
scoped_guard(mutex, &c->vfs.inodes_lock)
list_add(&inode->ei_vfs_inode_list, &c->vfs.inodes_list);
return inode;
}
}
@ -1853,7 +1853,7 @@ static void bch2_evict_inode(struct inode *vinode)
bch2_inode_hash_remove(c, inode);
}
scoped_guard(mutex, &c->vfs_inodes_lock)
scoped_guard(mutex, &c->vfs.inodes_lock)
list_del_init(&inode->ei_vfs_inode_list);
}
@ -1877,8 +1877,8 @@ again:
cond_resched();
this_pass_clean = true;
mutex_lock(&c->vfs_inodes_lock);
list_for_each_entry(inode, &c->vfs_inodes_list, ei_vfs_inode_list) {
mutex_lock(&c->vfs.inodes_lock);
list_for_each_entry(inode, &c->vfs.inodes_list, ei_vfs_inode_list) {
if (!snapshot_list_has_id(s, inode->ei_inum.subvol))
continue;
@ -1898,14 +1898,14 @@ again:
wq_head = inode_bit_waitqueue(&wqe, &inode->v, __I_NEW);
prepare_to_wait_event(wq_head, &wqe.wq_entry,
TASK_UNINTERRUPTIBLE);
mutex_unlock(&c->vfs_inodes_lock);
mutex_unlock(&c->vfs.inodes_lock);
schedule();
finish_wait(wq_head, &wqe.wq_entry);
goto again;
}
}
mutex_unlock(&c->vfs_inodes_lock);
mutex_unlock(&c->vfs.inodes_lock);
darray_for_each(grabbed, i) {
inode = *i;
@ -2377,22 +2377,54 @@ static int bch2_init_fs_context(struct fs_context *fc)
void bch2_fs_vfs_exit(struct bch_fs *c)
{
if (c->vfs_writeback_wq)
destroy_workqueue(c->vfs_writeback_wq);
if (c->vfs_inodes_by_inum_table.ht.tbl)
rhltable_destroy(&c->vfs_inodes_by_inum_table);
if (c->vfs_inodes_table.tbl)
rhashtable_destroy(&c->vfs_inodes_table);
bioset_exit(&c->vfs.dio_write_bioset);
bioset_exit(&c->vfs.dio_read_bioset);
bioset_exit(&c->vfs.writepage_bioset);
bioset_exit(&c->vfs.nocow_flush_bioset);
if (c->vfs.writeback_wq)
destroy_workqueue(c->vfs.writeback_wq);
if (c->vfs.inodes_by_inum_table.ht.tbl)
rhltable_destroy(&c->vfs.inodes_by_inum_table);
if (c->vfs.inodes_table.tbl)
rhashtable_destroy(&c->vfs.inodes_table);
}
int bch2_fs_vfs_init(struct bch_fs *c)
{
try(rhashtable_init(&c->vfs_inodes_table, &bch2_vfs_inodes_params));
try(rhltable_init(&c->vfs_inodes_by_inum_table, &bch2_vfs_inodes_by_inum_params));
INIT_LIST_HEAD(&c->vfs.inodes_list);
mutex_init(&c->vfs.inodes_lock);
c->vfs_writeback_wq = alloc_workqueue("bcachefs_vfs_writeback",
try(rhashtable_init(&c->vfs.inodes_table, &bch2_vfs_inodes_params));
try(rhltable_init(&c->vfs.inodes_by_inum_table, &bch2_vfs_inodes_by_inum_params));
if (bioset_init(&c->vfs.dio_read_bioset,
4, offsetof(struct dio_read, rbio.bio),
BIOSET_NEED_BVECS))
return bch_err_throw(c, ENOMEM_dio_read_bioset_init);
return 0;
}
int bch2_fs_vfs_init_rw(struct bch_fs *c)
{
if (bioset_init(&c->vfs.writepage_bioset,
4, offsetof(struct bch_writepage_io, op.wbio.bio),
BIOSET_NEED_BVECS))
return bch_err_throw(c, ENOMEM_writepage_bioset_init);
if (bioset_init(&c->vfs.dio_write_bioset,
4, offsetof(struct dio_write, op.wbio.bio),
BIOSET_NEED_BVECS))
return bch_err_throw(c, ENOMEM_dio_write_bioset_init);
if (bioset_init(&c->vfs.nocow_flush_bioset,
1, offsetof(struct nocow_flush, bio), 0))
return bch_err_throw(c, ENOMEM_nocow_flush_bioset_init);
c->vfs.writeback_wq = alloc_workqueue("bcachefs_vfs_writeback",
WQ_MEM_RECLAIM|WQ_FREEZABLE, 1);
if (!c->vfs_writeback_wq)
if (!c->vfs.writeback_wq)
return bch_err_throw(c, ENOMEM_fs_other_alloc);
return 0;

View File

@ -203,6 +203,7 @@ int bch2_fiemap(struct inode *, struct fiemap_extent_info *, u64, u64);
void bch2_fs_vfs_exit(struct bch_fs *);
int bch2_fs_vfs_init(struct bch_fs *);
int bch2_fs_vfs_init_rw(struct bch_fs *);
void bch2_vfs_exit(void);
int bch2_vfs_init(void);
@ -210,7 +211,7 @@ int bch2_vfs_init(void);
static inline void bch2_dirty_inode(struct bch_fs *c, struct bch_inode_info *inode)
{
if (c->opts.writeback_timeout)
queue_delayed_work(c->vfs_writeback_wq, &inode->ei_writeback_timer,
queue_delayed_work(c->vfs.writeback_wq, &inode->ei_writeback_timer,
c->opts.writeback_timeout * HZ);
}
@ -225,6 +226,7 @@ static inline void bch2_evict_subvolume_inodes(struct bch_fs *c,
static inline void bch2_fs_vfs_exit(struct bch_fs *c) {}
static inline int bch2_fs_vfs_init(struct bch_fs *c) { return 0; }
static inline int bch2_fs_vfs_init_rw(struct bch_fs *c) { return 0; }
static inline void bch2_vfs_exit(void) {}
static inline int bch2_vfs_init(void) { return 0; }

View File

@ -42,15 +42,8 @@
#include <trace/events/writeback.h>
struct nocow_flush {
struct closure *cl;
struct bch_dev *ca;
struct bio bio;
};
static void nocow_flush_endio(struct bio *_bio)
{
struct nocow_flush *bio = container_of(_bio, struct nocow_flush, bio);
closure_put(bio->cl);
@ -63,19 +56,16 @@ void bch2_inode_flush_nocow_writes_async(struct bch_fs *c,
struct bch_inode_info *inode,
struct closure *cl)
{
struct nocow_flush *bio;
struct bch_dev *ca;
struct bch_devs_mask devs;
unsigned dev;
dev = find_first_bit(inode->ei_devs_need_flush.d, BCH_SB_MEMBERS_MAX);
unsigned dev = find_first_bit(inode->ei_devs_need_flush.d, BCH_SB_MEMBERS_MAX);
if (dev == BCH_SB_MEMBERS_MAX)
return;
devs = inode->ei_devs_need_flush;
struct bch_devs_mask devs = inode->ei_devs_need_flush;
memset(&inode->ei_devs_need_flush, 0, sizeof(inode->ei_devs_need_flush));
for_each_set_bit(dev, devs.d, BCH_SB_MEMBERS_MAX) {
struct bch_dev *ca;
scoped_guard(rcu) {
ca = rcu_dereference(c->devs[dev]);
if (ca && !enumerated_ref_tryget(&ca->io_ref[WRITE],
@ -86,11 +76,11 @@ void bch2_inode_flush_nocow_writes_async(struct bch_fs *c,
if (!ca)
continue;
bio = container_of(bio_alloc_bioset(ca->disk_sb.bdev, 0,
REQ_OP_WRITE|REQ_PREFLUSH,
GFP_KERNEL,
&c->nocow_flush_bioset),
struct nocow_flush, bio);
struct nocow_flush *bio = container_of(bio_alloc_bioset(ca->disk_sb.bdev, 0,
REQ_OP_WRITE|REQ_PREFLUSH,
GFP_KERNEL,
&c->vfs.nocow_flush_bioset),
struct nocow_flush, bio);
bio->cl = cl;
bio->ca = ca;
bio->bio.bi_end_io = nocow_flush_endio;
@ -1089,18 +1079,4 @@ loff_t bch2_llseek(struct file *file, loff_t offset, int whence)
return bch2_err_class(ret);
}
void bch2_fs_fsio_exit(struct bch_fs *c)
{
bioset_exit(&c->nocow_flush_bioset);
}
int bch2_fs_fsio_init(struct bch_fs *c)
{
if (bioset_init(&c->nocow_flush_bioset,
1, offsetof(struct nocow_flush, bio), 0))
return -BCH_ERR_ENOMEM_nocow_flush_bioset_init;
return 0;
}
#endif /* NO_BCACHEFS_FS */

View File

@ -11,6 +11,12 @@
#include <linux/uio.h>
struct nocow_flush {
struct closure *cl;
struct bch_dev *ca;
struct bio bio;
};
struct folio_vec {
struct folio *fv_folio;
size_t fv_offset;
@ -170,12 +176,6 @@ loff_t bch2_remap_file_range(struct file *, loff_t, struct file *,
loff_t, loff_t, unsigned);
loff_t bch2_llseek(struct file *, loff_t, int);
void bch2_fs_fsio_exit(struct bch_fs *);
int bch2_fs_fsio_init(struct bch_fs *);
#else
static inline void bch2_fs_fsio_exit(struct bch_fs *c) {}
static inline int bch2_fs_fsio_init(struct bch_fs *c) { return 0; }
#endif
#endif /* _BCACHEFS_FS_IO_H */

View File

@ -142,6 +142,8 @@ struct bch_folio *__bch2_folio_create(struct folio *folio, gfp_t gfp)
struct bch_folio *bch2_folio_create(struct folio *folio, gfp_t gfp)
{
EBUG_ON(!folio_test_locked(folio));
return bch2_folio(folio) ?: __bch2_folio_create(folio, gfp);
}

View File

@ -99,16 +99,9 @@ static inline void bch2_folio_release(struct folio *folio)
__bch2_folio_release(folio);
}
static inline struct bch_folio *__bch2_folio(struct folio *folio)
{
return folio_get_private(folio);
}
static inline struct bch_folio *bch2_folio(struct folio *folio)
{
EBUG_ON(!folio_test_locked(folio));
return __bch2_folio(folio);
return folio_get_private(folio);
}
struct bch_folio *__bch2_folio_create(struct folio *, gfp_t);

20
libbcachefs/vfs/types.h Normal file
View File

@ -0,0 +1,20 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _BCACHEFS_VFS_TYPES_H
#define _BCACHEFS_VFS_TYPES_H
struct bch_fs_vfs {
#ifndef NO_BCACHEFS_FS
struct list_head inodes_list;
struct mutex inodes_lock;
struct rhashtable inodes_table;
struct rhltable inodes_by_inum_table;
struct bio_set writepage_bioset;
struct bio_set dio_write_bioset;
struct bio_set dio_read_bioset;
struct bio_set nocow_flush_bioset;
struct workqueue_struct *writeback_wq;
#endif
};
#endif /* _BCACHEFS_VFS_TYPES_H */