From: Keir Fraser Date: Thu, 17 Dec 2009 06:37:50 +0000 (+0000) Subject: Changes to various backends to handle GNTST_eagain errors. X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=873d26ad841d7bade26ea66ad1f245c017952146;p=legacy%2Flinux-2.6.18-xen.git Changes to various backends to handle GNTST_eagain errors. Signed-off-by: Grzegorz Milos --- diff --git a/drivers/xen/blktap/blktap.c b/drivers/xen/blktap/blktap.c index 0986b00a..eec9f6eb 100644 --- a/drivers/xen/blktap/blktap.c +++ b/drivers/xen/blktap/blktap.c @@ -1507,6 +1507,8 @@ static void dispatch_rw_block_io(blkif_t *blkif, if (unlikely(map[i].status != 0)) { WPRINTK("invalid kernel buffer -- " "could not remap it\n"); + if(map[i].status == GNTST_eagain) + WPRINTK("grant GNTST_eagain: please use blktap2\n"); ret |= 1; map[i].handle = INVALID_GRANT_HANDLE; } @@ -1544,6 +1546,8 @@ static void dispatch_rw_block_io(blkif_t *blkif, if (unlikely(map[i].status != 0)) { WPRINTK("invalid kernel buffer -- " "could not remap it\n"); + if(map[i].status == GNTST_eagain) + WPRINTK("grant GNTST_eagain: please use blktap2\n"); ret |= 1; map[i].handle = INVALID_GRANT_HANDLE; } diff --git a/drivers/xen/blktap/interface.c b/drivers/xen/blktap/interface.c index 9009ba62..b00992cf 100644 --- a/drivers/xen/blktap/interface.c +++ b/drivers/xen/blktap/interface.c @@ -33,6 +33,7 @@ #include "common.h" #include +#include static kmem_cache_t *blkif_cachep; @@ -62,8 +63,11 @@ static int map_frontend_page(blkif_t *blkif, unsigned long shared_page) gnttab_set_map_op(&op, (unsigned long)blkif->blk_ring_area->addr, GNTMAP_host_map, shared_page, blkif->domid); - if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) - BUG(); + do { + if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) + BUG(); + msleep(10); + } while(op.status == GNTST_eagain); if (op.status) { DPRINTK(" Grant table operation failure !\n"); diff --git a/drivers/xen/blktap2/device.c b/drivers/xen/blktap2/device.c index afdd8491..db5b3cb9 100644 --- a/drivers/xen/blktap2/device.c +++ b/drivers/xen/blktap2/device.c @@ -508,6 +508,8 @@ blktap_map_foreign(struct blktap *tap, if (unlikely(table->grants[grant].status)) { BTERR("invalid kernel buffer: could not remap it\n"); + /* This should never happen: blkback should handle eagain first */ + BUG_ON(table->grants[grant].status == GNTST_eagain); err |= 1; table->grants[grant].handle = INVALID_GRANT_HANDLE; } @@ -604,6 +606,8 @@ blktap_map(struct blktap *tap, err = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &map, 1); BUG_ON(err); + /* We are not expecting the grant op to fail */ + BUG_ON(map.status != GNTST_okay); err = vm_insert_page(ring->vma, uvaddr, tap_page); if (err) { diff --git a/drivers/xen/gntdev/gntdev.c b/drivers/xen/gntdev/gntdev.c index 5c18f346..dbd69293 100644 --- a/drivers/xen/gntdev/gntdev.c +++ b/drivers/xen/gntdev/gntdev.c @@ -501,7 +501,7 @@ static int gntdev_mmap (struct file *flip, struct vm_area_struct *vma) unsigned long kernel_vaddr, user_vaddr; uint32_t size = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; uint64_t ptep; - int ret; + int ret, exit_ret; int flags; int i; struct page *page; @@ -578,6 +578,7 @@ static int gntdev_mmap (struct file *flip, struct vm_area_struct *vma) vma->vm_mm->context.has_foreign_mappings = 1; #endif + exit_ret = -ENOMEM; for (i = 0; i < size; ++i) { flags = GNTMAP_host_map; @@ -599,13 +600,17 @@ static int gntdev_mmap (struct file *flip, struct vm_area_struct *vma) &op, 1); BUG_ON(ret); if (op.status) { - printk(KERN_ERR "Error mapping the grant reference " - "into the kernel (%d). domid = %d; ref = %d\n", - op.status, - private_data->grants[slot_index+i] - .u.valid.domid, - private_data->grants[slot_index+i] - .u.valid.ref); + if(op.status != GNTST_eagain) + printk(KERN_ERR "Error mapping the grant reference " + "into the kernel (%d). domid = %d; ref = %d\n", + op.status, + private_data->grants[slot_index+i] + .u.valid.domid, + private_data->grants[slot_index+i] + .u.valid.ref); + else + /* Propagate eagain instead of trying to fix it up */ + exit_ret = -EAGAIN; goto undo_map_out; } @@ -682,6 +687,9 @@ static int gntdev_mmap (struct file *flip, struct vm_area_struct *vma) .valid.domid, private_data->grants[slot_index+i].u .valid.ref); + /* This should never happen after we've mapped into + * the kernel space. */ + BUG_ON(op.status == GNTST_eagain); goto undo_map_out; } @@ -705,9 +713,10 @@ static int gntdev_mmap (struct file *flip, struct vm_area_struct *vma) } } + exit_ret = 0; up_write(&private_data->grants_sem); - return 0; + return exit_ret; undo_map_out: /* If we have a mapping failure, the unmapping will be taken care of @@ -725,7 +734,7 @@ undo_map_out: up_write(&private_data->grants_sem); - return -ENOMEM; + return exit_ret; } static pte_t gntdev_clear_pte(struct vm_area_struct *vma, unsigned long addr, diff --git a/drivers/xen/scsiback/interface.c b/drivers/xen/scsiback/interface.c index 21d90a62..a2d38127 100644 --- a/drivers/xen/scsiback/interface.c +++ b/drivers/xen/scsiback/interface.c @@ -37,6 +37,7 @@ #include #include +#include static kmem_cache_t *scsiback_cachep; @@ -69,8 +70,11 @@ static int map_frontend_page( struct vscsibk_info *info, GNTMAP_host_map, ring_ref, info->domid); - err = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1); - BUG_ON(err); + do { + err = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1); + BUG_ON(err); + msleep(10); + } while(op.status == GNTST_eagain); if (op.status) { printk(KERN_ERR "scsiback: Grant table operation failure !\n"); diff --git a/drivers/xen/scsiback/scsiback.c b/drivers/xen/scsiback/scsiback.c index 03faeb3e..d9b8a7cd 100644 --- a/drivers/xen/scsiback/scsiback.c +++ b/drivers/xen/scsiback/scsiback.c @@ -279,6 +279,17 @@ static int scsiback_gnttab_data_map(vscsiif_request_t *ring_req, err = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, map, nr_segments); BUG_ON(err); + /* Retry maps with GNTST_eagain */ + for(i=0; i < nr_segments; i++) { + while(unlikely(map[i].status == GNTST_eagain)) + { + msleep(10); + err = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, + &map[i], + 1); + BUG_ON(err); + } + } for (i = 0; i < nr_segments; i++) { struct page *pg; diff --git a/drivers/xen/sfc_netback/accel_xenbus.c b/drivers/xen/sfc_netback/accel_xenbus.c index cb6c9344..1e6e4acf 100644 --- a/drivers/xen/sfc_netback/accel_xenbus.c +++ b/drivers/xen/sfc_netback/accel_xenbus.c @@ -24,6 +24,7 @@ #include #include +#include /* drivers/xen/netback/common.h */ #include "common.h" diff --git a/drivers/xen/sfc_netutil/accel_util.c b/drivers/xen/sfc_netutil/accel_util.c index 32930799..cecc7635 100644 --- a/drivers/xen/sfc_netutil/accel_util.c +++ b/drivers/xen/sfc_netutil/accel_util.c @@ -23,6 +23,7 @@ */ #include +#include #include #include #include @@ -143,7 +144,7 @@ struct net_accel_valloc_grant_mapping { /* Map a series of grants into a contiguous virtual area */ static void *net_accel_map_grants_valloc(struct xenbus_device *dev, unsigned *grants, int npages, - unsigned flags, void **priv) + unsigned flags, void **priv, int *errno) { struct net_accel_valloc_grant_mapping *map; struct vm_struct *vm; @@ -171,11 +172,16 @@ static void *net_accel_map_grants_valloc(struct xenbus_device *dev, /* Do the actual mapping */ addr = vm->addr; + if(errno != NULL) *errno = 0; for (i = 0; i < npages; i++) { rc = net_accel_map_grant(dev, grants[i], map->grant_handles + i, addr, NULL, flags); if (rc != 0) + { + if(errno != NULL) + *errno = (rc == GNTST_eagain ? -EAGAIN : -EINVAL); goto undo; + } addr = (void*)((unsigned long)addr + PAGE_SIZE); } @@ -224,8 +230,16 @@ void *net_accel_map_grants_contig(struct xenbus_device *dev, unsigned *grants, int npages, void **priv) { - return net_accel_map_grants_valloc(dev, grants, npages, - GNTMAP_host_map, priv); + int errno; + void *ret; + + do { + ret = net_accel_map_grants_valloc(dev, grants, npages, + GNTMAP_host_map, priv, &errno); + if(errno) msleep(10); + } while(errno == -EAGAIN); + + return ret; } EXPORT_SYMBOL(net_accel_map_grants_contig); @@ -241,8 +255,16 @@ EXPORT_SYMBOL(net_accel_unmap_grants_contig); void *net_accel_map_iomem_page(struct xenbus_device *dev, int gnt_ref, void **priv) { - return net_accel_map_grants_valloc(dev, &gnt_ref, 1, - GNTMAP_host_map, priv); + int errno; + void *ret; + + do { + ret = net_accel_map_grants_valloc(dev, &gnt_ref, 1, + GNTMAP_host_map, priv, &errno); + if(errno) msleep(10); + } while(errno == -EAGAIN); + + return ret; } EXPORT_SYMBOL(net_accel_map_iomem_page); diff --git a/drivers/xen/tpmback/interface.c b/drivers/xen/tpmback/interface.c index 604f69eb..a1d032a7 100644 --- a/drivers/xen/tpmback/interface.c +++ b/drivers/xen/tpmback/interface.c @@ -12,6 +12,7 @@ */ #include "common.h" +#include #include #include @@ -84,8 +85,11 @@ static int map_frontend_page(tpmif_t *tpmif, unsigned long shared_page) gnttab_set_map_op(&op, (unsigned long)tpmif->tx_area->addr, GNTMAP_host_map, shared_page, tpmif->domid); - if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) - BUG(); + do { + if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) + BUG(); + msleep(10); + } while(op.status == GNTST_eagain); if (op.status) { DPRINTK(" Grant table operation failure !\n"); diff --git a/drivers/xen/tpmback/tpmback.c b/drivers/xen/tpmback/tpmback.c index 662144dd..9e28224d 100644 --- a/drivers/xen/tpmback/tpmback.c +++ b/drivers/xen/tpmback/tpmback.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -256,10 +257,12 @@ int _packet_write(struct packet *pak, gnttab_set_map_op(&map_op, idx_to_kaddr(tpmif, i), GNTMAP_host_map, tx->ref, tpmif->domid); - if (unlikely(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, - &map_op, 1))) { - BUG(); - } + do { + if (unlikely(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, + &map_op, 1))) + BUG(); + if(map_op.status) msleep(10); + } while(map_op.status == GNTST_eagain); handle = map_op.handle; @@ -394,10 +397,12 @@ static int packet_read_shmem(struct packet *pak, gnttab_set_map_op(&map_op, idx_to_kaddr(tpmif, i), GNTMAP_host_map, tx->ref, tpmif->domid); - if (unlikely(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, - &map_op, 1))) { - BUG(); - } + do { + if (unlikely(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, + &map_op, 1))) + BUG(); + if(map_op.status) msleep(10); + } while(map_op.status == GNTST_eagain); if (map_op.status) { DPRINTK(" Grant table operation failure !\n"); diff --git a/drivers/xen/usbback/interface.c b/drivers/xen/usbback/interface.c index 7571d2cb..81bad598 100644 --- a/drivers/xen/usbback/interface.c +++ b/drivers/xen/usbback/interface.c @@ -43,6 +43,7 @@ * DEALINGS IN THE SOFTWARE. */ +#include #include "usbback.h" static LIST_HEAD(usbif_list); @@ -109,8 +110,12 @@ static int map_frontend_pages(usbif_t *usbif, gnttab_set_map_op(&op, (unsigned long)usbif->urb_ring_area->addr, GNTMAP_host_map, urb_ring_ref, usbif->domid); - if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) - BUG(); + + do { + if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) + BUG(); + msleep(10); + } while (op.status == GNTST_eagain); if (op.status) { printk(KERN_ERR "grant table failure mapping urb_ring_ref\n"); @@ -123,8 +128,11 @@ static int map_frontend_pages(usbif_t *usbif, gnttab_set_map_op(&op, (unsigned long)usbif->conn_ring_area->addr, GNTMAP_host_map, conn_ring_ref, usbif->domid); - if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) - BUG(); + do { + if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) + BUG(); + msleep(10); + } while (op.status == GNTST_eagain); if (op.status) { struct gnttab_unmap_grant_ref unop; diff --git a/drivers/xen/usbback/usbback.c b/drivers/xen/usbback/usbback.c index 3c26214f..e3950c15 100644 --- a/drivers/xen/usbback/usbback.c +++ b/drivers/xen/usbback/usbback.c @@ -392,6 +392,16 @@ static int usbbk_gnttab_map(usbif_t *usbif, ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, map, nr_segs); BUG_ON(ret); + /* Make sure than none of the map ops failed with GNTST_eagain */ + for( i = 0; i < nr_segs; i++) { + while(map[i].status == GNTST_eagain) { + msleep(10); + ret = HYPERVISOR_grant_table_op( + GNTTABOP_map_grant_ref, + &map[i], 1); + BUG_ON(ret); + } + } for (i = 0; i < nr_segs; i++) { if (unlikely(map[i].status != 0)) { diff --git a/drivers/xen/xenbus/xenbus_backend_client.c b/drivers/xen/xenbus/xenbus_backend_client.c index 9b6fbc92..71687739 100644 --- a/drivers/xen/xenbus/xenbus_backend_client.c +++ b/drivers/xen/xenbus/xenbus_backend_client.c @@ -31,6 +31,7 @@ */ #include +#include #include #include #include @@ -48,8 +49,11 @@ struct vm_struct *xenbus_map_ring_valloc(struct xenbus_device *dev, int gnt_ref) gnttab_set_map_op(&op, (unsigned long)area->addr, GNTMAP_host_map, gnt_ref, dev->otherend_id); - if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) - BUG(); + do { + if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) + BUG(); + msleep(10); + } while(op.status == GNTST_eagain); if (op.status != GNTST_okay) { free_vm_area(area); @@ -75,8 +79,11 @@ int xenbus_map_ring(struct xenbus_device *dev, int gnt_ref, gnttab_set_map_op(&op, (unsigned long)vaddr, GNTMAP_host_map, gnt_ref, dev->otherend_id); - if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) - BUG(); + do { + if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) + BUG(); + msleep(10); + } while(op.status == GNTST_eagain); if (op.status != GNTST_okay) { xenbus_dev_fatal(dev, op.status,