The current implementation may cause BUG_ON() in blkfront_aio()
        BUG_ON(n > BLKIF_MAX_SEGMENTS_PER_REQUEST);

In pvblock_iop(), a read/write operation will be split into smaller
chunks of data so that the size in one access (aio_nbytes) is limited
to, at the maximum,
        BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE

But this works only if when the *buffer* passed in to pvblock_io()
is page-aligned. If not, the given data region may stand across
(BLKIF_MAX_SEGMENTS_PER_REQUEST + 1) pages. See the logic in
blkfront_aio():
        start = (uintptr_t)aiocbp->aio_buf & PAGE_MASK;
        end = ((uintptr_t)aiocbp->aio_buf + aiocbp->aio_nbytes +
               PAGE_SIZE - 1) & PAGE_MASK;
Then this will lead to BUG_ON() above.

This can be fixed by decreasing the maximum size of aio_nbytes.

Signed-off-by: AKASHI Takahiro <takahiro.aka...@linaro.org>
Fixes: commit 3a739cc6c948 ("xen: pvblock: Implement front-back protocol and do 
IO")
---
 drivers/xen/pvblock.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/xen/pvblock.c b/drivers/xen/pvblock.c
index 4ad548d599d5..1df04e239ad0 100644
--- a/drivers/xen/pvblock.c
+++ b/drivers/xen/pvblock.c
@@ -632,7 +632,8 @@ static ulong pvblock_iop(struct udevice *udev, lbaint_t 
blknr,
                        memcpy(blk_dev->bounce_buffer, buffer, desc->blksz);
 
                aiocb.aio_nbytes = unaligned ? desc->blksz :
-                       min((size_t)(BLKIF_MAX_SEGMENTS_PER_REQUEST * 
PAGE_SIZE),
+                       min((size_t)((BLKIF_MAX_SEGMENTS_PER_REQUEST - 1)
+                                       * PAGE_SIZE),
                            (size_t)(blocks_todo * desc->blksz));
 
                blkfront_io(&aiocb, write);
-- 
2.34.1

Reply via email to