thp01: Find largest arguments size
PATCH v4 1/1 thp01: Find largest arguments size
Because of kernel commit da029c11e6b1 the arguments size for exec has been reduced considerably. This causes exec to fail with E2BIG, so we call it repeatedly with a decreasing number of arguments until it is successful.
As far as I know, there is no other reliable and easy way to determine the maximum argument length.
---
V4 - Change the binary search implementation and add some comments.
testcases/kernel/mem/thp/thp01.c | 116 ++++++++++++++++++++++++++++----------- 1 file changed, 84 insertions(+), 32 deletions(-)
testcases/kernel/mem/thp/thp01.c +84 -32
@@ -28,8 +28,15 @@* invalid opcode: 0000 [#1] SMP * last sysfs file: /sys/devices/system/cpu/cpu23/cache/index2/shared_cpu_map * .... +* +* Due to commit da029c11e6b1 which reduced the stack size considerably, we +* now perform a binary search to find the largest possible argument we can +* use. Only the first iteration of the test performs the search; subsequent +* iterations use the result of the search which is stored in some shared +* memory. */ +#include <errno.h> #include <sys/types.h> #include <sys/resource.h> #include <sys/wait.h>
@@ -37,57 +44,102 @@#include <string.h> #include <stdlib.h> #include <unistd.h> +#include "tst_test.h" #include "mem.h" +#include "tst_minmax.h" + +#define ARGS_SZ (256 * 32) -#define ARRAY_SZ 256 +static struct bisection { +long left; +long right; +long mid; +} *bst; -static int ps; -static long length; -static char *array[ARRAY_SZ ]; +static char *args[ARGS_SZ ];static char *arg; -static struct rlimit rl = { - .rlim_cur =RLIM_INFINITY , - .rlim_max =RLIM_INFINITY , -};static void thp_test (void ) { -int i; -pid_t pid; - -switch (pid =SAFE_FORK ()) { -case 0 : -memset (arg,'c' , length -1 ); - arg[length -1 ] ='\0' ; - array[0 ] ="true" ; -for (i =1 ; i <ARRAY_SZ -1 ; i++) - array[i] = arg; - array[ARRAY_SZ -1 ] =NULL ; -if (setrlimit (RLIMIT_STACK , &rl) ==-1 ) { -perror ("setrlimit" ); -exit (1 ); - } -if (execvp ("true" , array) ==-1 ) { -perror ("execvp" ); -exit (1 ); +long prev_left; +int pid; + +while (bst->right - bst->left >1 ) { +pid_t pid =SAFE_FORK (); + +if (!pid) { +/* We set mid to left assuming exec will succeed. If +* exec fails with E2BIG (and thus returns) then we +* restore left and set right to mid instead. +*/ + prev_left = bst->left; + bst->mid = (bst->left + bst->right) /2 ; + bst->left = bst->mid; + args[bst->mid] =NULL ; + +TEST (execvp ("true" , args)); +if (TEST_ERRNO !=E2BIG ) +tst_brk (TBROK |TTERRNO ,"execvp(\"true\", ...)" ); + bst->left = prev_left; + bst->right = bst->mid; +exit (0 ); } -default : +tst_reap_children (); +tst_res (TINFO ,"left: %ld, right: %ld, mid: %ld" , + bst->left, bst->right, bst->mid); + } + +/* We end with mid == right or mid == left where right - left = +* 1. Regardless we must use left because right is only set to values +* which are too large. +*/ + pid =SAFE_FORK (); +if (pid ==0 ) { + args[bst->left] =NULL ; +TEST (execvp ("true" , args)); +if (TEST_ERRNO !=E2BIG ) +tst_brk (TBROK |TTERRNO ,"execvp(\"true\", ...)" ); +exit (0 ); } +tst_reap_children (); -tst_res (TPASS ,"system didn't crash, pass." ); +tst_res (TPASS ,"system didn't crash." ); }static void setup (void ) { - ps =sysconf (_SC_PAGESIZE); - length =32 * ps; - arg =SAFE_MALLOC (length); +struct rlimit rl = { + .rlim_cur =RLIM_INFINITY , + .rlim_max =RLIM_INFINITY , + }; +int i; +long arg_len, arg_count; + + bst =SAFE_MMAP (NULL ,sizeof (*bst), +PROT_READ |PROT_WRITE , +MAP_SHARED |MAP_ANONYMOUS ,-1 ,0 ); + bst->left =0 ; + bst->right =ARGS_SZ ; + + arg_len =sysconf (_SC_PAGESIZE); + arg =SAFE_MALLOC (arg_len); +memset (arg,'c' , arg_len -1 ); + arg[arg_len -1 ] ='\0' ; + + args[0 ] ="true" ; + arg_count =ARGS_SZ ; +tst_res (TINFO ,"Using %ld args of size %ld" , arg_count, arg_len); +for (i =1 ; i < arg_count; i++) + args[i] = arg; + +SAFE_SETRLIMIT (RLIMIT_STACK , &rl); }static void cleanup (void ) { -free (arg); +if (arg) +free (arg); }static struct tst_test test = {
Signature · 1 line
2.14.1
PATCH v4 1/1 thp01: Find largest arguments size
Quoted 9 lines · Richard Palethorpe
Because of kernel commit
da029c11e6b1the arguments size for exec has been reduced considerably. This causes exec to fail with E2BIG, so we call it repeatedly with a decreasing number of arguments until it is successful.As far as I know, there is no other reliable and easy way to determine the maximum argument length.
Signed-off-by Richard Palethorpe <[email protected]>---
Looks good! V4 get pass on my two platforms:
kernel-4.9.13-v7.1.el7 armv7l
kernel-4.13.0+ x86_64
Signature · 2 lines
Li Wang [email protected]
PATCH v4 1/1 thp01: Find largest arguments size
In reply to Richard PalethorpeHi!
testcases/kernel/mem/thp/thp01.c line 142
Quoted 5 lines
static void cleanup(void)
{testcases/kernel/mem/thp/thp01.c +2
-1-free (arg); +if (arg) +free (arg);
free(NULL) is no-op, I've removed this if and pushed, thanks.
Signature · 2 lines
Cyril Hrubis [email protected]