ublk_drv: check 'current' instead of 'ubq_daemon'
authorZiyangZhang <ZiyangZhang@linux.alibaba.com>
Fri, 23 Sep 2022 15:39:13 +0000 (23:39 +0800)
committerJens Axboe <axboe@kernel.dk>
Sat, 24 Sep 2022 01:09:56 +0000 (19:09 -0600)
This check is not atomic. So with recovery feature, ubq_daemon may be
modified simultaneously by recovery task. Instead, check 'current' is
safe here because 'current' never changes.

Also add comment explaining this check, which is really important for
understanding recovery feature.

Signed-off-by: ZiyangZhang <ZiyangZhang@linux.alibaba.com>
Reviewed-by: Ming Lei <ming.lei@redhat.com>
Link: https://lore.kernel.org/r/20220923153919.44078-2-ZiyangZhang@linux.alibaba.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
drivers/block/ublk_drv.c

index 6a4a94b4cdf42fa1d56d79d28d73c53aef941391..c39b67d7133d524d2b85a6c639349a16903a9128 100644 (file)
@@ -645,14 +645,22 @@ static inline void __ublk_rq_task_work(struct request *req)
        struct ublk_device *ub = ubq->dev;
        int tag = req->tag;
        struct ublk_io *io = &ubq->ios[tag];
-       bool task_exiting = current != ubq->ubq_daemon || ubq_daemon_is_dying(ubq);
        unsigned int mapped_bytes;
 
        pr_devel("%s: complete: op %d, qid %d tag %d io_flags %x addr %llx\n",
                        __func__, io->cmd->cmd_op, ubq->q_id, req->tag, io->flags,
                        ublk_get_iod(ubq, req->tag)->addr);
 
-       if (unlikely(task_exiting)) {
+       /*
+        * Task is exiting if either:
+        *
+        * (1) current != ubq_daemon.
+        * io_uring_cmd_complete_in_task() tries to run task_work
+        * in a workqueue if ubq_daemon(cmd's task) is PF_EXITING.
+        *
+        * (2) current->flags & PF_EXITING.
+        */
+       if (unlikely(current != ubq->ubq_daemon || current->flags & PF_EXITING)) {
                blk_mq_end_request(req, BLK_STS_IOERR);
                mod_delayed_work(system_wq, &ub->monitor_work, 0);
                return;