io-wq: fix max-workers not correctly set on multi-node system
authorBeld Zhang <beldzhang@gmail.com>
Tue, 2 Nov 2021 18:32:08 +0000 (12:32 -0600)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 18 Nov 2021 18:17:05 +0000 (19:17 +0100)
[ Upstream commit 71c9ce27bb57c59d8d7f5298e730c8096eef3d1f ]

In io-wq.c:io_wq_max_workers(), new_count[] was changed right after each
node's value was set. This caused the following node getting the setting
of the previous one.

Returned values are copied from node 0.

Fixes: 2e480058ddc2 ("io-wq: provide a way to limit max number of workers")
Signed-off-by: Beld Zhang <beldzhang@gmail.com>
[axboe: minor fixups]
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Sasha Levin <sashal@kernel.org>
fs/io-wq.c

index 5d189b24a8d4b121e4a6ecd3f7353cd68af0a10c..8c6131565754664f18704f24c1954f108342f1af 100644 (file)
@@ -1318,7 +1318,9 @@ int io_wq_cpu_affinity(struct io_wq *wq, cpumask_var_t mask)
  */
 int io_wq_max_workers(struct io_wq *wq, int *new_count)
 {
-       int i, node, prev = 0;
+       int prev[IO_WQ_ACCT_NR];
+       bool first_node = true;
+       int i, node;
 
        BUILD_BUG_ON((int) IO_WQ_ACCT_BOUND   != (int) IO_WQ_BOUND);
        BUILD_BUG_ON((int) IO_WQ_ACCT_UNBOUND != (int) IO_WQ_UNBOUND);
@@ -1329,6 +1331,9 @@ int io_wq_max_workers(struct io_wq *wq, int *new_count)
                        new_count[i] = task_rlimit(current, RLIMIT_NPROC);
        }
 
+       for (i = 0; i < IO_WQ_ACCT_NR; i++)
+               prev[i] = 0;
+
        rcu_read_lock();
        for_each_node(node) {
                struct io_wqe *wqe = wq->wqes[node];
@@ -1337,14 +1342,19 @@ int io_wq_max_workers(struct io_wq *wq, int *new_count)
                raw_spin_lock(&wqe->lock);
                for (i = 0; i < IO_WQ_ACCT_NR; i++) {
                        acct = &wqe->acct[i];
-                       prev = max_t(int, acct->max_workers, prev);
+                       if (first_node)
+                               prev[i] = max_t(int, acct->max_workers, prev[i]);
                        if (new_count[i])
                                acct->max_workers = new_count[i];
-                       new_count[i] = prev;
                }
                raw_spin_unlock(&wqe->lock);
+               first_node = false;
        }
        rcu_read_unlock();
+
+       for (i = 0; i < IO_WQ_ACCT_NR; i++)
+               new_count[i] = prev[i];
+
        return 0;
 }