bcache: improve multithreaded bch_sectors_dirty_init()
[platform/kernel/linux-starfive.git] / drivers / md / bcache / btree.c
index ad9f166..2362bb8 100644 (file)
@@ -2006,8 +2006,7 @@ int bch_btree_check(struct cache_set *c)
        int i;
        struct bkey *k = NULL;
        struct btree_iter iter;
-       struct btree_check_state *check_state;
-       char name[32];
+       struct btree_check_state check_state;
 
        /* check and mark root node keys */
        for_each_key_filter(&c->root->keys, k, &iter, bch_ptr_invalid)
@@ -2018,63 +2017,58 @@ int bch_btree_check(struct cache_set *c)
        if (c->root->level == 0)
                return 0;
 
-       check_state = kzalloc(sizeof(struct btree_check_state), GFP_KERNEL);
-       if (!check_state)
-               return -ENOMEM;
-
-       check_state->c = c;
-       check_state->total_threads = bch_btree_chkthread_nr();
-       check_state->key_idx = 0;
-       spin_lock_init(&check_state->idx_lock);
-       atomic_set(&check_state->started, 0);
-       atomic_set(&check_state->enough, 0);
-       init_waitqueue_head(&check_state->wait);
+       check_state.c = c;
+       check_state.total_threads = bch_btree_chkthread_nr();
+       check_state.key_idx = 0;
+       spin_lock_init(&check_state.idx_lock);
+       atomic_set(&check_state.started, 0);
+       atomic_set(&check_state.enough, 0);
+       init_waitqueue_head(&check_state.wait);
 
+       rw_lock(0, c->root, c->root->level);
        /*
         * Run multiple threads to check btree nodes in parallel,
-        * if check_state->enough is non-zero, it means current
+        * if check_state.enough is non-zero, it means current
         * running check threads are enough, unncessary to create
         * more.
         */
-       for (i = 0; i < check_state->total_threads; i++) {
-               /* fetch latest check_state->enough earlier */
+       for (i = 0; i < check_state.total_threads; i++) {
+               /* fetch latest check_state.enough earlier */
                smp_mb__before_atomic();
-               if (atomic_read(&check_state->enough))
+               if (atomic_read(&check_state.enough))
                        break;
 
-               check_state->infos[i].result = 0;
-               check_state->infos[i].state = check_state;
-               snprintf(name, sizeof(name), "bch_btrchk[%u]", i);
-               atomic_inc(&check_state->started);
+               check_state.infos[i].result = 0;
+               check_state.infos[i].state = &check_state;
 
-               check_state->infos[i].thread =
+               check_state.infos[i].thread =
                        kthread_run(bch_btree_check_thread,
-                                   &check_state->infos[i],
-                                   name);
-               if (IS_ERR(check_state->infos[i].thread)) {
+                                   &check_state.infos[i],
+                                   "bch_btrchk[%d]", i);
+               if (IS_ERR(check_state.infos[i].thread)) {
                        pr_err("fails to run thread bch_btrchk[%d]\n", i);
                        for (--i; i >= 0; i--)
-                               kthread_stop(check_state->infos[i].thread);
+                               kthread_stop(check_state.infos[i].thread);
                        ret = -ENOMEM;
                        goto out;
                }
+               atomic_inc(&check_state.started);
        }
 
        /*
         * Must wait for all threads to stop.
         */
-       wait_event_interruptible(check_state->wait,
-                                atomic_read(&check_state->started) == 0);
+       wait_event(check_state.wait, atomic_read(&check_state.started) == 0);
 
-       for (i = 0; i < check_state->total_threads; i++) {
-               if (check_state->infos[i].result) {
-                       ret = check_state->infos[i].result;
+       for (i = 0; i < check_state.total_threads; i++) {
+               if (check_state.infos[i].result) {
+                       ret = check_state.infos[i].result;
                        goto out;
                }
        }
 
 out:
-       kfree(check_state);
+       rw_unlock(0, c->root);
        return ret;
 }