]> git.sesse.net Git - bcachefs-tools-debian/blobdiff - libbcachefs/movinggc.c
Update bcachefs sources to c3e4d892b77b mean and variance: Promote to lib/math
[bcachefs-tools-debian] / libbcachefs / movinggc.c
index f73b9b7f4bf7ee111e586754d868e13c5fc1d0bb..794e4c56e5ea999f02cfa037bb6ac8f9f54a99e6 100644 (file)
@@ -91,7 +91,7 @@ static int bch2_bucket_is_movable(struct btree_trans *trans,
 
        a = bch2_alloc_to_v4(k, &_a);
        b->k.gen        = a->gen;
-       b->sectors      = a->dirty_sectors;
+       b->sectors      = bch2_bucket_sectors_dirty(*a);
 
        ret = data_type_movable(a->data_type) &&
                a->fragmentation_lru &&
@@ -128,7 +128,7 @@ static void move_buckets_wait(struct moving_context *ctxt,
                kfree(i);
        }
 
-       bch2_trans_unlock(ctxt->trans);
+       bch2_trans_unlock_long(ctxt->trans);
 }
 
 static bool bucket_in_flight(struct buckets_in_flight *list,
@@ -149,12 +149,16 @@ static int bch2_copygc_get_buckets(struct moving_context *ctxt,
        struct bkey_s_c k;
        size_t nr_to_get = max_t(size_t, 16U, buckets_in_flight->nr / 4);
        size_t saw = 0, in_flight = 0, not_movable = 0, sectors = 0;
+       struct bpos last_flushed_pos = POS_MIN;
        int ret;
 
        move_buckets_wait(ctxt, buckets_in_flight, false);
 
-       ret = bch2_btree_write_buffer_flush(trans);
-       if (bch2_fs_fatal_err_on(ret, c, "%s: error %s from bch2_btree_write_buffer_flush()",
+       ret = bch2_btree_write_buffer_tryflush(trans);
+       if (bch2_err_matches(ret, EROFS))
+               return ret;
+
+       if (bch2_fs_fatal_err_on(ret, c, "%s: error %s from bch2_btree_write_buffer_tryflush()",
                                 __func__, bch2_err_str(ret)))
                return ret;
 
@@ -162,11 +166,16 @@ static int bch2_copygc_get_buckets(struct moving_context *ctxt,
                                  lru_pos(BCH_LRU_FRAGMENTATION_START, 0, 0),
                                  lru_pos(BCH_LRU_FRAGMENTATION_START, U64_MAX, LRU_TIME_MAX),
                                  0, k, ({
-               struct move_bucket b = { .k.bucket = u64_to_bucket(k.k->p.offset) };
-               int ret2 = 0;
+               int ret2 = bch2_check_lru_key(trans, &iter, k, &last_flushed_pos);
+               if (ret2) {
+                       ret2 = ret2 < 0 ? ret2 : 0;
+                       goto next;
+               }
 
                saw++;
 
+               struct move_bucket b = { .k.bucket = u64_to_bucket(k.k->p.offset) };
+
                if (!bch2_bucket_is_movable(trans, &b, lru_pos_time(k.k->p)))
                        not_movable++;
                else if (bucket_in_flight(buckets_in_flight, b.k))
@@ -176,6 +185,7 @@ static int bch2_copygc_get_buckets(struct moving_context *ctxt,
                        if (ret2 >= 0)
                                sectors += b.sectors;
                }
+next:
                ret2;
        }));
 
@@ -188,7 +198,8 @@ static int bch2_copygc_get_buckets(struct moving_context *ctxt,
 
 noinline
 static int bch2_copygc(struct moving_context *ctxt,
-                      struct buckets_in_flight *buckets_in_flight)
+                      struct buckets_in_flight *buckets_in_flight,
+                      bool *did_work)
 {
        struct btree_trans *trans = ctxt->trans;
        struct bch_fs *c = trans->c;
@@ -206,7 +217,7 @@ static int bch2_copygc(struct moving_context *ctxt,
                goto err;
 
        darray_for_each(buckets, i) {
-               if (unlikely(freezing(current)))
+               if (kthread_should_stop() || freezing(current))
                        break;
 
                f = move_bucket_in_flight_add(buckets_in_flight, *i);
@@ -224,6 +235,8 @@ static int bch2_copygc(struct moving_context *ctxt,
                                             f->bucket.k.gen, data_opts);
                if (ret)
                        goto err;
+
+               *did_work = true;
        }
 err:
        darray_exit(&buckets);
@@ -302,14 +315,16 @@ static int bch2_copygc_thread(void *arg)
        struct moving_context ctxt;
        struct bch_move_stats move_stats;
        struct io_clock *clock = &c->io_clock[WRITE];
-       struct buckets_in_flight buckets;
+       struct buckets_in_flight *buckets;
        u64 last, wait;
        int ret = 0;
 
-       memset(&buckets, 0, sizeof(buckets));
-
-       ret = rhashtable_init(&buckets.table, &bch_move_bucket_params);
+       buckets = kzalloc(sizeof(struct buckets_in_flight), GFP_KERNEL);
+       if (!buckets)
+               return -ENOMEM;
+       ret = rhashtable_init(&buckets->table, &bch_move_bucket_params);
        if (ret) {
+               kfree(buckets);
                bch_err_msg(c, ret, "allocating copygc buckets in flight");
                return ret;
        }
@@ -322,16 +337,18 @@ static int bch2_copygc_thread(void *arg)
                              false);
 
        while (!ret && !kthread_should_stop()) {
-               bch2_trans_unlock(ctxt.trans);
+               bool did_work = false;
+
+               bch2_trans_unlock_long(ctxt.trans);
                cond_resched();
 
                if (!c->copy_gc_enabled) {
-                       move_buckets_wait(&ctxt, &buckets, true);
+                       move_buckets_wait(&ctxt, buckets, true);
                        kthread_wait_freezable(c->copy_gc_enabled);
                }
 
                if (unlikely(freezing(current))) {
-                       move_buckets_wait(&ctxt, &buckets, true);
+                       move_buckets_wait(&ctxt, buckets, true);
                        __refrigerator(false);
                        continue;
                }
@@ -342,7 +359,7 @@ static int bch2_copygc_thread(void *arg)
                if (wait > clock->max_slop) {
                        c->copygc_wait_at = last;
                        c->copygc_wait = last + wait;
-                       move_buckets_wait(&ctxt, &buckets, true);
+                       move_buckets_wait(&ctxt, buckets, true);
                        trace_and_count(c, copygc_wait, c, wait, last + wait);
                        bch2_kthread_io_clock_wait(clock, last + wait,
                                        MAX_SCHEDULE_TIMEOUT);
@@ -352,14 +369,27 @@ static int bch2_copygc_thread(void *arg)
                c->copygc_wait = 0;
 
                c->copygc_running = true;
-               ret = bch2_copygc(&ctxt, &buckets);
+               ret = bch2_copygc(&ctxt, buckets, &did_work);
                c->copygc_running = false;
 
                wake_up(&c->copygc_running_wq);
+
+               if (!wait && !did_work) {
+                       u64 min_member_capacity = bch2_min_rw_member_capacity(c);
+
+                       if (min_member_capacity == U64_MAX)
+                               min_member_capacity = 128 * 2048;
+
+                       bch2_trans_unlock_long(ctxt.trans);
+                       bch2_kthread_io_clock_wait(clock, last + (min_member_capacity >> 6),
+                                       MAX_SCHEDULE_TIMEOUT);
+               }
        }
 
-       move_buckets_wait(&ctxt, &buckets, true);
-       rhashtable_destroy(&buckets.table);
+       move_buckets_wait(&ctxt, buckets, true);
+
+       rhashtable_destroy(&buckets->table);
+       kfree(buckets);
        bch2_moving_ctxt_exit(&ctxt);
        bch2_move_stats_exit(&move_stats, c);