On 8/29/21 9:06 PM, Hao Xu wrote: > 在 2021/8/30 上午6:19, Jens Axboe 写道: >> For the two places where new workers are created, we diligently check if >> we are allowed to create a new worker. If we're currently at the limit >> of how many workers of a given type we can have, then we don't create >> any new ones. >> >> If you have a mixed workload with various types of bound and unbounded >> work, then it can happen that a worker finishes one type of work and >> is then transitioned to the other type. For this case, we don't check >> if we are actually allowed to do so. This can cause io-wq to temporarily >> exceed the allowed number of workers for a given type. >> >> When retrieving work, check that the types match. If they don't, check >> if we are allowed to transition to the other type. If not, then don't >> handle the new work. >> >> Cc: stable@xxxxxxxxxxxxxxx >> Reported-by: Johannes Lundberg <johalun0@xxxxxxxxx> >> Signed-off-by: Jens Axboe <axboe@xxxxxxxxx> >> >> --- >> >> diff --git a/fs/io-wq.c b/fs/io-wq.c >> index 4b5fc621ab39..dced22288983 100644 >> --- a/fs/io-wq.c >> +++ b/fs/io-wq.c >> @@ -424,7 +424,31 @@ static void io_wait_on_hash(struct io_wqe *wqe, unsigned int hash) >> spin_unlock(&wq->hash->wait.lock); >> } >> >> -static struct io_wq_work *io_get_next_work(struct io_wqe *wqe) >> +/* >> + * We can always run the work if the worker is currently the same type as >> + * the work (eg both are bound, or both are unbound). If they are not the >> + * same, only allow it if incrementing the worker count would be allowed. >> + */ >> +static bool io_worker_can_run_work(struct io_worker *worker, >> + struct io_wq_work *work) >> +{ >> + struct io_wqe_acct *acct; >> + >> + if ((worker->flags & IO_WORKER_F_BOUND) && >> + !(work->flags & IO_WQ_WORK_UNBOUND)) >> + return true; >> + else if (!(worker->flags & IO_WORKER_F_BOUND) && >> + (work->flags & IO_WQ_WORK_UNBOUND)) >> + return true; > > How about: > bool a = !(worker->flags & IO_WORKER_F_BOUND); > bool b = !(work->flags & IO_WQ_WORK_UNBOUND); > > if (a != b) > return true; Yeah good point, I'll change it to be: if (!(worker->flags & IO_WORKER_F_BOUND) != !(work->flags & IO_WQ_WORK_UNBOUND)) return 1; return acct->nr_workers < acct->max_workers; -- Jens Axboe