aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sys/nvpair.h1
-rw-r--r--module/nvpair/nvpair.c21
-rw-r--r--module/nvpair/nvpair_alloc_spl.c20
3 files changed, 38 insertions, 4 deletions
diff --git a/include/sys/nvpair.h b/include/sys/nvpair.h
index cc399fd16..c502568a6 100644
--- a/include/sys/nvpair.h
+++ b/include/sys/nvpair.h
@@ -144,6 +144,7 @@ extern nv_alloc_t *nv_alloc_nosleep;
#if defined(_KERNEL) && !defined(_BOOT)
extern nv_alloc_t *nv_alloc_sleep;
+extern nv_alloc_t *nv_alloc_pushpage;
#endif
int nv_alloc_init(nv_alloc_t *, const nv_alloc_ops_t *, /* args */ ...);
diff --git a/module/nvpair/nvpair.c b/module/nvpair/nvpair.c
index 5c6898446..36f4e4dc1 100644
--- a/module/nvpair/nvpair.c
+++ b/module/nvpair/nvpair.c
@@ -269,12 +269,25 @@ nvlist_nvflag(nvlist_t *nvl)
int
nvlist_alloc(nvlist_t **nvlp, uint_t nvflag, int kmflag)
{
+ nv_alloc_t *nva = nv_alloc_nosleep;
+
#if defined(_KERNEL) && !defined(_BOOT)
- return (nvlist_xalloc(nvlp, nvflag,
- (kmflag == KM_SLEEP ? nv_alloc_sleep : nv_alloc_nosleep)));
-#else
- return (nvlist_xalloc(nvlp, nvflag, nv_alloc_nosleep));
+ switch (kmflag) {
+ case KM_SLEEP:
+ nva = nv_alloc_sleep;
+ break;
+ case KM_PUSHPAGE:
+ nva = nv_alloc_pushpage;
+ break;
+ case KM_NOSLEEP:
+ nva = nv_alloc_nosleep;
+ break;
+ default:
+ return (EINVAL);
+ }
#endif
+
+ return (nvlist_xalloc(nvlp, nvflag, nva));
}
int
diff --git a/module/nvpair/nvpair_alloc_spl.c b/module/nvpair/nvpair_alloc_spl.c
index 63d57a19a..be6e8f0a5 100644
--- a/module/nvpair/nvpair_alloc_spl.c
+++ b/module/nvpair/nvpair_alloc_spl.c
@@ -34,6 +34,12 @@ nv_alloc_sleep_spl(nv_alloc_t *nva, size_t size)
}
static void *
+nv_alloc_pushpage_spl(nv_alloc_t *nva, size_t size)
+{
+ return (kmem_alloc(size, KM_PUSHPAGE | KM_NODEBUG));
+}
+
+static void *
nv_alloc_nosleep_spl(nv_alloc_t *nva, size_t size)
{
return (kmem_alloc(size, KM_NOSLEEP));
@@ -53,6 +59,14 @@ const nv_alloc_ops_t spl_sleep_ops_def = {
NULL /* nv_ao_reset() */
};
+const nv_alloc_ops_t spl_pushpage_ops_def = {
+ NULL, /* nv_ao_init() */
+ NULL, /* nv_ao_fini() */
+ nv_alloc_pushpage_spl, /* nv_ao_alloc() */
+ nv_free_spl, /* nv_ao_free() */
+ NULL /* nv_ao_reset() */
+};
+
const nv_alloc_ops_t spl_nosleep_ops_def = {
NULL, /* nv_ao_init() */
NULL, /* nv_ao_fini() */
@@ -66,10 +80,16 @@ nv_alloc_t nv_alloc_sleep_def = {
NULL
};
+nv_alloc_t nv_alloc_pushpage_def = {
+ &spl_pushpage_ops_def,
+ NULL
+};
+
nv_alloc_t nv_alloc_nosleep_def = {
&spl_nosleep_ops_def,
NULL
};
nv_alloc_t *nv_alloc_sleep = &nv_alloc_sleep_def;
+nv_alloc_t *nv_alloc_pushpage = &nv_alloc_pushpage_def;
nv_alloc_t *nv_alloc_nosleep = &nv_alloc_nosleep_def;