[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] Re: Ungranting
On Thu, 2005-11-03 at 08:42 +0000, Keir Fraser wrote: > On 3 Nov 2005, at 03:03, Rusty Russell wrote: > > > The simplest implementation I can think of, is to provide a mechanism > > in Xen to query the reference count of a page (1 meaning no other > > mappings). Linux would simply have a thread which, if any pages were > > in > > the "pending" queue, would query them all once a second. Since speed > > isn't important, this would be fine IMHO. > Linux can already tell whether a grant reference is 'in use' and then > atomically free the reference while it is not in use, using cmpxchg. > > I agree polling is the right answer -- explicit notification is > probably overkill and might slow down fast paths in Xen. OK, here's a (lightly) tested implementation. I use a separate bitmap, although we could probably use a reserved bit in the grant table flags. OTOH, if we wanted an arbitrary callback (rather than hardcoding free_page) we'd need an array of pointers. For the list: we have a problem in that if a driver wants to unload, it cannot simply ungrant a page then free it, as it may still be in use by the other side. The current code prints out a warning in this case and just returns without ungranting the page. This patch provides a mechanism drivers can use to get and grant a page, and to release that page. If it can't be release immediately, it's queued internally. Signed-off-by: Rusty Russell <rusty@xxxxxxxxxxxxxxx> diff -r 270469d40f02 linux-2.6-xen-sparse/arch/xen/kernel/gnttab.c --- a/linux-2.6-xen-sparse/arch/xen/kernel/gnttab.c Sun Nov 6 18:50:33 2005 +++ b/linux-2.6-xen-sparse/arch/xen/kernel/gnttab.c Mon Nov 7 14:22:13 2005 @@ -10,6 +10,7 @@ #include <linux/config.h> #include <linux/module.h> #include <linux/sched.h> +#include <linux/kthread.h> #include <asm/pgtable.h> #include <asm-xen/xen-public/xen.h> #include <asm/fixmap.h> @@ -56,6 +57,8 @@ static int gnttab_free_count; static grant_ref_t gnttab_free_head; static spinlock_t gnttab_list_lock = SPIN_LOCK_UNLOCKED; +static DECLARE_BITMAP(gnttab_freeing, NR_GRANT_ENTRIES); +static struct task_struct *gnttab_freer; static grant_entry_t *shared; @@ -454,6 +457,71 @@ return 0; } +void *alloc_granted_page(grant_ref_t *ref, domid_t dom, int readonly) +{ + int err; + void *page; + + page = (void *)get_zeroed_page(GFP_KERNEL); + if (!page) + return ERR_PTR(-ENOMEM); + + err = gnttab_grant_foreign_access(dom, virt_to_mfn(page), readonly); + if (err == -ENOSPC) { + free_page((unsigned long)page); + return ERR_PTR(err); + } + *ref = err; + return page; +} + +static int try_free_grant(grant_ref_t ref) +{ + u16 flags = shared[ref].flags; + + if (!(flags & (GTF_reading|GTF_writing)) && + synch_cmpxchg(&shared[ref].flags, flags, 0)) { + free_page((unsigned long)mfn_to_virt(shared[ref].frame)); + /* Clear this if set, before it can be reused. */ + clear_bit(ref, gnttab_freeing); + put_free_entry(ref); + printk("Grant %i freed\n", ref); + return 1; + } + return 0; +} + +/* Simplest possible code to poll while bits are pending... */ +static int gnttab_try_free(void *unused) +{ + for (;;) { + int bit, pending = 0; + + set_current_state(TASK_INTERRUPTIBLE); + + for (bit = find_first_bit(gnttab_freeing, NR_GRANT_ENTRIES); + bit < NR_GRANT_ENTRIES; + bit=find_next_bit(gnttab_freeing,bit+1,NR_GRANT_ENTRIES)) + if (!try_free_grant(bit)) + pending = 1; + + if (pending) + schedule_timeout(HZ); + else + schedule(); + } +} + +void free_granted_page(void *page, grant_ref_t ref) +{ + if (try_free_grant(ref)) + return; + + /* Deferred freeing. */ + set_bit(ref, gnttab_freeing); + wake_up_process(gnttab_freer); +} + static int __init gnttab_init(void) { @@ -488,6 +556,8 @@ grant_pde->read_proc = &grant_read; grant_pde->write_proc = &grant_write; #endif + + gnttab_freer = kthread_run(gnttab_try_free, NULL, "xengnttabd"); printk("Grant table initialized\n"); return 0; diff -r 270469d40f02 linux-2.6-xen-sparse/include/asm-xen/gnttab.h --- a/linux-2.6-xen-sparse/include/asm-xen/gnttab.h Sun Nov 6 18:50:33 2005 +++ b/linux-2.6-xen-sparse/include/asm-xen/gnttab.h Mon Nov 7 14:22:13 2005 @@ -57,6 +57,10 @@ int gnttab_query_foreign_access(grant_ref_t ref); +/* Convenient and safe helpers for granting/ungranting page. */ +void *alloc_granted_page(grant_ref_t *ref, domid_t dom, int readonly); +void free_granted_page(void *page, grant_ref_t ref); + /* * operations on reserved batches of grant references */ -- A bad analogy is like a leaky screwdriver -- Richard Braakman _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |