aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sys/zfs_context.h13
-rw-r--r--lib/libzpool/kernel.c48
-rw-r--r--man/man1/ztest.116
3 files changed, 47 insertions, 30 deletions
diff --git a/include/sys/zfs_context.h b/include/sys/zfs_context.h
index bbb8a0463..f26c827dc 100644
--- a/include/sys/zfs_context.h
+++ b/include/sys/zfs_context.h
@@ -203,16 +203,17 @@ extern void vpanic(const char *, va_list);
#else
#define SET_ERROR(err) (err)
#endif
+
/*
- * Threads
+ * Threads. TS_STACK_MIN is dictated by the minimum allowed pthread stack
+ * size. While TS_STACK_MAX is somewhat arbitrary, it was selected to be
+ * large enough for the expected stack depth while small enough to avoid
+ * exhausting address space with high thread counts.
*/
#define TS_MAGIC 0x72f158ab4261e538ull
#define TS_RUN 0x00000002
-#ifdef __linux__
-#define STACK_SIZE 8192 /* Linux x86 and amd64 */
-#else
-#define STACK_SIZE 24576 /* Solaris */
-#endif
+#define TS_STACK_MIN PTHREAD_STACK_MIN
+#define TS_STACK_MAX (256 * 1024)
/* in libzpool, p0 exists only to have its address taken */
typedef struct proc {
diff --git a/lib/libzpool/kernel.c b/lib/libzpool/kernel.c
index 03fbe3dd0..5adcfa617 100644
--- a/lib/libzpool/kernel.c
+++ b/lib/libzpool/kernel.c
@@ -146,41 +146,41 @@ zk_thread_create(caddr_t stk, size_t stksize, thread_func_t func, void *arg,
{
kthread_t *kt;
pthread_attr_t attr;
- size_t stack;
+ char *stkstr;
- ASSERT3S(state & ~TS_RUN, ==, 0);
+ ASSERT0(state & ~TS_RUN);
kt = umem_zalloc(sizeof (kthread_t), UMEM_NOFAIL);
kt->t_func = func;
kt->t_arg = arg;
+ VERIFY0(pthread_attr_init(&attr));
+ VERIFY0(pthread_attr_setdetachstate(&attr, detachstate));
+
/*
- * The Solaris kernel stack size is 24k for x86/x86_64.
- * The Linux kernel stack size is 8k for x86/x86_64.
- *
- * We reduce the default stack size in userspace, to ensure
- * we observe stack overruns in user space as well as in
- * kernel space. In practice we can't set the userspace stack
- * size to 8k because differences in stack usage between kernel
- * space and userspace could lead to spurious stack overflows
- * (especially when debugging is enabled). Nevertheless, we try
- * to set it to the lowest value that works (currently 8k*4).
- * PTHREAD_STACK_MIN is the minimum stack required for a NULL
- * procedure in user space and is added in to the stack
- * requirements.
+ * We allow the default stack size in user space to be specified by
+ * setting the ZFS_STACK_SIZE environment variable. This allows us
+ * the convenience of observing and debugging stack overruns in
+ * user space. Explicitly specified stack sizes will be honored.
+ * The usage of ZFS_STACK_SIZE is discussed further in the
+ * ENVIRONMENT VARIABLES sections of the ztest(1) man page.
*/
+ if (stksize == 0) {
+ stkstr = getenv("ZFS_STACK_SIZE");
- stack = PTHREAD_STACK_MIN + MAX(stksize, STACK_SIZE) * 4;
-
- VERIFY3S(pthread_attr_init(&attr), ==, 0);
- VERIFY3S(pthread_attr_setstacksize(&attr, stack), ==, 0);
- VERIFY3S(pthread_attr_setguardsize(&attr, PAGESIZE), ==, 0);
- VERIFY3S(pthread_attr_setdetachstate(&attr, detachstate), ==, 0);
+ if (stkstr == NULL)
+ stksize = TS_STACK_MAX;
+ else
+ stksize = MAX(atoi(stkstr), TS_STACK_MIN);
+ }
- VERIFY3S(pthread_create(&kt->t_tid, &attr, &zk_thread_helper, kt),
- ==, 0);
+ VERIFY3S(stksize, >, 0);
+ stksize = P2ROUNDUP(MAX(stksize, TS_STACK_MIN), PAGESIZE);
+ VERIFY0(pthread_attr_setstacksize(&attr, stksize));
+ VERIFY0(pthread_attr_setguardsize(&attr, PAGESIZE));
- VERIFY3S(pthread_attr_destroy(&attr), ==, 0);
+ VERIFY0(pthread_create(&kt->t_tid, &attr, &zk_thread_helper, kt));
+ VERIFY0(pthread_attr_destroy(&attr));
return (kt);
}
diff --git a/man/man1/ztest.1 b/man/man1/ztest.1
index 961a5b0de..f798bcfcb 100644
--- a/man/man1/ztest.1
+++ b/man/man1/ztest.1
@@ -144,6 +144,22 @@ Maybe you'd like to run ztest for longer? To do so simply use the -T
option and specify the runlength in seconds like so:
.IP
ztest -f / -V -T 120
+
+.SH "ENVIRONMENT VARIABLES"
+.TP
+.B "ZFS_STACK_SIZE=stacksize"
+Limit the default stack size to \fBstacksize\fR bytes for the purpose of
+detecting and debugging kernel stack overflows. For x86_64 platforms this
+value should be set as follows to simulate these platforms: \fB8192\fR
+(Linux), \fB20480\fR (Illumos), \fB16384\fR (FreeBSD).
+
+In practice you may need to set these value slightly higher because
+differences in stack usage between kernel and user space can lead to spurious
+stack overflows (especially when debugging is enabled). The specified value
+will be rounded up to a floor of PTHREAD_STACK_MIN which is the minimum stack
+required for a NULL procedure in user space.
+
+By default the stack size is limited to 256K.
.SH "SEE ALSO"
.BR "zpool (1)" ","
.BR "zfs (1)" ","