ChangeSet 1.1159.258.144, 2005/05/20 17:51:49+01:00, kaf24@xxxxxxxxxxxxxxxxxxxx
Handle mis-aligned I/O requests in blkback driver.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
blkback.c | 49 ++++++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 44 insertions(+), 5 deletions(-)
diff -Nru a/linux-2.6.11-xen-sparse/drivers/xen/blkback/blkback.c
b/linux-2.6.11-xen-sparse/drivers/xen/blkback/blkback.c
--- a/linux-2.6.11-xen-sparse/drivers/xen/blkback/blkback.c 2005-05-20
13:03:39 -04:00
+++ b/linux-2.6.11-xen-sparse/drivers/xen/blkback/blkback.c 2005-05-20
13:03:39 -04:00
@@ -47,6 +47,8 @@
atomic_t pendcnt;
unsigned short operation;
int status;
+ void *bounce_page;
+ unsigned int bounce_off, bounce_len;
} pending_req_t;
/*
@@ -232,6 +234,15 @@
if ( atomic_dec_and_test(&pending_req->pendcnt) )
{
int pending_idx = pending_req - pending_reqs;
+ if ( unlikely(pending_req->bounce_page != NULL) )
+ {
+ memcpy((void *)(MMAP_VADDR(pending_idx, 0) +
+ pending_req->bounce_off),
+ (void *)((unsigned long)pending_req->bounce_page +
+ pending_req->bounce_off),
+ pending_req->bounce_len);
+ free_page((unsigned long)pending_req->bounce_page);
+ }
fast_flush_area(pending_idx, pending_req->nr_pages);
make_response(pending_req->blkif, pending_req->id,
pending_req->operation, pending_req->status);
@@ -452,6 +463,7 @@
pending_req->operation = operation;
pending_req->status = BLKIF_RSP_OKAY;
pending_req->nr_pages = nr_psegs;
+ pending_req->bounce_page = NULL;
atomic_set(&pending_req->pendcnt, nr_psegs);
pending_cons++;
@@ -511,11 +523,38 @@
bio->bi_end_io = end_block_io_op;
bio->bi_sector = phys_seg[i].sector_number;
- bio_add_page(
- bio,
- virt_to_page(MMAP_VADDR(pending_idx, i)),
- phys_seg[i].nr_sects << 9,
- phys_seg[i].buffer & ~PAGE_MASK);
+ /* Is the request misaligned with respect to hardware sector size? */
+ if ( ((bio->bi_sector | phys_seg[i].nr_sects) &
+ ((bdev_hardsect_size(bio->bi_bdev) >> 9) - 1)) )
+ {
+ /* We can't bounce scatter-gather requests. */
+ if ( (nr_psegs != 1) ||
+ ((pending_req->bounce_page = (void *)
+ __get_free_page(GFP_KERNEL)) == NULL) )
+ {
+ printk("xen_blk: Unaligned scatter-gather request!\n");
+ bio_put(bio);
+ __end_block_io_op(pending_req, 0);
+ continue;
+ }
+
+ /* Record offset and length within a bounce page. */
+ pending_req->bounce_off = (bio->bi_sector << 9) & ~PAGE_MASK;
+ pending_req->bounce_len = phys_seg[i].nr_sects << 9;
+
+ /* Submit a page-aligned I/O. */
+ bio->bi_sector &= ~((PAGE_SIZE >> 9) - 1);
+ bio_add_page(
+ bio, virt_to_page(pending_req->bounce_page), PAGE_SIZE, 0);
+ }
+ else
+ {
+ bio_add_page(
+ bio,
+ virt_to_page(MMAP_VADDR(pending_idx, i)),
+ phys_seg[i].nr_sects << 9,
+ phys_seg[i].buffer & ~PAGE_MASK);
+ }
if ( (q = bdev_get_queue(bio->bi_bdev)) != plugged_queue )
{
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|