]> git.sesse.net Git - bcachefs-tools-debian/blobdiff - libbcachefs/nocow_locking.c
New upstream release
[bcachefs-tools-debian] / libbcachefs / nocow_locking.c
index 396357cd8f2fe715c278bfe486799e6fe039e335..3c21981a4a1c09f9c70596876ef71fdef72cddcb 100644 (file)
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 
 #include "bcachefs.h"
+#include "bkey_methods.h"
 #include "nocow_locking.h"
 #include "util.h"
 
@@ -29,9 +30,10 @@ void bch2_bucket_nocow_unlock(struct bucket_nocow_lock_table *t, struct bpos buc
 
        for (i = 0; i < ARRAY_SIZE(l->b); i++)
                if (l->b[i] == dev_bucket) {
-                       BUG_ON(sign(atomic_read(&l->l[i])) != lock_val);
+                       int v = atomic_sub_return(lock_val, &l->l[i]);
 
-                       if (!atomic_sub_return(lock_val, &l->l[i]))
+                       BUG_ON(v && sign(v) != lock_val);
+                       if (!v)
                                closure_wake_up(&l->wait);
                        return;
                }
@@ -64,6 +66,11 @@ got_entry:
        if (lock_val > 0 ? v < 0 : v > 0)
                goto fail;
 take_lock:
+       v = atomic_read(&l->l[i]);
+       /* Overflow? */
+       if (v && sign(v + lock_val) != sign(v))
+               goto fail;
+
        atomic_add(lock_val, &l->l[i]);
        spin_unlock(&l->lock);
        return true;
@@ -83,6 +90,7 @@ void __bch2_bucket_nocow_lock(struct bucket_nocow_lock_table *t,
 }
 
 void bch2_nocow_locks_to_text(struct printbuf *out, struct bucket_nocow_lock_table *t)
+
 {
        unsigned i, nr_zero = 0;
        struct nocow_lock_bucket *l;
@@ -102,9 +110,13 @@ void bch2_nocow_locks_to_text(struct printbuf *out, struct bucket_nocow_lock_tab
                        prt_printf(out, "(%u empty entries)\n", nr_zero);
                nr_zero = 0;
 
-               for (i = 0; i < ARRAY_SIZE(l->l); i++)
-                       if (atomic_read(&l->l[i]))
-                               prt_printf(out, "%llu: %i ", l->b[i], atomic_read(&l->l[i]));
+               for (i = 0; i < ARRAY_SIZE(l->l); i++) {
+                       int v = atomic_read(&l->l[i]);
+                       if (v) {
+                               bch2_bpos_to_text(out, u64_to_bucket(l->b[i]));
+                               prt_printf(out, ": %s %u ", v < 0 ? "copy" : "update", abs(v));
+                       }
+               }
                prt_newline(out);
        }
 
@@ -112,12 +124,21 @@ void bch2_nocow_locks_to_text(struct printbuf *out, struct bucket_nocow_lock_tab
                prt_printf(out, "(%u empty entries)\n", nr_zero);
 }
 
+void bch2_fs_nocow_locking_exit(struct bch_fs *c)
+{
+       struct bucket_nocow_lock_table *t = &c->nocow_locks;
+
+       for (struct nocow_lock_bucket *l = t->l; l < t->l + ARRAY_SIZE(t->l); l++)
+               for (unsigned j = 0; j < ARRAY_SIZE(l->l); j++)
+                       BUG_ON(atomic_read(&l->l[j]));
+}
+
 int bch2_fs_nocow_locking_init(struct bch_fs *c)
 {
-       unsigned i;
+       struct bucket_nocow_lock_table *t = &c->nocow_locks;
 
-       for (i = 0; i < ARRAY_SIZE(c->nocow_locks.l); i++)
-               spin_lock_init(&c->nocow_locks.l[i].lock);
+       for (struct nocow_lock_bucket *l = t->l; l < t->l + ARRAY_SIZE(t->l); l++)
+               spin_lock_init(&l->lock);
 
        return 0;
 }