From: Bodo Stroesser Date: Tue, 17 May 2022 19:29:13 +0000 (+0200) Subject: scsi: target: tcmu: Avoid holding XArray lock when calling lock_page X-Git-Tag: v5.15.73~3762 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=ff876b6cf5785e9604cd407022db917734b5d7ad;p=platform%2Fkernel%2Flinux-rpi.git scsi: target: tcmu: Avoid holding XArray lock when calling lock_page [ Upstream commit 325d5c5fb216674296f3902a8902b942da3adc5b ] In tcmu_blocks_release(), lock_page() is called to prevent a race causing possible data corruption. Since lock_page() might sleep, calling it while holding XArray lock is a bug. To fix this, replace the xas_for_each() call with xa_for_each_range(). Since the latter does its own handling of XArray locking, the xas_lock() and xas_unlock() calls around the original loop are no longer necessary. The switch to xa_for_each_range() slows down the loop slightly. This is acceptable since tcmu_blocks_release() is not relevant for performance. Link: https://lore.kernel.org/r/20220517192913.21405-1-bostroesser@gmail.com Fixes: bb9b9eb0ae2e ("scsi: target: tcmu: Fix possible data corruption") Reported-by: Dan Carpenter Signed-off-by: Bodo Stroesser Signed-off-by: Martin K. Petersen Signed-off-by: Sasha Levin --- diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c index 0173f44..1e8e9dd 100644 --- a/drivers/target/target_core_user.c +++ b/drivers/target/target_core_user.c @@ -1661,13 +1661,14 @@ static int tcmu_check_and_free_pending_cmd(struct tcmu_cmd *cmd) static u32 tcmu_blocks_release(struct tcmu_dev *udev, unsigned long first, unsigned long last) { - XA_STATE(xas, &udev->data_pages, first * udev->data_pages_per_blk); struct page *page; + unsigned long dpi; u32 pages_freed = 0; - xas_lock(&xas); - xas_for_each(&xas, page, (last + 1) * udev->data_pages_per_blk - 1) { - xas_store(&xas, NULL); + first = first * udev->data_pages_per_blk; + last = (last + 1) * udev->data_pages_per_blk - 1; + xa_for_each_range(&udev->data_pages, dpi, page, first, last) { + xa_erase(&udev->data_pages, dpi); /* * While reaching here there may be page faults occurring on * the to-be-released pages. A race condition may occur if @@ -1691,7 +1692,6 @@ static u32 tcmu_blocks_release(struct tcmu_dev *udev, unsigned long first, __free_page(page); pages_freed++; } - xas_unlock(&xas); atomic_sub(pages_freed, &global_page_count);