[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


 


Rackspace

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