Mailing List Archive

[PATCH] xenpaging: handle GNTST_eagain in kernel drivers
Handle GNTST_eagain status from GNTTABOP_map_grant_ref and GNTTABOP_copy
operations properly to allow usage of xenpaging without causing crashes or data
corruption.

Remove the existing retry code from net_rx_action(), dispatch_rw_block_io(),
net_accel_map_grants_contig() and net_accel_map_iomem_page() and replace all
relevant HYPERVISOR_grant_table_op() calls with a retry loop.
This loop is implemented as a macro to allow different GNTTABOP_* args.
It will sleep up to 33 seconds and wait for the page to be paged in again.

All ->status checks were updated to use the GNTST_* namespace.
All return values are converted from GNTST_* namespace to 0/-EINVAL, since all
callers did not use the actual return value.

Signed-off-by: Olaf Hering <olaf@aepfle.de>

---
Compiled with x86_64 and i386 configs

drivers/xen/blkback/blkback.c | 57 ++++++-----------------------
drivers/xen/blkback/common.h | 2 -
drivers/xen/blkback/interface.c | 22 +++++------
drivers/xen/blktap/blktap.c | 29 ++++++--------
drivers/xen/blktap/interface.c | 22 +++++------
drivers/xen/blktap2/device.c | 34 ++++++++---------
drivers/xen/core/gnttab.c | 4 +-
drivers/xen/gntdev/gntdev.c | 26 ++++++-------
drivers/xen/netback/interface.c | 26 ++++---------
drivers/xen/netback/netback.c | 52 +++++++-------------------
drivers/xen/scsiback/interface.c | 24 +++++-------
drivers/xen/scsiback/scsiback.c | 16 ++------
drivers/xen/sfc_netutil/accel_util.c | 41 +++++---------------
drivers/xen/tpmback/interface.c | 22 +++++------
drivers/xen/tpmback/tpmback.c | 22 +++--------
drivers/xen/usbback/interface.c | 25 ++++--------
drivers/xen/usbback/usbback.c | 16 ++------
drivers/xen/xenbus/xenbus_backend_client.c | 27 ++++++-------
include/xen/gnttab.h | 38 +++++++++++++++++++
19 files changed, 204 insertions(+), 301 deletions(-)

--- linux-2.6.18-xen.hg.orig/drivers/xen/blkback/blkback.c
+++ linux-2.6.18-xen.hg/drivers/xen/blkback/blkback.c
@@ -107,7 +107,7 @@ static inline unsigned long vaddr(pendin


static int do_block_io_op(blkif_t *blkif);
-static int dispatch_rw_block_io(blkif_t *blkif,
+static void dispatch_rw_block_io(blkif_t *blkif,
blkif_request_t *req,
pending_req_t *pending_req);
static void make_response(blkif_t *blkif, u64 id,
@@ -312,13 +312,13 @@ static int do_block_io_op(blkif_t *blkif
blkif_request_t req;
pending_req_t *pending_req;
RING_IDX rc, rp;
- int more_to_do = 0, ret;
+ int more_to_do = 0;

rc = blk_rings->common.req_cons;
rp = blk_rings->common.sring->req_prod;
rmb(); /* Ensure we see queued requests up to 'rp'. */

- while ((rc != rp) || (blkif->is_suspended_req)) {
+ while ((rc != rp)) {

if (RING_REQUEST_CONS_OVERFLOW(&blk_rings->common, rc))
break;
@@ -335,14 +335,6 @@ static int do_block_io_op(blkif_t *blkif
break;
}

- /* Handle the suspended request first, if one exists */
- if(blkif->is_suspended_req)
- {
- memcpy(&req, &blkif->suspended_req, sizeof(req));
- blkif->is_suspended_req = 0;
- goto handle_request;
- }
-
switch (blkif->blk_protocol) {
case BLKIF_PROTOCOL_NATIVE:
memcpy(&req, RING_GET_REQUEST(&blk_rings->native, rc), sizeof(req));
@@ -361,19 +353,17 @@ static int do_block_io_op(blkif_t *blkif
/* Apply all sanity checks to /private copy/ of request. */
barrier();

-handle_request:
- ret = 0;
switch (req.operation) {
case BLKIF_OP_READ:
blkif->st_rd_req++;
- ret = dispatch_rw_block_io(blkif, &req, pending_req);
+ dispatch_rw_block_io(blkif, &req, pending_req);
break;
case BLKIF_OP_WRITE_BARRIER:
blkif->st_br_req++;
/* fall through */
case BLKIF_OP_WRITE:
blkif->st_wr_req++;
- ret = dispatch_rw_block_io(blkif, &req, pending_req);
+ dispatch_rw_block_io(blkif, &req, pending_req);
break;
default:
/* A good sign something is wrong: sleep for a while to
@@ -386,17 +376,6 @@ handle_request:
free_req(pending_req);
break;
}
- BUG_ON(ret != 0 && ret != -EAGAIN);
- /* If we can't handle the request at the moment, save it, and break the
- * loop */
- if(ret == -EAGAIN)
- {
- memcpy(&blkif->suspended_req, &req, sizeof(req));
- blkif->is_suspended_req = 1;
- /* Return "no more work pending", restart will be handled 'out of
- * band' */
- return 0;
- }

/* Yield point for this unbounded loop. */
cond_resched();
@@ -405,7 +384,7 @@ handle_request:
return more_to_do;
}

-static int dispatch_rw_block_io(blkif_t *blkif,
+static void dispatch_rw_block_io(blkif_t *blkif,
blkif_request_t *req,
pending_req_t *pending_req)
{
@@ -474,15 +453,13 @@ static int dispatch_rw_block_io(blkif_t
ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, map, nseg);
BUG_ON(ret);

-#define GENERAL_ERR (1<<0)
-#define EAGAIN_ERR (1<<1)
for (i = 0; i < nseg; i++) {
- if (unlikely(map[i].status != 0)) {
+ if (unlikely(map[i].status == GNTST_eagain))
+ gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &map[i])
+ if (unlikely(map[i].status != GNTST_okay)) {
DPRINTK("invalid buffer -- could not remap it\n");
map[i].handle = BLKBACK_INVALID_HANDLE;
- ret |= GENERAL_ERR;
- if(map[i].status == GNTST_eagain)
- ret |= EAGAIN_ERR;
+ ret = 1;
} else {
blkback_pagemap_set(vaddr_pagenr(pending_req, i),
pending_page(pending_req, i),
@@ -502,14 +479,6 @@ static int dispatch_rw_block_io(blkif_t
(req->seg[i].first_sect << 9);
}

- /* If any of grant maps failed with GNTST_eagain, suspend and retry later */
- if(ret & EAGAIN_ERR)
- {
- fast_flush_area(pending_req);
- free_req(pending_req);
- return -EAGAIN;
- }
-
if (ret)
goto fail_flush;

@@ -575,7 +544,7 @@ static int dispatch_rw_block_io(blkif_t
else if (operation == WRITE || operation == WRITE_BARRIER)
blkif->st_wr_sect += preq.nr_sects;

- return 0;
+ return;

fail_flush:
fast_flush_area(pending_req);
@@ -583,7 +552,7 @@ static int dispatch_rw_block_io(blkif_t
make_response(blkif, req->id, req->operation, BLKIF_RSP_ERROR);
free_req(pending_req);
msleep(1); /* back off a bit */
- return 0;
+ return;

fail_put_bio:
__end_block_io_op(pending_req, -EINVAL);
@@ -591,7 +560,7 @@ static int dispatch_rw_block_io(blkif_t
bio_put(bio);
unplug_queue(blkif);
msleep(1); /* back off a bit */
- return 0;
+ return;
}


--- linux-2.6.18-xen.hg.orig/drivers/xen/blkback/common.h
+++ linux-2.6.18-xen.hg/drivers/xen/blkback/common.h
@@ -83,8 +83,6 @@ typedef struct blkif_st {
struct task_struct *xenblkd;
unsigned int waiting_reqs;
request_queue_t *plug;
- int is_suspended_req;
- blkif_request_t suspended_req;

/* statistics */
unsigned long st_print;
--- linux-2.6.18-xen.hg.orig/drivers/xen/blkback/interface.c
+++ linux-2.6.18-xen.hg/drivers/xen/blkback/interface.c
@@ -59,25 +59,23 @@ blkif_t *blkif_alloc(domid_t domid)
static int map_frontend_page(blkif_t *blkif, unsigned long shared_page)
{
struct gnttab_map_grant_ref op;
+ int ret;

gnttab_set_map_op(&op, (unsigned long)blkif->blk_ring_area->addr,
GNTMAP_host_map, shared_page, blkif->domid);

- do {
- if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
- BUG();
- msleep(100);
- } while(op.status == GNTST_eagain);
+ gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &op);

- if (op.status) {
- DPRINTK(" Grant table operation failure !\n");
- return op.status;
+ if (op.status == GNTST_okay) {
+ blkif->shmem_ref = shared_page;
+ blkif->shmem_handle = op.handle;
+ ret = 0;
+ } else {
+ DPRINTK(" Grant table operation failure %d!\n", (int)op.status);
+ ret = -EINVAL;
}

- blkif->shmem_ref = shared_page;
- blkif->shmem_handle = op.handle;
-
- return 0;
+ return ret;
}

static void unmap_frontend_page(blkif_t *blkif)
--- linux-2.6.18-xen.hg.orig/drivers/xen/blktap/blktap.c
+++ linux-2.6.18-xen.hg/drivers/xen/blktap/blktap.c
@@ -1526,19 +1526,17 @@ static void dispatch_rw_block_io(blkif_t

uvaddr = MMAP_VADDR(info->user_vstart, usr_idx, i/2);

- 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;
+ gnttab_check_GNTST_eagain_while(GNTTABOP_map_grant_ref, &map[i]);
+
+ if (unlikely(map[i].status != GNTST_okay)) {
+ WPRINTK("invalid kernel buffer -- could not remap it\n");
+ ret = 1;
map[i].handle = INVALID_GRANT_HANDLE;
}

- if (unlikely(map[i+1].status != 0)) {
- WPRINTK("invalid user buffer -- "
- "could not remap it\n");
- ret |= 1;
+ if (unlikely(map[i+1].status != GNTST_okay)) {
+ WPRINTK("invalid kernel buffer -- could not remap it\n");
+ ret = 1;
map[i+1].handle = INVALID_GRANT_HANDLE;
}

@@ -1565,12 +1563,11 @@ static void dispatch_rw_block_io(blkif_t

uvaddr = MMAP_VADDR(info->user_vstart, usr_idx, i);

- 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;
+ gnttab_check_GNTST_eagain_while(GNTTABOP_map_grant_ref, &map[i]);
+
+ if (unlikely(map[i].status != GNTST_okay)) {
+ WPRINTK("invalid kernel buffer -- could not remap it\n");
+ ret = 1;
map[i].handle = INVALID_GRANT_HANDLE;
}

--- linux-2.6.18-xen.hg.orig/drivers/xen/blktap/interface.c
+++ linux-2.6.18-xen.hg/drivers/xen/blktap/interface.c
@@ -59,25 +59,23 @@ blkif_t *tap_alloc_blkif(domid_t domid)
static int map_frontend_page(blkif_t *blkif, unsigned long shared_page)
{
struct gnttab_map_grant_ref op;
+ int ret;

gnttab_set_map_op(&op, (unsigned long)blkif->blk_ring_area->addr,
GNTMAP_host_map, shared_page, blkif->domid);

- do {
- if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
- BUG();
- msleep(10);
- } while(op.status == GNTST_eagain);
+ gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &op);

- if (op.status) {
- DPRINTK(" Grant table operation failure !\n");
- return op.status;
+ if (op.status == GNTST_okay) {
+ blkif->shmem_ref = shared_page;
+ blkif->shmem_handle = op.handle;
+ ret = 0;
+ } else {
+ DPRINTK("Grant table operation failure %d!\n", (int)op.status);
+ ret = -EINVAL;
}

- blkif->shmem_ref = shared_page;
- blkif->shmem_handle = op.handle;
-
- return 0;
+ return ret;
}

static void unmap_frontend_page(blkif_t *blkif)
--- linux-2.6.18-xen.hg.orig/drivers/xen/blktap2/device.c
+++ linux-2.6.18-xen.hg/drivers/xen/blktap2/device.c
@@ -505,10 +505,10 @@ blktap_map_foreign(struct blktap *tap,

uvaddr = MMAP_VADDR(ring->user_vstart, usr_idx, i);

- if (unlikely(table->grants[grant].status)) {
+ if (unlikely(table->grants[grant].status != GNTST_okay)) {
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);
+ /* 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;
}
@@ -517,19 +517,18 @@ blktap_map_foreign(struct blktap *tap,
foreign_mfn = table->grants[grant].dev_bus_addr >> PAGE_SHIFT;
grant++;

- if (xen_feature(XENFEAT_auto_translated_physmap))
- goto done;
-
- if (unlikely(table->grants[grant].status)) {
- BTERR("invalid user buffer: could not remap it\n");
- err |= 1;
+ if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+ if (unlikely(table->grants[grant].status != GNTST_okay)) {
+ /* This should never happen: blkback should handle eagain first */
+ WARN_ON(table->grants[grant].status == GNTST_eagain);
+ BTERR("invalid user buffer: could not remap it\n");
+ err |= 1;
+ }
table->grants[grant].handle = INVALID_GRANT_HANDLE;
+ request->handles[i].user = table->grants[grant].handle;
+ grant++;
}

- request->handles[i].user = table->grants[grant].handle;
- grant++;
-
- done:
if (err)
continue;

@@ -602,11 +601,10 @@ blktap_map(struct blktap *tap,
set_page_private(tap_page, page_private(page));
SetPageBlkback(tap_page);

- 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);
+ gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &map);
+
+ /* 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) {
--- linux-2.6.18-xen.hg.orig/drivers/xen/core/gnttab.c
+++ linux-2.6.18-xen.hg/drivers/xen/core/gnttab.c
@@ -487,7 +487,7 @@ static int gnttab_map(unsigned int start
return -ENOSYS;
}

- BUG_ON(rc || setup.status);
+ BUG_ON(rc || setup.status != GNTST_okay);

if (shared == NULL)
shared = arch_gnttab_alloc_shared(frames);
@@ -571,7 +571,7 @@ int gnttab_copy_grant_page(grant_ref_t r
err = HYPERVISOR_grant_table_op(GNTTABOP_unmap_and_replace,
&unmap, 1);
BUG_ON(err);
- BUG_ON(unmap.status);
+ BUG_ON(unmap.status != GNTST_okay);

write_sequnlock(&gnttab_dma_lock);

--- linux-2.6.18-xen.hg.orig/drivers/xen/gntdev/gntdev.c
+++ linux-2.6.18-xen.hg/drivers/xen/gntdev/gntdev.c
@@ -578,7 +578,7 @@ static int gntdev_mmap (struct file *fli
vma->vm_mm->context.has_foreign_mappings = 1;
#endif

- exit_ret = -ENOMEM;
+ exit_ret = -ENOMEM;
for (i = 0; i < size; ++i) {

flags = GNTMAP_host_map;
@@ -599,8 +599,8 @@ static int gntdev_mmap (struct file *fli
ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref,
&op, 1);
BUG_ON(ret);
- if (op.status) {
- if(op.status != GNTST_eagain)
+ if (op.status != GNTST_okay) {
+ if (op.status != GNTST_eagain)
printk(KERN_ERR "Error mapping the grant reference "
"into the kernel (%d). domid = %d; ref = %d\n",
op.status,
@@ -608,9 +608,9 @@ static int gntdev_mmap (struct file *fli
.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;
+ else
+ /* Propagate eagain instead of trying to fix it up */
+ exit_ret = -EAGAIN;
goto undo_map_out;
}

@@ -679,7 +679,7 @@ static int gntdev_mmap (struct file *fli
ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref,
&op, 1);
BUG_ON(ret);
- if (op.status) {
+ if (op.status != GNTST_okay) {
printk(KERN_ERR "Error mapping the grant "
"reference into user space (%d). domid "
"= %d; ref = %d\n", op.status,
@@ -687,9 +687,9 @@ static int gntdev_mmap (struct file *fli
.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);
+ /* This should never happen after we've mapped into
+ * the kernel space. */
+ BUG_ON(op.status == GNTST_eagain);
goto undo_map_out;
}

@@ -713,7 +713,7 @@ static int gntdev_mmap (struct file *fli
}

}
- exit_ret = 0;
+ exit_ret = 0;

up_write(&private_data->grants_sem);
return exit_ret;
@@ -785,7 +785,7 @@ static pte_t gntdev_clear_pte(struct vm_
ret = HYPERVISOR_grant_table_op(
GNTTABOP_unmap_grant_ref, &op, 1);
BUG_ON(ret);
- if (op.status)
+ if (op.status != GNTST_okay)
printk("User unmap grant status = %d\n",
op.status);
} else {
@@ -802,7 +802,7 @@ static pte_t gntdev_clear_pte(struct vm_
ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref,
&op, 1);
BUG_ON(ret);
- if (op.status)
+ if (op.status != GNTST_okay)
printk("Kernel unmap grant status = %d\n", op.status);


--- linux-2.6.18-xen.hg.orig/drivers/xen/netback/interface.c
+++ linux-2.6.18-xen.hg/drivers/xen/netback/interface.c
@@ -251,15 +251,11 @@ static int map_frontend_pages(

gnttab_set_map_op(&op, (unsigned long)netif->tx_comms_area->addr,
GNTMAP_host_map, tx_ring_ref, netif->domid);
- do {
- if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
- BUG();
- msleep(10);
- } while(op.status == GNTST_eagain);
-
- if (op.status) {
- DPRINTK(" Gnttab failure mapping tx_ring_ref!\n");
- return op.status;
+ gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &op);
+
+ if (op.status != GNTST_okay) {
+ DPRINTK(" Gnttab failure mapping tx_ring_ref %d!\n", (int)op.status);
+ return -EINVAL;
}

netif->tx_shmem_ref = tx_ring_ref;
@@ -267,13 +263,9 @@ static int map_frontend_pages(

gnttab_set_map_op(&op, (unsigned long)netif->rx_comms_area->addr,
GNTMAP_host_map, rx_ring_ref, netif->domid);
- do {
- if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
- BUG();
- msleep(10);
- } while(op.status == GNTST_eagain);
+ gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &op);

- if (op.status) {
+ if (op.status != GNTST_okay) {
struct gnttab_unmap_grant_ref unop;

gnttab_set_unmap_op(&unop,
@@ -281,8 +273,8 @@ static int map_frontend_pages(
GNTMAP_host_map, netif->tx_shmem_handle);
VOID(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref,
&unop, 1));
- DPRINTK(" Gnttab failure mapping rx_ring_ref!\n");
- return op.status;
+ DPRINTK(" Gnttab failure mapping rx_ring_ref %d!\n", (int)op.status);
+ return -EINVAL;
}

netif->rx_shmem_ref = rx_ring_ref;
--- linux-2.6.18-xen.hg.orig/drivers/xen/netback/netback.c
+++ linux-2.6.18-xen.hg/drivers/xen/netback/netback.c
@@ -494,8 +494,7 @@ static inline void netbk_free_pages(int
used to set up the operations on the top of
netrx_pending_operations, which have since been done. Check that
they didn't give any errors and advance over them. */
-static int netbk_check_gop(int nr_frags, domid_t domid,
- struct netrx_pending_operations *npo, int *eagain)
+static int netbk_check_gop(int nr_frags, domid_t domid, struct netrx_pending_operations *npo)
{
multicall_entry_t *mcl;
gnttab_transfer_t *gop;
@@ -503,17 +502,15 @@ static int netbk_check_gop(int nr_frags,
int status = NETIF_RSP_OKAY;
int i;

- *eagain = 0;
-
for (i = 0; i <= nr_frags; i++) {
if (npo->meta[npo->meta_cons + i].copy) {
copy_op = npo->copy + npo->copy_cons++;
- if (copy_op->status != GNTST_okay) {
+ if (unlikely(copy_op->status == GNTST_eagain))
+ gnttab_check_GNTST_eagain_while(GNTTABOP_copy, copy_op);
+ if (unlikely(copy_op->status != GNTST_okay)) {
DPRINTK("Bad status %d from copy to DOM%d.\n",
copy_op->status, domid);
status = NETIF_RSP_ERROR;
- if(copy_op->status == GNTST_eagain)
- *eagain = 1;
}
} else {
if (!xen_feature(XENFEAT_auto_translated_physmap)) {
@@ -524,7 +521,7 @@ static int netbk_check_gop(int nr_frags,

gop = npo->trans + npo->trans_cons++;
/* Check the reassignment error code. */
- if (gop->status != 0) {
+ if (unlikely(gop->status != GNTST_okay)) {
DPRINTK("Bad status %d from grant transfer to DOM%u\n",
gop->status, domid);
/*
@@ -533,8 +530,6 @@ static int netbk_check_gop(int nr_frags,
* a fatal error anyway.
*/
BUG_ON(gop->status == GNTST_bad_page);
- if(gop->status == GNTST_eagain)
- *eagain = 1;
status = NETIF_RSP_ERROR;
}
}
@@ -576,7 +571,6 @@ static void net_rx_action(unsigned long
int nr_frags;
int count;
unsigned long offset;
- int eagain;

/*
* Putting hundreds of bytes on the stack is considered rude.
@@ -680,7 +674,7 @@ static void net_rx_action(unsigned long

netif = netdev_priv(skb->dev);

- status = netbk_check_gop(nr_frags, netif->domid, &npo, &eagain);
+ status = netbk_check_gop(nr_frags, netif->domid, &npo);

/* We can't rely on skb_release_data to release the
pages used by fragments for us, since it tries to
@@ -691,22 +685,14 @@ static void net_rx_action(unsigned long
/* (Freeing the fragments is safe since we copy
non-linear skbs destined for flipping interfaces) */
if (!netif->copying_receiver) {
- /*
- * Cannot handle failed grant transfers at the moment (because
- * mmu_updates likely completed)
- */
- BUG_ON(eagain);
atomic_set(&(skb_shinfo(skb)->dataref), 1);
skb_shinfo(skb)->frag_list = NULL;
skb_shinfo(skb)->nr_frags = 0;
netbk_free_pages(nr_frags, meta + npo.meta_cons + 1);
}

- if(!eagain)
- {
- netif->stats.tx_bytes += skb->len;
- netif->stats.tx_packets++;
- }
+ netif->stats.tx_bytes += skb->len;
+ netif->stats.tx_packets++;

id = meta[npo.meta_cons].id;
flags = nr_frags ? NETRXF_more_data : 0;
@@ -756,18 +742,8 @@ static void net_rx_action(unsigned long
!netbk_queue_full(netif))
netif_wake_queue(netif->dev);

- if(!eagain || netbk_queue_full(netif))
- {
- netif_put(netif);
- dev_kfree_skb(skb);
- netif->stats.tx_dropped += !!eagain;
- }
- else
- {
- netif->rx_req_cons_peek += skb_shinfo(skb)->nr_frags + 1 +
- !!skb_shinfo(skb)->gso_size;
- skb_queue_head(&rx_queue, skb);
- }
+ netif_put(netif);
+ dev_kfree_skb(skb);

npo.meta_cons += nr_frags + 1;
}
@@ -1107,7 +1083,7 @@ static int netbk_tx_check_mop(struct sk_

/* Check status of header. */
err = mop->status;
- if (unlikely(err)) {
+ if (unlikely(err != GNTST_okay)) {
txp = &pending_tx_info[pending_idx].req;
make_tx_response(netif, txp, NETIF_RSP_ERROR);
pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx;
@@ -1128,12 +1104,12 @@ static int netbk_tx_check_mop(struct sk_

/* Check error status: if okay then remember grant handle. */
newerr = (++mop)->status;
- if (likely(!newerr)) {
+ if (likely(newerr == GNTST_okay)) {
set_phys_to_machine(idx_to_pfn(pending_idx),
FOREIGN_FRAME(mop->dev_bus_addr>>PAGE_SHIFT));
grant_tx_handle[pending_idx] = mop->handle;
/* Had a previous error? Invalidate this fragment. */
- if (unlikely(err))
+ if (unlikely(err != GNTST_okay))
netif_idx_release(pending_idx);
continue;
}
@@ -1145,7 +1121,7 @@ static int netbk_tx_check_mop(struct sk_
netif_put(netif);

/* Not the first error? Preceding frags already invalidated. */
- if (err)
+ if (err != GNTST_okay)
continue;

/* First error: invalidate header and preceding fragments. */
--- linux-2.6.18-xen.hg.orig/drivers/xen/scsiback/interface.c
+++ linux-2.6.18-xen.hg/drivers/xen/scsiback/interface.c
@@ -64,27 +64,23 @@ static int map_frontend_page( struct vsc
unsigned long ring_ref)
{
struct gnttab_map_grant_ref op;
- int err;
+ int ret;

gnttab_set_map_op(&op, (unsigned long)info->ring_area->addr,
GNTMAP_host_map, ring_ref,
info->domid);
+ gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &op);

- 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");
- return op.status;
+ if (op.status != GNTST_okay) {
+ printk(KERN_ERR "scsiback: Grant table operation failure %d!\n", (int)op.status);
+ ret = -EINVAL;
+ } else {
+ info->shmem_ref = ring_ref;
+ info->shmem_handle = op.handle;
+ ret = 0;
}

- info->shmem_ref = ring_ref;
- info->shmem_handle = op.handle;
-
- return (GNTST_okay);
+ return ret;
}

static void unmap_frontend_page(struct vscsibk_info *info)
--- linux-2.6.18-xen.hg.orig/drivers/xen/scsiback/scsiback.c
+++ linux-2.6.18-xen.hg/drivers/xen/scsiback/scsiback.c
@@ -279,22 +279,14 @@ static int scsiback_gnttab_data_map(vscs

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;

- if (unlikely(map[i].status != 0)) {
+ /* Retry maps with GNTST_eagain */
+ if (unlikely(map[i].status == GNTST_eagain))
+ gnttab_check_GNTST_eagain_while(GNTTABOP_map_grant_ref, &map[i]);
+ if (unlikely(map[i].status != GNTST_okay)) {
printk(KERN_ERR "scsiback: invalid buffer -- could not remap it\n");
map[i].handle = SCSIBACK_INVALID_HANDLE;
err |= 1;
--- linux-2.6.18-xen.hg.orig/drivers/xen/sfc_netutil/accel_util.c
+++ linux-2.6.18-xen.hg/drivers/xen/sfc_netutil/accel_util.c
@@ -71,24 +71,27 @@ static int net_accel_map_grant(struct xe
u64 *dev_bus_addr, unsigned flags)
{
struct gnttab_map_grant_ref op;
+ int ret;

gnttab_set_map_op(&op, (unsigned long)vaddr, flags,
gnt_ref, dev->otherend_id);

- BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1));
+ gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &op);

if (op.status != GNTST_okay) {
xenbus_dev_error
(dev, op.status,
"failed mapping in shared page %d from domain %d\n",
gnt_ref, dev->otherend_id);
+ ret = -EINVAL;
} else {
*handle = op.handle;
if (dev_bus_addr)
*dev_bus_addr = op.dev_bus_addr;
+ ret = 0;
}

- return op.status;
+ return ret;
}


@@ -112,7 +115,7 @@ static int net_accel_unmap_grant(struct
"failed unmapping page at handle %d error %d\n",
handle, op.status);

- return op.status;
+ return op.status == GNTST_okay ? 0 : -EINVAL;
}


@@ -144,7 +147,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, int *errno)
+ unsigned flags, void **priv)
{
struct net_accel_valloc_grant_mapping *map;
struct vm_struct *vm;
@@ -172,16 +175,12 @@ static void *net_accel_map_grants_valloc

/* 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);
+ if (rc < 0)
goto undo;
- }
addr = (void*)((unsigned long)addr + PAGE_SIZE);
}

@@ -230,16 +229,7 @@ void *net_accel_map_grants_contig(struct
unsigned *grants, int npages,
void **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;
+ return net_accel_map_grants_valloc(dev, grants, npages, GNTMAP_host_map, priv);
}
EXPORT_SYMBOL(net_accel_map_grants_contig);

@@ -255,16 +245,7 @@ EXPORT_SYMBOL(net_accel_unmap_grants_con
void *net_accel_map_iomem_page(struct xenbus_device *dev, int gnt_ref,
void **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;
+ return net_accel_map_grants_valloc(dev, &gnt_ref, 1, GNTMAP_host_map, priv);
}
EXPORT_SYMBOL(net_accel_map_iomem_page);

--- linux-2.6.18-xen.hg.orig/drivers/xen/tpmback/interface.c
+++ linux-2.6.18-xen.hg/drivers/xen/tpmback/interface.c
@@ -81,25 +81,23 @@ tpmif_t *tpmif_find(domid_t domid, struc
static int map_frontend_page(tpmif_t *tpmif, unsigned long shared_page)
{
struct gnttab_map_grant_ref op;
+ int ret;

gnttab_set_map_op(&op, (unsigned long)tpmif->tx_area->addr,
GNTMAP_host_map, shared_page, tpmif->domid);

- do {
- if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
- BUG();
- msleep(10);
- } while(op.status == GNTST_eagain);
+ gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &op);

- if (op.status) {
- DPRINTK(" Grant table operation failure !\n");
- return op.status;
+ if (op.status != GNTST_okay) {
+ DPRINTK(" Grant table operation failure %d!\n", (int)op.status);
+ ret = -EINVAL;
+ } else {
+ tpmif->shmem_ref = shared_page;
+ tpmif->shmem_handle = op.handle;
+ ret = 0;
}

- tpmif->shmem_ref = shared_page;
- tpmif->shmem_handle = op.handle;
-
- return 0;
+ return ret;
}

static void unmap_frontend_page(tpmif_t *tpmif)
--- linux-2.6.18-xen.hg.orig/drivers/xen/tpmback/tpmback.c
+++ linux-2.6.18-xen.hg/drivers/xen/tpmback/tpmback.c
@@ -257,20 +257,15 @@ int _packet_write(struct packet *pak,
gnttab_set_map_op(&map_op, idx_to_kaddr(tpmif, i),
GNTMAP_host_map, tx->ref, tpmif->domid);

- 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);
+ gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &map_op);

- handle = map_op.handle;
-
- if (map_op.status) {
+ if (map_op.status != GNTST_okay) {
DPRINTK(" Grant table operation failure !\n");
return 0;
}

+ handle = map_op.handle;
+
tocopy = min_t(size_t, size - offset, PAGE_SIZE);

if (copy_from_buffer((void *)(idx_to_kaddr(tpmif, i) |
@@ -397,14 +392,9 @@ static int packet_read_shmem(struct pack
gnttab_set_map_op(&map_op, idx_to_kaddr(tpmif, i),
GNTMAP_host_map, tx->ref, tpmif->domid);

- 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);
+ gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &map_op);

- if (map_op.status) {
+ if (map_op.status != GNTST_okay) {
DPRINTK(" Grant table operation failure !\n");
return -EFAULT;
}
--- linux-2.6.18-xen.hg.orig/drivers/xen/usbback/interface.c
+++ linux-2.6.18-xen.hg/drivers/xen/usbback/interface.c
@@ -110,16 +110,11 @@ static int map_frontend_pages(usbif_t *u
gnttab_set_map_op(&op, (unsigned long)usbif->urb_ring_area->addr,
GNTMAP_host_map, urb_ring_ref, usbif->domid);

+ gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &op);

- 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");
- return op.status;
+ if (op.status != GNTST_okay) {
+ printk(KERN_ERR "grant table failure mapping urb_ring_ref %d\n", (int)op.status);
+ return -EINVAL;
}

usbif->urb_shmem_ref = urb_ring_ref;
@@ -128,21 +123,17 @@ static int map_frontend_pages(usbif_t *u
gnttab_set_map_op(&op, (unsigned long)usbif->conn_ring_area->addr,
GNTMAP_host_map, conn_ring_ref, usbif->domid);

- do {
- if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
- BUG();
- msleep(10);
- } while (op.status == GNTST_eagain);
+ gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &op);

- if (op.status) {
+ if (op.status != GNTST_okay) {
struct gnttab_unmap_grant_ref unop;
gnttab_set_unmap_op(&unop,
(unsigned long) usbif->urb_ring_area->addr,
GNTMAP_host_map, usbif->urb_shmem_handle);
VOID(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &unop,
1));
- printk(KERN_ERR "grant table failure mapping conn_ring_ref\n");
- return op.status;
+ printk(KERN_ERR "grant table failure mapping conn_ring_ref %d\n", (int)op.status);
+ return -EINVAL;
}

usbif->conn_shmem_ref = conn_ring_ref;
--- linux-2.6.18-xen.hg.orig/drivers/xen/usbback/usbback.c
+++ linux-2.6.18-xen.hg/drivers/xen/usbback/usbback.c
@@ -392,19 +392,13 @@ static int usbbk_gnttab_map(usbif_t *usb
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)) {
+ /* Make sure than none of the map ops failed with GNTST_eagain */
+ if (unlikely(map[i].status == GNTST_eagain))
+ gnttab_check_GNTST_eagain_while(GNTTABOP_map_grant_ref, &map[i]);
+
+ if (unlikely(map[i].status != GNTST_okay)) {
printk(KERN_ERR "usbback: invalid buffer -- could not remap it\n");
map[i].handle = USBBACK_INVALID_HANDLE;
ret |= 1;
--- linux-2.6.18-xen.hg.orig/drivers/xen/xenbus/xenbus_backend_client.c
+++ linux-2.6.18-xen.hg/drivers/xen/xenbus/xenbus_backend_client.c
@@ -49,11 +49,7 @@ struct vm_struct *xenbus_map_ring_valloc
gnttab_set_map_op(&op, (unsigned long)area->addr, GNTMAP_host_map,
gnt_ref, dev->otherend_id);

- do {
- if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
- BUG();
- msleep(10);
- } while(op.status == GNTST_eagain);
+ gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &op);

if (op.status != GNTST_okay) {
free_vm_area(area);
@@ -61,7 +57,7 @@ struct vm_struct *xenbus_map_ring_valloc
"mapping in shared page %d from domain %d",
gnt_ref, dev->otherend_id);
BUG_ON(!IS_ERR(ERR_PTR(op.status)));
- return ERR_PTR(op.status);
+ return ERR_PTR(-EINVAL);
}

/* Stuff the handle in an unused field */
@@ -76,23 +72,24 @@ int xenbus_map_ring(struct xenbus_device
grant_handle_t *handle, void *vaddr)
{
struct gnttab_map_grant_ref op;
+ int ret;

gnttab_set_map_op(&op, (unsigned long)vaddr, GNTMAP_host_map,
gnt_ref, dev->otherend_id);
- do {
- if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
- BUG();
- msleep(10);
- } while(op.status == GNTST_eagain);
+
+ gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &op);

if (op.status != GNTST_okay) {
xenbus_dev_fatal(dev, op.status,
"mapping in shared page %d from domain %d",
gnt_ref, dev->otherend_id);
- } else
+ ret = -EINVAL;
+ } else {
*handle = op.handle;
+ ret = 0;
+ }

- return op.status;
+ return ret;
}
EXPORT_SYMBOL_GPL(xenbus_map_ring);

@@ -115,7 +112,7 @@ int xenbus_unmap_ring_vfree(struct xenbu
"unmapping page at handle %d error %d",
(int16_t)area->phys_addr, op.status);

- return op.status;
+ return op.status == GNTST_okay ? 0 : -EINVAL;
}
EXPORT_SYMBOL_GPL(xenbus_unmap_ring_vfree);

@@ -135,7 +132,7 @@ int xenbus_unmap_ring(struct xenbus_devi
"unmapping page at handle %d error %d",
handle, op.status);

- return op.status;
+ return op.status == GNTST_okay ? 0 : -EINVAL;
}
EXPORT_SYMBOL_GPL(xenbus_unmap_ring);

--- linux-2.6.18-xen.hg.orig/include/xen/gnttab.h
+++ linux-2.6.18-xen.hg/include/xen/gnttab.h
@@ -40,6 +40,7 @@
#include <asm/hypervisor.h>
#include <asm/maddr.h> /* maddr_t */
#include <linux/mm.h>
+#include <linux/delay.h>
#include <xen/interface/grant_table.h>
#include <xen/features.h>

@@ -161,4 +162,41 @@ gnttab_set_replace_op(struct gnttab_unma
unmap->handle = handle;
}

+#define gnttab_check_GNTST_eagain_while(__HCop, __HCarg_p) \
+{ \
+ u8 __hc_delay = 1; \
+ int __ret; \
+ while (unlikely((__HCarg_p)->status == GNTST_eagain && __hc_delay)) { \
+ msleep(__hc_delay++); \
+ __ret = HYPERVISOR_grant_table_op(__HCop, (__HCarg_p), 1); \
+ BUG_ON(__ret); \
+ } \
+ if (__hc_delay == 0) { \
+ printk(KERN_ERR "%s: %s gnt busy\n", __func__, current->comm); \
+ (__HCarg_p)->status = GNTST_bad_page; \
+ } \
+ if ((__HCarg_p)->status != GNTST_okay) \
+ printk(KERN_ERR "%s: %s gnt status %x\n", \
+ __func__, current->comm, (__HCarg_p)->status); \
+}
+
+#define gnttab_check_GNTST_eagain_do_while(__HCop, __HCarg_p) \
+{ \
+ u8 __hc_delay = 1; \
+ int __ret; \
+ do { \
+ __ret = HYPERVISOR_grant_table_op(__HCop, (__HCarg_p), 1); \
+ BUG_ON(__ret); \
+ if ((__HCarg_p)->status == GNTST_eagain) \
+ msleep(__hc_delay++); \
+ } while ((__HCarg_p)->status == GNTST_eagain && __hc_delay); \
+ if (__hc_delay == 0) { \
+ printk(KERN_ERR "%s: %s gnt busy\n", __func__, current->comm); \
+ (__HCarg_p)->status = GNTST_bad_page; \
+ } \
+ if ((__HCarg_p)->status != GNTST_okay) \
+ printk(KERN_ERR "%s: %s gnt status %x\n", \
+ __func__, current->comm, (__HCarg_p)->status); \
+}
+
#endif /* __ASM_GNTTAB_H__ */

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
Re: [PATCH] xenpaging: handle GNTST_eagain in kernel drivers [ In reply to ]
Is there any particular reason for 33 seconds? This number seems a bit
high to me. Did you run into situations where that amount of time was
needed? Otherwise I'm happy with everything. Thanks for all the hard
work!

Acked-by: Patrick Colp <pjcolp@cs.ubc.ca>


Patrick


On 15 September 2010 09:08, Olaf Hering <olaf@aepfle.de> wrote:
>
> Handle GNTST_eagain status from GNTTABOP_map_grant_ref and GNTTABOP_copy
> operations properly to allow usage of xenpaging without causing crashes or data
> corruption.
>
> Remove the existing retry code from net_rx_action(), dispatch_rw_block_io(),
> net_accel_map_grants_contig() and net_accel_map_iomem_page() and replace all
> relevant HYPERVISOR_grant_table_op() calls with a retry loop.
> This loop is implemented as a macro to allow different GNTTABOP_* args.
> It will sleep up to 33 seconds and wait for the page to be paged in again.
>
> All ->status checks were updated to use the GNTST_* namespace.
> All return values are converted from GNTST_* namespace to 0/-EINVAL, since all
> callers did not use the actual return value.
>
> Signed-off-by: Olaf Hering <olaf@aepfle.de>
>
> ---
> Compiled with x86_64 and i386 configs
>
>  drivers/xen/blkback/blkback.c              |   57 ++++++-----------------------
>  drivers/xen/blkback/common.h               |    2 -
>  drivers/xen/blkback/interface.c            |   22 +++++------
>  drivers/xen/blktap/blktap.c                |   29 ++++++--------
>  drivers/xen/blktap/interface.c             |   22 +++++------
>  drivers/xen/blktap2/device.c               |   34 ++++++++---------
>  drivers/xen/core/gnttab.c                  |    4 +-
>  drivers/xen/gntdev/gntdev.c                |   26 ++++++-------
>  drivers/xen/netback/interface.c            |   26 ++++---------
>  drivers/xen/netback/netback.c              |   52 +++++++-------------------
>  drivers/xen/scsiback/interface.c           |   24 +++++-------
>  drivers/xen/scsiback/scsiback.c            |   16 ++------
>  drivers/xen/sfc_netutil/accel_util.c       |   41 +++++---------------
>  drivers/xen/tpmback/interface.c            |   22 +++++------
>  drivers/xen/tpmback/tpmback.c              |   22 +++--------
>  drivers/xen/usbback/interface.c            |   25 ++++--------
>  drivers/xen/usbback/usbback.c              |   16 ++------
>  drivers/xen/xenbus/xenbus_backend_client.c |   27 ++++++-------
>  include/xen/gnttab.h                       |   38 +++++++++++++++++++
>  19 files changed, 204 insertions(+), 301 deletions(-)
>
> --- linux-2.6.18-xen.hg.orig/drivers/xen/blkback/blkback.c
> +++ linux-2.6.18-xen.hg/drivers/xen/blkback/blkback.c
> @@ -107,7 +107,7 @@ static inline unsigned long vaddr(pendin
>
>
>  static int do_block_io_op(blkif_t *blkif);
> -static int dispatch_rw_block_io(blkif_t *blkif,
> +static void dispatch_rw_block_io(blkif_t *blkif,
>                                 blkif_request_t *req,
>                                 pending_req_t *pending_req);
>  static void make_response(blkif_t *blkif, u64 id,
> @@ -312,13 +312,13 @@ static int do_block_io_op(blkif_t *blkif
>        blkif_request_t req;
>        pending_req_t *pending_req;
>        RING_IDX rc, rp;
> -       int more_to_do = 0, ret;
> +       int more_to_do = 0;
>
>        rc = blk_rings->common.req_cons;
>        rp = blk_rings->common.sring->req_prod;
>        rmb(); /* Ensure we see queued requests up to 'rp'. */
>
> -       while ((rc != rp) || (blkif->is_suspended_req)) {
> +       while ((rc != rp)) {
>
>                if (RING_REQUEST_CONS_OVERFLOW(&blk_rings->common, rc))
>                        break;
> @@ -335,14 +335,6 @@ static int do_block_io_op(blkif_t *blkif
>                        break;
>                }
>
> -        /* Handle the suspended request first, if one exists */
> -        if(blkif->is_suspended_req)
> -        {
> -            memcpy(&req, &blkif->suspended_req, sizeof(req));
> -            blkif->is_suspended_req = 0;
> -            goto handle_request;
> -        }
> -
>                switch (blkif->blk_protocol) {
>                case BLKIF_PROTOCOL_NATIVE:
>                        memcpy(&req, RING_GET_REQUEST(&blk_rings->native, rc), sizeof(req));
> @@ -361,19 +353,17 @@ static int do_block_io_op(blkif_t *blkif
>                /* Apply all sanity checks to /private copy/ of request. */
>                barrier();
>
> -handle_request:
> -        ret = 0;
>                switch (req.operation) {
>                case BLKIF_OP_READ:
>                        blkif->st_rd_req++;
> -                       ret = dispatch_rw_block_io(blkif, &req, pending_req);
> +                       dispatch_rw_block_io(blkif, &req, pending_req);
>                        break;
>                case BLKIF_OP_WRITE_BARRIER:
>                        blkif->st_br_req++;
>                        /* fall through */
>                case BLKIF_OP_WRITE:
>                        blkif->st_wr_req++;
> -                       ret = dispatch_rw_block_io(blkif, &req, pending_req);
> +                       dispatch_rw_block_io(blkif, &req, pending_req);
>                        break;
>                default:
>                        /* A good sign something is wrong: sleep for a while to
> @@ -386,17 +376,6 @@ handle_request:
>                        free_req(pending_req);
>                        break;
>                }
> -        BUG_ON(ret != 0 && ret != -EAGAIN);
> -        /* If we can't handle the request at the moment, save it, and break the
> -         * loop */
> -        if(ret == -EAGAIN)
> -        {
> -            memcpy(&blkif->suspended_req, &req, sizeof(req));
> -            blkif->is_suspended_req = 1;
> -            /* Return "no more work pending", restart will be handled 'out of
> -             * band' */
> -            return 0;
> -        }
>
>                /* Yield point for this unbounded loop. */
>                cond_resched();
> @@ -405,7 +384,7 @@ handle_request:
>        return more_to_do;
>  }
>
> -static int dispatch_rw_block_io(blkif_t *blkif,
> +static void dispatch_rw_block_io(blkif_t *blkif,
>                                 blkif_request_t *req,
>                                 pending_req_t *pending_req)
>  {
> @@ -474,15 +453,13 @@ static int dispatch_rw_block_io(blkif_t
>        ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, map, nseg);
>        BUG_ON(ret);
>
> -#define GENERAL_ERR   (1<<0)
> -#define EAGAIN_ERR    (1<<1)
>        for (i = 0; i < nseg; i++) {
> -               if (unlikely(map[i].status != 0)) {
> +               if (unlikely(map[i].status == GNTST_eagain))
> +                       gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &map[i])
> +               if (unlikely(map[i].status != GNTST_okay)) {
>                        DPRINTK("invalid buffer -- could not remap it\n");
>                        map[i].handle = BLKBACK_INVALID_HANDLE;
> -                       ret |= GENERAL_ERR;
> -            if(map[i].status == GNTST_eagain)
> -                           ret |= EAGAIN_ERR;
> +                       ret = 1;
>                } else {
>                        blkback_pagemap_set(vaddr_pagenr(pending_req, i),
>                                            pending_page(pending_req, i),
> @@ -502,14 +479,6 @@ static int dispatch_rw_block_io(blkif_t
>                        (req->seg[i].first_sect << 9);
>        }
>
> -    /* If any of grant maps failed with GNTST_eagain, suspend and retry later */
> -    if(ret & EAGAIN_ERR)
> -    {
> -        fast_flush_area(pending_req);
> -        free_req(pending_req);
> -        return -EAGAIN;
> -    }
> -
>        if (ret)
>                goto fail_flush;
>
> @@ -575,7 +544,7 @@ static int dispatch_rw_block_io(blkif_t
>        else if (operation == WRITE || operation == WRITE_BARRIER)
>                blkif->st_wr_sect += preq.nr_sects;
>
> -       return 0;
> +       return;
>
>  fail_flush:
>        fast_flush_area(pending_req);
> @@ -583,7 +552,7 @@ static int dispatch_rw_block_io(blkif_t
>        make_response(blkif, req->id, req->operation, BLKIF_RSP_ERROR);
>        free_req(pending_req);
>        msleep(1); /* back off a bit */
> -       return 0;
> +       return;
>
>  fail_put_bio:
>        __end_block_io_op(pending_req, -EINVAL);
> @@ -591,7 +560,7 @@ static int dispatch_rw_block_io(blkif_t
>                bio_put(bio);
>        unplug_queue(blkif);
>        msleep(1); /* back off a bit */
> -       return 0;
> +       return;
>  }
>
>
> --- linux-2.6.18-xen.hg.orig/drivers/xen/blkback/common.h
> +++ linux-2.6.18-xen.hg/drivers/xen/blkback/common.h
> @@ -83,8 +83,6 @@ typedef struct blkif_st {
>        struct task_struct  *xenblkd;
>        unsigned int        waiting_reqs;
>        request_queue_t     *plug;
> -    int                 is_suspended_req;
> -    blkif_request_t     suspended_req;
>
>        /* statistics */
>        unsigned long       st_print;
> --- linux-2.6.18-xen.hg.orig/drivers/xen/blkback/interface.c
> +++ linux-2.6.18-xen.hg/drivers/xen/blkback/interface.c
> @@ -59,25 +59,23 @@ blkif_t *blkif_alloc(domid_t domid)
>  static int map_frontend_page(blkif_t *blkif, unsigned long shared_page)
>  {
>        struct gnttab_map_grant_ref op;
> +       int ret;
>
>        gnttab_set_map_op(&op, (unsigned long)blkif->blk_ring_area->addr,
>                          GNTMAP_host_map, shared_page, blkif->domid);
>
> -    do {
> -           if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
> -                   BUG();
> -        msleep(100);
> -    } while(op.status == GNTST_eagain);
> +       gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &op);
>
> -       if (op.status) {
> -               DPRINTK(" Grant table operation failure !\n");
> -               return op.status;
> +       if (op.status == GNTST_okay) {
> +               blkif->shmem_ref = shared_page;
> +               blkif->shmem_handle = op.handle;
> +               ret = 0;
> +       } else {
> +               DPRINTK(" Grant table operation failure %d!\n", (int)op.status);
> +               ret = -EINVAL;
>        }
>
> -       blkif->shmem_ref = shared_page;
> -       blkif->shmem_handle = op.handle;
> -
> -       return 0;
> +       return ret;
>  }
>
>  static void unmap_frontend_page(blkif_t *blkif)
> --- linux-2.6.18-xen.hg.orig/drivers/xen/blktap/blktap.c
> +++ linux-2.6.18-xen.hg/drivers/xen/blktap/blktap.c
> @@ -1526,19 +1526,17 @@ static void dispatch_rw_block_io(blkif_t
>
>                        uvaddr = MMAP_VADDR(info->user_vstart, usr_idx, i/2);
>
> -                       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;
> +                       gnttab_check_GNTST_eagain_while(GNTTABOP_map_grant_ref, &map[i]);
> +
> +                       if (unlikely(map[i].status != GNTST_okay)) {
> +                               WPRINTK("invalid kernel buffer -- could not remap it\n");
> +                               ret = 1;
>                                map[i].handle = INVALID_GRANT_HANDLE;
>                        }
>
> -                       if (unlikely(map[i+1].status != 0)) {
> -                               WPRINTK("invalid user buffer -- "
> -                                       "could not remap it\n");
> -                               ret |= 1;
> +                       if (unlikely(map[i+1].status != GNTST_okay)) {
> +                               WPRINTK("invalid kernel buffer -- could not remap it\n");
> +                               ret = 1;
>                                map[i+1].handle = INVALID_GRANT_HANDLE;
>                        }
>
> @@ -1565,12 +1563,11 @@ static void dispatch_rw_block_io(blkif_t
>
>                        uvaddr = MMAP_VADDR(info->user_vstart, usr_idx, i);
>
> -                       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;
> +                       gnttab_check_GNTST_eagain_while(GNTTABOP_map_grant_ref, &map[i]);
> +
> +                       if (unlikely(map[i].status != GNTST_okay)) {
> +                               WPRINTK("invalid kernel buffer -- could not remap it\n");
> +                               ret = 1;
>                                map[i].handle = INVALID_GRANT_HANDLE;
>                        }
>
> --- linux-2.6.18-xen.hg.orig/drivers/xen/blktap/interface.c
> +++ linux-2.6.18-xen.hg/drivers/xen/blktap/interface.c
> @@ -59,25 +59,23 @@ blkif_t *tap_alloc_blkif(domid_t domid)
>  static int map_frontend_page(blkif_t *blkif, unsigned long shared_page)
>  {
>        struct gnttab_map_grant_ref op;
> +       int ret;
>
>        gnttab_set_map_op(&op, (unsigned long)blkif->blk_ring_area->addr,
>                          GNTMAP_host_map, shared_page, blkif->domid);
>
> -    do {
> -           if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
> -                   BUG();
> -        msleep(10);
> -    } while(op.status == GNTST_eagain);
> +       gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &op);
>
> -       if (op.status) {
> -               DPRINTK(" Grant table operation failure !\n");
> -               return op.status;
> +       if (op.status == GNTST_okay) {
> +               blkif->shmem_ref = shared_page;
> +               blkif->shmem_handle = op.handle;
> +               ret = 0;
> +       } else {
> +               DPRINTK("Grant table operation failure %d!\n", (int)op.status);
> +               ret = -EINVAL;
>        }
>
> -       blkif->shmem_ref = shared_page;
> -       blkif->shmem_handle = op.handle;
> -
> -       return 0;
> +       return ret;
>  }
>
>  static void unmap_frontend_page(blkif_t *blkif)
> --- linux-2.6.18-xen.hg.orig/drivers/xen/blktap2/device.c
> +++ linux-2.6.18-xen.hg/drivers/xen/blktap2/device.c
> @@ -505,10 +505,10 @@ blktap_map_foreign(struct blktap *tap,
>
>                uvaddr = MMAP_VADDR(ring->user_vstart, usr_idx, i);
>
> -               if (unlikely(table->grants[grant].status)) {
> +               if (unlikely(table->grants[grant].status != GNTST_okay)) {
>                        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);
> +                       /* 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;
>                }
> @@ -517,19 +517,18 @@ blktap_map_foreign(struct blktap *tap,
>                foreign_mfn = table->grants[grant].dev_bus_addr >> PAGE_SHIFT;
>                grant++;
>
> -               if (xen_feature(XENFEAT_auto_translated_physmap))
> -                       goto done;
> -
> -               if (unlikely(table->grants[grant].status)) {
> -                       BTERR("invalid user buffer: could not remap it\n");
> -                       err |= 1;
> +               if (!xen_feature(XENFEAT_auto_translated_physmap)) {
> +                       if (unlikely(table->grants[grant].status != GNTST_okay)) {
> +                               /* This should never happen: blkback should handle eagain first */
> +                               WARN_ON(table->grants[grant].status == GNTST_eagain);
> +                               BTERR("invalid user buffer: could not remap it\n");
> +                               err |= 1;
> +                       }
>                        table->grants[grant].handle = INVALID_GRANT_HANDLE;
> +                       request->handles[i].user = table->grants[grant].handle;
> +                       grant++;
>                }
>
> -               request->handles[i].user = table->grants[grant].handle;
> -               grant++;
> -
> -       done:
>                if (err)
>                        continue;
>
> @@ -602,11 +601,10 @@ blktap_map(struct blktap *tap,
>                set_page_private(tap_page, page_private(page));
>                SetPageBlkback(tap_page);
>
> -               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);
> +               gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &map);
> +
> +               /* 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) {
> --- linux-2.6.18-xen.hg.orig/drivers/xen/core/gnttab.c
> +++ linux-2.6.18-xen.hg/drivers/xen/core/gnttab.c
> @@ -487,7 +487,7 @@ static int gnttab_map(unsigned int start
>                return -ENOSYS;
>        }
>
> -       BUG_ON(rc || setup.status);
> +       BUG_ON(rc || setup.status != GNTST_okay);
>
>        if (shared == NULL)
>                shared = arch_gnttab_alloc_shared(frames);
> @@ -571,7 +571,7 @@ int gnttab_copy_grant_page(grant_ref_t r
>        err = HYPERVISOR_grant_table_op(GNTTABOP_unmap_and_replace,
>                                        &unmap, 1);
>        BUG_ON(err);
> -       BUG_ON(unmap.status);
> +       BUG_ON(unmap.status != GNTST_okay);
>
>        write_sequnlock(&gnttab_dma_lock);
>
> --- linux-2.6.18-xen.hg.orig/drivers/xen/gntdev/gntdev.c
> +++ linux-2.6.18-xen.hg/drivers/xen/gntdev/gntdev.c
> @@ -578,7 +578,7 @@ static int gntdev_mmap (struct file *fli
>        vma->vm_mm->context.has_foreign_mappings = 1;
>  #endif
>
> -    exit_ret = -ENOMEM;
> +       exit_ret = -ENOMEM;
>        for (i = 0; i < size; ++i) {
>
>                flags = GNTMAP_host_map;
> @@ -599,8 +599,8 @@ static int gntdev_mmap (struct file *fli
>                ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref,
>                                                &op, 1);
>                BUG_ON(ret);
> -               if (op.status) {
> -            if(op.status != GNTST_eagain)
> +               if (op.status != GNTST_okay) {
> +                       if (op.status != GNTST_eagain)
>                                printk(KERN_ERR "Error mapping the grant reference "
>                                       "into the kernel (%d). domid = %d; ref = %d\n",
>                                       op.status,
> @@ -608,9 +608,9 @@ static int gntdev_mmap (struct file *fli
>                                       .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;
> +                       else
> +                               /* Propagate eagain instead of trying to fix it up */
> +                               exit_ret = -EAGAIN;
>                        goto undo_map_out;
>                }
>
> @@ -679,7 +679,7 @@ static int gntdev_mmap (struct file *fli
>                        ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref,
>                                                        &op, 1);
>                        BUG_ON(ret);
> -                       if (op.status) {
> +                       if (op.status != GNTST_okay) {
>                                printk(KERN_ERR "Error mapping the grant "
>                                       "reference into user space (%d). domid "
>                                       "= %d; ref = %d\n", op.status,
> @@ -687,9 +687,9 @@ static int gntdev_mmap (struct file *fli
>                                       .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);
> +                               /* This should never happen after we've mapped into
> +                               * the kernel space. */
> +                               BUG_ON(op.status == GNTST_eagain);
>                                goto undo_map_out;
>                        }
>
> @@ -713,7 +713,7 @@ static int gntdev_mmap (struct file *fli
>                }
>
>        }
> -    exit_ret = 0;
> +       exit_ret = 0;
>
>        up_write(&private_data->grants_sem);
>        return exit_ret;
> @@ -785,7 +785,7 @@ static pte_t gntdev_clear_pte(struct vm_
>                        ret = HYPERVISOR_grant_table_op(
>                                GNTTABOP_unmap_grant_ref, &op, 1);
>                        BUG_ON(ret);
> -                       if (op.status)
> +                       if (op.status != GNTST_okay)
>                                printk("User unmap grant status = %d\n",
>                                       op.status);
>                } else {
> @@ -802,7 +802,7 @@ static pte_t gntdev_clear_pte(struct vm_
>                ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref,
>                                                &op, 1);
>                BUG_ON(ret);
> -               if (op.status)
> +               if (op.status != GNTST_okay)
>                        printk("Kernel unmap grant status = %d\n", op.status);
>
>
> --- linux-2.6.18-xen.hg.orig/drivers/xen/netback/interface.c
> +++ linux-2.6.18-xen.hg/drivers/xen/netback/interface.c
> @@ -251,15 +251,11 @@ static int map_frontend_pages(
>
>        gnttab_set_map_op(&op, (unsigned long)netif->tx_comms_area->addr,
>                          GNTMAP_host_map, tx_ring_ref, netif->domid);
> -    do {
> -               if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
> -                       BUG();
> -        msleep(10);
> -    } while(op.status == GNTST_eagain);
> -
> -       if (op.status) {
> -               DPRINTK(" Gnttab failure mapping tx_ring_ref!\n");
> -               return op.status;
> +       gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &op);
> +
> +       if (op.status != GNTST_okay) {
> +               DPRINTK(" Gnttab failure mapping tx_ring_ref %d!\n", (int)op.status);
> +               return -EINVAL;
>        }
>
>        netif->tx_shmem_ref    = tx_ring_ref;
> @@ -267,13 +263,9 @@ static int map_frontend_pages(
>
>        gnttab_set_map_op(&op, (unsigned long)netif->rx_comms_area->addr,
>                          GNTMAP_host_map, rx_ring_ref, netif->domid);
> -    do {
> -           if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
> -                   BUG();
> -        msleep(10);
> -    } while(op.status == GNTST_eagain);
> +       gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &op);
>
> -       if (op.status) {
> +       if (op.status != GNTST_okay) {
>                struct gnttab_unmap_grant_ref unop;
>
>                gnttab_set_unmap_op(&unop,
> @@ -281,8 +273,8 @@ static int map_frontend_pages(
>                                    GNTMAP_host_map, netif->tx_shmem_handle);
>                VOID(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref,
>                                               &unop, 1));
> -               DPRINTK(" Gnttab failure mapping rx_ring_ref!\n");
> -               return op.status;
> +               DPRINTK(" Gnttab failure mapping rx_ring_ref %d!\n", (int)op.status);
> +               return -EINVAL;
>        }
>
>        netif->rx_shmem_ref    = rx_ring_ref;
> --- linux-2.6.18-xen.hg.orig/drivers/xen/netback/netback.c
> +++ linux-2.6.18-xen.hg/drivers/xen/netback/netback.c
> @@ -494,8 +494,7 @@ static inline void netbk_free_pages(int
>    used to set up the operations on the top of
>    netrx_pending_operations, which have since been done.  Check that
>    they didn't give any errors and advance over them. */
> -static int netbk_check_gop(int nr_frags, domid_t domid,
> -                          struct netrx_pending_operations *npo, int *eagain)
> +static int netbk_check_gop(int nr_frags, domid_t domid, struct netrx_pending_operations *npo)
>  {
>        multicall_entry_t *mcl;
>        gnttab_transfer_t *gop;
> @@ -503,17 +502,15 @@ static int netbk_check_gop(int nr_frags,
>        int status = NETIF_RSP_OKAY;
>        int i;
>
> -    *eagain = 0;
> -
>        for (i = 0; i <= nr_frags; i++) {
>                if (npo->meta[npo->meta_cons + i].copy) {
>                        copy_op = npo->copy + npo->copy_cons++;
> -                       if (copy_op->status != GNTST_okay) {
> +                       if (unlikely(copy_op->status == GNTST_eagain))
> +                               gnttab_check_GNTST_eagain_while(GNTTABOP_copy, copy_op);
> +                       if (unlikely(copy_op->status != GNTST_okay)) {
>                                DPRINTK("Bad status %d from copy to DOM%d.\n",
>                                        copy_op->status, domid);
>                                status = NETIF_RSP_ERROR;
> -                if(copy_op->status == GNTST_eagain)
> -                    *eagain = 1;
>                        }
>                } else {
>                        if (!xen_feature(XENFEAT_auto_translated_physmap)) {
> @@ -524,7 +521,7 @@ static int netbk_check_gop(int nr_frags,
>
>                        gop = npo->trans + npo->trans_cons++;
>                        /* Check the reassignment error code. */
> -                       if (gop->status != 0) {
> +                       if (unlikely(gop->status != GNTST_okay)) {
>                                DPRINTK("Bad status %d from grant transfer to DOM%u\n",
>                                        gop->status, domid);
>                                /*
> @@ -533,8 +530,6 @@ static int netbk_check_gop(int nr_frags,
>                                 * a fatal error anyway.
>                                 */
>                                BUG_ON(gop->status == GNTST_bad_page);
> -                if(gop->status == GNTST_eagain)
> -                    *eagain = 1;
>                                status = NETIF_RSP_ERROR;
>                        }
>                }
> @@ -576,7 +571,6 @@ static void net_rx_action(unsigned long
>        int nr_frags;
>        int count;
>        unsigned long offset;
> -    int eagain;
>
>        /*
>         * Putting hundreds of bytes on the stack is considered rude.
> @@ -680,7 +674,7 @@ static void net_rx_action(unsigned long
>
>                netif = netdev_priv(skb->dev);
>
> -               status = netbk_check_gop(nr_frags, netif->domid, &npo, &eagain);
> +               status = netbk_check_gop(nr_frags, netif->domid, &npo);
>
>                /* We can't rely on skb_release_data to release the
>                   pages used by fragments for us, since it tries to
> @@ -691,22 +685,14 @@ static void net_rx_action(unsigned long
>                /* (Freeing the fragments is safe since we copy
>                   non-linear skbs destined for flipping interfaces) */
>                if (!netif->copying_receiver) {
> -            /*
> -             * Cannot handle failed grant transfers at the moment (because
> -             * mmu_updates likely completed)
> -             */
> -            BUG_ON(eagain);
>                        atomic_set(&(skb_shinfo(skb)->dataref), 1);
>                        skb_shinfo(skb)->frag_list = NULL;
>                        skb_shinfo(skb)->nr_frags = 0;
>                        netbk_free_pages(nr_frags, meta + npo.meta_cons + 1);
>                }
>
> -        if(!eagain)
> -        {
> -                   netif->stats.tx_bytes += skb->len;
> -                   netif->stats.tx_packets++;
> -        }
> +               netif->stats.tx_bytes += skb->len;
> +               netif->stats.tx_packets++;
>
>                id = meta[npo.meta_cons].id;
>                flags = nr_frags ? NETRXF_more_data : 0;
> @@ -756,18 +742,8 @@ static void net_rx_action(unsigned long
>                    !netbk_queue_full(netif))
>                        netif_wake_queue(netif->dev);
>
> -        if(!eagain || netbk_queue_full(netif))
> -        {
> -                   netif_put(netif);
> -                   dev_kfree_skb(skb);
> -                   netif->stats.tx_dropped += !!eagain;
> -        }
> -        else
> -        {
> -               netif->rx_req_cons_peek += skb_shinfo(skb)->nr_frags + 1 +
> -                                  !!skb_shinfo(skb)->gso_size;
> -            skb_queue_head(&rx_queue, skb);
> -        }
> +               netif_put(netif);
> +               dev_kfree_skb(skb);
>
>                npo.meta_cons += nr_frags + 1;
>        }
> @@ -1107,7 +1083,7 @@ static int netbk_tx_check_mop(struct sk_
>
>        /* Check status of header. */
>        err = mop->status;
> -       if (unlikely(err)) {
> +       if (unlikely(err != GNTST_okay)) {
>                txp = &pending_tx_info[pending_idx].req;
>                make_tx_response(netif, txp, NETIF_RSP_ERROR);
>                pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx;
> @@ -1128,12 +1104,12 @@ static int netbk_tx_check_mop(struct sk_
>
>                /* Check error status: if okay then remember grant handle. */
>                newerr = (++mop)->status;
> -               if (likely(!newerr)) {
> +               if (likely(newerr == GNTST_okay)) {
>                        set_phys_to_machine(idx_to_pfn(pending_idx),
>                                FOREIGN_FRAME(mop->dev_bus_addr>>PAGE_SHIFT));
>                        grant_tx_handle[pending_idx] = mop->handle;
>                        /* Had a previous error? Invalidate this fragment. */
> -                       if (unlikely(err))
> +                       if (unlikely(err != GNTST_okay))
>                                netif_idx_release(pending_idx);
>                        continue;
>                }
> @@ -1145,7 +1121,7 @@ static int netbk_tx_check_mop(struct sk_
>                netif_put(netif);
>
>                /* Not the first error? Preceding frags already invalidated. */
> -               if (err)
> +               if (err != GNTST_okay)
>                        continue;
>
>                /* First error: invalidate header and preceding fragments. */
> --- linux-2.6.18-xen.hg.orig/drivers/xen/scsiback/interface.c
> +++ linux-2.6.18-xen.hg/drivers/xen/scsiback/interface.c
> @@ -64,27 +64,23 @@ static int map_frontend_page( struct vsc
>                                unsigned long ring_ref)
>  {
>        struct gnttab_map_grant_ref op;
> -       int err;
> +       int ret;
>
>        gnttab_set_map_op(&op, (unsigned long)info->ring_area->addr,
>                                GNTMAP_host_map, ring_ref,
>                                info->domid);
> +       gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &op);
>
> -    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");
> -               return op.status;
> +       if (op.status != GNTST_okay) {
> +               printk(KERN_ERR "scsiback: Grant table operation failure %d!\n", (int)op.status);
> +               ret = -EINVAL;
> +       } else {
> +               info->shmem_ref    = ring_ref;
> +               info->shmem_handle = op.handle;
> +               ret = 0;
>        }
>
> -       info->shmem_ref    = ring_ref;
> -       info->shmem_handle = op.handle;
> -
> -       return (GNTST_okay);
> +       return ret;
>  }
>
>  static void unmap_frontend_page(struct vscsibk_info *info)
> --- linux-2.6.18-xen.hg.orig/drivers/xen/scsiback/scsiback.c
> +++ linux-2.6.18-xen.hg/drivers/xen/scsiback/scsiback.c
> @@ -279,22 +279,14 @@ static int scsiback_gnttab_data_map(vscs
>
>                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;
>
> -                       if (unlikely(map[i].status != 0)) {
> +                       /* Retry maps with GNTST_eagain */
> +                       if (unlikely(map[i].status == GNTST_eagain))
> +                               gnttab_check_GNTST_eagain_while(GNTTABOP_map_grant_ref, &map[i]);
> +                       if (unlikely(map[i].status != GNTST_okay)) {
>                                printk(KERN_ERR "scsiback: invalid buffer -- could not remap it\n");
>                                map[i].handle = SCSIBACK_INVALID_HANDLE;
>                                err |= 1;
> --- linux-2.6.18-xen.hg.orig/drivers/xen/sfc_netutil/accel_util.c
> +++ linux-2.6.18-xen.hg/drivers/xen/sfc_netutil/accel_util.c
> @@ -71,24 +71,27 @@ static int net_accel_map_grant(struct xe
>                               u64 *dev_bus_addr, unsigned flags)
>  {
>        struct gnttab_map_grant_ref op;
> +       int ret;
>
>        gnttab_set_map_op(&op, (unsigned long)vaddr, flags,
>                          gnt_ref, dev->otherend_id);
>
> -       BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1));
> +       gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &op);
>
>        if (op.status != GNTST_okay) {
>                xenbus_dev_error
>                        (dev, op.status,
>                         "failed mapping in shared page %d from domain %d\n",
>                         gnt_ref, dev->otherend_id);
> +               ret = -EINVAL;
>        } else {
>                *handle = op.handle;
>                if (dev_bus_addr)
>                        *dev_bus_addr = op.dev_bus_addr;
> +               ret = 0;
>        }
>
> -       return op.status;
> +       return ret;
>  }
>
>
> @@ -112,7 +115,7 @@ static int net_accel_unmap_grant(struct
>                                 "failed unmapping page at handle %d error %d\n",
>                                 handle, op.status);
>
> -       return op.status;
> +       return op.status == GNTST_okay ? 0 : -EINVAL;
>  }
>
>
> @@ -144,7 +147,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, int *errno)
> +                                        unsigned flags, void **priv)
>  {
>        struct net_accel_valloc_grant_mapping *map;
>        struct vm_struct *vm;
> @@ -172,16 +175,12 @@ static void *net_accel_map_grants_valloc
>
>        /* 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);
> +               if (rc < 0)
>                        goto undo;
> -        }
>                addr = (void*)((unsigned long)addr + PAGE_SIZE);
>        }
>
> @@ -230,16 +229,7 @@ void *net_accel_map_grants_contig(struct
>                                unsigned *grants, int npages,
>                                void **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;
> +    return net_accel_map_grants_valloc(dev, grants, npages, GNTMAP_host_map, priv);
>  }
>  EXPORT_SYMBOL(net_accel_map_grants_contig);
>
> @@ -255,16 +245,7 @@ EXPORT_SYMBOL(net_accel_unmap_grants_con
>  void *net_accel_map_iomem_page(struct xenbus_device *dev, int gnt_ref,
>                             void **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;
> +       return net_accel_map_grants_valloc(dev, &gnt_ref, 1, GNTMAP_host_map, priv);
>  }
>  EXPORT_SYMBOL(net_accel_map_iomem_page);
>
> --- linux-2.6.18-xen.hg.orig/drivers/xen/tpmback/interface.c
> +++ linux-2.6.18-xen.hg/drivers/xen/tpmback/interface.c
> @@ -81,25 +81,23 @@ tpmif_t *tpmif_find(domid_t domid, struc
>  static int map_frontend_page(tpmif_t *tpmif, unsigned long shared_page)
>  {
>        struct gnttab_map_grant_ref op;
> +       int ret;
>
>        gnttab_set_map_op(&op, (unsigned long)tpmif->tx_area->addr,
>                          GNTMAP_host_map, shared_page, tpmif->domid);
>
> -    do {
> -           if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
> -                   BUG();
> -        msleep(10);
> -    } while(op.status == GNTST_eagain);
> +       gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &op);
>
> -       if (op.status) {
> -               DPRINTK(" Grant table operation failure !\n");
> -               return op.status;
> +       if (op.status != GNTST_okay) {
> +               DPRINTK(" Grant table operation failure %d!\n", (int)op.status);
> +               ret = -EINVAL;
> +       } else {
> +               tpmif->shmem_ref = shared_page;
> +               tpmif->shmem_handle = op.handle;
> +               ret = 0;
>        }
>
> -       tpmif->shmem_ref = shared_page;
> -       tpmif->shmem_handle = op.handle;
> -
> -       return 0;
> +       return ret;
>  }
>
>  static void unmap_frontend_page(tpmif_t *tpmif)
> --- linux-2.6.18-xen.hg.orig/drivers/xen/tpmback/tpmback.c
> +++ linux-2.6.18-xen.hg/drivers/xen/tpmback/tpmback.c
> @@ -257,20 +257,15 @@ int _packet_write(struct packet *pak,
>                gnttab_set_map_op(&map_op, idx_to_kaddr(tpmif, i),
>                                  GNTMAP_host_map, tx->ref, tpmif->domid);
>
> -        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);
> +               gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &map_op);
>
> -               handle = map_op.handle;
> -
> -               if (map_op.status) {
> +               if (map_op.status != GNTST_okay) {
>                        DPRINTK(" Grant table operation failure !\n");
>                        return 0;
>                }
>
> +               handle = map_op.handle;
> +
>                tocopy = min_t(size_t, size - offset, PAGE_SIZE);
>
>                if (copy_from_buffer((void *)(idx_to_kaddr(tpmif, i) |
> @@ -397,14 +392,9 @@ static int packet_read_shmem(struct pack
>                gnttab_set_map_op(&map_op, idx_to_kaddr(tpmif, i),
>                                  GNTMAP_host_map, tx->ref, tpmif->domid);
>
> -        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);
> +               gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &map_op);
>
> -               if (map_op.status) {
> +               if (map_op.status != GNTST_okay) {
>                        DPRINTK(" Grant table operation failure !\n");
>                        return -EFAULT;
>                }
> --- linux-2.6.18-xen.hg.orig/drivers/xen/usbback/interface.c
> +++ linux-2.6.18-xen.hg/drivers/xen/usbback/interface.c
> @@ -110,16 +110,11 @@ static int map_frontend_pages(usbif_t *u
>        gnttab_set_map_op(&op, (unsigned long)usbif->urb_ring_area->addr,
>                          GNTMAP_host_map, urb_ring_ref, usbif->domid);
>
> +       gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &op);
>
> -    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");
> -               return op.status;
> +       if (op.status != GNTST_okay) {
> +               printk(KERN_ERR "grant table failure mapping urb_ring_ref %d\n", (int)op.status);
> +               return -EINVAL;
>        }
>
>        usbif->urb_shmem_ref = urb_ring_ref;
> @@ -128,21 +123,17 @@ static int map_frontend_pages(usbif_t *u
>        gnttab_set_map_op(&op, (unsigned long)usbif->conn_ring_area->addr,
>                          GNTMAP_host_map, conn_ring_ref, usbif->domid);
>
> -    do {
> -           if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
> -                   BUG();
> -        msleep(10);
> -    } while (op.status == GNTST_eagain);
> +       gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &op);
>
> -       if (op.status) {
> +       if (op.status != GNTST_okay) {
>                struct gnttab_unmap_grant_ref unop;
>                gnttab_set_unmap_op(&unop,
>                                (unsigned long) usbif->urb_ring_area->addr,
>                                GNTMAP_host_map, usbif->urb_shmem_handle);
>                VOID(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &unop,
>                                1));
> -               printk(KERN_ERR "grant table failure mapping conn_ring_ref\n");
> -               return op.status;
> +               printk(KERN_ERR "grant table failure mapping conn_ring_ref %d\n", (int)op.status);
> +               return -EINVAL;
>        }
>
>        usbif->conn_shmem_ref = conn_ring_ref;
> --- linux-2.6.18-xen.hg.orig/drivers/xen/usbback/usbback.c
> +++ linux-2.6.18-xen.hg/drivers/xen/usbback/usbback.c
> @@ -392,19 +392,13 @@ static int usbbk_gnttab_map(usbif_t *usb
>                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)) {
> +                       /* Make sure than none of the map ops failed with GNTST_eagain */
> +                       if (unlikely(map[i].status == GNTST_eagain))
> +                               gnttab_check_GNTST_eagain_while(GNTTABOP_map_grant_ref, &map[i]);
> +
> +                       if (unlikely(map[i].status != GNTST_okay)) {
>                                printk(KERN_ERR "usbback: invalid buffer -- could not remap it\n");
>                                map[i].handle = USBBACK_INVALID_HANDLE;
>                                ret |= 1;
> --- linux-2.6.18-xen.hg.orig/drivers/xen/xenbus/xenbus_backend_client.c
> +++ linux-2.6.18-xen.hg/drivers/xen/xenbus/xenbus_backend_client.c
> @@ -49,11 +49,7 @@ struct vm_struct *xenbus_map_ring_valloc
>        gnttab_set_map_op(&op, (unsigned long)area->addr, GNTMAP_host_map,
>                          gnt_ref, dev->otherend_id);
>
> -    do {
> -           if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
> -                   BUG();
> -        msleep(10);
> -    } while(op.status == GNTST_eagain);
> +       gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &op);
>
>        if (op.status != GNTST_okay) {
>                free_vm_area(area);
> @@ -61,7 +57,7 @@ struct vm_struct *xenbus_map_ring_valloc
>                                 "mapping in shared page %d from domain %d",
>                                 gnt_ref, dev->otherend_id);
>                BUG_ON(!IS_ERR(ERR_PTR(op.status)));
> -               return ERR_PTR(op.status);
> +               return ERR_PTR(-EINVAL);
>        }
>
>        /* Stuff the handle in an unused field */
> @@ -76,23 +72,24 @@ int xenbus_map_ring(struct xenbus_device
>                   grant_handle_t *handle, void *vaddr)
>  {
>        struct gnttab_map_grant_ref op;
> +       int ret;
>
>        gnttab_set_map_op(&op, (unsigned long)vaddr, GNTMAP_host_map,
>                          gnt_ref, dev->otherend_id);
> -    do {
> -           if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
> -                   BUG();
> -        msleep(10);
> -    } while(op.status == GNTST_eagain);
> +
> +       gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &op);
>
>        if (op.status != GNTST_okay) {
>                xenbus_dev_fatal(dev, op.status,
>                                 "mapping in shared page %d from domain %d",
>                                 gnt_ref, dev->otherend_id);
> -       } else
> +               ret = -EINVAL;
> +       } else {
>                *handle = op.handle;
> +               ret = 0;
> +       }
>
> -       return op.status;
> +       return ret;
>  }
>  EXPORT_SYMBOL_GPL(xenbus_map_ring);
>
> @@ -115,7 +112,7 @@ int xenbus_unmap_ring_vfree(struct xenbu
>                                 "unmapping page at handle %d error %d",
>                                 (int16_t)area->phys_addr, op.status);
>
> -       return op.status;
> +       return op.status == GNTST_okay ? 0 : -EINVAL;
>  }
>  EXPORT_SYMBOL_GPL(xenbus_unmap_ring_vfree);
>
> @@ -135,7 +132,7 @@ int xenbus_unmap_ring(struct xenbus_devi
>                                 "unmapping page at handle %d error %d",
>                                 handle, op.status);
>
> -       return op.status;
> +       return op.status == GNTST_okay ? 0 : -EINVAL;
>  }
>  EXPORT_SYMBOL_GPL(xenbus_unmap_ring);
>
> --- linux-2.6.18-xen.hg.orig/include/xen/gnttab.h
> +++ linux-2.6.18-xen.hg/include/xen/gnttab.h
> @@ -40,6 +40,7 @@
>  #include <asm/hypervisor.h>
>  #include <asm/maddr.h> /* maddr_t */
>  #include <linux/mm.h>
> +#include <linux/delay.h>
>  #include <xen/interface/grant_table.h>
>  #include <xen/features.h>
>
> @@ -161,4 +162,41 @@ gnttab_set_replace_op(struct gnttab_unma
>        unmap->handle = handle;
>  }
>
> +#define gnttab_check_GNTST_eagain_while(__HCop, __HCarg_p)                     \
> +{                                                                              \
> +       u8 __hc_delay = 1;                                                      \
> +       int __ret;                                                              \
> +       while (unlikely((__HCarg_p)->status == GNTST_eagain && __hc_delay)) {   \
> +               msleep(__hc_delay++);                                           \
> +               __ret = HYPERVISOR_grant_table_op(__HCop, (__HCarg_p), 1);      \
> +               BUG_ON(__ret);                                                  \
> +       }                                                                       \
> +       if (__hc_delay == 0) {                                                  \
> +               printk(KERN_ERR "%s: %s gnt busy\n", __func__, current->comm);  \
> +               (__HCarg_p)->status = GNTST_bad_page;                           \
> +       }                                                                       \
> +       if ((__HCarg_p)->status != GNTST_okay)                                  \
> +               printk(KERN_ERR "%s: %s gnt status %x\n",                       \
> +                       __func__, current->comm, (__HCarg_p)->status);          \
> +}
> +
> +#define gnttab_check_GNTST_eagain_do_while(__HCop, __HCarg_p)                  \
> +{                                                                              \
> +       u8 __hc_delay = 1;                                                      \
> +       int __ret;                                                              \
> +       do {                                                                    \
> +               __ret = HYPERVISOR_grant_table_op(__HCop, (__HCarg_p), 1);      \
> +               BUG_ON(__ret);                                                  \
> +               if ((__HCarg_p)->status == GNTST_eagain)                        \
> +                       msleep(__hc_delay++);                                   \
> +       } while ((__HCarg_p)->status == GNTST_eagain && __hc_delay);            \
> +       if (__hc_delay == 0) {                                                  \
> +               printk(KERN_ERR "%s: %s gnt busy\n", __func__, current->comm);  \
> +               (__HCarg_p)->status = GNTST_bad_page;                           \
> +       }                                                                       \
> +       if ((__HCarg_p)->status != GNTST_okay)                                  \
> +               printk(KERN_ERR "%s: %s gnt status %x\n",                       \
> +                       __func__, current->comm, (__HCarg_p)->status);          \
> +}
> +
>  #endif /* __ASM_GNTTAB_H__ */
>
>
Re: Re: [PATCH] xenpaging: handle GNTST_eagain in kernel drivers [ In reply to ]
Olaf,

The patch doesn't apply for me to the linux-2.6.18-xen tree. I seem to have
problems with very large inline patches getting corrupted by our mail
server. You might want to try resending as an attachment.

-- Keir

On 16/09/2010 04:44, "Patrick Colp" <pjcolp@cs.ubc.ca> wrote:

> Is there any particular reason for 33 seconds? This number seems a bit
> high to me. Did you run into situations where that amount of time was
> needed? Otherwise I'm happy with everything. Thanks for all the hard
> work!
>
> Acked-by: Patrick Colp <pjcolp@cs.ubc.ca>
>
>
> Patrick
>
>
> On 15 September 2010 09:08, Olaf Hering <olaf@aepfle.de> wrote:
>>
>> Handle GNTST_eagain status from GNTTABOP_map_grant_ref and GNTTABOP_copy
>> operations properly to allow usage of xenpaging without causing crashes or
>> data
>> corruption.
>>
>> Remove the existing retry code from net_rx_action(), dispatch_rw_block_io(),
>> net_accel_map_grants_contig() and net_accel_map_iomem_page() and replace all
>> relevant HYPERVISOR_grant_table_op() calls with a retry loop.
>> This loop is implemented as a macro to allow different GNTTABOP_* args.
>> It will sleep up to 33 seconds and wait for the page to be paged in again.
>>
>> All ->status checks were updated to use the GNTST_* namespace.
>> All return values are converted from GNTST_* namespace to 0/-EINVAL, since
>> all
>> callers did not use the actual return value.
>>
>> Signed-off-by: Olaf Hering <olaf@aepfle.de>
>>
>> ---
>> Compiled with x86_64 and i386 configs
>>
>> drivers/xen/blkback/blkback.c | 57
>> ++++++-----------------------
>> drivers/xen/blkback/common.h | 2 -
>> drivers/xen/blkback/interface.c | 22 +++++------
>> drivers/xen/blktap/blktap.c | 29 ++++++--------
>> drivers/xen/blktap/interface.c | 22 +++++------
>> drivers/xen/blktap2/device.c | 34 ++++++++---------
>> drivers/xen/core/gnttab.c | 4 +-
>> drivers/xen/gntdev/gntdev.c | 26 ++++++-------
>> drivers/xen/netback/interface.c | 26 ++++---------
>> drivers/xen/netback/netback.c | 52 +++++++-------------------
>> drivers/xen/scsiback/interface.c | 24 +++++-------
>> drivers/xen/scsiback/scsiback.c | 16 ++------
>> drivers/xen/sfc_netutil/accel_util.c | 41 +++++---------------
>> drivers/xen/tpmback/interface.c | 22 +++++------
>> drivers/xen/tpmback/tpmback.c | 22 +++--------
>> drivers/xen/usbback/interface.c | 25 ++++--------
>> drivers/xen/usbback/usbback.c | 16 ++------
>> drivers/xen/xenbus/xenbus_backend_client.c | 27 ++++++-------
>> include/xen/gnttab.h | 38 +++++++++++++++++++
>> 19 files changed, 204 insertions(+), 301 deletions(-)
>>
>> --- linux-2.6.18-xen.hg.orig/drivers/xen/blkback/blkback.c
>> +++ linux-2.6.18-xen.hg/drivers/xen/blkback/blkback.c
>> @@ -107,7 +107,7 @@ static inline unsigned long vaddr(pendin
>>
>>
>> static int do_block_io_op(blkif_t *blkif);
>> -static int dispatch_rw_block_io(blkif_t *blkif,
>> +static void dispatch_rw_block_io(blkif_t *blkif,
>> blkif_request_t *req,
>> pending_req_t *pending_req);
>> static void make_response(blkif_t *blkif, u64 id,
>> @@ -312,13 +312,13 @@ static int do_block_io_op(blkif_t *blkif
>> blkif_request_t req;
>> pending_req_t *pending_req;
>> RING_IDX rc, rp;
>> - int more_to_do = 0, ret;
>> + int more_to_do = 0;
>>
>> rc = blk_rings->common.req_cons;
>> rp = blk_rings->common.sring->req_prod;
>> rmb(); /* Ensure we see queued requests up to 'rp'. */
>>
>> - while ((rc != rp) || (blkif->is_suspended_req)) {
>> + while ((rc != rp)) {
>>
>> if (RING_REQUEST_CONS_OVERFLOW(&blk_rings->common, rc))
>> break;
>> @@ -335,14 +335,6 @@ static int do_block_io_op(blkif_t *blkif
>> break;
>> }
>>
>> - /* Handle the suspended request first, if one exists */
>> - if(blkif->is_suspended_req)
>> - {
>> - memcpy(&req, &blkif->suspended_req, sizeof(req));
>> - blkif->is_suspended_req = 0;
>> - goto handle_request;
>> - }
>> -
>> switch (blkif->blk_protocol) {
>> case BLKIF_PROTOCOL_NATIVE:
>> memcpy(&req, RING_GET_REQUEST(&blk_rings->native, rc),
>> sizeof(req));
>> @@ -361,19 +353,17 @@ static int do_block_io_op(blkif_t *blkif
>> /* Apply all sanity checks to /private copy/ of request. */
>> barrier();
>>
>> -handle_request:
>> - ret = 0;
>> switch (req.operation) {
>> case BLKIF_OP_READ:
>> blkif->st_rd_req++;
>> - ret = dispatch_rw_block_io(blkif, &req, pending_req);
>> + dispatch_rw_block_io(blkif, &req, pending_req);
>> break;
>> case BLKIF_OP_WRITE_BARRIER:
>> blkif->st_br_req++;
>> /* fall through */
>> case BLKIF_OP_WRITE:
>> blkif->st_wr_req++;
>> - ret = dispatch_rw_block_io(blkif, &req, pending_req);
>> + dispatch_rw_block_io(blkif, &req, pending_req);
>> break;
>> default:
>> /* A good sign something is wrong: sleep for a while
>> to
>> @@ -386,17 +376,6 @@ handle_request:
>> free_req(pending_req);
>> break;
>> }
>> - BUG_ON(ret != 0 && ret != -EAGAIN);
>> - /* If we can't handle the request at the moment, save it, and break
>> the
>> - * loop */
>> - if(ret == -EAGAIN)
>> - {
>> - memcpy(&blkif->suspended_req, &req, sizeof(req));
>> - blkif->is_suspended_req = 1;
>> - /* Return "no more work pending", restart will be handled 'out
>> of
>> - * band' */
>> - return 0;
>> - }
>>
>> /* Yield point for this unbounded loop. */
>> cond_resched();
>> @@ -405,7 +384,7 @@ handle_request:
>> return more_to_do;
>> }
>>
>> -static int dispatch_rw_block_io(blkif_t *blkif,
>> +static void dispatch_rw_block_io(blkif_t *blkif,
>> blkif_request_t *req,
>> pending_req_t *pending_req)
>> {
>> @@ -474,15 +453,13 @@ static int dispatch_rw_block_io(blkif_t
>> ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, map, nseg);
>> BUG_ON(ret);
>>
>> -#define GENERAL_ERR (1<<0)
>> -#define EAGAIN_ERR (1<<1)
>> for (i = 0; i < nseg; i++) {
>> - if (unlikely(map[i].status != 0)) {
>> + if (unlikely(map[i].status == GNTST_eagain))
>> +
>> gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &map[i])
>> + if (unlikely(map[i].status != GNTST_okay)) {
>> DPRINTK("invalid buffer -- could not remap it\n");
>> map[i].handle = BLKBACK_INVALID_HANDLE;
>> - ret |= GENERAL_ERR;
>> - if(map[i].status == GNTST_eagain)
>> - ret |= EAGAIN_ERR;
>> + ret = 1;
>> } else {
>> blkback_pagemap_set(vaddr_pagenr(pending_req, i),
>> pending_page(pending_req, i),
>> @@ -502,14 +479,6 @@ static int dispatch_rw_block_io(blkif_t
>> (req->seg[i].first_sect << 9);
>> }
>>
>> - /* If any of grant maps failed with GNTST_eagain, suspend and retry
>> later */
>> - if(ret & EAGAIN_ERR)
>> - {
>> - fast_flush_area(pending_req);
>> - free_req(pending_req);
>> - return -EAGAIN;
>> - }
>> -
>> if (ret)
>> goto fail_flush;
>>
>> @@ -575,7 +544,7 @@ static int dispatch_rw_block_io(blkif_t
>> else if (operation == WRITE || operation == WRITE_BARRIER)
>> blkif->st_wr_sect += preq.nr_sects;
>>
>> - return 0;
>> + return;
>>
>> fail_flush:
>> fast_flush_area(pending_req);
>> @@ -583,7 +552,7 @@ static int dispatch_rw_block_io(blkif_t
>> make_response(blkif, req->id, req->operation, BLKIF_RSP_ERROR);
>> free_req(pending_req);
>> msleep(1); /* back off a bit */
>> - return 0;
>> + return;
>>
>> fail_put_bio:
>> __end_block_io_op(pending_req, -EINVAL);
>> @@ -591,7 +560,7 @@ static int dispatch_rw_block_io(blkif_t
>> bio_put(bio);
>> unplug_queue(blkif);
>> msleep(1); /* back off a bit */
>> - return 0;
>> + return;
>> }
>>
>>
>> --- linux-2.6.18-xen.hg.orig/drivers/xen/blkback/common.h
>> +++ linux-2.6.18-xen.hg/drivers/xen/blkback/common.h
>> @@ -83,8 +83,6 @@ typedef struct blkif_st {
>> struct task_struct *xenblkd;
>> unsigned int waiting_reqs;
>> request_queue_t *plug;
>> - int is_suspended_req;
>> - blkif_request_t suspended_req;
>>
>> /* statistics */
>> unsigned long st_print;
>> --- linux-2.6.18-xen.hg.orig/drivers/xen/blkback/interface.c
>> +++ linux-2.6.18-xen.hg/drivers/xen/blkback/interface.c
>> @@ -59,25 +59,23 @@ blkif_t *blkif_alloc(domid_t domid)
>> static int map_frontend_page(blkif_t *blkif, unsigned long shared_page)
>> {
>> struct gnttab_map_grant_ref op;
>> + int ret;
>>
>> gnttab_set_map_op(&op, (unsigned long)blkif->blk_ring_area->addr,
>> GNTMAP_host_map, shared_page, blkif->domid);
>>
>> - do {
>> - if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
>> - BUG();
>> - msleep(100);
>> - } while(op.status == GNTST_eagain);
>> + gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &op);
>>
>> - if (op.status) {
>> - DPRINTK(" Grant table operation failure !\n");
>> - return op.status;
>> + if (op.status == GNTST_okay) {
>> + blkif->shmem_ref = shared_page;
>> + blkif->shmem_handle = op.handle;
>> + ret = 0;
>> + } else {
>> + DPRINTK(" Grant table operation failure %d!\n",
>> (int)op.status);
>> + ret = -EINVAL;
>> }
>>
>> - blkif->shmem_ref = shared_page;
>> - blkif->shmem_handle = op.handle;
>> -
>> - return 0;
>> + return ret;
>> }
>>
>> static void unmap_frontend_page(blkif_t *blkif)
>> --- linux-2.6.18-xen.hg.orig/drivers/xen/blktap/blktap.c
>> +++ linux-2.6.18-xen.hg/drivers/xen/blktap/blktap.c
>> @@ -1526,19 +1526,17 @@ static void dispatch_rw_block_io(blkif_t
>>
>> uvaddr = MMAP_VADDR(info->user_vstart, usr_idx, i/2);
>>
>> - 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;
>> +
>> gnttab_check_GNTST_eagain_while(GNTTABOP_map_grant_ref, &map[i]);
>> +
>> + if (unlikely(map[i].status != GNTST_okay)) {
>> + WPRINTK("invalid kernel buffer -- could not
>> remap it\n");
>> + ret = 1;
>> map[i].handle = INVALID_GRANT_HANDLE;
>> }
>>
>> - if (unlikely(map[i+1].status != 0)) {
>> - WPRINTK("invalid user buffer -- "
>> - "could not remap it\n");
>> - ret |= 1;
>> + if (unlikely(map[i+1].status != GNTST_okay)) {
>> + WPRINTK("invalid kernel buffer -- could not
>> remap it\n");
>> + ret = 1;
>> map[i+1].handle = INVALID_GRANT_HANDLE;
>> }
>>
>> @@ -1565,12 +1563,11 @@ static void dispatch_rw_block_io(blkif_t
>>
>> uvaddr = MMAP_VADDR(info->user_vstart, usr_idx, i);
>>
>> - 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;
>> +
>> gnttab_check_GNTST_eagain_while(GNTTABOP_map_grant_ref, &map[i]);
>> +
>> + if (unlikely(map[i].status != GNTST_okay)) {
>> + WPRINTK("invalid kernel buffer -- could not
>> remap it\n");
>> + ret = 1;
>> map[i].handle = INVALID_GRANT_HANDLE;
>> }
>>
>> --- linux-2.6.18-xen.hg.orig/drivers/xen/blktap/interface.c
>> +++ linux-2.6.18-xen.hg/drivers/xen/blktap/interface.c
>> @@ -59,25 +59,23 @@ blkif_t *tap_alloc_blkif(domid_t domid)
>> static int map_frontend_page(blkif_t *blkif, unsigned long shared_page)
>> {
>> struct gnttab_map_grant_ref op;
>> + int ret;
>>
>> gnttab_set_map_op(&op, (unsigned long)blkif->blk_ring_area->addr,
>> GNTMAP_host_map, shared_page, blkif->domid);
>>
>> - do {
>> - if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
>> - BUG();
>> - msleep(10);
>> - } while(op.status == GNTST_eagain);
>> + gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &op);
>>
>> - if (op.status) {
>> - DPRINTK(" Grant table operation failure !\n");
>> - return op.status;
>> + if (op.status == GNTST_okay) {
>> + blkif->shmem_ref = shared_page;
>> + blkif->shmem_handle = op.handle;
>> + ret = 0;
>> + } else {
>> + DPRINTK("Grant table operation failure %d!\n",
>> (int)op.status);
>> + ret = -EINVAL;
>> }
>>
>> - blkif->shmem_ref = shared_page;
>> - blkif->shmem_handle = op.handle;
>> -
>> - return 0;
>> + return ret;
>> }
>>
>> static void unmap_frontend_page(blkif_t *blkif)
>> --- linux-2.6.18-xen.hg.orig/drivers/xen/blktap2/device.c
>> +++ linux-2.6.18-xen.hg/drivers/xen/blktap2/device.c
>> @@ -505,10 +505,10 @@ blktap_map_foreign(struct blktap *tap,
>>
>> uvaddr = MMAP_VADDR(ring->user_vstart, usr_idx, i);
>>
>> - if (unlikely(table->grants[grant].status)) {
>> + if (unlikely(table->grants[grant].status != GNTST_okay)) {
>> 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);
>> + /* 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;
>> }
>> @@ -517,19 +517,18 @@ blktap_map_foreign(struct blktap *tap,
>> foreign_mfn = table->grants[grant].dev_bus_addr >> PAGE_SHIFT;
>> grant++;
>>
>> - if (xen_feature(XENFEAT_auto_translated_physmap))
>> - goto done;
>> -
>> - if (unlikely(table->grants[grant].status)) {
>> - BTERR("invalid user buffer: could not remap it\n");
>> - err |= 1;
>> + if (!xen_feature(XENFEAT_auto_translated_physmap)) {
>> + if (unlikely(table->grants[grant].status !=
>> GNTST_okay)) {
>> + /* This should never happen: blkback should
>> handle eagain first */
>> + WARN_ON(table->grants[grant].status ==
>> GNTST_eagain);
>> + BTERR("invalid user buffer: could not remap
>> it\n");
>> + err |= 1;
>> + }
>> table->grants[grant].handle = INVALID_GRANT_HANDLE;
>> + request->handles[i].user =
>> table->grants[grant].handle;
>> + grant++;
>> }
>>
>> - request->handles[i].user = table->grants[grant].handle;
>> - grant++;
>> -
>> - done:
>> if (err)
>> continue;
>>
>> @@ -602,11 +601,10 @@ blktap_map(struct blktap *tap,
>> set_page_private(tap_page, page_private(page));
>> SetPageBlkback(tap_page);
>>
>> - 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);
>> + gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref,
>> &map);
>> +
>> + /* 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) {
>> --- linux-2.6.18-xen.hg.orig/drivers/xen/core/gnttab.c
>> +++ linux-2.6.18-xen.hg/drivers/xen/core/gnttab.c
>> @@ -487,7 +487,7 @@ static int gnttab_map(unsigned int start
>> return -ENOSYS;
>> }
>>
>> - BUG_ON(rc || setup.status);
>> + BUG_ON(rc || setup.status != GNTST_okay);
>>
>> if (shared == NULL)
>> shared = arch_gnttab_alloc_shared(frames);
>> @@ -571,7 +571,7 @@ int gnttab_copy_grant_page(grant_ref_t r
>> err = HYPERVISOR_grant_table_op(GNTTABOP_unmap_and_replace,
>> &unmap, 1);
>> BUG_ON(err);
>> - BUG_ON(unmap.status);
>> + BUG_ON(unmap.status != GNTST_okay);
>>
>> write_sequnlock(&gnttab_dma_lock);
>>
>> --- linux-2.6.18-xen.hg.orig/drivers/xen/gntdev/gntdev.c
>> +++ linux-2.6.18-xen.hg/drivers/xen/gntdev/gntdev.c
>> @@ -578,7 +578,7 @@ static int gntdev_mmap (struct file *fli
>> vma->vm_mm->context.has_foreign_mappings = 1;
>> #endif
>>
>> - exit_ret = -ENOMEM;
>> + exit_ret = -ENOMEM;
>> for (i = 0; i < size; ++i) {
>>
>> flags = GNTMAP_host_map;
>> @@ -599,8 +599,8 @@ static int gntdev_mmap (struct file *fli
>> ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref,
>> &op, 1);
>> BUG_ON(ret);
>> - if (op.status) {
>> - if(op.status != GNTST_eagain)
>> + if (op.status != GNTST_okay) {
>> + if (op.status != GNTST_eagain)
>> printk(KERN_ERR "Error mapping the grant
>> reference "
>> "into the kernel (%d). domid = %d; ref
>> = %d\n",
>> op.status,
>> @@ -608,9 +608,9 @@ static int gntdev_mmap (struct file *fli
>> .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;
>> + else
>> + /* Propagate eagain instead of trying to fix
>> it up */
>> + exit_ret = -EAGAIN;
>> goto undo_map_out;
>> }
>>
>> @@ -679,7 +679,7 @@ static int gntdev_mmap (struct file *fli
>> ret =
>> HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref,
>> &op, 1);
>> BUG_ON(ret);
>> - if (op.status) {
>> + if (op.status != GNTST_okay) {
>> printk(KERN_ERR "Error mapping the grant "
>> "reference into user space (%d). domid
>> "
>> "= %d; ref = %d\n", op.status,
>> @@ -687,9 +687,9 @@ static int gntdev_mmap (struct file *fli
>> .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);
>> + /* This should never happen after we've
>> mapped into
>> + * the kernel space. */
>> + BUG_ON(op.status == GNTST_eagain);
>> goto undo_map_out;
>> }
>>
>> @@ -713,7 +713,7 @@ static int gntdev_mmap (struct file *fli
>> }
>>
>> }
>> - exit_ret = 0;
>> + exit_ret = 0;
>>
>> up_write(&private_data->grants_sem);
>> return exit_ret;
>> @@ -785,7 +785,7 @@ static pte_t gntdev_clear_pte(struct vm_
>> ret = HYPERVISOR_grant_table_op(
>> GNTTABOP_unmap_grant_ref, &op, 1);
>> BUG_ON(ret);
>> - if (op.status)
>> + if (op.status != GNTST_okay)
>> printk("User unmap grant status = %d\n",
>> op.status);
>> } else {
>> @@ -802,7 +802,7 @@ static pte_t gntdev_clear_pte(struct vm_
>> ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref,
>> &op, 1);
>> BUG_ON(ret);
>> - if (op.status)
>> + if (op.status != GNTST_okay)
>> printk("Kernel unmap grant status = %d\n", op.status);
>>
>>
>> --- linux-2.6.18-xen.hg.orig/drivers/xen/netback/interface.c
>> +++ linux-2.6.18-xen.hg/drivers/xen/netback/interface.c
>> @@ -251,15 +251,11 @@ static int map_frontend_pages(
>>
>> gnttab_set_map_op(&op, (unsigned long)netif->tx_comms_area->addr,
>> GNTMAP_host_map, tx_ring_ref, netif->domid);
>> - do {
>> - if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op,
>> 1))
>> - BUG();
>> - msleep(10);
>> - } while(op.status == GNTST_eagain);
>> -
>> - if (op.status) {
>> - DPRINTK(" Gnttab failure mapping tx_ring_ref!\n");
>> - return op.status;
>> + gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &op);
>> +
>> + if (op.status != GNTST_okay) {
>> + DPRINTK(" Gnttab failure mapping tx_ring_ref %d!\n",
>> (int)op.status);
>> + return -EINVAL;
>> }
>>
>> netif->tx_shmem_ref = tx_ring_ref;
>> @@ -267,13 +263,9 @@ static int map_frontend_pages(
>>
>> gnttab_set_map_op(&op, (unsigned long)netif->rx_comms_area->addr,
>> GNTMAP_host_map, rx_ring_ref, netif->domid);
>> - do {
>> - if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
>> - BUG();
>> - msleep(10);
>> - } while(op.status == GNTST_eagain);
>> + gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &op);
>>
>> - if (op.status) {
>> + if (op.status != GNTST_okay) {
>> struct gnttab_unmap_grant_ref unop;
>>
>> gnttab_set_unmap_op(&unop,
>> @@ -281,8 +273,8 @@ static int map_frontend_pages(
>> GNTMAP_host_map, netif->tx_shmem_handle);
>> VOID(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref,
>> &unop, 1));
>> - DPRINTK(" Gnttab failure mapping rx_ring_ref!\n");
>> - return op.status;
>> + DPRINTK(" Gnttab failure mapping rx_ring_ref %d!\n",
>> (int)op.status);
>> + return -EINVAL;
>> }
>>
>> netif->rx_shmem_ref = rx_ring_ref;
>> --- linux-2.6.18-xen.hg.orig/drivers/xen/netback/netback.c
>> +++ linux-2.6.18-xen.hg/drivers/xen/netback/netback.c
>> @@ -494,8 +494,7 @@ static inline void netbk_free_pages(int
>> used to set up the operations on the top of
>> netrx_pending_operations, which have since been done. Check that
>> they didn't give any errors and advance over them. */
>> -static int netbk_check_gop(int nr_frags, domid_t domid,
>> - struct netrx_pending_operations *npo, int *eagain)
>> +static int netbk_check_gop(int nr_frags, domid_t domid, struct
>> netrx_pending_operations *npo)
>> {
>> multicall_entry_t *mcl;
>> gnttab_transfer_t *gop;
>> @@ -503,17 +502,15 @@ static int netbk_check_gop(int nr_frags,
>> int status = NETIF_RSP_OKAY;
>> int i;
>>
>> - *eagain = 0;
>> -
>> for (i = 0; i <= nr_frags; i++) {
>> if (npo->meta[npo->meta_cons + i].copy) {
>> copy_op = npo->copy + npo->copy_cons++;
>> - if (copy_op->status != GNTST_okay) {
>> + if (unlikely(copy_op->status == GNTST_eagain))
>> +
>> gnttab_check_GNTST_eagain_while(GNTTABOP_copy, copy_op);
>> + if (unlikely(copy_op->status != GNTST_okay)) {
>> DPRINTK("Bad status %d from copy to DOM%d.\n",
>> copy_op->status, domid);
>> status = NETIF_RSP_ERROR;
>> - if(copy_op->status == GNTST_eagain)
>> - *eagain = 1;
>> }
>> } else {
>> if (!xen_feature(XENFEAT_auto_translated_physmap)) {
>> @@ -524,7 +521,7 @@ static int netbk_check_gop(int nr_frags,
>>
>> gop = npo->trans + npo->trans_cons++;
>> /* Check the reassignment error code. */
>> - if (gop->status != 0) {
>> + if (unlikely(gop->status != GNTST_okay)) {
>> DPRINTK("Bad status %d from grant transfer to
>> DOM%u\n",
>> gop->status, domid);
>> /*
>> @@ -533,8 +530,6 @@ static int netbk_check_gop(int nr_frags,
>> * a fatal error anyway.
>> */
>> BUG_ON(gop->status == GNTST_bad_page);
>> - if(gop->status == GNTST_eagain)
>> - *eagain = 1;
>> status = NETIF_RSP_ERROR;
>> }
>> }
>> @@ -576,7 +571,6 @@ static void net_rx_action(unsigned long
>> int nr_frags;
>> int count;
>> unsigned long offset;
>> - int eagain;
>>
>> /*
>> * Putting hundreds of bytes on the stack is considered rude.
>> @@ -680,7 +674,7 @@ static void net_rx_action(unsigned long
>>
>> netif = netdev_priv(skb->dev);
>>
>> - status = netbk_check_gop(nr_frags, netif->domid, &npo,
>> &eagain);
>> + status = netbk_check_gop(nr_frags, netif->domid, &npo);
>>
>> /* We can't rely on skb_release_data to release the
>> pages used by fragments for us, since it tries to
>> @@ -691,22 +685,14 @@ static void net_rx_action(unsigned long
>> /* (Freeing the fragments is safe since we copy
>> non-linear skbs destined for flipping interfaces) */
>> if (!netif->copying_receiver) {
>> - /*
>> - * Cannot handle failed grant transfers at the moment (because
>> - * mmu_updates likely completed)
>> - */
>> - BUG_ON(eagain);
>> atomic_set(&(skb_shinfo(skb)->dataref), 1);
>> skb_shinfo(skb)->frag_list = NULL;
>> skb_shinfo(skb)->nr_frags = 0;
>> netbk_free_pages(nr_frags, meta + npo.meta_cons + 1);
>> }
>>
>> - if(!eagain)
>> - {
>> - netif->stats.tx_bytes += skb->len;
>> - netif->stats.tx_packets++;
>> - }
>> + netif->stats.tx_bytes += skb->len;
>> + netif->stats.tx_packets++;
>>
>> id = meta[npo.meta_cons].id;
>> flags = nr_frags ? NETRXF_more_data : 0;
>> @@ -756,18 +742,8 @@ static void net_rx_action(unsigned long
>> !netbk_queue_full(netif))
>> netif_wake_queue(netif->dev);
>>
>> - if(!eagain || netbk_queue_full(netif))
>> - {
>> - netif_put(netif);
>> - dev_kfree_skb(skb);
>> - netif->stats.tx_dropped += !!eagain;
>> - }
>> - else
>> - {
>> - netif->rx_req_cons_peek += skb_shinfo(skb)->nr_frags + 1 +
>> - !!skb_shinfo(skb)->gso_size;
>> - skb_queue_head(&rx_queue, skb);
>> - }
>> + netif_put(netif);
>> + dev_kfree_skb(skb);
>>
>> npo.meta_cons += nr_frags + 1;
>> }
>> @@ -1107,7 +1083,7 @@ static int netbk_tx_check_mop(struct sk_
>>
>> /* Check status of header. */
>> err = mop->status;
>> - if (unlikely(err)) {
>> + if (unlikely(err != GNTST_okay)) {
>> txp = &pending_tx_info[pending_idx].req;
>> make_tx_response(netif, txp, NETIF_RSP_ERROR);
>> pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx;
>> @@ -1128,12 +1104,12 @@ static int netbk_tx_check_mop(struct sk_
>>
>> /* Check error status: if okay then remember grant handle. */
>> newerr = (++mop)->status;
>> - if (likely(!newerr)) {
>> + if (likely(newerr == GNTST_okay)) {
>> set_phys_to_machine(idx_to_pfn(pending_idx),
>> FOREIGN_FRAME(mop->dev_bus_addr>>PAGE_SHIFT));
>> grant_tx_handle[pending_idx] = mop->handle;
>> /* Had a previous error? Invalidate this fragment. */
>> - if (unlikely(err))
>> + if (unlikely(err != GNTST_okay))
>> netif_idx_release(pending_idx);
>> continue;
>> }
>> @@ -1145,7 +1121,7 @@ static int netbk_tx_check_mop(struct sk_
>> netif_put(netif);
>>
>> /* Not the first error? Preceding frags already invalidated.
>> */
>> - if (err)
>> + if (err != GNTST_okay)
>> continue;
>>
>> /* First error: invalidate header and preceding fragments. */
>> --- linux-2.6.18-xen.hg.orig/drivers/xen/scsiback/interface.c
>> +++ linux-2.6.18-xen.hg/drivers/xen/scsiback/interface.c
>> @@ -64,27 +64,23 @@ static int map_frontend_page( struct vsc
>> unsigned long ring_ref)
>> {
>> struct gnttab_map_grant_ref op;
>> - int err;
>> + int ret;
>>
>> gnttab_set_map_op(&op, (unsigned long)info->ring_area->addr,
>> GNTMAP_host_map, ring_ref,
>> info->domid);
>> + gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &op);
>>
>> - 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");
>> - return op.status;
>> + if (op.status != GNTST_okay) {
>> + printk(KERN_ERR "scsiback: Grant table operation failure
>> %d!\n", (int)op.status);
>> + ret = -EINVAL;
>> + } else {
>> + info->shmem_ref = ring_ref;
>> + info->shmem_handle = op.handle;
>> + ret = 0;
>> }
>>
>> - info->shmem_ref = ring_ref;
>> - info->shmem_handle = op.handle;
>> -
>> - return (GNTST_okay);
>> + return ret;
>> }
>>
>> static void unmap_frontend_page(struct vscsibk_info *info)
>> --- linux-2.6.18-xen.hg.orig/drivers/xen/scsiback/scsiback.c
>> +++ linux-2.6.18-xen.hg/drivers/xen/scsiback/scsiback.c
>> @@ -279,22 +279,14 @@ static int scsiback_gnttab_data_map(vscs
>>
>> 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;
>>
>> - if (unlikely(map[i].status != 0)) {
>> + /* Retry maps with GNTST_eagain */
>> + if (unlikely(map[i].status == GNTST_eagain))
>> +
>> gnttab_check_GNTST_eagain_while(GNTTABOP_map_grant_ref, &map[i]);
>> + if (unlikely(map[i].status != GNTST_okay)) {
>> printk(KERN_ERR "scsiback: invalid buffer --
>> could not remap it\n");
>> map[i].handle = SCSIBACK_INVALID_HANDLE;
>> err |= 1;
>> --- linux-2.6.18-xen.hg.orig/drivers/xen/sfc_netutil/accel_util.c
>> +++ linux-2.6.18-xen.hg/drivers/xen/sfc_netutil/accel_util.c
>> @@ -71,24 +71,27 @@ static int net_accel_map_grant(struct xe
>> u64 *dev_bus_addr, unsigned flags)
>> {
>> struct gnttab_map_grant_ref op;
>> + int ret;
>>
>> gnttab_set_map_op(&op, (unsigned long)vaddr, flags,
>> gnt_ref, dev->otherend_id);
>>
>> - BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1));
>> + gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &op);
>>
>> if (op.status != GNTST_okay) {
>> xenbus_dev_error
>> (dev, op.status,
>> "failed mapping in shared page %d from domain %d\n",
>> gnt_ref, dev->otherend_id);
>> + ret = -EINVAL;
>> } else {
>> *handle = op.handle;
>> if (dev_bus_addr)
>> *dev_bus_addr = op.dev_bus_addr;
>> + ret = 0;
>> }
>>
>> - return op.status;
>> + return ret;
>> }
>>
>>
>> @@ -112,7 +115,7 @@ static int net_accel_unmap_grant(struct
>> "failed unmapping page at handle %d error
>> %d\n",
>> handle, op.status);
>>
>> - return op.status;
>> + return op.status == GNTST_okay ? 0 : -EINVAL;
>> }
>>
>>
>> @@ -144,7 +147,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, int
>> *errno)
>> + unsigned flags, void **priv)
>> {
>> struct net_accel_valloc_grant_mapping *map;
>> struct vm_struct *vm;
>> @@ -172,16 +175,12 @@ static void *net_accel_map_grants_valloc
>>
>> /* 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);
>> + if (rc < 0)
>> goto undo;
>> - }
>> addr = (void*)((unsigned long)addr + PAGE_SIZE);
>> }
>>
>> @@ -230,16 +229,7 @@ void *net_accel_map_grants_contig(struct
>> unsigned *grants, int npages,
>> void **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;
>> + return net_accel_map_grants_valloc(dev, grants, npages, GNTMAP_host_map,
>> priv);
>> }
>> EXPORT_SYMBOL(net_accel_map_grants_contig);
>>
>> @@ -255,16 +245,7 @@ EXPORT_SYMBOL(net_accel_unmap_grants_con
>> void *net_accel_map_iomem_page(struct xenbus_device *dev, int gnt_ref,
>> void **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;
>> + return net_accel_map_grants_valloc(dev, &gnt_ref, 1, GNTMAP_host_map,
>> priv);
>> }
>> EXPORT_SYMBOL(net_accel_map_iomem_page);
>>
>> --- linux-2.6.18-xen.hg.orig/drivers/xen/tpmback/interface.c
>> +++ linux-2.6.18-xen.hg/drivers/xen/tpmback/interface.c
>> @@ -81,25 +81,23 @@ tpmif_t *tpmif_find(domid_t domid, struc
>> static int map_frontend_page(tpmif_t *tpmif, unsigned long shared_page)
>> {
>> struct gnttab_map_grant_ref op;
>> + int ret;
>>
>> gnttab_set_map_op(&op, (unsigned long)tpmif->tx_area->addr,
>> GNTMAP_host_map, shared_page, tpmif->domid);
>>
>> - do {
>> - if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
>> - BUG();
>> - msleep(10);
>> - } while(op.status == GNTST_eagain);
>> + gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &op);
>>
>> - if (op.status) {
>> - DPRINTK(" Grant table operation failure !\n");
>> - return op.status;
>> + if (op.status != GNTST_okay) {
>> + DPRINTK(" Grant table operation failure %d!\n",
>> (int)op.status);
>> + ret = -EINVAL;
>> + } else {
>> + tpmif->shmem_ref = shared_page;
>> + tpmif->shmem_handle = op.handle;
>> + ret = 0;
>> }
>>
>> - tpmif->shmem_ref = shared_page;
>> - tpmif->shmem_handle = op.handle;
>> -
>> - return 0;
>> + return ret;
>> }
>>
>> static void unmap_frontend_page(tpmif_t *tpmif)
>> --- linux-2.6.18-xen.hg.orig/drivers/xen/tpmback/tpmback.c
>> +++ linux-2.6.18-xen.hg/drivers/xen/tpmback/tpmback.c
>> @@ -257,20 +257,15 @@ int _packet_write(struct packet *pak,
>> gnttab_set_map_op(&map_op, idx_to_kaddr(tpmif, i),
>> GNTMAP_host_map, tx->ref, tpmif->domid);
>>
>> - 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);
>> + gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref,
>> &map_op);
>>
>> - handle = map_op.handle;
>> -
>> - if (map_op.status) {
>> + if (map_op.status != GNTST_okay) {
>> DPRINTK(" Grant table operation failure !\n");
>> return 0;
>> }
>>
>> + handle = map_op.handle;
>> +
>> tocopy = min_t(size_t, size - offset, PAGE_SIZE);
>>
>> if (copy_from_buffer((void *)(idx_to_kaddr(tpmif, i) |
>> @@ -397,14 +392,9 @@ static int packet_read_shmem(struct pack
>> gnttab_set_map_op(&map_op, idx_to_kaddr(tpmif, i),
>> GNTMAP_host_map, tx->ref, tpmif->domid);
>>
>> - 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);
>> + gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref,
>> &map_op);
>>
>> - if (map_op.status) {
>> + if (map_op.status != GNTST_okay) {
>> DPRINTK(" Grant table operation failure !\n");
>> return -EFAULT;
>> }
>> --- linux-2.6.18-xen.hg.orig/drivers/xen/usbback/interface.c
>> +++ linux-2.6.18-xen.hg/drivers/xen/usbback/interface.c
>> @@ -110,16 +110,11 @@ static int map_frontend_pages(usbif_t *u
>> gnttab_set_map_op(&op, (unsigned long)usbif->urb_ring_area->addr,
>> GNTMAP_host_map, urb_ring_ref, usbif->domid);
>>
>> + gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &op);
>>
>> - 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");
>> - return op.status;
>> + if (op.status != GNTST_okay) {
>> + printk(KERN_ERR "grant table failure mapping urb_ring_ref
>> %d\n", (int)op.status);
>> + return -EINVAL;
>> }
>>
>> usbif->urb_shmem_ref = urb_ring_ref;
>> @@ -128,21 +123,17 @@ static int map_frontend_pages(usbif_t *u
>> gnttab_set_map_op(&op, (unsigned long)usbif->conn_ring_area->addr,
>> GNTMAP_host_map, conn_ring_ref, usbif->domid);
>>
>> - do {
>> - if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
>> - BUG();
>> - msleep(10);
>> - } while (op.status == GNTST_eagain);
>> + gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &op);
>>
>> - if (op.status) {
>> + if (op.status != GNTST_okay) {
>> struct gnttab_unmap_grant_ref unop;
>> gnttab_set_unmap_op(&unop,
>> (unsigned long) usbif->urb_ring_area->addr,
>> GNTMAP_host_map, usbif->urb_shmem_handle);
>> VOID(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref,
>> &unop,
>> 1));
>> - printk(KERN_ERR "grant table failure mapping
>> conn_ring_ref\n");
>> - return op.status;
>> + printk(KERN_ERR "grant table failure mapping conn_ring_ref
>> %d\n", (int)op.status);
>> + return -EINVAL;
>> }
>>
>> usbif->conn_shmem_ref = conn_ring_ref;
>> --- linux-2.6.18-xen.hg.orig/drivers/xen/usbback/usbback.c
>> +++ linux-2.6.18-xen.hg/drivers/xen/usbback/usbback.c
>> @@ -392,19 +392,13 @@ static int usbbk_gnttab_map(usbif_t *usb
>> 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)) {
>> + /* Make sure than none of the map ops failed with
>> GNTST_eagain */
>> + if (unlikely(map[i].status == GNTST_eagain))
>> +
>> gnttab_check_GNTST_eagain_while(GNTTABOP_map_grant_ref, &map[i]);
>> +
>> + if (unlikely(map[i].status != GNTST_okay)) {
>> printk(KERN_ERR "usbback: invalid buffer --
>> could not remap it\n");
>> map[i].handle = USBBACK_INVALID_HANDLE;
>> ret |= 1;
>> --- linux-2.6.18-xen.hg.orig/drivers/xen/xenbus/xenbus_backend_client.c
>> +++ linux-2.6.18-xen.hg/drivers/xen/xenbus/xenbus_backend_client.c
>> @@ -49,11 +49,7 @@ struct vm_struct *xenbus_map_ring_valloc
>> gnttab_set_map_op(&op, (unsigned long)area->addr, GNTMAP_host_map,
>> gnt_ref, dev->otherend_id);
>>
>> - do {
>> - if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
>> - BUG();
>> - msleep(10);
>> - } while(op.status == GNTST_eagain);
>> + gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &op);
>>
>> if (op.status != GNTST_okay) {
>> free_vm_area(area);
>> @@ -61,7 +57,7 @@ struct vm_struct *xenbus_map_ring_valloc
>> "mapping in shared page %d from domain %d",
>> gnt_ref, dev->otherend_id);
>> BUG_ON(!IS_ERR(ERR_PTR(op.status)));
>> - return ERR_PTR(op.status);
>> + return ERR_PTR(-EINVAL);
>> }
>>
>> /* Stuff the handle in an unused field */
>> @@ -76,23 +72,24 @@ int xenbus_map_ring(struct xenbus_device
>> grant_handle_t *handle, void *vaddr)
>> {
>> struct gnttab_map_grant_ref op;
>> + int ret;
>>
>> gnttab_set_map_op(&op, (unsigned long)vaddr, GNTMAP_host_map,
>> gnt_ref, dev->otherend_id);
>> - do {
>> - if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
>> - BUG();
>> - msleep(10);
>> - } while(op.status == GNTST_eagain);
>> +
>> + gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &op);
>>
>> if (op.status != GNTST_okay) {
>> xenbus_dev_fatal(dev, op.status,
>> "mapping in shared page %d from domain %d",
>> gnt_ref, dev->otherend_id);
>> - } else
>> + ret = -EINVAL;
>> + } else {
>> *handle = op.handle;
>> + ret = 0;
>> + }
>>
>> - return op.status;
>> + return ret;
>> }
>> EXPORT_SYMBOL_GPL(xenbus_map_ring);
>>
>> @@ -115,7 +112,7 @@ int xenbus_unmap_ring_vfree(struct xenbu
>> "unmapping page at handle %d error %d",
>> (int16_t)area->phys_addr, op.status);
>>
>> - return op.status;
>> + return op.status == GNTST_okay ? 0 : -EINVAL;
>> }
>> EXPORT_SYMBOL_GPL(xenbus_unmap_ring_vfree);
>>
>> @@ -135,7 +132,7 @@ int xenbus_unmap_ring(struct xenbus_devi
>> "unmapping page at handle %d error %d",
>> handle, op.status);
>>
>> - return op.status;
>> + return op.status == GNTST_okay ? 0 : -EINVAL;
>> }
>> EXPORT_SYMBOL_GPL(xenbus_unmap_ring);
>>
>> --- linux-2.6.18-xen.hg.orig/include/xen/gnttab.h
>> +++ linux-2.6.18-xen.hg/include/xen/gnttab.h
>> @@ -40,6 +40,7 @@
>> #include <asm/hypervisor.h>
>> #include <asm/maddr.h> /* maddr_t */
>> #include <linux/mm.h>
>> +#include <linux/delay.h>
>> #include <xen/interface/grant_table.h>
>> #include <xen/features.h>
>>
>> @@ -161,4 +162,41 @@ gnttab_set_replace_op(struct gnttab_unma
>> unmap->handle = handle;
>> }
>>
>> +#define gnttab_check_GNTST_eagain_while(__HCop, __HCarg_p)
>> \
>> +{
>> \
>> + u8 __hc_delay = 1;
>> \
>> + int __ret;
>> \
>> + while (unlikely((__HCarg_p)->status == GNTST_eagain && __hc_delay)) {
>> \
>> + msleep(__hc_delay++);
>> \
>> + __ret = HYPERVISOR_grant_table_op(__HCop, (__HCarg_p), 1);
>> \
>> + BUG_ON(__ret);
>> \
>> + }
>> \
>> + if (__hc_delay == 0) {
>> \
>> + printk(KERN_ERR "%s: %s gnt busy\n", __func__,
>> current->comm); \
>> + (__HCarg_p)->status = GNTST_bad_page;
>> \
>> + }
>> \
>> + if ((__HCarg_p)->status != GNTST_okay)
>> \
>> + printk(KERN_ERR "%s: %s gnt status %x\n",
>> \
>> + __func__, current->comm, (__HCarg_p)->status);
>> \
>> +}
>> +
>> +#define gnttab_check_GNTST_eagain_do_while(__HCop, __HCarg_p)
>> \
>> +{
>> \
>> + u8 __hc_delay = 1;
>> \
>> + int __ret;
>> \
>> + do {
>> \
>> + __ret = HYPERVISOR_grant_table_op(__HCop, (__HCarg_p), 1);
>> \
>> + BUG_ON(__ret);
>> \
>> + if ((__HCarg_p)->status == GNTST_eagain)
>> \
>> + msleep(__hc_delay++);
>> \
>> + } while ((__HCarg_p)->status == GNTST_eagain && __hc_delay);
>> \
>> + if (__hc_delay == 0) {
>> \
>> + printk(KERN_ERR "%s: %s gnt busy\n", __func__,
>> current->comm); \
>> + (__HCarg_p)->status = GNTST_bad_page;
>> \
>> + }
>> \
>> + if ((__HCarg_p)->status != GNTST_okay)
>> \
>> + printk(KERN_ERR "%s: %s gnt status %x\n",
>> \
>> + __func__, current->comm, (__HCarg_p)->status);
>> \
>> +}
>> +
>> #endif /* __ASM_GNTTAB_H__ */
>>
>>



_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
Re: [PATCH] xenpaging: handle GNTST_eagain in kernel drivers [ In reply to ]
On Wed, Sep 15, Patrick Colp wrote:

> Is there any particular reason for 33 seconds? This number seems a bit
> high to me. Did you run into situations where that amount of time was
> needed? Otherwise I'm happy with everything. Thanks for all the hard
> work!

Its just when the wrap of u8 happens, it keeps the code simple. In my
testing it was never over 100 loop iterations. Most of the time its
between 1 and 10.

Olaf

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel