diff options
-rw-r--r-- | fs/bcachefs/btree_iter.c | 5 | ||||
-rw-r--r-- | fs/bcachefs/btree_update_interior.c | 41 | ||||
-rw-r--r-- | fs/bcachefs/extents.c | 14 | ||||
-rw-r--r-- | fs/bcachefs/extents.h | 2 | ||||
-rw-r--r-- | mm/shrinker.c | 1 |
5 files changed, 57 insertions, 6 deletions
diff --git a/fs/bcachefs/btree_iter.c b/fs/bcachefs/btree_iter.c index cc771affa511..a282c3886168 100644 --- a/fs/bcachefs/btree_iter.c +++ b/fs/bcachefs/btree_iter.c @@ -2860,8 +2860,9 @@ struct bkey_s_c bch2_btree_iter_peek_slot(struct btree_trans *trans, struct btre !bkey_deleted(k.k) && (k2 = btree_trans_peek_key_cache(trans, iter, iter->pos)).k) { k = k2; - if (!bkey_err(k)) - iter->k = *k.k; + if (bkey_err(k)) + goto out; + iter->k = *k.k; } if (unlikely(k.k->type == KEY_TYPE_whiteout && diff --git a/fs/bcachefs/btree_update_interior.c b/fs/bcachefs/btree_update_interior.c index 312ef203b27b..e4aa4fa749bc 100644 --- a/fs/bcachefs/btree_update_interior.c +++ b/fs/bcachefs/btree_update_interior.c @@ -14,6 +14,7 @@ #include "btree_locking.h" #include "buckets.h" #include "clock.h" +#include "disk_groups.h" #include "enumerated_ref.h" #include "error.h" #include "extents.h" @@ -277,6 +278,36 @@ static void bch2_btree_node_free_never_used(struct btree_update *as, bch2_trans_node_drop(trans, b); } +static bool can_use_btree_node(struct bch_fs *c, + struct disk_reservation *res, + unsigned target, + struct bkey_s_c k) +{ + if (!bch2_bkey_devs_rw(c, k)) + return false; + + if (target && !bch2_bkey_in_target(c, k, target)) + return false; + + unsigned durability = bch2_bkey_durability(c, k); + + if (durability >= res->nr_replicas) + return true; + + struct bch_devs_mask devs = target_rw_devs(c, BCH_DATA_btree, target); + + guard(rcu)(); + + unsigned durability_available = 0, i; + for_each_set_bit(i, devs.d, BCH_SB_MEMBERS_MAX) { + struct bch_dev *ca = bch2_dev_rcu_noerror(c, i); + if (ca) + durability_available += ca->mi.durability; + } + + return durability >= durability_available; +} + static struct btree *__bch2_btree_node_alloc(struct btree_trans *trans, struct disk_reservation *res, struct closure *cl, @@ -303,10 +334,14 @@ static struct btree *__bch2_btree_node_alloc(struct btree_trans *trans, mutex_lock(&c->btree_reserve_cache_lock); if (c->btree_reserve_cache_nr > nr_reserve) { for (struct btree_alloc *a = c->btree_reserve_cache; - a < c->btree_reserve_cache + c->btree_reserve_cache_nr; - a++) { - if (target && !bch2_bkey_in_target(c, bkey_i_to_s_c(&a->k), target)) + a < c->btree_reserve_cache + c->btree_reserve_cache_nr;) { + /* check if it has sufficient durability */ + + if (!can_use_btree_node(c, res, target, bkey_i_to_s_c(&a->k))) { + bch2_open_buckets_put(c, &a->ob); + *a = c->btree_reserve_cache[--c->btree_reserve_cache_nr]; continue; + } bkey_copy(&b->key, &a->k); b->ob = a->ob; diff --git a/fs/bcachefs/extents.c b/fs/bcachefs/extents.c index b36ecfc0ab9d..8152ef1cbbcd 100644 --- a/fs/bcachefs/extents.c +++ b/fs/bcachefs/extents.c @@ -1006,6 +1006,20 @@ const struct bch_extent_ptr *bch2_bkey_has_device_c(struct bkey_s_c k, unsigned return NULL; } +bool bch2_bkey_devs_rw(struct bch_fs *c, struct bkey_s_c k) +{ + struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k); + + guard(rcu)(); + bkey_for_each_ptr(ptrs, ptr) { + CLASS(bch2_dev_tryget, ca)(c, ptr->dev); + if (!ca || ca->mi.state != BCH_MEMBER_STATE_rw) + return false; + } + + return true; +} + bool bch2_bkey_has_target(struct bch_fs *c, struct bkey_s_c k, unsigned target) { struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k); diff --git a/fs/bcachefs/extents.h b/fs/bcachefs/extents.h index f212f91c278d..35ee03cd5065 100644 --- a/fs/bcachefs/extents.h +++ b/fs/bcachefs/extents.h @@ -614,6 +614,8 @@ static inline struct bch_extent_ptr *bch2_bkey_has_device(struct bkey_s k, unsig return (void *) bch2_bkey_has_device_c(k.s_c, dev); } +bool bch2_bkey_devs_rw(struct bch_fs *, struct bkey_s_c); + bool bch2_bkey_has_target(struct bch_fs *, struct bkey_s_c, unsigned); bool bch2_bkey_in_target(struct bch_fs *, struct bkey_s_c, unsigned); diff --git a/mm/shrinker.c b/mm/shrinker.c index cbadd4d4437c..c94eedf2cfd8 100644 --- a/mm/shrinker.c +++ b/mm/shrinker.c @@ -833,7 +833,6 @@ void shrinker_to_text(struct seq_buf *out, struct shrinker *shrinker) }; unsigned long nr_freed = atomic_long_read(&shrinker->objects_freed); - seq_buf_puts(out, shrinker->name); seq_buf_putc(out, '\n'); |