diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2022-03-13 19:21:13 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2022-03-13 19:21:13 -0400 |
commit | 3765483ff0cf9abd0243fcafe11aebd0f9beb03d (patch) | |
tree | 232ba4c4c17b2c2579782b01422ae68994c9b5bf /libbcachefs/buckets.h | |
parent | d34e731082d8fcd710c2af6377a3b7fa927c8451 (diff) |
Update bcachefs sources to f05b3c1af9 bcachefs: Improve bucket_alloc_fail tracepointv0.19
Diffstat (limited to 'libbcachefs/buckets.h')
-rw-r--r-- | libbcachefs/buckets.h | 123 |
1 files changed, 42 insertions, 81 deletions
diff --git a/libbcachefs/buckets.h b/libbcachefs/buckets.h index 392e03d4..4a3d6bf1 100644 --- a/libbcachefs/buckets.h +++ b/libbcachefs/buckets.h @@ -15,52 +15,32 @@ for (_b = (_buckets)->b + (_buckets)->first_bucket; \ _b < (_buckets)->b + (_buckets)->nbuckets; _b++) -#define bucket_cmpxchg(g, new, expr) \ -({ \ - struct bucket *_g = g; \ - u64 _v = atomic64_read(&(g)->_mark.v); \ - struct bucket_mark _old; \ - \ - do { \ - (new).v.counter = _old.v.counter = _v; \ - expr; \ - } while ((_v = atomic64_cmpxchg(&(_g)->_mark.v, \ - _old.v.counter, \ - (new).v.counter)) != _old.v.counter);\ - _old; \ -}) - -static inline struct bucket_array *__bucket_array(struct bch_dev *ca, - bool gc) +static inline void bucket_unlock(struct bucket *b) { - return rcu_dereference_check(ca->buckets[gc], - !ca->fs || - percpu_rwsem_is_held(&ca->fs->mark_lock) || - lockdep_is_held(&ca->fs->gc_lock) || - lockdep_is_held(&ca->bucket_lock)); + smp_store_release(&b->lock, 0); } -static inline struct bucket_array *bucket_array(struct bch_dev *ca) +static inline void bucket_lock(struct bucket *b) { - return __bucket_array(ca, false); + while (xchg(&b->lock, 1)) + cpu_relax(); } -static inline struct bucket *__bucket(struct bch_dev *ca, size_t b, bool gc) +static inline struct bucket_array *gc_bucket_array(struct bch_dev *ca) { - struct bucket_array *buckets = __bucket_array(ca, gc); - - BUG_ON(b < buckets->first_bucket || b >= buckets->nbuckets); - return buckets->b + b; + return rcu_dereference_check(ca->buckets_gc, + !ca->fs || + percpu_rwsem_is_held(&ca->fs->mark_lock) || + lockdep_is_held(&ca->fs->gc_lock) || + lockdep_is_held(&ca->bucket_lock)); } static inline struct bucket *gc_bucket(struct bch_dev *ca, size_t b) { - return __bucket(ca, b, true); -} + struct bucket_array *buckets = gc_bucket_array(ca); -static inline struct bucket *bucket(struct bch_dev *ca, size_t b) -{ - return __bucket(ca, b, false); + BUG_ON(b < buckets->first_bucket || b >= buckets->nbuckets); + return buckets->b + b; } static inline struct bucket_gens *bucket_gens(struct bch_dev *ca) @@ -70,7 +50,6 @@ static inline struct bucket_gens *bucket_gens(struct bch_dev *ca) percpu_rwsem_is_held(&ca->fs->mark_lock) || lockdep_is_held(&ca->fs->gc_lock) || lockdep_is_held(&ca->bucket_lock)); - } static inline u8 *bucket_gen(struct bch_dev *ca, size_t b) @@ -81,16 +60,6 @@ static inline u8 *bucket_gen(struct bch_dev *ca, size_t b) return gens->b + b; } -/* - * bucket_gc_gen() returns the difference between the bucket's current gen and - * the oldest gen of any pointer into that bucket in the btree. - */ - -static inline u8 bucket_gc_gen(struct bucket *g) -{ - return g->mark.gen - g->oldest_gen; -} - static inline size_t PTR_BUCKET_NR(const struct bch_dev *ca, const struct bch_extent_ptr *ptr) { @@ -141,62 +110,55 @@ static inline u8 ptr_stale(struct bch_dev *ca, return ret; } -/* bucket gc marks */ - -static inline bool is_available_bucket(struct bucket_mark mark) -{ - return !mark.dirty_sectors && !mark.stripe; -} - /* Device usage: */ struct bch_dev_usage bch2_dev_usage_read(struct bch_dev *); static inline u64 __dev_buckets_available(struct bch_dev *ca, - struct bch_dev_usage stats) + struct bch_dev_usage stats, + enum alloc_reserve reserve) { - u64 total = ca->mi.nbuckets - ca->mi.first_bucket; + s64 total = ca->mi.nbuckets - ca->mi.first_bucket; + s64 reserved = 0; + + switch (reserve) { + case RESERVE_NONE: + reserved += ca->mi.nbuckets >> 6; + fallthrough; + case RESERVE_MOVINGGC: + reserved += ca->nr_btree_reserve; + fallthrough; + case RESERVE_BTREE: + reserved += ca->nr_btree_reserve; + fallthrough; + case RESERVE_BTREE_MOVINGGC: + break; + default: + BUG(); + } if (WARN_ONCE(stats.buckets_unavailable > total, "buckets_unavailable overflow (%llu > %llu)\n", stats.buckets_unavailable, total)) return 0; - return total - stats.buckets_unavailable; -} - -static inline u64 dev_buckets_available(struct bch_dev *ca) -{ - return __dev_buckets_available(ca, bch2_dev_usage_read(ca)); -} - -static inline u64 __dev_buckets_reclaimable(struct bch_dev *ca, - struct bch_dev_usage stats) -{ - struct bch_fs *c = ca->fs; - s64 available = __dev_buckets_available(ca, stats); - unsigned i; - - spin_lock(&c->freelist_lock); - for (i = 0; i < RESERVE_NR; i++) - available -= fifo_used(&ca->free[i]); - available -= fifo_used(&ca->free_inc); - available -= ca->nr_open_buckets; - spin_unlock(&c->freelist_lock); - - return max(available, 0LL); + return max_t(s64, 0, + total - + stats.buckets_unavailable - + ca->nr_open_buckets - + reserved); } -static inline u64 dev_buckets_reclaimable(struct bch_dev *ca) +static inline u64 dev_buckets_available(struct bch_dev *ca, + enum alloc_reserve reserve) { - return __dev_buckets_reclaimable(ca, bch2_dev_usage_read(ca)); + return __dev_buckets_available(ca, bch2_dev_usage_read(ca), reserve); } /* Filesystem usage: */ static inline unsigned fs_usage_u64s(struct bch_fs *c) { - return sizeof(struct bch_fs_usage) / sizeof(u64) + READ_ONCE(c->replicas.nr); } @@ -224,7 +186,6 @@ bch2_fs_usage_read_short(struct bch_fs *); void bch2_fs_usage_initialize(struct bch_fs *); -void bch2_mark_alloc_bucket(struct bch_fs *, struct bch_dev *, size_t, bool); void bch2_mark_metadata_bucket(struct bch_fs *, struct bch_dev *, size_t, enum bch_data_type, unsigned, struct gc_pos, unsigned); |