]> git.sesse.net Git - bcachefs-tools-debian/blobdiff - libbcachefs/btree_write_buffer.c
Update bcachefs sources to c3e4d892b77b mean and variance: Promote to lib/math
[bcachefs-tools-debian] / libbcachefs / btree_write_buffer.c
index 6a19156804079d1a0538e2cba7e0f8a50ba0fdb8..6ab26576252c17edc603ad42438e7a9ebd9b4181 100644 (file)
@@ -33,17 +33,32 @@ static int btree_write_buffered_journal_cmp(const void *_l, const void *_r)
        return  cmp_int(l->journal_seq, r->journal_seq);
 }
 
-static int bch2_btree_write_buffer_flush_one(struct btree_trans *trans,
-                                            struct btree_iter *iter,
-                                            struct btree_write_buffered_key *wb,
-                                            unsigned commit_flags,
-                                            bool *write_locked,
-                                            size_t *fast)
+static noinline int wb_flush_one_slowpath(struct btree_trans *trans,
+                                         struct btree_iter *iter,
+                                         struct btree_write_buffered_key *wb)
+{
+       bch2_btree_node_unlock_write(trans, iter->path, iter->path->l[0].b);
+
+       trans->journal_res.seq = wb->journal_seq;
+
+       return bch2_trans_update(trans, iter, &wb->k,
+                                BTREE_UPDATE_INTERNAL_SNAPSHOT_NODE) ?:
+               bch2_trans_commit(trans, NULL, NULL,
+                                 BCH_TRANS_COMMIT_no_enospc|
+                                 BCH_TRANS_COMMIT_no_check_rw|
+                                 BCH_TRANS_COMMIT_no_journal_res|
+                                 BCH_TRANS_COMMIT_journal_reclaim);
+}
+
+static inline int wb_flush_one(struct btree_trans *trans, struct btree_iter *iter,
+                              struct btree_write_buffered_key *wb,
+                              bool *write_locked, size_t *fast)
 {
        struct bch_fs *c = trans->c;
        struct btree_path *path;
        int ret;
 
+       EBUG_ON(!wb->journal_seq);
        ret = bch2_btree_iter_traverse(iter);
        if (ret)
                return ret;
@@ -66,26 +81,14 @@ static int bch2_btree_write_buffer_flush_one(struct btree_trans *trans,
                *write_locked = true;
        }
 
-       if (!bch2_btree_node_insert_fits(c, path->l[0].b, wb->k.k.u64s)) {
-               bch2_btree_node_unlock_write(trans, path, path->l[0].b);
+       if (unlikely(!bch2_btree_node_insert_fits(c, path->l[0].b, wb->k.k.u64s))) {
                *write_locked = false;
-               goto trans_commit;
+               return wb_flush_one_slowpath(trans, iter, wb);
        }
 
        bch2_btree_insert_key_leaf(trans, path, &wb->k, wb->journal_seq);
        (*fast)++;
        return 0;
-trans_commit:
-       trans->journal_res.seq = wb->journal_seq;
-
-       return  bch2_trans_update(trans, iter, &wb->k,
-                                 BTREE_UPDATE_INTERNAL_SNAPSHOT_NODE) ?:
-               bch2_trans_commit(trans, NULL, NULL,
-                                 commit_flags|
-                                 BCH_TRANS_COMMIT_no_check_rw|
-                                 BCH_TRANS_COMMIT_no_enospc|
-                                 BCH_TRANS_COMMIT_no_journal_res|
-                                 BCH_TRANS_COMMIT_journal_reclaim);
 }
 
 static union btree_write_buffer_state btree_write_buffer_switch(struct btree_write_buffer *wb)
@@ -160,9 +163,6 @@ int bch2_btree_write_buffer_flush_locked(struct btree_trans *trans)
        keys = wb->keys[s.idx];
        nr = s.nr;
 
-       if (race_fault())
-               goto slowpath;
-
        /*
         * We first sort so that we can detect and skip redundant updates, and
         * then we attempt to flush in sorted btree order, as this is most
@@ -206,66 +206,68 @@ int bch2_btree_write_buffer_flush_locked(struct btree_trans *trans)
                iter.path->preserve = false;
 
                do {
-                       ret = bch2_btree_write_buffer_flush_one(trans, &iter, i, 0,
-                                                               &write_locked, &fast);
+                       if (race_fault()) {
+                               ret = -BCH_ERR_journal_reclaim_would_deadlock;
+                               break;
+                       }
+
+                       ret = wb_flush_one(trans, &iter, i, &write_locked, &fast);
                        if (!write_locked)
                                bch2_trans_begin(trans);
                } while (bch2_err_matches(ret, BCH_ERR_transaction_restart));
 
-               if (ret == -BCH_ERR_journal_reclaim_would_deadlock) {
+               if (!ret) {
+                       i->journal_seq = 0;
+               } else if (ret == -BCH_ERR_journal_reclaim_would_deadlock) {
                        slowpath++;
-                       continue;
-               }
-               if (ret)
+                       ret = 0;
+               } else
                        break;
-
-               i->journal_seq = 0;
        }
 
        if (write_locked)
                bch2_btree_node_unlock_write(trans, iter.path, iter.path->l[0].b);
        bch2_trans_iter_exit(trans, &iter);
 
-       trace_write_buffer_flush(trans, nr, skipped, fast, wb->size);
-
-       if (slowpath)
-               goto slowpath;
-
+       if (ret)
+               goto err;
+
+       if (slowpath) {
+               /*
+                * Flush in the order they were present in the journal, so that
+                * we can release journal pins:
+                * The fastpath zapped the seq of keys that were successfully flushed so
+                * we can skip those here.
+                */
+               trace_and_count(c, write_buffer_flush_slowpath, trans, slowpath, nr);
+
+               sort(keys, nr, sizeof(keys[0]),
+                    btree_write_buffered_journal_cmp,
+                    NULL);
+
+               for (i = keys; i < keys + nr; i++) {
+                       if (!i->journal_seq)
+                               continue;
+
+                       bch2_journal_pin_update(j, i->journal_seq, &pin,
+                                     bch2_btree_write_buffer_journal_flush);
+
+                       ret = commit_do(trans, NULL, NULL,
+                                       BCH_WATERMARK_reclaim|
+                                       BCH_TRANS_COMMIT_no_check_rw|
+                                       BCH_TRANS_COMMIT_no_enospc|
+                                       BCH_TRANS_COMMIT_no_journal_res|
+                                       BCH_TRANS_COMMIT_journal_reclaim,
+                                       btree_write_buffered_insert(trans, i));
+                       if (ret)
+                               goto err;
+               }
+       }
+err:
        bch2_fs_fatal_err_on(ret, c, "%s: insert error %s", __func__, bch2_err_str(ret));
