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.

block: fix partial IOVA mapping cleanup in blk_rq_dma_map_iova

When dma_iova_link() fails partway through mapping a request's bvec
list, the function breaks out of the loop without cleaning up
already mapped segments. Similarly, if dma_iova_sync() fails after
linking all segments, no cleanup is performed.

This leaves partial IOVA mappings in place. The completion path
attempts to unmap the full expected size via dma_iova_destroy() or
nvme_unmap_data(), but only a partial size was actually mapped,
leading to incorrect unmap operations.

Add an out_unlink error path that calls dma_iova_destroy() to clean
up partial mappings before returning failure. The dma_iova_destroy()
function handles both partial unlink and IOVA space freeing. It
correctly handles the mapped_len == 0 case (first dma_iova_link()
failure) by only freeing the IOVA allocation without attempting to
unmap.

Signed-off-by: Chaitanya Kulkarni <kch@nvidia.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Chaitanya Kulkarni and committed by
Jens Axboe
81e7223b 5991bfa3

+8 -5
+8 -5
block/blk-mq-dma.c
··· 121 121 error = dma_iova_link(dma_dev, state, vec->paddr, mapped, 122 122 vec->len, dir, attrs); 123 123 if (error) 124 - break; 124 + goto out_unlink; 125 125 mapped += vec->len; 126 126 } while (blk_map_iter_next(req, &iter->iter, vec)); 127 127 128 128 error = dma_iova_sync(dma_dev, state, 0, mapped); 129 - if (error) { 130 - iter->status = errno_to_blk_status(error); 131 - return false; 132 - } 129 + if (error) 130 + goto out_unlink; 133 131 134 132 return true; 133 + 134 + out_unlink: 135 + dma_iova_destroy(dma_dev, state, mapped, dir, attrs); 136 + iter->status = errno_to_blk_status(error); 137 + return false; 135 138 } 136 139 137 140 static inline void blk_rq_map_iter_init(struct request *rq,