]> git.sesse.net Git - bcachefs-tools-debian/blobdiff - libbcachefs/alloc_foreground.c
Merge https://github.com/fougner/bcachefs-tools
[bcachefs-tools-debian] / libbcachefs / alloc_foreground.c
index c4f971c12a5100175a81da9bf0eef2dac3dc7166..f1cfb90b6d54c9cd6f5088cdbf9b11471ba1b06b 100644 (file)
@@ -28,6 +28,7 @@
 #include "io.h"
 #include "journal.h"
 #include "movinggc.h"
+#include "nocow_locking.h"
 
 #include <linux/math64.h>
 #include <linux/rculist.h>
@@ -194,7 +195,7 @@ static inline unsigned open_buckets_reserved(enum alloc_reserve reserve)
 static struct open_bucket *__try_alloc_bucket(struct bch_fs *c, struct bch_dev *ca,
                                              u64 bucket,
                                              enum alloc_reserve reserve,
-                                             struct bch_alloc_v4 *a,
+                                             const struct bch_alloc_v4 *a,
                                              struct bucket_alloc_state *s,
                                              struct closure *cl)
 {
@@ -285,7 +286,8 @@ static struct open_bucket *try_alloc_bucket(struct btree_trans *trans, struct bc
        struct btree_iter iter = { NULL };
        struct bkey_s_c k;
        struct open_bucket *ob;
-       struct bch_alloc_v4 a;
+       struct bch_alloc_v4 a_convert;
+       const struct bch_alloc_v4 *a;
        u64 b = free_entry & ~(~0ULL << 56);
        unsigned genbits = free_entry >> 56;
        struct printbuf buf = PRINTBUF;
@@ -309,30 +311,36 @@ static struct open_bucket *try_alloc_bucket(struct btree_trans *trans, struct bc
                goto err;
        }
 
-       bch2_alloc_to_v4(k, &a);
+       a = bch2_alloc_to_v4(k, &a_convert);
 
-       if (genbits != (alloc_freespace_genbits(a) >> 56)) {
-               prt_printf(&buf, "bucket in freespace btree with wrong genbits (got %u should be %llu)\n"
-                      "  freespace key ",
-                      genbits, alloc_freespace_genbits(a) >> 56);
+       if (a->data_type != BCH_DATA_free) {
+               if (!test_bit(BCH_FS_CHECK_ALLOC_DONE, &c->flags)) {
+                       ob = NULL;
+                       goto err;
+               }
+
+               prt_printf(&buf, "non free bucket in freespace btree\n"
+                      "  freespace key ");
                bch2_bkey_val_to_text(&buf, c, freespace_k);
                prt_printf(&buf, "\n  ");
                bch2_bkey_val_to_text(&buf, c, k);
                bch2_trans_inconsistent(trans, "%s", buf.buf);
                ob = ERR_PTR(-EIO);
                goto err;
-
        }
 
-       if (a.data_type != BCH_DATA_free) {
-               prt_printf(&buf, "non free bucket in freespace btree\n"
-                      "  freespace key ");
+       if (genbits != (alloc_freespace_genbits(*a) >> 56) &&
+           test_bit(BCH_FS_CHECK_ALLOC_DONE, &c->flags)) {
+               prt_printf(&buf, "bucket in freespace btree with wrong genbits (got %u should be %llu)\n"
+                      "  freespace key ",
+                      genbits, alloc_freespace_genbits(*a) >> 56);
                bch2_bkey_val_to_text(&buf, c, freespace_k);
                prt_printf(&buf, "\n  ");
                bch2_bkey_val_to_text(&buf, c, k);
                bch2_trans_inconsistent(trans, "%s", buf.buf);
                ob = ERR_PTR(-EIO);
                goto err;
+
        }
 
        if (!test_bit(BCH_FS_CHECK_BACKPOINTERS_DONE, &c->flags)) {
@@ -358,7 +366,7 @@ static struct open_bucket *try_alloc_bucket(struct btree_trans *trans, struct bc
                }
        }
 
-       ob = __try_alloc_bucket(c, ca, b, reserve, &a, s, cl);
+       ob = __try_alloc_bucket(c, ca, b, reserve, a, s, cl);
        if (!ob)
                iter.path->preserve = false;
 err:
@@ -417,23 +425,24 @@ bch2_bucket_alloc_early(struct btree_trans *trans,
 
        for_each_btree_key_norestart(trans, iter, BTREE_ID_alloc, POS(ca->dev_idx, s->cur_bucket),
                           BTREE_ITER_SLOTS, k, ret) {
-               struct bch_alloc_v4 a;
+               struct bch_alloc_v4 a_convert;
+               const struct bch_alloc_v4 *a;
 
-               if (bkey_cmp(k.k->p, POS(ca->dev_idx, ca->mi.nbuckets)) >= 0)
+               if (bkey_ge(k.k->p, POS(ca->dev_idx, ca->mi.nbuckets)))
                        break;
 
                if (ca->new_fs_bucket_idx &&
                    is_superblock_bucket(ca, k.k->p.offset))
                        continue;
 
-               bch2_alloc_to_v4(k, &a);
+               a = bch2_alloc_to_v4(k, &a_convert);
 
-               if (a.data_type != BCH_DATA_free)
+               if (a->data_type != BCH_DATA_free)
                        continue;
 
                s->buckets_seen++;
 
-               ob = __try_alloc_bucket(trans->c, ca, k.k->p.offset, reserve, &a, s, cl);
+               ob = __try_alloc_bucket(trans->c, ca, k.k->p.offset, reserve, a, s, cl);
                if (ob)
                        break;
        }
@@ -504,8 +513,8 @@ static struct open_bucket *bch2_bucket_alloc_trans(struct btree_trans *trans,
 {
        struct bch_fs *c = trans->c;
        struct open_bucket *ob = NULL;
-       bool freespace_initialized = READ_ONCE(ca->mi.freespace_initialized);
-       u64 start = freespace_initialized ? 0 : ca->bucket_alloc_trans_early_cursor;
+       bool freespace = READ_ONCE(ca->mi.freespace_initialized);
+       u64 start = freespace ? 0 : ca->bucket_alloc_trans_early_cursor;
        u64 avail;
        struct bucket_alloc_state s = { .cur_bucket = start };
        bool waiting = false;
@@ -544,20 +553,25 @@ again:
                if (ob)
                        return ob;
        }
-
-       ob = likely(ca->mi.freespace_initialized)
+alloc:
+       ob = likely(freespace)
                ? bch2_bucket_alloc_freelist(trans, ca, reserve, &s, cl)
                : bch2_bucket_alloc_early(trans, ca, reserve, &s, cl);
 
        if (s.skipped_need_journal_commit * 2 > avail)
                bch2_journal_flush_async(&c->journal, NULL);
 
-       if (!ob && !freespace_initialized && start) {
+       if (!ob && !freespace && start) {
                start = s.cur_bucket = 0;
-               goto again;
+               goto alloc;
        }
 
-       if (!freespace_initialized)
+       if (!ob && freespace && !test_bit(BCH_FS_CHECK_ALLOC_DONE, &c->flags)) {
+               freespace = false;
+               goto alloc;
+       }
+
+       if (!freespace)
                ca->bucket_alloc_trans_early_cursor = s.cur_bucket;
 err:
        if (!ob)
@@ -1222,12 +1236,9 @@ err:
        if (bch2_err_matches(ret, BCH_ERR_open_buckets_empty) ||
            bch2_err_matches(ret, BCH_ERR_freelist_empty))
                return cl
-                       ? -EAGAIN
+                       ? -BCH_ERR_bucket_alloc_blocked
                        : -BCH_ERR_ENOSPC_bucket_alloc;
 
-       if (bch2_err_matches(ret, BCH_ERR_insufficient_devices))
-               return -EROFS;
-
        return ret;
 }
 
@@ -1245,34 +1256,11 @@ struct bch_extent_ptr bch2_ob_ptr(struct bch_fs *c, struct open_bucket *ob)
        };
 }
 
-/*
- * Append pointers to the space we just allocated to @k, and mark @sectors space
- * as allocated out of @ob
- */
 void bch2_alloc_sectors_append_ptrs(struct bch_fs *c, struct write_point *wp,
                                    struct bkey_i *k, unsigned sectors,
                                    bool cached)
-
 {
-       struct open_bucket *ob;
-       unsigned i;
-
-       BUG_ON(sectors > wp->sectors_free);
-       wp->sectors_free -= sectors;
-
-       open_bucket_for_each(c, &wp->ptrs, ob, i) {
-               struct bch_dev *ca = bch_dev_bkey_exists(c, ob->dev);
-               struct bch_extent_ptr ptr = bch2_ob_ptr(c, ob);
-
-               ptr.cached = cached ||
-                       (!ca->mi.durability &&
-                        wp->data_type == BCH_DATA_user);
-
-               bch2_bkey_append_ptr(k, ptr);
-
-               BUG_ON(sectors > ob->sectors_free);
-               ob->sectors_free -= sectors;
-       }
+       bch2_alloc_sectors_append_ptrs_inlined(c, wp, k, sectors, cached);
 }
 
 /*
@@ -1281,17 +1269,7 @@ void bch2_alloc_sectors_append_ptrs(struct bch_fs *c, struct write_point *wp,
  */
 void bch2_alloc_sectors_done(struct bch_fs *c, struct write_point *wp)
 {
-       struct open_buckets ptrs = { .nr = 0 }, keep = { .nr = 0 };
-       struct open_bucket *ob;
-       unsigned i;
-
-       open_bucket_for_each(c, &wp->ptrs, ob, i)
-               ob_push(c, !ob->sectors_free ? &ptrs : &keep, ob);
-       wp->ptrs = keep;
-
-       mutex_unlock(&wp->lock);
-
-       bch2_open_buckets_put(c, &ptrs);
+       bch2_alloc_sectors_done_inlined(c, wp);
 }
 
 static inline void writepoint_init(struct write_point *wp,