From: Olaf Hering <olaf@aepfle.de>
To: Patrick Colp <pjcolp@cs.ubc.ca>
Cc: xen-devel@lists.xensource.com
Subject: [PATCH] xenpaging: handle GNTST_eagain in kernel drivers
Date: Wed, 15 Sep 2010 18:08:43 +0200 [thread overview]
Message-ID: <20100915160843.GA16689@aepfle.de> (raw)
In-Reply-To: <20100915160521.GA16644@aepfle.de>
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__ */
next prev parent reply other threads:[~2010-09-15 16:08 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-09-15 16:05 xenpaging fixes for kernel and hypervisor Olaf Hering
2010-09-15 16:08 ` Olaf Hering [this message]
2010-09-16 3:44 ` [PATCH] xenpaging: handle GNTST_eagain in kernel drivers Patrick Colp
2010-09-16 9:05 ` Keir Fraser
2010-09-16 13:33 ` Olaf Hering
2010-09-15 16:10 ` [PATCH] xenpaging: page-in granttable entries Olaf Hering
2010-09-15 16:11 ` [PATCH] xenpaging: fix crash in notify_via_xen_event_channel Olaf Hering
2010-09-15 16:12 ` [PATCH] xenpaging: avoid empty pagefile on unsupported hardware Olaf Hering
2010-09-22 15:38 ` [PATCH] xenpaging: handle XENMEM_decrease_reservation Olaf Hering
2010-09-22 15:40 ` [PATCH] xenpaging: break endless loop during inital page-out with large pagefiles Olaf Hering
2010-09-22 15:41 ` [PATCH] xenpaging: allow only one xenpaging call per guest Olaf Hering
2010-09-22 15:48 ` xenpaging fixes for kernel and hypervisor Olaf Hering
2010-09-22 16:49 ` Patrick Colp
2010-09-22 17:13 ` Keir Fraser
2010-09-22 17:14 ` Keir Fraser
2010-09-22 17:20 ` Olaf Hering
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20100915160843.GA16689@aepfle.de \
--to=olaf@aepfle.de \
--cc=pjcolp@cs.ubc.ca \
--cc=xen-devel@lists.xensource.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.