mirror of
				https://git.proxmox.com/git/mirror_zfs.git
				synced 2025-10-26 18:05:04 +03:00 
			
		
		
		
	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
	
	Block a user
	 Brian Behlendorf
						Brian Behlendorf