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

Re: [Xen-devel] [RFC/PATCH] XENMEM_claim_pages (subop of an existing) hypercall



>>> On 13.11.12 at 23:23, Dan Magenheimer <dan.magenheimer@xxxxxxxxxx> wrote:
> --- a/xen/common/memory.c
> +++ b/xen/common/memory.c
> @@ -454,7 +454,7 @@ static long 
> memory_exchange(XEN_GUEST_HANDLE_PARAM(xen_memory_exchange_t) arg)
>                               (j * (1UL << exch.out.extent_order)));
>  
>                  spin_lock(&d->page_alloc_lock);
> -                d->tot_pages -= dec_count;
> +                domain_decrease_tot_pages(d, dec_count);
>                  drop_dom_ref = (dec_count && !d->tot_pages);
>                  spin_unlock(&d->page_alloc_lock);
>  
> @@ -685,6 +685,19 @@ long do_memory_op(unsigned long cmd, 
> XEN_GUEST_HANDLE_PARAM(void) arg)
>          break;
>      }
>  
> +    case XENMEM_claim_pages:
> +
> +        rc = rcu_lock_target_domain_by_id(domid, &d);

Where does "domid" come from?

> +        if ( rc )
> +            return rc;
> +
> +        rc = domain_set_unclaimed_pages(d, reservation.nr_extents,
> +                                        reservation.mem_flags);

Where do you initialize "reservation"?

And if you're indeed intending to re-use struct
xen_memory_reservation for this sub-function, then you either
ought to honor the other fields, or bail on them not being zero.

> +
> +        rcu_unlock_domain(d);
> +
> +        break;
> +
>      default:
>          rc = arch_memory_op(op, arg);
>          break;
> --- a/xen/common/page_alloc.c
> +++ b/xen/common/page_alloc.c
> @@ -238,6 +238,90 @@ static long midsize_alloc_zone_pages;
>  #define MIDSIZE_ALLOC_FRAC 128
>  
>  static DEFINE_SPINLOCK(heap_lock);
> +static long total_unclaimed_pages; /* total outstanding claims by all 
> domains */
> +
> +unsigned long domain_increase_tot_pages(struct domain *d, unsigned long 
> pages)
> +{
> +    long dom_before, dom_after, dom_claimed, sys_before, sys_after;
> +
> +    ASSERT(spin_is_locked(&d->page_alloc_lock));
> +    ASSERT(!spin_is_locked(&heap_lock));
> +    spin_lock(&heap_lock);
> +    d->tot_pages += pages;
> +    if ( d->unclaimed_pages )
> +    {
> +        dom_before = d->unclaimed_pages;
> +        dom_after = dom_before - pages;
> +        if ( (dom_before > 0) && (dom_after < 0) )
> +            dom_claimed = 0;
> +        else
> +            dom_claimed = dom_after;
> +     sys_before = total_unclaimed_pages;
> +     sys_after = sys_before - (dom_before - dom_claimed);
> +     BUG_ON( (sys_before > 0) && (sys_after < 0) );
> +        total_unclaimed_pages = sys_after;
> +        d->unclaimed_pages = dom_claimed;
> +    }
> +    spin_unlock(&heap_lock);
> +    return d->tot_pages;
> +}
> +
> +unsigned long domain_decrease_tot_pages(struct domain *d, unsigned long 
> pages)
> +{
> +    ASSERT(spin_is_locked(&d->page_alloc_lock));
> +    ASSERT(!spin_is_locked(&heap_lock));
> +    spin_lock(&heap_lock);
> +    d->tot_pages -= pages;
> +    if ( d->unclaimed_pages )
> +    {
> +        d->unclaimed_pages += pages;
> +     total_unclaimed_pages += pages;
> +    }
> +    spin_unlock(&heap_lock);
> +    return d->tot_pages;
> +}
> +
> +int domain_set_unclaimed_pages(struct domain *d, unsigned long pages,
> +                                unsigned long flags)
> +{
> +    int ret = -ENOMEM;
> +    unsigned long avail_pages;
> +
> +    ASSERT(!spin_is_locked(&d->page_alloc_lock));
> +    ASSERT(!spin_is_locked(&heap_lock));
> +    spin_lock(&d->page_alloc_lock);
> +    spin_lock(&heap_lock);
> +    /* only one active claim per domain please */
> +    if ( d->unclaimed_pages )
> +     goto out;
> +    avail_pages = total_avail_pages;
> +    if ( !(flags & XENMEM_CLAIMF_free_only) )
> +        avail_pages += tmem_freeable_pages();
> +    avail_pages -= total_unclaimed_pages;
> +    if ( pages < avail_pages )
> +    {
> +        /* ok if domain has allocated some pages before making a claim */
> +        d->unclaimed_pages = pages - d->tot_pages;
> +        total_unclaimed_pages += total_unclaimed_pages;

        total_unclaimed_pages += d->unclaimed_pages;

> +        ret = 0;
> +    }
> +out:
> +    spin_unlock(&heap_lock);
> +    spin_unlock(&d->page_alloc_lock);
> +    return ret;
> +}
> +
> +void domain_reset_unclaimed_pages(struct domain *d)
> +{
> +    ASSERT(!spin_is_locked(&d->page_alloc_lock));
> +    ASSERT(!spin_is_locked(&heap_lock));
> +    spin_lock(&d->page_alloc_lock);
> +    spin_lock(&heap_lock);
> +    total_unclaimed_pages -= d->unclaimed_pages;
> +    d->unclaimed_pages = 0;
> +    spin_unlock(&heap_lock);
> +    spin_unlock(&d->page_alloc_lock);

What is the point of acquiring d->page_alloc_lock here if
d->unclaimed_pages is always manipulated with heap_lock
held anyway?

Also, you mention the need to use this function at least
during domain shutdown, but there is no user of it throughout
the patch.

> +}
>  
>  static unsigned long init_node_heap(int node, unsigned long mfn,
>                                      unsigned long nr, bool_t *use_tail)
> @@ -442,6 +526,11 @@ static struct page_info *alloc_heap_pages(
>  
>      spin_lock(&heap_lock);
>  
> +    /* Claimed memory is considered not available */
> +    if ( total_unclaimed_pages + request >
> +         total_avail_pages + tmem_freeable_pages() )

So how would a domain having an active claim get to allocate
its memory if total_unclaimed_pages == total_avail_pages +
tmem_freeable_pages()?

> +        goto not_found;
> +
>      /*
>       * TMEM: When available memory is scarce due to tmem absorbing it, allow
>       * only mid-size allocations to avoid worst of fragmentation issues.

There are also a few uses of tabs for indentation that would
need cleaning up.

Finally, assuming we really want/need this, shouldn't there be
a way for claims to expire (e.g. in case of tool stack problems),
so they don't indefinitely prevent (perhaps large) portions of
memory to be used for other purpose (e.g. when a domain can't
get fully cleaned up)?

Jan

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

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