From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from psmtp.com (na3sys010amx140.postini.com [74.125.245.140]) by kanga.kvack.org (Postfix) with SMTP id E53A96B00A7 for ; Wed, 3 Apr 2013 01:37:37 -0400 (EDT) Received: from /spool/local by e35.co.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Tue, 2 Apr 2013 23:37:37 -0600 Received: from d03relay01.boulder.ibm.com (d03relay01.boulder.ibm.com [9.17.195.226]) by d03dlp01.boulder.ibm.com (Postfix) with ESMTP id 680621FF003E for ; Tue, 2 Apr 2013 23:32:36 -0600 (MDT) Received: from d03av02.boulder.ibm.com (d03av02.boulder.ibm.com [9.17.195.168]) by d03relay01.boulder.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id r335bYSI122004 for ; Tue, 2 Apr 2013 23:37:34 -0600 Received: from d03av02.boulder.ibm.com (loopback [127.0.0.1]) by d03av02.boulder.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id r335bYDJ015682 for ; Tue, 2 Apr 2013 23:37:34 -0600 Date: Wed, 3 Apr 2013 13:37:20 +0800 From: Ram Pai Subject: Re: [PATCH 2/3] resource: Add release_mem_region_adjustable() Message-ID: <20130403053720.GA26398@ram.oc3035372033.ibm.com> Reply-To: Ram Pai References: <1364919450-8741-1-git-send-email-toshi.kani@hp.com> <1364919450-8741-3-git-send-email-toshi.kani@hp.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1364919450-8741-3-git-send-email-toshi.kani@hp.com> Sender: owner-linux-mm@kvack.org List-ID: To: Toshi Kani Cc: akpm@linux-foundation.org, linux-mm@kvack.org, linux-kernel@vger.kernel.org, tmac@hp.com, isimatu.yasuaki@jp.fujitsu.com, wency@cn.fujitsu.com, tangchen@cn.fujitsu.com, jiang.liu@huawei.com On Tue, Apr 02, 2013 at 10:17:29AM -0600, Toshi Kani wrote: > Added release_mem_region_adjustable(), which releases a requested > region from a currently busy memory resource. This interface > adjusts the matched memory resource accordingly if the requested > region does not match exactly but still fits into. > > This new interface is intended for memory hot-delete. During > bootup, memory resources are inserted from the boot descriptor > table, such as EFI Memory Table and e820. Each memory resource > entry usually covers the whole contigous memory range. Memory > hot-delete request, on the other hand, may target to a particular > range of memory resource, and its size can be much smaller than > the whole contiguous memory. Since the existing release interfaces > like __release_region() require a requested region to be exactly > matched to a resource entry, they do not allow a partial resource > to be released. > > There is no change to the existing interfaces since their restriction > is valid for I/O resources. > > Signed-off-by: Toshi Kani > --- > include/linux/ioport.h | 2 + > kernel/resource.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 89 insertions(+) > > diff --git a/include/linux/ioport.h b/include/linux/ioport.h > index 85ac9b9b..0fe1a82 100644 > --- a/include/linux/ioport.h > +++ b/include/linux/ioport.h > @@ -192,6 +192,8 @@ extern struct resource * __request_region(struct resource *, > extern int __check_region(struct resource *, resource_size_t, resource_size_t); > extern void __release_region(struct resource *, resource_size_t, > resource_size_t); > +extern int release_mem_region_adjustable(struct resource *, resource_size_t, > + resource_size_t); > > static inline int __deprecated check_region(resource_size_t s, > resource_size_t n) > diff --git a/kernel/resource.c b/kernel/resource.c > index ae246f9..789f160 100644 > --- a/kernel/resource.c > +++ b/kernel/resource.c > @@ -1021,6 +1021,93 @@ void __release_region(struct resource *parent, resource_size_t start, > } > EXPORT_SYMBOL(__release_region); > > +/** > + * release_mem_region_adjustable - release a previously reserved memory region > + * @parent: parent resource descriptor > + * @start: resource start address > + * @size: resource region size > + * > + * The requested region is released from a currently busy memory resource. > + * It adjusts the matched busy memory resource accordingly if the requested > + * region does not match exactly but still fits into. Existing children of > + * the busy memory resource must be immutable in this request. > + * > + * Note, when the busy memory resource gets split into two entries, the code > + * assumes that all children remain in the lower address entry for simplicity. > + * Enhance this logic when necessary. > + */ > +int release_mem_region_adjustable(struct resource *parent, > + resource_size_t start, resource_size_t size) > +{ > + struct resource **p; > + struct resource *res, *new; > + resource_size_t end; > + int ret = 0; > + > + p = &parent->child; > + end = start + size - 1; > + > + write_lock(&resource_lock); > + > + while ((res = *p)) { > + if (res->start > start || res->end < end) { This check looks sub-optimal; possbily wrong, to me. if the res->start is greater than 'start', then obviously its sibling's start will also be greater than 'start'. So it will loop through all the resources unnecesarily. you might want something like if (start >= res->end) { > + p = &res->sibling; > + continue; > + } > + > + if (!(res->flags & IORESOURCE_MEM)) { > + ret = -EINVAL; > + break; > + } > + > + if (!(res->flags & IORESOURCE_BUSY)) { > + p = &res->child; > + continue; > + } > + > + if (res->start == start && res->end == end) { > + /* free the whole entry */ > + *p = res->sibling; > + kfree(res); This is incomplete. the prev resource's sibling should now point to this resource's sibling. The parent's child has to be updated if this resource is the first child resource. no? > + } else if (res->start == start && res->end != end) { > + /* adjust the start */ > + ret = __adjust_resource(res, end+1, > + res->end - end); > + } else if (res->start != start && res->end == end) { > + /* adjust the end */ > + ret = __adjust_resource(res, res->start, > + start - res->start); > + } else { > + /* split into two entries */ > + new = kzalloc(sizeof(struct resource), GFP_KERNEL); > + if (!new) { > + ret = -ENOMEM; > + break; > + } > + new->name = res->name; > + new->start = end + 1; > + new->end = res->end; > + new->flags = res->flags; > + new->parent = res->parent; > + new->sibling = res->sibling; > + new->child = NULL; > + > + ret = __adjust_resource(res, res->start, > + start - res->start); > + if (ret) { > + kfree(new); > + break; > + } > + res->sibling = new; > + } > + > + break; > + } > + > + write_unlock(&resource_lock); > + return ret; > +} > + > /* > * Managed region resource > */ -- Ram Pai -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to majordomo@kvack.org. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: email@kvack.org