[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] Re: [PATCH] xenpaging: handle GNTST_eagain in kernel drivers



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@xxxxxxxxx> 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@xxxxxxxxx>
> 
> 
> Patrick
> 
> 
> On 15 September 2010 09:08, Olaf Hering <olaf@xxxxxxxxx> 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@xxxxxxxxx>
>> 
>> ---
>> 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@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.