Make user stack limit configurable
To aid in detecting and debugging stack overflow issues make the user space stack limit configurable via a new ZFS_STACK_SIZE environment variable. The value assigned to ZFS_STACK_SIZE will be used as the default stack size in bytes. Because this is mainly useful as a debugging aid in conjunction with ztest the stack limit is disabled by default. See the ztest(1) man page for additional details on using the ZFS_STACK_SIZE environment variable. Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Ned Bass <bass6@llnl.gov> Closes #2743 Issue #2293
This commit is contained in:
parent
cb08f06307
commit
aa0ac7caa4
|
@ -203,16 +203,17 @@ extern void vpanic(const char *, va_list);
|
||||||
#else
|
#else
|
||||||
#define SET_ERROR(err) (err)
|
#define SET_ERROR(err) (err)
|
||||||
#endif
|
#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_MAGIC 0x72f158ab4261e538ull
|
||||||
#define TS_RUN 0x00000002
|
#define TS_RUN 0x00000002
|
||||||
#ifdef __linux__
|
#define TS_STACK_MIN PTHREAD_STACK_MIN
|
||||||
#define STACK_SIZE 8192 /* Linux x86 and amd64 */
|
#define TS_STACK_MAX (256 * 1024)
|
||||||
#else
|
|
||||||
#define STACK_SIZE 24576 /* Solaris */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* in libzpool, p0 exists only to have its address taken */
|
/* in libzpool, p0 exists only to have its address taken */
|
||||||
typedef struct proc {
|
typedef struct proc {
|
||||||
|
|
|
@ -146,41 +146,41 @@ zk_thread_create(caddr_t stk, size_t stksize, thread_func_t func, void *arg,
|
||||||
{
|
{
|
||||||
kthread_t *kt;
|
kthread_t *kt;
|
||||||
pthread_attr_t attr;
|
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 = umem_zalloc(sizeof (kthread_t), UMEM_NOFAIL);
|
||||||
kt->t_func = func;
|
kt->t_func = func;
|
||||||
kt->t_arg = arg;
|
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.
|
* We allow the default stack size in user space to be specified by
|
||||||
* The Linux kernel stack size is 8k for x86/x86_64.
|
* setting the ZFS_STACK_SIZE environment variable. This allows us
|
||||||
*
|
* the convenience of observing and debugging stack overruns in
|
||||||
* We reduce the default stack size in userspace, to ensure
|
* user space. Explicitly specified stack sizes will be honored.
|
||||||
* we observe stack overruns in user space as well as in
|
* The usage of ZFS_STACK_SIZE is discussed further in the
|
||||||
* kernel space. In practice we can't set the userspace stack
|
* ENVIRONMENT VARIABLES sections of the ztest(1) man page.
|
||||||
* 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.
|
|
||||||
*/
|
*/
|
||||||
|
if (stksize == 0) {
|
||||||
|
stkstr = getenv("ZFS_STACK_SIZE");
|
||||||
|
|
||||||
stack = PTHREAD_STACK_MIN + MAX(stksize, STACK_SIZE) * 4;
|
if (stkstr == NULL)
|
||||||
|
stksize = TS_STACK_MAX;
|
||||||
|
else
|
||||||
|
stksize = MAX(atoi(stkstr), TS_STACK_MIN);
|
||||||
|
}
|
||||||
|
|
||||||
VERIFY3S(pthread_attr_init(&attr), ==, 0);
|
VERIFY3S(stksize, >, 0);
|
||||||
VERIFY3S(pthread_attr_setstacksize(&attr, stack), ==, 0);
|
stksize = P2ROUNDUP(MAX(stksize, TS_STACK_MIN), PAGESIZE);
|
||||||
VERIFY3S(pthread_attr_setguardsize(&attr, PAGESIZE), ==, 0);
|
VERIFY0(pthread_attr_setstacksize(&attr, stksize));
|
||||||
VERIFY3S(pthread_attr_setdetachstate(&attr, detachstate), ==, 0);
|
VERIFY0(pthread_attr_setguardsize(&attr, PAGESIZE));
|
||||||
|
|
||||||
VERIFY3S(pthread_create(&kt->t_tid, &attr, &zk_thread_helper, kt),
|
VERIFY0(pthread_create(&kt->t_tid, &attr, &zk_thread_helper, kt));
|
||||||
==, 0);
|
VERIFY0(pthread_attr_destroy(&attr));
|
||||||
|
|
||||||
VERIFY3S(pthread_attr_destroy(&attr), ==, 0);
|
|
||||||
|
|
||||||
return (kt);
|
return (kt);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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:
|
option and specify the runlength in seconds like so:
|
||||||
.IP
|
.IP
|
||||||
ztest -f / -V -T 120
|
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"
|
.SH "SEE ALSO"
|
||||||
.BR "zpool (1)" ","
|
.BR "zpool (1)" ","
|
||||||
.BR "zfs (1)" ","
|
.BR "zfs (1)" ","
|
||||||
|
|
Loading…
Reference in New Issue