From mboxrd@z Thu Jan 1 00:00:00 1970 From: Paul Durrant Subject: [PATCH v6 6/9] Add an option to limit ranges per rangeset Date: Thu, 8 May 2014 14:23:41 +0100 Message-ID: <1399555424-25201-7-git-send-email-paul.durrant@citrix.com> References: <1399555424-25201-1-git-send-email-paul.durrant@citrix.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: <1399555424-25201-1-git-send-email-paul.durrant@citrix.com> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org To: xen-devel@lists.xen.org Cc: Paul Durrant , Keir Fraser , Jan Beulich List-Id: xen-devel@lists.xenproject.org A subsequent patch exposes rangesets to secondary emulators, so to allow a limit to be placed on the amount of xenheap that an emulator can cause to be consumed, add a new parameter to rangeset_new() to set the maximum number of ranges allowed in a rangeset. A value of 0 means no limit is applied. Signed-off-by: Paul Durrant Cc: Keir Fraser Cc: Jan Beulich --- xen/arch/x86/domain.c | 2 +- xen/arch/x86/mm/p2m.c | 2 +- xen/arch/x86/setup.c | 2 +- xen/common/domain.c | 5 ++-- xen/common/rangeset.c | 55 ++++++++++++++++++++++++++++++++++++-------- xen/include/xen/rangeset.h | 15 +++++++++++- 6 files changed, 65 insertions(+), 16 deletions(-) diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index 1436aee..c177e29 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -560,7 +560,7 @@ int arch_domain_create(struct domain *d, unsigned int domcr_flags) } d->arch.ioport_caps = - rangeset_new(d, "I/O Ports", RANGESETF_prettyprint_hex); + rangeset_new(d, "I/O Ports", RANGESETF_prettyprint_hex, 0); rc = -ENOMEM; if ( d->arch.ioport_caps == NULL ) goto fail; diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c index 03e9ad5..b0964f1 100644 --- a/xen/arch/x86/mm/p2m.c +++ b/xen/arch/x86/mm/p2m.c @@ -117,7 +117,7 @@ static int p2m_init_hostp2m(struct domain *d) if ( p2m ) { p2m->logdirty_ranges = rangeset_new(d, "log-dirty", - RANGESETF_prettyprint_hex); + RANGESETF_prettyprint_hex, 0); if ( p2m->logdirty_ranges ) { d->arch.p2m = p2m; diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c index 2e30701..a22e829 100644 --- a/xen/arch/x86/setup.c +++ b/xen/arch/x86/setup.c @@ -1236,7 +1236,7 @@ void __init noreturn __start_xen(unsigned long mbi_p) zap_low_mappings(); mmio_ro_ranges = rangeset_new(NULL, "r/o mmio ranges", - RANGESETF_prettyprint_hex); + RANGESETF_prettyprint_hex, 0); init_apic_mappings(); diff --git a/xen/common/domain.c b/xen/common/domain.c index 4291e29..b11cecd 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -300,8 +300,9 @@ struct domain *domain_create( rangeset_domain_initialise(d); init_status |= INIT_rangeset; - d->iomem_caps = rangeset_new(d, "I/O Memory", RANGESETF_prettyprint_hex); - d->irq_caps = rangeset_new(d, "Interrupts", 0); + d->iomem_caps = rangeset_new(d, "I/O Memory", + RANGESETF_prettyprint_hex, 0); + d->irq_caps = rangeset_new(d, "Interrupts", 0, 0); if ( (d->iomem_caps == NULL) || (d->irq_caps == NULL) ) goto fail; diff --git a/xen/common/rangeset.c b/xen/common/rangeset.c index 2b986fb..8293c76 100644 --- a/xen/common/rangeset.c +++ b/xen/common/rangeset.c @@ -25,6 +25,8 @@ struct rangeset { /* Ordered list of ranges contained in this set, and protecting lock. */ struct list_head range_list; + unsigned int nr_ranges; + unsigned int max_nr_ranges; spinlock_t lock; /* Pretty-printing name. */ @@ -81,12 +83,32 @@ static void insert_range( /* Remove a range from its list and free it. */ static void destroy_range( - struct range *x) + struct rangeset *r, struct range *x) { + ASSERT(r->nr_ranges != 0); + r->nr_ranges--; + list_del(&x->list); xfree(x); } +/* Allocate a new range */ +static struct range *alloc_range( + struct rangeset *r) +{ + struct range *x; + + ASSERT(!r->max_nr_ranges || r->nr_ranges <= r->max_nr_ranges); + if ( r->max_nr_ranges && (r->nr_ranges == r->max_nr_ranges) ) + return NULL; + + x = xmalloc(struct range); + if ( x ) + r->nr_ranges++; + + return x; +} + /***************************** * Core public functions */ @@ -108,7 +130,7 @@ int rangeset_add_range( { if ( (x == NULL) || ((x->e < s) && ((x->e + 1) != s)) ) { - x = xmalloc(struct range); + x = alloc_range(r); if ( x == NULL ) { rc = -ENOMEM; @@ -143,7 +165,7 @@ int rangeset_add_range( y = next_range(r, x); if ( (y == NULL) || (y->e > x->e) ) break; - destroy_range(y); + destroy_range(r, y); } } @@ -151,7 +173,7 @@ int rangeset_add_range( if ( (y != NULL) && ((x->e + 1) == y->s) ) { x->e = y->e; - destroy_range(y); + destroy_range(r, y); } out: @@ -179,7 +201,7 @@ int rangeset_remove_range( if ( (x->s < s) && (x->e > e) ) { - y = xmalloc(struct range); + y = alloc_range(r); if ( y == NULL ) { rc = -ENOMEM; @@ -193,7 +215,7 @@ int rangeset_remove_range( insert_range(r, x, y); } else if ( (x->s == s) && (x->e <= e) ) - destroy_range(x); + destroy_range(r, x); else if ( x->s == s ) x->s = e + 1; else if ( x->e <= e ) @@ -214,12 +236,12 @@ int rangeset_remove_range( { t = x; x = next_range(r, x); - destroy_range(t); + destroy_range(r, t); } x->s = e + 1; if ( x->s > x->e ) - destroy_range(x); + destroy_range(r, x); } out: @@ -302,7 +324,8 @@ int rangeset_is_empty( } struct rangeset *rangeset_new( - struct domain *d, char *name, unsigned int flags) + struct domain *d, char *name, unsigned int flags, + unsigned int max_nr_ranges) { struct rangeset *r; @@ -312,6 +335,8 @@ struct rangeset *rangeset_new( spin_lock_init(&r->lock); INIT_LIST_HEAD(&r->range_list); + r->nr_ranges = 0; + r->max_nr_ranges = max_nr_ranges; BUG_ON(flags & ~RANGESETF_prettyprint_hex); r->flags = flags; @@ -351,7 +376,7 @@ void rangeset_destroy( } while ( (x = first_range(r)) != NULL ) - destroy_range(x); + destroy_range(r, x); xfree(r); } @@ -461,3 +486,13 @@ void rangeset_domain_printk( spin_unlock(&d->rangesets_lock); } + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/xen/include/xen/rangeset.h b/xen/include/xen/rangeset.h index 2c122c1..53c7c2f 100644 --- a/xen/include/xen/rangeset.h +++ b/xen/include/xen/rangeset.h @@ -29,12 +29,15 @@ void rangeset_domain_destroy( * Create/destroy a rangeset. Optionally attach to specified domain @d for * auto-destruction when the domain dies. A name may be specified, for use * in debug pretty-printing, and various RANGESETF flags (defined below). + * @max_nr_ranges may be set to a non-zero value to limit the number of + * ranges in the set. * * It is invalid to perform any operation on a rangeset @r after calling * rangeset_destroy(r). */ struct rangeset *rangeset_new( - struct domain *d, char *name, unsigned int flags); + struct domain *d, char *name, unsigned int flags, + unsigned int max_nr_ranges); void rangeset_destroy( struct rangeset *r); @@ -77,3 +80,13 @@ void rangeset_domain_printk( struct domain *d); #endif /* __XEN_RANGESET_H__ */ + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ -- 1.7.10.4