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;
}
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;
}
#include "common.h"
#include <xen/evtchn.h>
+#include <linux/delay.h>
static kmem_cache_t *blkif_cachep;
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");
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;
}
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) {
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;
vma->vm_mm->context.has_foreign_mappings = 1;
#endif
+ exit_ret = -ENOMEM;
for (i = 0; i < size; ++i) {
flags = GNTMAP_host_map;
&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;
}
.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;
}
}
}
+ 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
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,
#include <xen/evtchn.h>
#include <linux/kthread.h>
+#include <linux/delay.h>
static kmem_cache_t *scsiback_cachep;
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");
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;
#include <xen/evtchn.h>
#include <linux/mutex.h>
+#include <linux/delay.h>
/* drivers/xen/netback/common.h */
#include "common.h"
*/
#include <linux/if_ether.h>
+#include <linux/delay.h>
#include <asm/io.h>
#include <asm/pgtable.h>
#include <asm/hypercall.h>
/* 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;
/* 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);
}
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);
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);
*/
#include "common.h"
+#include <linux/delay.h>
#include <xen/balloon.h>
#include <xen/gnttab.h>
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");
#include <linux/list.h>
#include <linux/miscdevice.h>
#include <linux/poll.h>
+#include <linux/delay.h>
#include <asm/uaccess.h>
#include <xen/xenbus.h>
#include <xen/interface/grant_table.h>
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;
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");
* DEALINGS IN THE SOFTWARE.
*/
+#include <linux/delay.h>
#include "usbback.h"
static LIST_HEAD(usbif_list);
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");
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;
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)) {
*/
#include <linux/err.h>
+#include <linux/delay.h>
#include <xen/gnttab.h>
#include <xen/xenbus.h>
#include <xen/driver_util.h>
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);
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,