[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] Change the grant table interface so that gnttab_end_foreign_access_ref returns
# HG changeset patch # User emellor@xxxxxxxxxxxxxxxxxxxxxx # Node ID b50eb7619dd46427169f3d40580f973604643448 # Parent ecae9e6c7331184f916c095a2ef7ff90750ed3d7 Change the grant table interface so that gnttab_end_foreign_access_ref returns an error code if the page is still in use, and gnttab_end_foreign_access takes a page to free. This allows us to cope with frontends wanting to end access while backends are still using pages by, eventually, placing the page and grant table entry on a list, for freeing later. At the moment, the page and grant table entry are leaked, with a diagnostic. Tidied up netfront.c's clean-up code. Signed-off-by: Ewan Mellor <ewan@xxxxxxxxxxxxx> diff -r ecae9e6c7331 -r b50eb7619dd4 linux-2.6-xen-sparse/arch/xen/kernel/gnttab.c --- a/linux-2.6-xen-sparse/arch/xen/kernel/gnttab.c Sun Oct 30 15:25:52 2005 +++ b/linux-2.6-xen-sparse/arch/xen/kernel/gnttab.c Sun Oct 30 15:33:05 2005 @@ -165,25 +165,39 @@ return (nflags & (GTF_reading|GTF_writing)); } -void +int gnttab_end_foreign_access_ref(grant_ref_t ref, int readonly) { u16 flags, nflags; nflags = shared[ref].flags; do { - if ( (flags = nflags) & (GTF_reading|GTF_writing) ) + if ( (flags = nflags) & (GTF_reading|GTF_writing) ) { printk(KERN_ALERT "WARNING: g.e. still in use!\n"); + return 0; + } } while ((nflags = synch_cmpxchg(&shared[ref].flags, flags, 0)) != flags); -} - -void -gnttab_end_foreign_access(grant_ref_t ref, int readonly) -{ - gnttab_end_foreign_access_ref(ref, readonly); - put_free_entry(ref); + + return 1; +} + +void +gnttab_end_foreign_access(grant_ref_t ref, int readonly, unsigned long page) +{ + if (gnttab_end_foreign_access_ref(ref, readonly)) { + put_free_entry(ref); + if (page != 0) { + free_page(page); + } + } + else { + /* XXX This needs to be fixed so that the ref and page are + placed on a list to be freed up later. */ + printk(KERN_WARNING + "WARNING: leaking g.e. and page still in use!\n"); + } } int diff -r ecae9e6c7331 -r b50eb7619dd4 linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c Sun Oct 30 15:25:52 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c Sun Oct 30 15:33:05 2005 @@ -350,13 +350,12 @@ spin_unlock_irq(&blkif_io_lock); /* Free resources associated with old device channel. */ - if (info->ring.sring != NULL) { - free_page((unsigned long)info->ring.sring); + if (info->ring_ref != GRANT_INVALID_REF) { + gnttab_end_foreign_access(info->ring_ref, 0, + (unsigned long)info->ring.sring); + info->ring_ref = GRANT_INVALID_REF; info->ring.sring = NULL; } - if (info->ring_ref != GRANT_INVALID_REF) - gnttab_end_foreign_access(info->ring_ref, 0); - info->ring_ref = GRANT_INVALID_REF; if (info->irq) unbind_evtchn_from_irqhandler(info->irq, info); info->evtchn = info->irq = 0; @@ -515,10 +514,10 @@ err = HYPERVISOR_event_channel_op(&op); if (err) { - gnttab_end_foreign_access(info->ring_ref, 0); + gnttab_end_foreign_access(info->ring_ref, 0, + (unsigned long)info->ring.sring); info->ring_ref = GRANT_INVALID_REF; - free_page((unsigned long)info->ring.sring); - info->ring.sring = 0; + info->ring.sring = NULL; xenbus_dev_error(dev, err, "allocating event channel"); return err; } @@ -740,7 +739,7 @@ int i; for (i = 0; i < s->req.nr_segments; i++) gnttab_end_foreign_access( - blkif_gref_from_fas(s->req.frame_and_sects[i]), 0); + blkif_gref_from_fas(s->req.frame_and_sects[i]), 0, 0UL); } /* diff -r ecae9e6c7331 -r b50eb7619dd4 linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Sun Oct 30 15:25:52 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Sun Oct 30 15:33:05 2005 @@ -90,6 +90,8 @@ static void network_tx_buf_gc(struct net_device *dev); static void network_alloc_rx_buffers(struct net_device *dev); + +static void netif_free(struct netfront_info *info); static unsigned long rx_pfn_array[NETIF_RX_RING_SIZE]; static multicall_entry_t rx_mcl[NETIF_RX_RING_SIZE+1]; @@ -978,6 +980,9 @@ info->tx_ring_ref = GRANT_INVALID_REF; info->rx_ring_ref = GRANT_INVALID_REF; + info->rx = NULL; + info->tx = NULL; + info->irq = 0; info->tx = (netif_tx_interface_t *)__get_free_page(GFP_KERNEL); if (info->tx == 0) { @@ -1022,40 +1027,24 @@ return 0; out: - if (info->tx) - free_page((unsigned long)info->tx); - info->tx = 0; - if (info->rx) - free_page((unsigned long)info->rx); - info->rx = 0; - - if (info->tx_ring_ref != GRANT_INVALID_REF) - gnttab_end_foreign_access(info->tx_ring_ref, 0); + netif_free(info); + return err; +} + +static void end_access(int ref, void *page) +{ + if (ref != GRANT_INVALID_REF) + gnttab_end_foreign_access(ref, 0, (unsigned long)page); +} + +static void netif_free(struct netfront_info *info) +{ + end_access(info->tx_ring_ref, info->tx); + end_access(info->rx_ring_ref, info->rx); info->tx_ring_ref = GRANT_INVALID_REF; - - if (info->rx_ring_ref != GRANT_INVALID_REF) - gnttab_end_foreign_access(info->rx_ring_ref, 0); info->rx_ring_ref = GRANT_INVALID_REF; - - return err; -} - -static void netif_free(struct netfront_info *info) -{ - if (info->tx) - free_page((unsigned long)info->tx); - info->tx = 0; - if (info->rx) - free_page((unsigned long)info->rx); - info->rx = 0; - - if (info->tx_ring_ref != GRANT_INVALID_REF) - gnttab_end_foreign_access(info->tx_ring_ref, 0); - info->tx_ring_ref = GRANT_INVALID_REF; - - if (info->rx_ring_ref != GRANT_INVALID_REF) - gnttab_end_foreign_access(info->rx_ring_ref, 0); - info->rx_ring_ref = GRANT_INVALID_REF; + info->tx = NULL; + info->rx = NULL; if (info->irq) unbind_evtchn_from_irqhandler(info->irq, info->netdev); diff -r ecae9e6c7331 -r b50eb7619dd4 linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c --- a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c Sun Oct 30 15:25:52 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c Sun Oct 30 15:33:05 2005 @@ -276,8 +276,8 @@ err = HYPERVISOR_event_channel_op(&op); if (err) { - gnttab_end_foreign_access(info->ring_ref, 0); - free_page((unsigned long)sring); + gnttab_end_foreign_access(info->ring_ref, 0, + (unsigned long)sring); tp->tx = NULL; xenbus_dev_error(dev, err, "allocating event channel"); return err; @@ -294,8 +294,8 @@ tpmif_set_connected_state(tp,0); if ( tp->tx != NULL ) { - gnttab_end_foreign_access(info->ring_ref, 0); - free_page((unsigned long)tp->tx); + gnttab_end_foreign_access(info->ring_ref, 0, + (unsigned long)tp->tx); tp->tx = NULL; } diff -r ecae9e6c7331 -r b50eb7619dd4 linux-2.6-xen-sparse/include/asm-xen/gnttab.h --- a/linux-2.6-xen-sparse/include/asm-xen/gnttab.h Sun Oct 30 15:25:52 2005 +++ b/linux-2.6-xen-sparse/include/asm-xen/gnttab.h Sun Oct 30 15:33:05 2005 @@ -34,8 +34,21 @@ int gnttab_grant_foreign_access(domid_t domid, unsigned long frame, int readonly); -void gnttab_end_foreign_access_ref(grant_ref_t ref, int readonly); -void gnttab_end_foreign_access(grant_ref_t ref, int readonly); +/* + * End access through the given grant reference, iff the grant entry is no + * longer in use. Return 1 if the grant entry was freed, 0 if it is still in + * use. + */ +int gnttab_end_foreign_access_ref(grant_ref_t ref, int readonly); + +/* + * Eventually end access through the given grant reference, and once that + * access has been ended, free the given page too. Access will be ended + * immediately iff the grant entry is not in use, otherwise it will happen + * some time later. page may be 0, in which case no freeing will occur. + */ +void gnttab_end_foreign_access(grant_ref_t ref, int readonly, + unsigned long page); int gnttab_grant_foreign_transfer(domid_t domid); _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |