mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Matthew Wilcox <willy@debian.org>
To: Linus Torvalds <torvalds@osdl.org>
Cc: linux-kernel@vger.kernel.org
Subject: [PATCH] expand_resource
Date: Tue, 30 Sep 2003 22:04:10 +0100	[thread overview]
Message-ID: <20030930210410.GD24824@parcelfarce.linux.theplanet.co.uk> (raw)


Rewrite expand_resource() to be racefree and move it to kernel/resource.c.

Index: linux-2.6/kernel/resource.c
===================================================================
RCS file: /var/cvs/linux-2.6/kernel/resource.c,v
retrieving revision 1.3.2.1
retrieving revision 1.4
diff -u -p -r1.3.2.1 -r1.4
--- linux-2.6/kernel/resource.c	28 Sep 2003 02:27:48 -0000	1.3.2.1
+++ linux-2.6/kernel/resource.c	28 Sep 2003 04:06:24 -0000	1.4
@@ -266,6 +268,53 @@ int allocate_resource(struct resource *r
 		err = -EBUSY;
 	write_unlock(&resource_lock);
 	return err;
+}
+
+/*
+ * Expand an existing resource by size amount.
+ */
+int expand_resource(struct resource *res, unsigned long size,
+			   unsigned long align)
+{
+	unsigned long start, end;
+
+	/* see if we can expand above */
+	end = (res->end + size + align - 1) & ~(align - 1);
+
+	write_lock(&resource_lock);
+	if (res->sibling) {
+		if (res->sibling->start > end)
+			goto end;
+	} else {
+		if (res->parent->end >= end)
+			goto end;
+	}
+
+	/* now try below */
+	start = ((res->start - size + align) & ~(align - 1)) - align;
+
+	if (res->parent->child == res) {
+		if (res->start <= start)
+			goto start;
+	} else {
+		struct resource *prev = res->parent->child;
+		while (prev->sibling != res)
+			prev = prev->sibling;
+		if (prev->end < start)
+			goto start;
+	}
+
+	write_unlock(&resource_lock);
+	return -ENOMEM;
+
+ start:
+	res->start = start;
+	write_unlock(&resource_lock);
+	return 0;
+ end:
+	res->end = end;
+	write_unlock(&resource_lock);
+	return 0;
 }
 
 /*
Index: linux-2.6/drivers/parisc/ccio-dma.c
===================================================================
RCS file: /var/cvs/linux-2.6/drivers/parisc/ccio-dma.c,v
retrieving revision 1.7.2.1
retrieving revision 1.7
diff -u -p -r1.7.2.1 -r1.7
--- linux-2.6/drivers/parisc/ccio-dma.c	28 Sep 2003 02:27:09 -0000	1.7.2.1
+++ linux-2.6/drivers/parisc/ccio-dma.c	27 Sep 2003 20:03:16 -0000	1.7
@@ -1534,42 +1534,6 @@ static void __init ccio_init_resources(s
 			(unsigned long)&ioc->ioc_hpa->io_io_low_hv);
 }
 
-static int expand_resource(struct resource *res, unsigned long size,
-			   unsigned long align)
-{
-	struct resource *temp_res;
-	unsigned long start = res->start;
-	unsigned long end ;
-
-	/* see if we can expand above */
-	end = (res->end + size + align - 1) & ~(align - 1);;
-	
-	temp_res = __request_region(res->parent, res->end, end - res->end,
-				    "expansion");
-	if(!temp_res) {
-		/* now try below */
-		start = ((res->start - size + align) & ~(align - 1)) - align;
-		end = res->end;
-		temp_res = __request_region(res->parent, start, size,
-					    "expansion");	
-		if(!temp_res) {
-			return -ENOMEM;
-		}
-	} 
-	release_resource(temp_res);
-	temp_res = res->parent;
-	release_resource(res);
-	res->start = start;
-	res->end = end;
-
-	/* This could be caused by some sort of race.  Basically, if
-	 * this tripped something stole the region we just reserved
-	 * and then released to check for expansion */
-	BUG_ON(request_resource(temp_res, res) != 0);
-
-	return 0;
-}
-
 static void expand_ioc_area(struct resource *parent, struct ioc *ioc,
 			    unsigned long size,	unsigned long min,
 			    unsigned long max, unsigned long align)
Index: linux-2.6/include/linux/ioport.h
===================================================================
RCS file: /var/cvs/linux-2.6/include/linux/ioport.h,v
retrieving revision 1.2.2.1
retrieving revision 1.2
diff -u -p -r1.2.2.1 -r1.2
--- linux-2.6/include/linux/ioport.h	28 Sep 2003 02:27:45 -0000	1.2.2.1
+++ linux-2.6/include/linux/ioport.h	27 Sep 2003 20:03:18 -0000	1.2
@@ -97,6 +97,8 @@ extern int allocate_resource(struct reso
 			     void (*alignf)(void *, struct resource *,
 					    unsigned long, unsigned long),
 			     void *alignf_data);
+int expand_resource(struct resource *res, unsigned long size,
+		    unsigned long align);
 
 /* Convenience shorthand with allocation */
 #define request_region(start,n,name)	__request_region(&ioport_resource, (start), (n), (name))

-- 
"It's not Hollywood.  War is real, war is primarily not about defeat or
victory, it is about death.  I've seen thousands and thousands of dead bodies.
Do you think I want to have an academic debate on this subject?" -- Robert Fisk

             reply	other threads:[~2003-09-30 21:05 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2003-09-30 21:04 Matthew Wilcox [this message]
2003-09-30 21:27 ` Russell King
2003-09-30 22:14   ` Matthew Wilcox
2003-09-30 22:33     ` Russell King
2003-10-01 14:25       ` Matthew Wilcox
2003-10-01 17:50         ` Matthias Urlichs

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20030930210410.GD24824@parcelfarce.linux.theplanet.co.uk \
    --to=willy@debian.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=torvalds@osdl.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

Powered by JetHome