Changeset View
Changeset View
Standalone View
Standalone View
head/tests/sys/kern/kern_descrip_test.c
Show All 22 Lines | |||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||||
* SUCH DAMAGE. | * SUCH DAMAGE. | ||||
*/ | */ | ||||
#include <sys/cdefs.h> | #include <sys/cdefs.h> | ||||
__FBSDID("$FreeBSD$"); | __FBSDID("$FreeBSD$"); | ||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/limits.h> | |||||
#include <sys/resource.h> | |||||
#include <sys/stat.h> | |||||
#include <sys/sysctl.h> | |||||
#include <sys/time.h> | |||||
#include <sys/wait.h> | |||||
#include <errno.h> | #include <errno.h> | ||||
#include <fcntl.h> | #include <fcntl.h> | ||||
#include <signal.h> | #include <signal.h> | ||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <string.h> | |||||
#include <strings.h> | #include <strings.h> | ||||
#include <sys/limits.h> | |||||
#include <sys/stat.h> | |||||
#include <sys/sysctl.h> | |||||
#include <unistd.h> | #include <unistd.h> | ||||
#include <atf-c.h> | #include <atf-c.h> | ||||
static volatile sig_atomic_t done; | static volatile sig_atomic_t done; | ||||
#define AFILE "afile" | #define AFILE "afile" | ||||
#define EXPANDBY 1000 | #define EXPANDBY 1000 | ||||
#define PARALLEL 4 | #define PARALLEL 4 | ||||
#define RENDEZVOUS "rendezvous" | #define RENDEZVOUS "rendezvous" | ||||
Show All 38 Lines | |||||
static void | static void | ||||
openfiles2(size_t n) | openfiles2(size_t n) | ||||
{ | { | ||||
size_t i; | size_t i; | ||||
int r; | int r; | ||||
errno = 0; | errno = 0; | ||||
for (i = 0; i < n; i++) | for (i = 0; i < n; i++) { | ||||
ATF_REQUIRE((r = open(AFILE, O_RDONLY)) != -1); | r = open(AFILE, O_RDONLY); | ||||
if (r < 0) { | |||||
fprintf(stderr, "open: %s\n", strerror(errno)); | |||||
_exit(1); | |||||
} | |||||
} | |||||
kill(getppid(), SIGUSR1); | kill(getppid(), SIGUSR1); | ||||
for (;;) { | for (;;) { | ||||
if (access(RENDEZVOUS, R_OK) != 0) | if (access(RENDEZVOUS, R_OK) != 0) | ||||
break; | break; | ||||
usleep(1000); | usleep(1000); | ||||
} | } | ||||
_exit(0); | _exit(0); | ||||
} | } | ||||
static void | static void | ||||
openfiles(size_t n) | openfiles(size_t n) | ||||
{ | { | ||||
int i, fd; | int i, fd; | ||||
signal(SIGUSR1, handler); | signal(SIGUSR1, handler); | ||||
ATF_REQUIRE((fd = open(AFILE, O_CREAT, 0644)) != -1); | ATF_REQUIRE((fd = open(AFILE, O_CREAT, 0644)) != -1); | ||||
close(fd); | close(fd); | ||||
ATF_REQUIRE((fd = open(RENDEZVOUS, O_CREAT, 0644)) != -1); | ATF_REQUIRE((fd = open(RENDEZVOUS, O_CREAT, 0644)) != -1); | ||||
close(fd); | close(fd); | ||||
done = 0; | done = 0; | ||||
for (i = 0; i < PARALLEL; i++) | for (i = 0; i < PARALLEL; i++) | ||||
if (fork() == 0) | if (fork() == 0) | ||||
openfiles2(n / PARALLEL); | openfiles2(n / PARALLEL); | ||||
while (done != PARALLEL) | while (done != PARALLEL) { | ||||
usleep(1000); | usleep(1000); | ||||
ATF_REQUIRE_EQ_MSG(0, waitpid(-1, NULL, WNOHANG), | |||||
"a child exited unexpectedly"); | |||||
} | |||||
unlink(RENDEZVOUS); | unlink(RENDEZVOUS); | ||||
usleep(40000); | for (i = 0; i < PARALLEL; i++) | ||||
ATF_CHECK_MSG(wait(NULL) > 0, "wait: %s", strerror(errno)); | |||||
} | } | ||||
ATF_TC_WITH_CLEANUP(kern_maxfiles__increase); | ATF_TC_WITH_CLEANUP(kern_maxfiles__increase); | ||||
ATF_TC_HEAD(kern_maxfiles__increase, tc) | ATF_TC_HEAD(kern_maxfiles__increase, tc) | ||||
{ | { | ||||
atf_tc_set_md_var(tc, "require.user", "root"); | atf_tc_set_md_var(tc, "require.user", "root"); | ||||
atf_tc_set_md_var(tc, "require.config", "allow_sysctl_side_effects"); | atf_tc_set_md_var(tc, "require.config", "allow_sysctl_side_effects"); | ||||
atf_tc_set_md_var(tc, "descr", | atf_tc_set_md_var(tc, "descr", | ||||
"Check kern.maxfiles expansion"); | "Check kern.maxfiles expansion"); | ||||
} | } | ||||
ATF_TC_BODY(kern_maxfiles__increase, tc) | ATF_TC_BODY(kern_maxfiles__increase, tc) | ||||
{ | { | ||||
size_t oldlen; | size_t oldlen; | ||||
int maxfiles, oldmaxfiles, current; | int maxfiles, oldmaxfiles, current; | ||||
char buf[80]; | char buf[80]; | ||||
struct rlimit rl; | |||||
oldlen = sizeof(maxfiles); | oldlen = sizeof(maxfiles); | ||||
if (sysctlbyname("kern.maxfiles", &maxfiles, &oldlen, NULL, 0) == -1) | if (sysctlbyname("kern.maxfiles", &maxfiles, &oldlen, NULL, 0) == -1) | ||||
atf_tc_fail("getsysctlbyname(%s): %s", "kern.maxfiles", | atf_tc_fail("getsysctlbyname(%s): %s", "kern.maxfiles", | ||||
strerror(errno)); | strerror(errno)); | ||||
if (sysctlbyname("kern.openfiles", ¤t, &oldlen, NULL, 0) == -1) | if (sysctlbyname("kern.openfiles", ¤t, &oldlen, NULL, 0) == -1) | ||||
atf_tc_fail("getsysctlbyname(%s): %s", "kern.openfiles", | atf_tc_fail("getsysctlbyname(%s): %s", "kern.openfiles", | ||||
strerror(errno)); | strerror(errno)); | ||||
oldmaxfiles = maxfiles; | oldmaxfiles = maxfiles; | ||||
/* Store old kern.maxfiles in a symlink for cleanup */ | /* Store old kern.maxfiles in a symlink for cleanup */ | ||||
snprintf(buf, sizeof(buf), "%d", oldmaxfiles); | snprintf(buf, sizeof(buf), "%d", oldmaxfiles); | ||||
if (symlink(buf, VALUE) == 1) | if (symlink(buf, VALUE) == 1) | ||||
atf_tc_fail("symlink(%s, %s): %s", buf, VALUE, | atf_tc_fail("symlink(%s, %s): %s", buf, VALUE, | ||||
strerror(errno)); | strerror(errno)); | ||||
maxfiles += EXPANDBY; | maxfiles += EXPANDBY; | ||||
if (sysctlbyname("kern.maxfiles", NULL, 0, &maxfiles, oldlen) == -1) | if (sysctlbyname("kern.maxfiles", NULL, 0, &maxfiles, oldlen) == -1) | ||||
atf_tc_fail("getsysctlbyname(%s): %s", "kern.maxfiles", | atf_tc_fail("getsysctlbyname(%s): %s", "kern.maxfiles", | ||||
strerror(errno)); | strerror(errno)); | ||||
openfiles(oldmaxfiles - current + 1); | rl.rlim_cur = rl.rlim_max = maxfiles; | ||||
(void)unlink(VALUE); | ATF_REQUIRE_EQ_MSG(0, setrlimit(RLIMIT_NOFILE, &rl), | ||||
"setrlimit(RLIMIT_NOFILE, %d): %s", maxfiles, strerror(errno)); | |||||
openfiles(oldmaxfiles - current + EXPANDBY / 2); | |||||
} | } | ||||
ATF_TC_CLEANUP(kern_maxfiles__increase, tc) | ATF_TC_CLEANUP(kern_maxfiles__increase, tc) | ||||
{ | { | ||||
size_t oldlen; | size_t oldlen; | ||||
int n, oldmaxfiles; | int n, oldmaxfiles; | ||||
char buf[80]; | char buf[80]; | ||||
if ((n = readlink(VALUE, buf, sizeof(buf))) > 0) { | if ((n = readlink(VALUE, buf, sizeof(buf))) > 0) { | ||||
buf[MIN((size_t)n, sizeof(buf) - 1)] = '\0'; | buf[MIN((size_t)n, sizeof(buf) - 1)] = '\0'; | ||||
if (sscanf(buf, "%d", &oldmaxfiles) == 1) { | if (sscanf(buf, "%d", &oldmaxfiles) == 1) { | ||||
oldlen = sizeof(oldmaxfiles); | oldlen = sizeof(oldmaxfiles); | ||||
(void) sysctlbyname("kern.maxfiles", NULL, 0, | (void) sysctlbyname("kern.maxfiles", NULL, 0, | ||||
&oldmaxfiles, oldlen); | &oldmaxfiles, oldlen); | ||||
} | } | ||||
} | } | ||||
(void)unlink(VALUE); | |||||
(void)unlink(AFILE); | |||||
} | } | ||||
ATF_TP_ADD_TCS(tp) | ATF_TP_ADD_TCS(tp) | ||||
{ | { | ||||
ATF_TP_ADD_TC(tp, dup2__simple); | ATF_TP_ADD_TC(tp, dup2__simple); | ||||
ATF_TP_ADD_TC(tp, dup2__ebadf_when_2nd_arg_out_of_range); | ATF_TP_ADD_TC(tp, dup2__ebadf_when_2nd_arg_out_of_range); | ||||
ATF_TP_ADD_TC(tp, kern_maxfiles__increase); | ATF_TP_ADD_TC(tp, kern_maxfiles__increase); | ||||
return (atf_no_error()); | return (atf_no_error()); | ||||
} | } |