diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2018-01-14 16:26:42 -0500 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2018-05-22 00:44:18 -0400 |
commit | fe79e76e31f8e254d82a4d5b5019b1d89bfe2863 (patch) | |
tree | ba149304d3509b1fd490e34d886576014d0e5d42 | |
parent | 479e7b1b28403b813aed98924fcf4a39d5f11960 (diff) |
bcachefs: better comments/cleanups
-rw-r--r-- | fs/bcachefs/btree_io.h | 29 | ||||
-rw-r--r-- | fs/bcachefs/btree_update_interior.c | 28 | ||||
-rw-r--r-- | fs/bcachefs/btree_update_leaf.c | 2 |
3 files changed, 50 insertions, 9 deletions
diff --git a/fs/bcachefs/btree_io.h b/fs/bcachefs/btree_io.h index c8417ac32fea..bfb437b7dd85 100644 --- a/fs/bcachefs/btree_io.h +++ b/fs/bcachefs/btree_io.h @@ -97,16 +97,35 @@ bool bch2_btree_post_write_cleanup(struct bch_fs *, struct btree *); void bch2_btree_node_write(struct bch_fs *, struct btree *, struct closure *, enum six_lock_type); -#define bch2_btree_node_write_dirty(_c, _b, _cl, cond) \ +/* + * btree_node_dirty() can be cleared with only a read lock, + * and for bch2_btree_node_write_cond() we want to set need_write iff it's + * still dirty: + */ +static inline void set_btree_node_need_write_if_dirty(struct btree *b) +{ + unsigned long old, new, v = READ_ONCE(b->flags); + + do { + old = new = v; + + if (!(old & (1 << BTREE_NODE_dirty))) + return; + + new |= (1 << BTREE_NODE_need_write); + } while ((v = cmpxchg(&b->flags, old, new)) != old); +} + +#define bch2_btree_node_write_cond(_c, _b, cond) \ do { \ while ((_b)->written && btree_node_dirty(_b) && (cond)) { \ - set_btree_node_need_write(_b); \ - \ - if (!btree_node_may_write(_b)) \ + if (!btree_node_may_write(_b)) { \ + set_btree_node_need_write_if_dirty(_b); \ break; \ + } \ \ if (!btree_node_write_in_flight(_b)) { \ - bch2_btree_node_write(_c, _b, _cl, SIX_LOCK_read);\ + bch2_btree_node_write(_c, _b, NULL, SIX_LOCK_read);\ break; \ } \ \ diff --git a/fs/bcachefs/btree_update_interior.c b/fs/bcachefs/btree_update_interior.c index a0f37c4ceb09..b307e33e41c5 100644 --- a/fs/bcachefs/btree_update_interior.c +++ b/fs/bcachefs/btree_update_interior.c @@ -601,8 +601,12 @@ static void btree_update_nodes_reachable(struct closure *cl) b->will_make_reachable = NULL; mutex_unlock(&c->btree_interior_update_lock); + /* + * b->will_make_reachable prevented it from being written, so + * write it now if it needs to be written: + */ six_lock_read(&b->lock); - bch2_btree_node_write_dirty(c, b, NULL, btree_node_need_write(b)); + bch2_btree_node_write_cond(c, b, btree_node_need_write(b)); six_unlock_read(&b->lock); mutex_lock(&c->btree_interior_update_lock); } @@ -651,8 +655,11 @@ retry: list_del(&as->write_blocked_list); mutex_unlock(&c->btree_interior_update_lock); - bch2_btree_node_write_dirty(c, b, NULL, - btree_node_need_write(b)); + /* + * b->write_blocked prevented it from being written, so + * write it now if it needs to be written: + */ + bch2_btree_node_write_cond(c, b, btree_node_need_write(b)); six_unlock_read(&b->lock); break; @@ -952,6 +959,12 @@ void bch2_btree_interior_update_will_free_node(struct btree_update *as, clear_btree_node_need_write(b); w = btree_current_write(b); + /* + * Does this node have any btree_update operations waiting on this node + * to be written? + * + * If so, wake them up when this btree_update operation is reachable: + */ llist_for_each_entry_safe(cl, cl_n, llist_del_all(&w->wait.list), list) llist_add(&cl->list, &as->wait.list); @@ -972,6 +985,15 @@ void bch2_btree_interior_update_will_free_node(struct btree_update *as, &as->journal, interior_update_flush); bch2_journal_pin_drop(&c->journal, &w->journal); + /* + * Is this a node that isn't reachable on disk yet? + * + * Nodes that aren't reachable yet have writes blocked until they're + * reachable - now that we've cancelled any pending writes and moved + * things waiting on that write to wait on this update, we can drop this + * node from the list of nodes that the other update is making + * reachable, prior to freeing it: + */ if (b->will_make_reachable) __btree_interior_update_drop_new_node(b); diff --git a/fs/bcachefs/btree_update_leaf.c b/fs/bcachefs/btree_update_leaf.c index e62e0d2e7fec..dbf705696973 100644 --- a/fs/bcachefs/btree_update_leaf.c +++ b/fs/bcachefs/btree_update_leaf.c @@ -109,7 +109,7 @@ static void __btree_node_flush(struct journal *j, struct journal_entry_pin *pin, struct btree *b = container_of(w, struct btree, writes[i]); six_lock_read(&b->lock); - bch2_btree_node_write_dirty(c, b, NULL, + bch2_btree_node_write_cond(c, b, (btree_current_write(b) == w && w->journal.pin_list == journal_seq_pin(j, seq))); six_unlock_read(&b->lock); |