"Fossies" - the Fresh Open Source Software Archive

Member "stress-ng-0.09.56/stress-kcmp.c" (15 Mar 2019, 7246 Bytes) of package /linux/privat/stress-ng-0.09.56.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "stress-kcmp.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 0.09.52_vs_0.09.54.

    1 /*
    2  * Copyright (C) 2013-2019 Canonical, Ltd.
    3  *
    4  * This program is free software; you can redistribute it and/or
    5  * modify it under the terms of the GNU General Public License
    6  * as published by the Free Software Foundation; either version 2
    7  * of the License, or (at your option) any later version.
    8  *
    9  * This program is distributed in the hope that it will be useful,
   10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   12  * GNU General Public License for more details.
   13  *
   14  * You should have received a copy of the GNU General Public License
   15  * along with this program; if not, write to the Free Software
   16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
   17  *
   18  * This code is a complete clean re-write of the stress tool by
   19  * Colin Ian King <colin.king@canonical.com> and attempts to be
   20  * backwardly compatible with the stress tool by Amos Waterland
   21  * <apw@rossby.metr.ou.edu> but has more stress tests and more
   22  * functionality.
   23  *
   24  */
   25 #include "stress-ng.h"
   26 
   27 #if defined(HAVE_KCMP)
   28 
   29 /* Urgh, should be from linux/kcmp.h */
   30 enum {
   31     SHIM_KCMP_FILE,
   32     SHIM_KCMP_VM,
   33     SHIM_KCMP_FILES,
   34     SHIM_KCMP_FS,
   35     SHIM_KCMP_SIGHAND,
   36     SHIM_KCMP_IO,
   37     SHIM_KCMP_SYSVSEM,
   38     SHIM_KCMP_EPOLL_TFD,
   39 
   40     SHIM_KCMP_TYPES,
   41 };
   42 
   43 /* Slot for KCMP_EPOLL_TFD */
   44 struct kcmp_epoll_slot {
   45     uint32_t efd;
   46     uint32_t tfd;
   47     uint32_t toff;
   48 };
   49 
   50 #define KCMP(pid1, pid2, type, idx1, idx2)          \
   51 {                               \
   52     int rc = shim_kcmp(pid1, pid2, type, idx1, idx2);   \
   53                                 \
   54     if (rc < 0) {                       \
   55         if (errno == EPERM) {               \
   56             pr_inf(capfail, args->name);        \
   57             break;                  \
   58         }                       \
   59         if (errno != EINVAL)                \
   60             pr_fail_err("kcmp: " # type);       \
   61     }                           \
   62     if (!g_keep_stressing_flag)             \
   63         break;                      \
   64 }
   65 
   66 #define KCMP_VERIFY(pid1, pid2, type, idx1, idx2, res)      \
   67 {                               \
   68     int rc = shim_kcmp(pid1, pid2, type, idx1, idx2);   \
   69                                 \
   70     if (rc != res) {                    \
   71         if (rc < 0) {                   \
   72             if (errno == EPERM) {           \
   73                 pr_inf(capfail, args->name);    \
   74                 break;              \
   75             }                   \
   76             if (errno != EINVAL)            \
   77                 pr_fail_err("kcmp: " # type);   \
   78         } else {                    \
   79             pr_fail( "%s: kcmp " # type     \
   80             " returned %d, expected: %d\n",     \
   81             args->name, rc, ret);           \
   82         }                       \
   83     }                           \
   84     if (!g_keep_stressing_flag)             \
   85         break;                      \
   86 }
   87 
   88 /*
   89  *  stress_kcmp
   90  *  stress sys_kcmp
   91  */
   92 static int stress_kcmp(const args_t *args)
   93 {
   94     pid_t pid1;
   95     int fd1;
   96 
   97 #if defined(HAVE_SYS_EPOLL_H) && NEED_GLIBC(2,3,2)
   98     int efd, sfd;
   99     int so_reuseaddr = 1;
  100     struct epoll_event ev;
  101     struct sockaddr *addr = NULL;
  102     socklen_t addr_len = 0;
  103 #endif
  104     int ret = EXIT_SUCCESS;
  105 
  106     static const char *capfail =
  107         "%s: need CAP_SYS_PTRACE capability to run kcmp stressor, "
  108         "aborting stress test\n";
  109 
  110     if ((fd1 = open("/dev/null", O_WRONLY)) < 0) {
  111         pr_fail_err("open");
  112         return EXIT_FAILURE;
  113     }
  114 
  115 #if defined(HAVE_SYS_EPOLL_H) && NEED_GLIBC(2,3,2)
  116     efd = -1;
  117     if ((sfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  118         sfd = -1;
  119         goto again;
  120     }
  121     if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR,
  122             &so_reuseaddr, sizeof(so_reuseaddr)) < 0) {
  123         (void)close(sfd);
  124         sfd = -1;
  125         goto again;
  126     }
  127     stress_set_sockaddr(args->name, args->instance, args->ppid,
  128         AF_INET, 23000, &addr, &addr_len, NET_ADDR_ANY);
  129 
  130     if (bind(sfd, addr, addr_len) < 0) {
  131         (void)close(sfd);
  132         sfd = -1;
  133         goto again;
  134     }
  135     if (listen(sfd, SOMAXCONN) < 0) {
  136         (void)close(sfd);
  137         sfd = -1;
  138         goto again;
  139     }
  140 
  141     efd = epoll_create1(0);
  142     if (efd < 0) {
  143         (void)close(sfd);
  144         sfd = -1;
  145         efd = -1;
  146         goto again;
  147     }
  148 
  149     (void)memset(&ev, 0, sizeof(ev));
  150     ev.data.fd = efd;
  151     ev.events = EPOLLIN | EPOLLET;
  152     if (epoll_ctl(efd, EPOLL_CTL_ADD, sfd, &ev) < 0) {
  153         (void)close(sfd);
  154         (void)close(efd);
  155         sfd = -1;
  156         efd = -1;
  157     }
  158 #endif
  159 
  160 again:
  161     pid1 = fork();
  162     if (pid1 < 0) {
  163         if (g_keep_stressing_flag &&
  164             ((errno == EAGAIN) || (errno == ENOMEM)))
  165             goto again;
  166 
  167         pr_fail_dbg("fork");
  168         (void)close(fd1);
  169 #if defined(HAVE_SYS_EPOLL_H) && NEED_GLIBC(2,3,2)
  170         if (sfd != -1)
  171             (void)close(sfd);
  172 #endif
  173         return EXIT_FAILURE;
  174     } else if (pid1 == 0) {
  175         (void)setpgid(0, g_pgrp);
  176         stress_parent_died_alarm();
  177 
  178         /* Child */
  179         while (g_keep_stressing_flag)
  180             (void)pause();
  181 
  182         /* will never get here */
  183         (void)close(fd1);
  184 #if defined(HAVE_SYS_EPOLL_H) && NEED_GLIBC(2,3,2)
  185         if (efd != -1)
  186             (void)close(efd);
  187         if (sfd != -1)
  188             (void)close(sfd);
  189 #endif
  190         _exit(EXIT_SUCCESS);
  191     } else {
  192         /* Parent */
  193         int fd2, status, pid2;
  194 
  195         (void)setpgid(pid1, g_pgrp);
  196         pid2 = getpid();
  197         if ((fd2 = open("/dev/null", O_WRONLY)) < 0) {
  198             pr_fail_err("open");
  199             ret = EXIT_FAILURE;
  200             goto reap;
  201         }
  202 
  203         do {
  204             KCMP(pid1, pid2, SHIM_KCMP_FILE, fd1, fd2);
  205             KCMP(pid1, pid1, SHIM_KCMP_FILE, fd1, fd1);
  206             KCMP(pid2, pid2, SHIM_KCMP_FILE, fd1, fd1);
  207             KCMP(pid2, pid2, SHIM_KCMP_FILE, fd2, fd2);
  208 
  209             KCMP(pid1, pid2, SHIM_KCMP_FILES, 0, 0);
  210             KCMP(pid1, pid1, SHIM_KCMP_FILES, 0, 0);
  211             KCMP(pid2, pid2, SHIM_KCMP_FILES, 0, 0);
  212 
  213             KCMP(pid1, pid2, SHIM_KCMP_FS, 0, 0);
  214             KCMP(pid1, pid1, SHIM_KCMP_FS, 0, 0);
  215             KCMP(pid2, pid2, SHIM_KCMP_FS, 0, 0);
  216 
  217             KCMP(pid1, pid2, SHIM_KCMP_IO, 0, 0);
  218             KCMP(pid1, pid1, SHIM_KCMP_IO, 0, 0);
  219             KCMP(pid2, pid2, SHIM_KCMP_IO, 0, 0);
  220 
  221             KCMP(pid1, pid2, SHIM_KCMP_SIGHAND, 0, 0);
  222             KCMP(pid1, pid1, SHIM_KCMP_SIGHAND, 0, 0);
  223             KCMP(pid2, pid2, SHIM_KCMP_SIGHAND, 0, 0);
  224 
  225             KCMP(pid1, pid2, SHIM_KCMP_SYSVSEM, 0, 0);
  226             KCMP(pid1, pid1, SHIM_KCMP_SYSVSEM, 0, 0);
  227             KCMP(pid2, pid2, SHIM_KCMP_SYSVSEM, 0, 0);
  228 
  229             KCMP(pid1, pid2, SHIM_KCMP_VM, 0, 0);
  230             KCMP(pid1, pid1, SHIM_KCMP_VM, 0, 0);
  231             KCMP(pid2, pid2, SHIM_KCMP_VM, 0, 0);
  232 
  233 #if defined(HAVE_SYS_EPOLL_H) && NEED_GLIBC(2,3,2)
  234             if (efd != -1) {
  235                 struct kcmp_epoll_slot slot;
  236 
  237                 slot.efd = efd;
  238                 slot.tfd = sfd;
  239                 slot.toff = 0;
  240                 KCMP(pid1, pid2, SHIM_KCMP_EPOLL_TFD, efd, (unsigned long)&slot);
  241                 KCMP(pid2, pid1, SHIM_KCMP_EPOLL_TFD, efd, (unsigned long)&slot);
  242                 KCMP(pid2, pid2, SHIM_KCMP_EPOLL_TFD, efd, (unsigned long)&slot);
  243             }
  244 #endif
  245 
  246             /* Same simple checks */
  247             if (g_opt_flags & OPT_FLAGS_VERIFY) {
  248                 KCMP_VERIFY(pid1, pid1, SHIM_KCMP_FILE, fd1, fd1, 0);
  249                 KCMP_VERIFY(pid1, pid1, SHIM_KCMP_FILES, 0, 0, 0);
  250                 KCMP_VERIFY(pid1, pid1, SHIM_KCMP_FS, 0, 0, 0);
  251                 KCMP_VERIFY(pid1, pid1, SHIM_KCMP_IO, 0, 0, 0);
  252                 KCMP_VERIFY(pid1, pid1, SHIM_KCMP_SIGHAND, 0, 0, 0);
  253                 KCMP_VERIFY(pid1, pid1, SHIM_KCMP_SYSVSEM, 0, 0, 0);
  254                 KCMP_VERIFY(pid1, pid1, SHIM_KCMP_VM, 0, 0, 0);
  255                 KCMP_VERIFY(pid1, pid2, SHIM_KCMP_SYSVSEM, 0, 0, 0);
  256 #if defined(HAVE_SYS_EPOLL_H) && NEED_GLIBC(2,3,2)
  257                 if (efd != -1) {
  258                     struct kcmp_epoll_slot slot;
  259 
  260                     slot.efd = efd;
  261                     slot.tfd = sfd;
  262                     slot.toff = 0;
  263                     KCMP(pid1, pid2, SHIM_KCMP_EPOLL_TFD, efd, (unsigned long)&slot);
  264                 }
  265 #endif
  266             }
  267             inc_counter(args);
  268         } while (keep_stressing());
  269 reap:
  270         if (fd2 >= 0)
  271             (void)close(fd2);
  272         (void)kill(pid1, SIGKILL);
  273         (void)waitpid(pid1, &status, 0);
  274         (void)close(fd1);
  275     }
  276 #if defined(HAVE_SYS_EPOLL_H) && NEED_GLIBC(2,3,2)
  277     if (efd != -1)
  278         (void)close(efd);
  279     if (sfd != -1)
  280         (void)close(sfd);
  281 #endif
  282     return ret;
  283 }
  284 
  285 stressor_info_t stress_kcmp_info = {
  286     .stressor = stress_kcmp,
  287     .class = CLASS_OS
  288 };
  289 #else
  290 stressor_info_t stress_kcmp_info = {
  291     .stressor = stress_not_implemented,
  292     .class = CLASS_OS
  293 };
  294 #endif