summaryrefslogtreecommitdiff
path: root/sys/kern/subr_extent.c
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2014-01-21 21:45:59 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2014-01-21 21:45:59 +0000
commitd8d377d11784828e3116ae60b953f3f53ff1f647 (patch)
tree10c379d1dd8e3f26f522128f357c475a49148c1a /sys/kern/subr_extent.c
parent8ef3c99976ca044dd12bd7886ff39b8e625e19b6 (diff)
Add extent_alloc_subregion_with_descr(9) which allows the caller to provide
a region descriptor such that the extent manager doesn't need to call malloc(9). ok miod@, deraadt@
Diffstat (limited to 'sys/kern/subr_extent.c')
-rw-r--r--sys/kern/subr_extent.c67
1 files changed, 50 insertions, 17 deletions
diff --git a/sys/kern/subr_extent.c b/sys/kern/subr_extent.c
index 65449463750..f5f29cb1cbd 100644
--- a/sys/kern/subr_extent.c
+++ b/sys/kern/subr_extent.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: subr_extent.c,v 1.49 2014/01/21 01:48:44 tedu Exp $ */
+/* $OpenBSD: subr_extent.c,v 1.50 2014/01/21 21:45:58 kettenis Exp $ */
/* $NetBSD: subr_extent.c,v 1.7 1996/11/21 18:46:34 cgd Exp $ */
/*-
@@ -78,6 +78,8 @@ static void extent_insert_and_optimize(struct extent *, u_long, u_long,
static struct extent_region *extent_alloc_region_descriptor(struct extent *, int);
static void extent_free_region_descriptor(struct extent *,
struct extent_region *);
+int extent_do_alloc(struct extent *, u_long, u_long, u_long, u_long,
+ u_long, u_long, int, struct extent_region *, u_long *);
/*
* Shortcut to align to an arbitrary power-of-two boundary.
@@ -580,11 +582,11 @@ extent_alloc_region(struct extent *ex, u_long start, u_long size, int flags)
* a power of 2.
*/
int
-extent_alloc_subregion(struct extent *ex, u_long substart, u_long subend,
+extent_do_alloc(struct extent *ex, u_long substart, u_long subend,
u_long size, u_long alignment, u_long skew, u_long boundary, int flags,
- u_long *result)
+ struct extent_region *myrp, u_long *result)
{
- struct extent_region *rp, *myrp, *last, *bestlast;
+ struct extent_region *rp, *last, *bestlast;
u_long newstart, newend, exend, beststart, bestovh, ovh;
u_long dontcross;
int error;
@@ -593,6 +595,8 @@ extent_alloc_subregion(struct extent *ex, u_long substart, u_long subend,
/* Check arguments. */
if (ex == NULL)
panic("%s: NULL extent", __func__);
+ if (myrp == NULL)
+ panic("%s: NULL region descriptor", __func__);
if (result == NULL)
panic("%s: NULL result pointer", __func__);
if ((substart < ex->ex_start) || (substart > ex->ex_end) ||
@@ -617,18 +621,6 @@ extent_alloc_subregion(struct extent *ex, u_long substart, u_long subend,
}
#endif
- /*
- * Allocate the region descriptor. It will be freed later
- * if we can coalesce with another region.
- */
- myrp = extent_alloc_region_descriptor(ex, flags);
- if (myrp == NULL) {
-#ifdef DIAGNOSTIC
- printf("%s: can't allocate region descriptor\n", __func__);
-#endif
- return (ENOMEM);
- }
-
alloc_start:
/*
* Keep a pointer to the last region we looked at so
@@ -927,6 +919,44 @@ skip:
}
int
+extent_alloc_subregion(struct extent *ex, u_long substart, u_long subend,
+ u_long size, u_long alignment, u_long skew, u_long boundary, int flags,
+ u_long *result)
+{
+ struct extent_region *rp;
+
+ /*
+ * Allocate the region descriptor. It will be freed later
+ * if we can coalesce with another region.
+ */
+ rp = extent_alloc_region_descriptor(ex, flags);
+ if (rp == NULL) {
+#ifdef DIAGNOSTIC
+ printf("%s: can't allocate region descriptor\n", __func__);
+#endif
+ return (ENOMEM);
+ }
+
+ return extent_do_alloc(ex, substart, subend, size, alignment, skew,
+ boundary, flags, rp, result);
+}
+
+int
+extent_alloc_subregion_with_descr(struct extent *ex, u_long substart,
+ u_long subend, u_long size, u_long alignment, u_long skew,
+ u_long boundary, int flags, struct extent_region *rp, u_long *result)
+{
+#ifdef DIAGNOSTIC
+ if ((ex->ex_flags & EXF_NOCOALESCE) == 0)
+ panic("%s: EX_NOCOALESCE not set", __func__);
+#endif
+
+ rp->er_flags = ER_DISCARD;
+ return extent_do_alloc(ex, substart, subend, size, alignment, skew,
+ boundary, flags, rp, result);
+}
+
+int
extent_free(struct extent *ex, u_long start, u_long size, int flags)
{
struct extent_region *rp, *nrp = NULL;
@@ -1111,6 +1141,9 @@ extent_alloc_region_descriptor(struct extent *ex, int flags)
static void
extent_free_region_descriptor(struct extent *ex, struct extent_region *rp)
{
+ if (rp->er_flags & ER_DISCARD)
+ return;
+
if (ex->ex_flags & EXF_FIXED) {
struct extent_fixed *fex = (struct extent_fixed *)ex;
@@ -1149,7 +1182,7 @@ extent_free_region_descriptor(struct extent *ex, struct extent_region *rp)
pool_put(&ex_region_pl, rp);
}
-
+
#if defined(DIAGNOSTIC) || defined(DDB) || !defined(_KERNEL)
void