diff options
-rw-r--r-- | fs/bcachefs/btree_update.h | 2 | ||||
-rw-r--r-- | fs/bcachefs/btree_update_leaf.c | 13 | ||||
-rw-r--r-- | fs/bcachefs/btree_write_buffer.c | 37 | ||||
-rw-r--r-- | fs/bcachefs/btree_write_buffer_types.h | 3 | ||||
-rw-r--r-- | fs/bcachefs/journal_io.c | 4 | ||||
-rw-r--r-- | fs/bcachefs/opts.h | 2 |
6 files changed, 41 insertions, 20 deletions
diff --git a/fs/bcachefs/btree_update.h b/fs/bcachefs/btree_update.h index 46fb4a9ed295..9ac7e5b3dc3f 100644 --- a/fs/bcachefs/btree_update.h +++ b/fs/bcachefs/btree_update.h @@ -31,6 +31,7 @@ enum btree_insert_flags { __BTREE_INSERT_JOURNAL_RECLAIM, __BTREE_INSERT_NOWAIT, __BTREE_INSERT_GC_LOCK_HELD, + __BTREE_INSERT_WRITE_BUFFER_FLUSH, __BCH_HASH_SET_MUST_CREATE, __BCH_HASH_SET_MUST_REPLACE, }; @@ -53,6 +54,7 @@ enum btree_insert_flags { /* Don't block on allocation failure (for new btree nodes: */ #define BTREE_INSERT_NOWAIT (1 << __BTREE_INSERT_NOWAIT) #define BTREE_INSERT_GC_LOCK_HELD (1 << __BTREE_INSERT_GC_LOCK_HELD) +#define BTREE_INSERT_WRITE_BUFFER_FLUSH (1 << __BTREE_INSERT_WRITE_BUFFER_FLUSH) #define BCH_HASH_SET_MUST_CREATE (1 << __BCH_HASH_SET_MUST_CREATE) #define BCH_HASH_SET_MUST_REPLACE (1 << __BCH_HASH_SET_MUST_REPLACE) diff --git a/fs/bcachefs/btree_update_leaf.c b/fs/bcachefs/btree_update_leaf.c index 1dc2c1138ad4..512692e7c362 100644 --- a/fs/bcachefs/btree_update_leaf.c +++ b/fs/bcachefs/btree_update_leaf.c @@ -640,7 +640,8 @@ bch2_trans_commit_write_locked(struct btree_trans *trans, unsigned flags, marking = true; } - if (c->btree_write_buffer.nr > c->btree_write_buffer.size / 2) + if (!(flags & BTREE_INSERT_WRITE_BUFFER_FLUSH) && + c->btree_write_buffer.nr > c->btree_write_buffer.size / 2) return -BCH_ERR_btree_insert_need_flush_buffer; /* @@ -997,17 +998,19 @@ int bch2_trans_commit_error(struct btree_trans *trans, unsigned flags, case -BCH_ERR_btree_insert_need_flush_buffer: { struct btree_write_buffer *wb = &c->btree_write_buffer; + BUG_ON(flags & BTREE_INSERT_WRITE_BUFFER_FLUSH); + ret = 0; if (wb->nr) { bch2_trans_reset_updates(trans); bch2_trans_unlock(trans); - mutex_lock(&wb->lock); + mutex_lock(&wb->flush_lock); if (wb->nr) ret = bch2_btree_write_buffer_flush_locked(trans, flags|BTREE_INSERT_NOCHECK_RW, true); - mutex_unlock(&wb->lock); + mutex_unlock(&wb->flush_lock); if (!ret) { trace_and_count(c, trans_restart_write_buffer_flush, trans, _THIS_IP_); @@ -1106,13 +1109,13 @@ int __bch2_trans_commit(struct btree_trans *trans, unsigned flags) } if (c->btree_write_buffer.nr && - mutex_trylock(&c->btree_write_buffer.lock)) { + mutex_trylock(&c->btree_write_buffer.flush_lock)) { bch2_trans_begin(trans); bch2_trans_unlock(trans); ret = bch2_btree_write_buffer_flush_locked(trans, flags|BTREE_INSERT_NOCHECK_RW, true); - mutex_unlock(&trans->c->btree_write_buffer.lock); + mutex_unlock(&c->btree_write_buffer.flush_lock); if (!ret) { trace_and_count(c, trans_restart_write_buffer_flush, trans, _THIS_IP_); ret = btree_trans_restart(trans, BCH_ERR_transaction_restart_write_buffer_flush); diff --git a/fs/bcachefs/btree_write_buffer.c b/fs/bcachefs/btree_write_buffer.c index 1ba17fa6fecf..d9d8aa50f13f 100644 --- a/fs/bcachefs/btree_write_buffer.c +++ b/fs/bcachefs/btree_write_buffer.c @@ -149,7 +149,9 @@ trans_commit: bch2_trans_commit(trans, NULL, NULL, commit_flags| BTREE_INSERT_NOFAIL| - BTREE_INSERT_JOURNAL_RECLAIM); + BTREE_INSERT_JOURNAL_RECLAIM| + BTREE_INSERT_WRITE_BUFFER_FLUSH); + } int bch2_btree_write_buffer_flush_locked(struct btree_trans *trans, unsigned commit_flags, @@ -167,11 +169,16 @@ int bch2_btree_write_buffer_flush_locked(struct btree_trans *trans, unsigned com memset(&pin, 0, sizeof(pin)); + lockdep_assert_held(&wb->flush_lock); + + mutex_lock(&wb->lock); bch2_journal_pin_copy(j, &pin, &wb->journal_pin, NULL); bch2_journal_pin_drop(j, &wb->journal_pin); - keys = wb->keys; + keys = wb->keys[0]; + swap(wb->keys[0], wb->keys[1]); swap(nr, wb->nr); + mutex_unlock(&wb->lock); /* * We first sort so that we can detect and skip redundant updates, and @@ -272,6 +279,7 @@ slowpath: ret = commit_do(trans, NULL, NULL, commit_flags| BTREE_INSERT_NOFAIL| + BTREE_INSERT_WRITE_BUFFER_FLUSH| BTREE_INSERT_JOURNAL_RECLAIM| JOURNAL_WATERMARK_reserved, __bch2_btree_insert(trans, i->btree, &i->k, 0)); @@ -288,11 +296,11 @@ int bch2_btree_write_buffer_flush(struct btree_trans *trans) struct btree_write_buffer *wb = &c->btree_write_buffer; int ret; - if (!mutex_trylock(&wb->lock)) + if (!mutex_trylock(&wb->flush_lock)) return 0; ret = bch2_btree_write_buffer_flush_locked(trans, 0, true); - mutex_unlock(&wb->lock); + mutex_unlock(&wb->flush_lock); return ret; } @@ -303,9 +311,9 @@ int bch2_btree_write_buffer_flush_sync(struct btree_trans *trans, unsigned commi bch2_trans_unlock(trans); - mutex_lock(&trans->c->btree_write_buffer.lock); + mutex_lock(&trans->c->btree_write_buffer.flush_lock); ret = bch2_btree_write_buffer_flush_locked(trans, commit_flags, true); - mutex_unlock(&trans->c->btree_write_buffer.lock); + mutex_unlock(&trans->c->btree_write_buffer.flush_lock); return ret; } @@ -336,10 +344,10 @@ int bch2_write_buffer_key(struct bch_fs *c, u64 seq, unsigned offset, */ } - wb->keys[wb->nr].journal_seq = seq; - wb->keys[wb->nr].journal_offset = offset; - wb->keys[wb->nr].btree = btree; - bkey_copy(&wb->keys[wb->nr].k, k); + wb->keys[0][wb->nr].journal_seq = seq; + wb->keys[0][wb->nr].journal_offset = offset; + wb->keys[0][wb->nr].btree = btree; + bkey_copy(&wb->keys[0][wb->nr].k, k); wb->nr++; bch2_journal_pin_add(&c->journal, seq, &wb->journal_pin, @@ -353,7 +361,8 @@ void bch2_fs_btree_write_buffer_exit(struct bch_fs *c) WARN_ON(wb->nr && !bch2_journal_error(&c->journal)); - kvfree(wb->keys); + kvfree(wb->keys[1]); + kvfree(wb->keys[0]); } int bch2_fs_btree_write_buffer_init(struct bch_fs *c) @@ -361,10 +370,12 @@ int bch2_fs_btree_write_buffer_init(struct bch_fs *c) struct btree_write_buffer *wb = &c->btree_write_buffer; mutex_init(&wb->lock); + mutex_init(&wb->flush_lock); wb->size = c->opts.btree_write_buffer_size; - wb->keys = kvmalloc_array(wb->size, sizeof(*wb->keys), GFP_KERNEL); - if (!wb->keys) + wb->keys[0] = kvmalloc_array(wb->size, sizeof(*wb->keys[0]), GFP_KERNEL); + wb->keys[1] = kvmalloc_array(wb->size, sizeof(*wb->keys[1]), GFP_KERNEL); + if (!wb->keys[0] || !wb->keys[1]) return -BCH_ERR_ENOMEM_fs_btree_write_buffer_init; return 0; diff --git a/fs/bcachefs/btree_write_buffer_types.h b/fs/bcachefs/btree_write_buffer_types.h index be224c3c1850..14251b4ae990 100644 --- a/fs/bcachefs/btree_write_buffer_types.h +++ b/fs/bcachefs/btree_write_buffer_types.h @@ -16,12 +16,13 @@ struct btree_write_buffered_key { struct btree_write_buffer { struct mutex lock; + struct mutex flush_lock; struct journal_entry_pin journal_pin; size_t nr; size_t size; - struct btree_write_buffered_key *keys; + struct btree_write_buffered_key *keys[2]; }; #endif /* _BCACHEFS_BTREE_WRITE_BUFFER_TYPES_H */ diff --git a/fs/bcachefs/journal_io.c b/fs/bcachefs/journal_io.c index 6c1bfcf92dc4..f9a1c8a6a8e2 100644 --- a/fs/bcachefs/journal_io.c +++ b/fs/bcachefs/journal_io.c @@ -1641,8 +1641,10 @@ static void bch2_journal_entries_postprocess(struct bch_fs *c, struct jset *jset { struct jset_entry *i, *next, *prev = NULL; u64 seq = le64_to_cpu(jset->seq); + unsigned nr; mutex_lock(&c->btree_write_buffer.lock); + nr = c->btree_write_buffer.nr; /* * Simple compaction, dropping empty jset_entries (from journal @@ -1695,6 +1697,8 @@ static void bch2_journal_entries_postprocess(struct bch_fs *c, struct jset *jset prev = prev ? vstruct_next(prev) : jset->start; jset->u64s = cpu_to_le32((u64 *) prev - jset->_data); + //pr_info("write_buffer %u - %zu", nr, c->btree_write_buffer.nr); + mutex_unlock(&c->btree_write_buffer.lock); } diff --git a/fs/bcachefs/opts.h b/fs/bcachefs/opts.h index 719693b333da..603749eb253e 100644 --- a/fs/bcachefs/opts.h +++ b/fs/bcachefs/opts.h @@ -215,7 +215,7 @@ enum opt_type { x(btree_write_buffer_size, u32, \ OPT_FS|OPT_MOUNT, \ OPT_UINT(16, (1U << 20) - 1), \ - BCH2_NO_SB_OPT, 1U << 13, \ + BCH2_NO_SB_OPT, 1U << 15, \ NULL, "Number of btree write buffer entries") \ x(gc_reserve_percent, u8, \ OPT_FS|OPT_FORMAT|OPT_MOUNT|OPT_RUNTIME, \ |