[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH 2 of 2] xenpaging: handle GNTST_eagain in kernel drivers
On Thu, Dec 01, 2011 at 03:51:55PM -0500, Andres Lagar-Cavilla wrote: > drivers/xen/blkback/blkback.c | 6 ++- > drivers/xen/blkback/interface.c | 9 +++- > drivers/xen/core/gnttab.c | 4 +- > drivers/xen/gntdev/gntdev.c | 49 > +++++++++++++++++------------ > drivers/xen/netback/interface.c | 5 +- > drivers/xen/netback/netback.c | 16 ++++++--- > drivers/xen/scsiback/interface.c | 10 +++--- > drivers/xen/scsiback/scsiback.c | 4 +- > drivers/xen/tpmback/interface.c | 7 +-- > drivers/xen/tpmback/tpmback.c | 20 ++++------- > drivers/xen/usbback/interface.c | 16 ++++---- > drivers/xen/usbback/usbback.c | 4 +- > drivers/xen/xenbus/xenbus_backend_client.c | 10 +++--- > include/xen/gnttab.h | 37 ++++++++++++++++++++++ > 14 files changed, 126 insertions(+), 71 deletions(-) > > > 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. > > 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. Any plans to do this for the pvops tree? > > Signed-off-by: Olaf Hering <olaf@xxxxxxxxx> > Acked-by: Patrick Colp <pjcolp@xxxxxxxxx> > > This is a port from xenlinux 2.6.18 to the 2.6.32 xcp tree > Signed-off-by: Andres Lagar-Cavilla <andres@xxxxxxxxxxxxxxxx> > > diff -r df9e25a0189b -r 1170bc32db41 drivers/xen/blkback/blkback.c > --- a/drivers/xen/blkback/blkback.c > +++ b/drivers/xen/blkback/blkback.c > @@ -701,11 +701,13 @@ static void dispatch_rw_block_io(blkif_t > BUG_ON(ret); > > 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("grant map of dom %u gref %u failed: status > %d\n", > blkif->domid, req->seg[i].gref, map[i].status); > map[i].handle = BLKBACK_INVALID_HANDLE; > - ret |= 1; > + ret = 1; > continue; > } > > diff -r df9e25a0189b -r 1170bc32db41 drivers/xen/blkback/interface.c > --- a/drivers/xen/blkback/interface.c > +++ b/drivers/xen/blkback/interface.c > @@ -95,7 +95,7 @@ static int map_frontend_pages(blkif_t *b > struct vm_struct *area = blkif->blk_ring_area; > struct gnttab_map_grant_ref op[BLKIF_MAX_RING_PAGES]; > unsigned int i; > - int status = 0; > + int status = GNTST_okay; > > for (i = 0; i < nr_shared_pages; i++) { > unsigned long addr = (unsigned long)area->addr + > @@ -110,7 +110,10 @@ static int map_frontend_pages(blkif_t *b > BUG(); > > for (i = 0; i < nr_shared_pages; i++) { > - if ((status = op[i].status) != 0) { > + if (op[i].status == GNTST_eagain) > + > gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &op[i]); > + if (op[i].status != GNTST_okay) { > + status = op[i].status; > blkif->shmem_handle[i] = INVALID_GRANT_HANDLE; > continue; > } > @@ -120,7 +123,7 @@ static int map_frontend_pages(blkif_t *b > > blkif->nr_shared_pages = nr_shared_pages; > > - if (status != 0) { > + if (status != GNTST_okay) { > DPRINTK(" Grant table operation failure !\n"); > unmap_frontend_pages(blkif); > } > diff -r df9e25a0189b -r 1170bc32db41 drivers/xen/core/gnttab.c > --- a/drivers/xen/core/gnttab.c > +++ b/drivers/xen/core/gnttab.c > @@ -773,7 +773,7 @@ static int gnttab_map(unsigned int start > return -ENOSYS; > } > > - BUG_ON(rc || setup.status); > + BUG_ON(rc || (setup.status != GNTST_okay)); > > if (shared.raw == NULL) > shared.raw = arch_gnttab_alloc_shared(gframes); > @@ -901,7 +901,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_irq(&gnttab_dma_lock); > > diff -r df9e25a0189b -r 1170bc32db41 drivers/xen/gntdev/gntdev.c > --- a/drivers/xen/gntdev/gntdev.c > +++ b/drivers/xen/gntdev/gntdev.c > @@ -503,7 +503,7 @@ static int gntdev_mmap (struct file *fli > uint64_t ptep; > int ret; > int flags; > - int i; > + int i, exit_ret; > struct page *page; > gntdev_file_private_data_t *private_data = flip->private_data; > > @@ -578,6 +578,7 @@ static int gntdev_mmap (struct file *fli > vma->vm_mm->context.has_foreign_mappings = 1; > #endif > > + exit_ret = -ENOMEM; > for (i = 0; i < size; ++i) { > > flags = GNTMAP_host_map; > @@ -598,14 +599,18 @@ static int gntdev_mmap (struct file *fli > ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, > &op, 1); > BUG_ON(ret); > - if (op.status) { > - printk(KERN_ERR "Error mapping the grant reference " > - "into the kernel (%d). domid = %d; ref = %d\n", > - op.status, > - private_data->grants[slot_index+i] > - .u.valid.domid, > - private_data->grants[slot_index+i] > - .u.valid.ref); > + if (op.status != GNTST_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, > + private_data->grants[slot_index+i] > + .u.valid.domid, > + private_data->grants[slot_index+i] > + .u.valid.ref); > + else > + /* Propagate instead of trying to fix it up */ > + exit_ret = -EAGAIN; > goto undo_map_out; > } > > @@ -674,14 +679,17 @@ 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, > - private_data->grants[slot_index+i].u > - .valid.domid, > - private_data->grants[slot_index+i].u > - .valid.ref); > + "reference into user space (%d). > domid " > + "= %d; ref = %d\n", op.status, > + private_data->grants[slot_index+i].u > + .valid.domid, > + private_data->grants[slot_index+i].u > + .valid.ref); > + /* GNTST_eagain (i.e. page paged out) sohuld > never happen > + * once we've mapped into kernel space */ > + BUG_ON(op.status == GNTST_eagain); > goto undo_map_out; > } > > @@ -705,9 +713,10 @@ static int gntdev_mmap (struct file *fli > } > > } > + exit_ret = 0; > > up_write(&private_data->grants_sem); > - return 0; > + return exit_ret; > > undo_map_out: > /* If we have a mapping failure, the unmapping will be taken care of > @@ -725,7 +734,7 @@ undo_map_out: > > up_write(&private_data->grants_sem); > > - return -ENOMEM; > + return exit_ret; > } > > static pte_t gntdev_clear_pte(struct vm_area_struct *vma, unsigned long addr, > @@ -777,7 +786,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 { > @@ -794,7 +803,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 df9e25a0189b -r 1170bc32db41 drivers/xen/netback/interface.c > --- a/drivers/xen/netback/interface.c > +++ b/drivers/xen/netback/interface.c > @@ -381,10 +381,9 @@ static int map_frontend_pages(struct xen > gnttab_set_map_op(&op, (unsigned long)comms->ring_area->addr, > GNTMAP_host_map, ring_ref, domid); > > - if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) > - BUG(); > + gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &op); > > - if (op.status) { > + if (op.status != GNTST_okay) { > DPRINTK(" Gnttab failure mapping ring_ref!\n"); > free_vm_area(comms->ring_area); > return op.status; > diff -r df9e25a0189b -r 1170bc32db41 drivers/xen/netback/netback.c > --- a/drivers/xen/netback/netback.c > +++ b/drivers/xen/netback/netback.c > @@ -419,11 +419,13 @@ static int netbk_check_gop(int nr_copy_s > > for (i = 0; i < nr_copy_slots; i++) { > copy_op = npo->copy + npo->copy_cons++; > + if (copy_op->status == GNTST_eagain) > + gnttab_check_GNTST_eagain_while(GNTTABOP_copy, copy_op); > if (copy_op->status != GNTST_okay) { > - DPRINTK("Bad status %d from copy to DOM%d.\n", > - copy_op->status, domid); > - status = NETIF_RSP_ERROR; > - } > + DPRINTK("Bad status %d from copy to DOM%d.\n", > + copy_op->status, domid); > + status = NETIF_RSP_ERROR; > + } > } > > return status; > @@ -1020,7 +1022,11 @@ static int netbk_tx_check_mop(struct xen > > /* Check status of header. */ > err = mop->status; > - if (unlikely(err)) { > + if (err == GNTST_eagain) { > + gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, mop); > + err = mop->status; > + } > + if (unlikely(err != GNTST_okay)) { > pending_ring_idx_t index; > index = pending_index(netbk->pending_prod++); > txp = &pending_tx_info[pending_idx].req; > diff -r df9e25a0189b -r 1170bc32db41 drivers/xen/scsiback/interface.c > --- a/drivers/xen/scsiback/interface.c > +++ b/drivers/xen/scsiback/interface.c > @@ -69,18 +69,18 @@ static int map_frontend_page( struct vsc > GNTMAP_host_map, ring_ref, > info->domid); > > - err = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1); > - BUG_ON(err); > + gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &op); > > - if (op.status) { > - printk(KERN_ERR "scsiback: Grant table operation failure !\n"); > + if (op.status != GNTST_okay) { > + printk(KERN_ERR "scsiback: Grant table operation failure > %d!\n", > + (int) op.status); > return op.status; > } > > info->shmem_ref = ring_ref; > info->shmem_handle = op.handle; > > - return (GNTST_okay); > + return 0; > } > > static void unmap_frontend_page(struct vscsibk_info *info) > diff -r df9e25a0189b -r 1170bc32db41 drivers/xen/scsiback/scsiback.c > --- a/drivers/xen/scsiback/scsiback.c > +++ b/drivers/xen/scsiback/scsiback.c > @@ -287,7 +287,9 @@ static int scsiback_gnttab_data_map(vscs > for_each_sg (pending_req->sgl, sg, nr_segments, i) { > struct page *pg; > > - if (unlikely(map[i].status != 0)) { > + 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 df9e25a0189b -r 1170bc32db41 drivers/xen/tpmback/interface.c > --- a/drivers/xen/tpmback/interface.c > +++ b/drivers/xen/tpmback/interface.c > @@ -86,11 +86,10 @@ static int map_frontend_page(tpmif_t *tp > gnttab_set_map_op(&op, (unsigned long)tpmif->tx_area->addr, > GNTMAP_host_map, shared_page, tpmif->domid); > > - if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) > - BUG(); > + gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &op); > > - if (op.status) { > - DPRINTK(" Grant table operation failure !\n"); > + if (op.status != GNTST_okay) { > + DPRINTK(" Grant table operation failure %d!\n", (int) > op.status); > return op.status; > } > > diff -r df9e25a0189b -r 1170bc32db41 drivers/xen/tpmback/tpmback.c > --- a/drivers/xen/tpmback/tpmback.c > +++ b/drivers/xen/tpmback/tpmback.c > @@ -256,15 +256,13 @@ int _packet_write(struct packet *pak, > gnttab_set_map_op(&map_op, idx_to_kaddr(tpmif, i), > GNTMAP_host_map, tx->ref, tpmif->domid); > > - if (unlikely(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, > - &map_op, 1))) { > - BUG(); > - } > + gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, > &map_op); > > handle = map_op.handle; > > - if (map_op.status) { > - DPRINTK(" Grant table operation failure !\n"); > + if (map_op.status != GNTST_okay) { > + DPRINTK(" Grant table operation failure %d!\n", > + (int) map_op.status); > return 0; > } > > @@ -394,13 +392,11 @@ 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); > > - if (unlikely(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, > - &map_op, 1))) { > - BUG(); > - } > + gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, > &map_op); > > - if (map_op.status) { > - DPRINTK(" Grant table operation failure !\n"); > + if (map_op.status != GNTST_okay) { > + DPRINTK(" Grant table operation failure %d!\n", > + (int) map_op.status); > return -EFAULT; > } > > diff -r df9e25a0189b -r 1170bc32db41 drivers/xen/usbback/interface.c > --- a/drivers/xen/usbback/interface.c > +++ b/drivers/xen/usbback/interface.c > @@ -109,11 +109,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); > > - if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) > - BUG(); > + gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &op); > > - if (op.status) { > - printk(KERN_ERR "grant table failure mapping urb_ring_ref\n"); > + if (op.status != GNTST_okay) { > + printk(KERN_ERR "grant table failure mapping urb_ring_ref %d\n", > + (int) op.status); > return op.status; > } > > @@ -123,17 +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); > > - if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) > - BUG(); > + 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"); > + printk(KERN_ERR "grant table failure mapping conn_ring_ref > %d\n", > + (int) op.status); > return op.status; > } > > diff -r df9e25a0189b -r 1170bc32db41 drivers/xen/usbback/usbback.c > --- a/drivers/xen/usbback/usbback.c > +++ b/drivers/xen/usbback/usbback.c > @@ -428,7 +428,9 @@ static int usbbk_gnttab_map(usbif_t *usb > BUG_ON(ret); > > for (i = 0; i < nr_segs; i++) { > - if (unlikely(map[i].status != 0)) { > + 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 df9e25a0189b -r 1170bc32db41 > drivers/xen/xenbus/xenbus_backend_client.c > --- a/drivers/xen/xenbus/xenbus_backend_client.c > +++ b/drivers/xen/xenbus/xenbus_backend_client.c > @@ -48,8 +48,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); > > - if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) > - BUG(); > + gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &op); > > if (op.status != GNTST_okay) { > free_vm_area(area); > @@ -75,15 +74,16 @@ int xenbus_map_ring(struct xenbus_device > > gnttab_set_map_op(&op, (unsigned long)vaddr, GNTMAP_host_map, > gnt_ref, dev->otherend_id); > - if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) > - BUG(); > + 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 > + } else { > *handle = op.handle; > + return 0; > + } > > return op.status; > } > diff -r df9e25a0189b -r 1170bc32db41 include/xen/gnttab.h > --- a/include/xen/gnttab.h > +++ b/include/xen/gnttab.h > @@ -187,4 +187,41 @@ gnttab_set_replace_op(struct gnttab_unma > unmap->handle = handle; > } > > +#define gnttab_check_GNTST_eagain_while(__HCop, __HCarg_p) > \ > +do { > \ > + 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); > \ > +} while(0) > + > +#define gnttab_check_GNTST_eagain_do_while(__HCop, __HCarg_p) > \ > +do { > \ > + 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); > \ > +} while(0) > + > #endif /* __ASM_GNTTAB_H__ */ > > _______________________________________________ > Xen-devel mailing list > Xen-devel@xxxxxxxxxxxxxxxxxxx > http://lists.xensource.com/xen-devel _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |