summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/bcachefs/btree_update.h2
-rw-r--r--fs/bcachefs/btree_update_leaf.c13
-rw-r--r--fs/bcachefs/btree_write_buffer.c37
-rw-r--r--fs/bcachefs/btree_write_buffer_types.h3
-rw-r--r--fs/bcachefs/journal_io.c4
-rw-r--r--fs/bcachefs/opts.h2
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, \