-out:
+       trace_write_buffer_flush(trans, nr, skipped, fast, wb->size);
        bch2_journal_pin_drop(j, &pin);
        return ret;
-slowpath:
-       trace_and_count(c, write_buffer_flush_slowpath, trans, slowpath, nr);
-
-       /*
-        * Now sort the rest by journal seq and bump the journal pin as we go.
-        * The slowpath zapped the seq of keys that were successfully flushed so
-        * we can skip those here.
-        */
-       sort(keys, nr, sizeof(keys[0]),
-            btree_write_buffered_journal_cmp,
-            NULL);
-
-       for (i = keys; i < keys + nr; i++) {
-               if (!i->journal_seq)
-                       continue;
-
-               bch2_journal_pin_update(j, i->journal_seq, &pin,
-                             bch2_btree_write_buffer_journal_flush);
-
-               ret = commit_do(trans, NULL, NULL,
-                               BCH_WATERMARK_reclaim|
-                               BCH_TRANS_COMMIT_no_check_rw|
-                               BCH_TRANS_COMMIT_no_enospc|
-                               BCH_TRANS_COMMIT_no_journal_res|
-                               BCH_TRANS_COMMIT_journal_reclaim,
-                               btree_write_buffered_insert(trans, i));
-               if (bch2_fs_fatal_err_on(ret, c, "%s: insert error %s", __func__, bch2_err_str(ret)))
-                       break;
-       }
-
-       goto out;
 }
 
 int bch2_btree_write_buffer_flush_sync(struct btree_trans *trans)