[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [linux-2.6.18-xen] xenpaging: handle GNTST_eagain in kernel drivers
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1284739243 -3600 # Node ID 7c7efaea8b54cc05d53ca4a23d9fad0da619bd23 # Parent 039cf55773a9c627844b17a2c2aa2df749807c4c 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@xxxxxxxxx> Acked-by: Patrick Colp <pjcolp@xxxxxxxxx> --- 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 | 38 +++++++++---------- drivers/xen/core/gnttab.c | 4 +- drivers/xen/gntdev/gntdev.c | 26 ++++++------- drivers/xen/netback/interface.c | 28 +++++--------- 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 | 45 ++++++---------------- drivers/xen/tpmback/interface.c | 22 +++++------ drivers/xen/tpmback/tpmback.c | 26 ++++--------- drivers/xen/usbback/interface.c | 29 +++++--------- drivers/xen/usbback/usbback.c | 16 ++------ drivers/xen/xenbus/xenbus_backend_client.c | 27 ++++++------- include/xen/gnttab.h | 38 +++++++++++++++++++ 19 files changed, 213 insertions(+), 310 deletions(-) diff -r 039cf55773a9 -r 7c7efaea8b54 drivers/xen/blkback/blkback.c --- a/drivers/xen/blkback/blkback.c Wed Sep 15 07:46:47 2010 +0100 +++ b/drivers/xen/blkback/blkback.c Fri Sep 17 17:00:43 2010 +0100 @@ -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), @@ -501,14 +478,6 @@ static int dispatch_rw_block_io(blkif_t seg[i].buf = map[i].dev_bus_addr | (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; } diff -r 039cf55773a9 -r 7c7efaea8b54 drivers/xen/blkback/common.h --- a/drivers/xen/blkback/common.h Wed Sep 15 07:46:47 2010 +0100 +++ b/drivers/xen/blkback/common.h Fri Sep 17 17:00:43 2010 +0100 @@ -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; diff -r 039cf55773a9 -r 7c7efaea8b54 drivers/xen/blkback/interface.c --- a/drivers/xen/blkback/interface.c Wed Sep 15 07:46:47 2010 +0100 +++ b/drivers/xen/blkback/interface.c Fri Sep 17 17:00:43 2010 +0100 @@ -59,25 +59,23 @@ static int map_frontend_page(blkif_t *bl 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) diff -r 039cf55773a9 -r 7c7efaea8b54 drivers/xen/blktap/blktap.c --- a/drivers/xen/blktap/blktap.c Wed Sep 15 07:46:47 2010 +0100 +++ b/drivers/xen/blktap/blktap.c Fri Sep 17 17:00:43 2010 +0100 @@ -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; } diff -r 039cf55773a9 -r 7c7efaea8b54 drivers/xen/blktap/interface.c --- a/drivers/xen/blktap/interface.c Wed Sep 15 07:46:47 2010 +0100 +++ b/drivers/xen/blktap/interface.c Fri Sep 17 17:00:43 2010 +0100 @@ -59,25 +59,23 @@ static int map_frontend_page(blkif_t *bl 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) diff -r 039cf55773a9 -r 7c7efaea8b54 drivers/xen/blktap2/device.c --- a/drivers/xen/blktap2/device.c Wed Sep 15 07:46:47 2010 +0100 +++ b/drivers/xen/blktap2/device.c Fri Sep 17 17:00:43 2010 +0100 @@ -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++; - - done: + request->handles[i].user = table->grants[grant].handle; + grant++; + } + 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) { diff -r 039cf55773a9 -r 7c7efaea8b54 drivers/xen/core/gnttab.c --- a/drivers/xen/core/gnttab.c Wed Sep 15 07:46:47 2010 +0100 +++ b/drivers/xen/core/gnttab.c Fri Sep 17 17:00:43 2010 +0100 @@ -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); diff -r 039cf55773a9 -r 7c7efaea8b54 drivers/xen/gntdev/gntdev.c --- a/drivers/xen/gntdev/gntdev.c Wed Sep 15 07:46:47 2010 +0100 +++ b/drivers/xen/gntdev/gntdev.c Fri Sep 17 17:00:43 2010 +0100 @@ -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); diff -r 039cf55773a9 -r 7c7efaea8b54 drivers/xen/netback/interface.c --- a/drivers/xen/netback/interface.c Wed Sep 15 07:46:47 2010 +0100 +++ b/drivers/xen/netback/interface.c Fri Sep 17 17:00:43 2010 +0100 @@ -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); - - if (op.status) { + gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &op); + + 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; diff -r 039cf55773a9 -r 7c7efaea8b54 drivers/xen/netback/netback.c --- a/drivers/xen/netback/netback.c Wed Sep 15 07:46:47 2010 +0100 +++ b/drivers/xen/netback/netback.c Fri Sep 17 17:00:43 2010 +0100 @@ -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; } @@ -1109,7 +1085,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; @@ -1130,12 +1106,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; } @@ -1147,7 +1123,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. */ diff -r 039cf55773a9 -r 7c7efaea8b54 drivers/xen/scsiback/interface.c --- a/drivers/xen/scsiback/interface.c Wed Sep 15 07:46:47 2010 +0100 +++ b/drivers/xen/scsiback/interface.c Fri Sep 17 17:00:43 2010 +0100 @@ -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) diff -r 039cf55773a9 -r 7c7efaea8b54 drivers/xen/scsiback/scsiback.c --- a/drivers/xen/scsiback/scsiback.c Wed Sep 15 07:46:47 2010 +0100 +++ b/drivers/xen/scsiback/scsiback.c Fri Sep 17 17:00:43 2010 +0100 @@ -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; diff -r 039cf55773a9 -r 7c7efaea8b54 drivers/xen/sfc_netutil/accel_util.c --- a/drivers/xen/sfc_netutil/accel_util.c Wed Sep 15 07:46:47 2010 +0100 +++ b/drivers/xen/sfc_netutil/accel_util.c Fri Sep 17 17:00:43 2010 +0100 @@ -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; - } - - return op.status; + ret = 0; + } + + 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 @@ void *net_accel_map_iomem_page(struct xe 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); diff -r 039cf55773a9 -r 7c7efaea8b54 drivers/xen/tpmback/interface.c --- a/drivers/xen/tpmback/interface.c Wed Sep 15 07:46:47 2010 +0100 +++ b/drivers/xen/tpmback/interface.c Fri Sep 17 17:00:43 2010 +0100 @@ -81,25 +81,23 @@ static int map_frontend_page(tpmif_t *tp 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) diff -r 039cf55773a9 -r 7c7efaea8b54 drivers/xen/tpmback/tpmback.c --- a/drivers/xen/tpmback/tpmback.c Wed Sep 15 07:46:47 2010 +0100 +++ b/drivers/xen/tpmback/tpmback.c Fri Sep 17 17:00:43 2010 +0100 @@ -257,19 +257,14 @@ 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); - - handle = map_op.handle; - - if (map_op.status) { + gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &map_op); + + 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); @@ -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); - - if (map_op.status) { + gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &map_op); + + if (map_op.status != GNTST_okay) { DPRINTK(" Grant table operation failure !\n"); return -EFAULT; } diff -r 039cf55773a9 -r 7c7efaea8b54 drivers/xen/usbback/interface.c --- a/drivers/xen/usbback/interface.c Wed Sep 15 07:46:47 2010 +0100 +++ b/drivers/xen/usbback/interface.c Fri Sep 17 17:00:43 2010 +0100 @@ -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); - - 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; + gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &op); + + 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); - - if (op.status) { + gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &op); + + 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; diff -r 039cf55773a9 -r 7c7efaea8b54 drivers/xen/usbback/usbback.c --- a/drivers/xen/usbback/usbback.c Wed Sep 15 07:46:47 2010 +0100 +++ b/drivers/xen/usbback/usbback.c Fri Sep 17 17:00:43 2010 +0100 @@ -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; diff -r 039cf55773a9 -r 7c7efaea8b54 drivers/xen/xenbus/xenbus_backend_client.c --- a/drivers/xen/xenbus/xenbus_backend_client.c Wed Sep 15 07:46:47 2010 +0100 +++ b/drivers/xen/xenbus/xenbus_backend_client.c Fri Sep 17 17:00:43 2010 +0100 @@ -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); diff -r 039cf55773a9 -r 7c7efaea8b54 include/xen/gnttab.h --- a/include/xen/gnttab.h Wed Sep 15 07:46:47 2010 +0100 +++ b/include/xen/gnttab.h Fri Sep 17 17:00:43 2010 +0100 @@ -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-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |