1 // SPDX-License-Identifier: GPL-2.0
4 #include "nocow_locking.h"
7 #include <linux/closure.h>
9 bool bch2_bucket_nocow_is_locked(struct bucket_nocow_lock_table *t, struct bpos bucket)
11 u64 dev_bucket = bucket_to_u64(bucket);
12 struct nocow_lock_bucket *l = bucket_nocow_lock(t, dev_bucket);
15 for (i = 0; i < ARRAY_SIZE(l->b); i++)
16 if (l->b[i] == dev_bucket && atomic_read(&l->l[i]))
21 void bch2_bucket_nocow_unlock(struct bucket_nocow_lock_table *t, struct bpos bucket, int flags)
23 u64 dev_bucket = bucket_to_u64(bucket);
24 struct nocow_lock_bucket *l = bucket_nocow_lock(t, dev_bucket);
25 int lock_val = flags ? 1 : -1;
28 for (i = 0; i < ARRAY_SIZE(l->b); i++)
29 if (l->b[i] == dev_bucket) {
30 if (!atomic_sub_return(lock_val, &l->l[i]))
31 closure_wake_up(&l->wait);
38 static bool bch2_bucket_nocow_trylock(struct nocow_lock_bucket *l,
39 u64 dev_bucket, int flags)
41 int v, lock_val = flags ? 1 : -1;
46 for (i = 0; i < ARRAY_SIZE(l->b); i++)
47 if (l->b[i] == dev_bucket)
50 for (i = 0; i < ARRAY_SIZE(l->b); i++)
51 if (!atomic_read(&l->l[i])) {
56 spin_unlock(&l->lock);
59 v = atomic_read(&l->l[i]);
60 if (lock_val > 0 ? v < 0 : v > 0)
63 atomic_add(lock_val, &l->l[i]);
64 spin_unlock(&l->lock);
68 void __bch2_bucket_nocow_lock(struct bucket_nocow_lock_table *t,
69 struct nocow_lock_bucket *l,
70 u64 dev_bucket, int flags)
72 if (!bch2_bucket_nocow_trylock(l, dev_bucket, flags)) {
73 struct bch_fs *c = container_of(t, struct bch_fs, nocow_locks);
74 u64 start_time = local_clock();
76 __closure_wait_event(&l->wait, bch2_bucket_nocow_trylock(l, dev_bucket, flags));
77 bch2_time_stats_update(&c->times[BCH_TIME_nocow_lock_contended], start_time);
81 void bch2_nocow_locks_to_text(struct printbuf *out, struct bucket_nocow_lock_table *t)
83 unsigned i, nr_zero = 0;
84 struct nocow_lock_bucket *l;
86 for (l = t->l; l < t->l + ARRAY_SIZE(t->l); l++) {
89 for (i = 0; i < ARRAY_SIZE(l->l); i++)
90 v |= atomic_read(&l->l[i]);
98 prt_printf(out, "(%u empty entries)\n", nr_zero);
101 for (i = 0; i < ARRAY_SIZE(l->l); i++)
102 if (atomic_read(&l->l[i]))
103 prt_printf(out, "%llu: %i ", l->b[i], atomic_read(&l->l[i]));
108 prt_printf(out, "(%u empty entries)\n", nr_zero);
111 int bch2_fs_nocow_locking_init(struct bch_fs *c)
115 for (i = 0; i < ARRAY_SIZE(c->nocow_locks.l); i++)
116 spin_lock_init(&c->nocow_locks.l[i].lock);