diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2020-02-08 16:39:37 -0500 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-10-22 17:08:35 -0400 |
commit | ac7c51b2180e757feaaabcb84794bcc9912a4edf (patch) | |
tree | 82cbc9feaeeff3fb038fbb2b3d104e4f7e04f879 | |
parent | 548b3d209fa5c6aaa9db58a69d9f6cf4ce8978b6 (diff) | |
download | lwn-ac7c51b2180e757feaaabcb84794bcc9912a4edf.tar.gz lwn-ac7c51b2180e757feaaabcb84794bcc9912a4edf.zip |
bcachefs: Seralize btree_update operations at btree_update_nodes_written()
Prep work for journalling updates to interior nodes - enforcing ordering
will greatly simplify those changes.
Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
-rw-r--r-- | fs/bcachefs/bcachefs.h | 1 | ||||
-rw-r--r-- | fs/bcachefs/btree_update_interior.c | 32 | ||||
-rw-r--r-- | fs/bcachefs/btree_update_interior.h | 1 | ||||
-rw-r--r-- | fs/bcachefs/super.c | 1 |
4 files changed, 29 insertions, 6 deletions
diff --git a/fs/bcachefs/bcachefs.h b/fs/bcachefs/bcachefs.h index 0d4a8b75ff42..32cdf87ee55d 100644 --- a/fs/bcachefs/bcachefs.h +++ b/fs/bcachefs/bcachefs.h @@ -610,6 +610,7 @@ struct bch_fs { mempool_t btree_interior_update_pool; struct list_head btree_interior_update_list; + struct list_head btree_interior_updates_unwritten; struct mutex btree_interior_update_lock; struct closure_waitlist btree_interior_update_wait; diff --git a/fs/bcachefs/btree_update_interior.c b/fs/bcachefs/btree_update_interior.c index 3d8b6218c983..677cb76731c1 100644 --- a/fs/bcachefs/btree_update_interior.c +++ b/fs/bcachefs/btree_update_interior.c @@ -666,9 +666,15 @@ static void btree_update_nodes_written(struct closure *cl) * to child nodes that weren't written yet: now, the child nodes have * been written so we can write out the update to the interior node. */ -retry: mutex_lock(&c->btree_interior_update_lock); as->nodes_written = true; +retry: + as = list_first_entry_or_null(&c->btree_interior_updates_unwritten, + struct btree_update, unwritten_list); + if (!as || !as->nodes_written) { + mutex_unlock(&c->btree_interior_update_lock); + return; + } switch (as->mode) { case BTREE_INTERIOR_NO_UPDATE: @@ -681,11 +687,12 @@ retry: mutex_unlock(&c->btree_interior_update_lock); btree_node_lock_type(c, b, SIX_LOCK_read); six_unlock_read(&b->c.lock); + mutex_lock(&c->btree_interior_update_lock); goto retry; } BUG_ON(!btree_node_dirty(b)); - closure_wait(&btree_current_write(b)->wait, cl); + closure_wait(&btree_current_write(b)->wait, &as->cl); list_del(&as->write_blocked_list); @@ -694,6 +701,8 @@ retry: * nodes to be writeable: */ closure_wake_up(&c->btree_interior_update_wait); + + list_del(&as->unwritten_list); mutex_unlock(&c->btree_interior_update_lock); /* @@ -702,6 +711,7 @@ retry: */ bch2_btree_node_write_cond(c, b, true); six_unlock_read(&b->c.lock); + continue_at(&as->cl, btree_update_nodes_reachable, system_wq); break; case BTREE_INTERIOR_UPDATING_AS: @@ -716,8 +726,12 @@ retry: /* * and then we have to wait on that btree_update to finish: */ - closure_wait(&as->parent_as->wait, cl); + closure_wait(&as->parent_as->wait, &as->cl); + + list_del(&as->unwritten_list); mutex_unlock(&c->btree_interior_update_lock); + + continue_at(&as->cl, btree_update_nodes_reachable, system_wq); break; case BTREE_INTERIOR_UPDATING_ROOT: @@ -728,6 +742,7 @@ retry: mutex_unlock(&c->btree_interior_update_lock); btree_node_lock_type(c, b, SIX_LOCK_read); six_unlock_read(&b->c.lock); + mutex_lock(&c->btree_interior_update_lock); goto retry; } @@ -744,6 +759,8 @@ retry: * can reuse the old nodes it'll have to do a journal commit: */ six_unlock_read(&b->c.lock); + + list_del(&as->unwritten_list); mutex_unlock(&c->btree_interior_update_lock); /* @@ -762,11 +779,12 @@ retry: as->journal_seq = bch2_journal_last_unwritten_seq(&c->journal); - btree_update_wait_on_journal(cl); - return; + btree_update_wait_on_journal(&as->cl); + break; } - continue_at(cl, btree_update_nodes_reachable, system_wq); + mutex_lock(&c->btree_interior_update_lock); + goto retry; } /* @@ -778,6 +796,7 @@ static void btree_update_updated_node(struct btree_update *as, struct btree *b) struct bch_fs *c = as->c; mutex_lock(&c->btree_interior_update_lock); + list_add_tail(&as->unwritten_list, &c->btree_interior_updates_unwritten); BUG_ON(as->mode != BTREE_INTERIOR_NO_UPDATE); BUG_ON(!btree_node_dirty(b)); @@ -858,6 +877,7 @@ static void btree_update_updated_root(struct btree_update *as) struct btree_root *r = &c->btree_roots[as->btree_id]; mutex_lock(&c->btree_interior_update_lock); + list_add_tail(&as->unwritten_list, &c->btree_interior_updates_unwritten); BUG_ON(as->mode != BTREE_INTERIOR_NO_UPDATE); diff --git a/fs/bcachefs/btree_update_interior.h b/fs/bcachefs/btree_update_interior.h index 8f9d4a0b68ea..e3204f32cc68 100644 --- a/fs/bcachefs/btree_update_interior.h +++ b/fs/bcachefs/btree_update_interior.h @@ -55,6 +55,7 @@ struct btree_update { struct bch_fs *c; struct list_head list; + struct list_head unwritten_list; /* What kind of update are we doing? */ enum { diff --git a/fs/bcachefs/super.c b/fs/bcachefs/super.c index 586636a4c204..2ba04b08529d 100644 --- a/fs/bcachefs/super.c +++ b/fs/bcachefs/super.c @@ -642,6 +642,7 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts) INIT_LIST_HEAD(&c->list); INIT_LIST_HEAD(&c->btree_interior_update_list); + INIT_LIST_HEAD(&c->btree_interior_updates_unwritten); mutex_init(&c->btree_reserve_cache_lock); mutex_init(&c->btree_interior_update_lock); |