Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ublk: check list membership before cancelling batch fetch command

Add !list_empty(&fcmd->node) check in ublk_batch_cancel_cmd() to ensure
the fcmd hasn't already been removed from the list. Once an fcmd is
removed from the list, it's considered claimed by whoever removed it
and will be freed by that path.

Meantime switch to list_del_init() for deleting it from list.

Signed-off-by: Ming Lei <ming.lei@redhat.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Ming Lei and committed by
Jens Axboe
66d3af8d 373df2c0

+13 -3
+13 -3
drivers/block/ublk_drv.c
··· 738 738 int res) 739 739 { 740 740 spin_lock(&ubq->evts_lock); 741 - list_del(&fcmd->node); 741 + list_del_init(&fcmd->node); 742 742 WARN_ON_ONCE(fcmd != ubq->active_fcmd); 743 743 __ublk_release_fcmd(ubq); 744 744 spin_unlock(&ubq->evts_lock); ··· 2693 2693 io_uring_cmd_done(io->cmd, UBLK_IO_RES_ABORT, issue_flags); 2694 2694 } 2695 2695 2696 + /* 2697 + * Cancel a batch fetch command if it hasn't been claimed by another path. 2698 + * 2699 + * An fcmd can only be cancelled if: 2700 + * 1. It's not the active_fcmd (which is currently being processed) 2701 + * 2. It's still on the list (!list_empty check) - once removed from the list, 2702 + * the fcmd is considered claimed and will be freed by whoever removed it 2703 + * 2704 + * Use list_del_init() so subsequent list_empty() checks work correctly. 2705 + */ 2696 2706 static void ublk_batch_cancel_cmd(struct ublk_queue *ubq, 2697 2707 struct ublk_batch_fetch_cmd *fcmd, 2698 2708 unsigned int issue_flags) ··· 2710 2700 bool done; 2711 2701 2712 2702 spin_lock(&ubq->evts_lock); 2713 - done = (READ_ONCE(ubq->active_fcmd) != fcmd); 2703 + done = (READ_ONCE(ubq->active_fcmd) != fcmd) && !list_empty(&fcmd->node); 2714 2704 if (done) 2715 - list_del(&fcmd->node); 2705 + list_del_init(&fcmd->node); 2716 2706 spin_unlock(&ubq->evts_lock); 2717 2707 2718 2708 if (done) {