diff options
author | Matthew Wilcox <matthew@wil.cx> | 2006-06-30 05:31:24 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-09-26 20:43:52 -0400 |
commit | d33b6fba2c4350651f3f61ff2ab858a2f116e9a4 (patch) | |
tree | fa4fa45fd6cc3bf177e13c2e9544b3e8134e1456 /kernel/resource.c | |
parent | b278240839e20fa9384ea430df463b367b90e04e (diff) |
Resources: insert identical resources above existing resources
If you have two resources which aree exactly the same size,
insert_resource() currently inserts the new one below the existing one.
This is wrong because there's no way to insert a resource of the same size
above an existing one.
I took this opportunity to rewrite the initial loop to be a for-loop
instead of a goto-loop and fix the documentation.
Signed-off-by: Matthew Wilcox <matthew@wil.cx>
Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
Cc: Dominik Brodowski <linux@dominikbrodowski.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'kernel/resource.c')
-rw-r--r-- | kernel/resource.c | 32 |
1 files changed, 16 insertions, 16 deletions
diff --git a/kernel/resource.c b/kernel/resource.c index 46286434af80..9db38a1a7520 100644 --- a/kernel/resource.c +++ b/kernel/resource.c | |||
@@ -344,12 +344,11 @@ EXPORT_SYMBOL(allocate_resource); | |||
344 | * | 344 | * |
345 | * Returns 0 on success, -EBUSY if the resource can't be inserted. | 345 | * Returns 0 on success, -EBUSY if the resource can't be inserted. |
346 | * | 346 | * |
347 | * This function is equivalent of request_resource when no conflict | 347 | * This function is equivalent to request_resource when no conflict |
348 | * happens. If a conflict happens, and the conflicting resources | 348 | * happens. If a conflict happens, and the conflicting resources |
349 | * entirely fit within the range of the new resource, then the new | 349 | * entirely fit within the range of the new resource, then the new |
350 | * resource is inserted and the conflicting resources become childs of | 350 | * resource is inserted and the conflicting resources become children of |
351 | * the new resource. Otherwise the new resource becomes the child of | 351 | * the new resource. |
352 | * the conflicting resource | ||
353 | */ | 352 | */ |
354 | int insert_resource(struct resource *parent, struct resource *new) | 353 | int insert_resource(struct resource *parent, struct resource *new) |
355 | { | 354 | { |
@@ -357,20 +356,21 @@ int insert_resource(struct resource *parent, struct resource *new) | |||
357 | struct resource *first, *next; | 356 | struct resource *first, *next; |
358 | 357 | ||
359 | write_lock(&resource_lock); | 358 | write_lock(&resource_lock); |
360 | begin: | ||
361 | result = 0; | ||
362 | first = __request_resource(parent, new); | ||
363 | if (!first) | ||
364 | goto out; | ||
365 | 359 | ||
366 | result = -EBUSY; | 360 | for (;; parent = first) { |
367 | if (first == parent) | 361 | result = 0; |
368 | goto out; | 362 | first = __request_resource(parent, new); |
363 | if (!first) | ||
364 | goto out; | ||
369 | 365 | ||
370 | /* Resource fully contained by the clashing resource? Recurse into it */ | 366 | result = -EBUSY; |
371 | if (first->start <= new->start && first->end >= new->end) { | 367 | if (first == parent) |
372 | parent = first; | 368 | goto out; |
373 | goto begin; | 369 | |
370 | if ((first->start > new->start) || (first->end < new->end)) | ||
371 | break; | ||
372 | if ((first->start == new->start) && (first->end == new->end)) | ||
373 | break; | ||
374 | } | 374 | } |
375 | 375 | ||
376 | for (next = first; ; next = next->sibling) { | 376 | for (next = first; ; next = next->sibling) { |