"Fossies" - the Fresh Open Source Software Archive

Member "stress-ng-0.09.56/stress-unshare.c" (15 Mar 2019, 4777 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-unshare.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 0.09.54_vs_0.09.55.

    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_UNSHARE)
   28 
   29 #define MAX_PIDS    (32)
   30 
   31 #if defined(CLONE_FS)       || \
   32     defined(CLONE_FILES)    || \
   33     defined(CLONE_NEWCGROUP)    || \
   34     defined(CLONE_NEWIPC)   || \
   35     defined(CLONE_NEWNET)   || \
   36     defined(CLONE_NEWNS)    || \
   37     defined(CLONE_NEWPID)   || \
   38     defined(CLONE_NEWUSER)  || \
   39     defined(CLONE_NEWUTS)   || \
   40     defined(CLONE_SYSVSEM)  || \
   41     defined(CLONE_THREAD)   || \
   42     defined(CLONE_SIGHAND)  || \
   43     defined(CLONE_VM)
   44 
   45 #define UNSHARE(flags)  \
   46     check_unshare(args, flags, #flags);
   47 
   48 /*
   49  *  unshare with some error checking
   50  */
   51 static void check_unshare(const args_t *args, int flags, const char *flags_name)
   52 {
   53     int rc;
   54     rc = shim_unshare(flags);
   55     if ((rc < 0) && (errno != EPERM) && (errno != EINVAL)) {
   56         pr_fail("%s: unshare(%s) failed, "
   57             "errno=%d (%s)\n", args->name, flags_name,
   58             errno, strerror(errno));
   59     }
   60 }
   61 #endif
   62 
   63 /*
   64  *  enough_memory()
   65  *  returns true if we have enough memory, ensures
   66  *  we don't throttle back the unsharing because we
   67  *  get into deep swappiness
   68  */
   69 static inline bool enough_memory(void)
   70 {
   71     size_t shmall, freemem, totalmem, freeswap;
   72     bool enough;
   73 
   74     stress_get_memlimits(&shmall, &freemem, &totalmem, &freeswap);
   75 
   76     enough = (freemem == 0) ? true : freemem > (8 * MB);
   77 
   78     return enough;
   79 }
   80 
   81 /*
   82  *  stress_unshare()
   83  *  stress resource unsharing
   84  */
   85 static int stress_unshare(const args_t *args)
   86 {
   87     pid_t pids[MAX_PIDS];
   88 #if defined(CLONE_NEWNET)
   89     const uid_t euid = geteuid();
   90 #endif
   91 
   92     do {
   93         size_t i, n;
   94 
   95         (void)memset(pids, 0, sizeof(pids));
   96 
   97         for (n = 0; n < MAX_PIDS; n++) {
   98             if (!g_keep_stressing_flag)
   99                 break;
  100             if (!enough_memory()) {
  101                 /* memory too low, back off */
  102                 (void)sleep(1);
  103                 break;
  104             }
  105             pids[n] = fork();
  106             if (pids[n] < 0) {
  107                 /* Out of resources for fork */
  108                 if (errno == EAGAIN)
  109                     break;
  110             } else if (pids[n] == 0) {
  111                 /* Child */
  112                 (void)setpgid(0, g_pgrp);
  113                 stress_parent_died_alarm();
  114 
  115                 /* Make sure this is killable by OOM killer */
  116                 set_oom_adjustment(args->name, true);
  117 
  118 #if defined(CLONE_FS)
  119                 UNSHARE(CLONE_FS);
  120 #endif
  121 #if defined(CLONE_FILES)
  122                 UNSHARE(CLONE_FILES);
  123 #endif
  124 #if defined(CLONE_NEWCGROUP)
  125                 UNSHARE(CLONE_NEWCGROUP);
  126 #endif
  127 #if defined(CLONE_NEWIPC)
  128                 UNSHARE(CLONE_NEWIPC);
  129 #endif
  130 #if defined(CLONE_NEWNET)
  131                 /*
  132                  *  CLONE_NEWNET when running as root on
  133                  *  hundreds of processes can be stupidly
  134                  *  expensive on older kernels so limit
  135                  *  this to just one per stressor instance
  136                  *  and don't unshare of root
  137                  */
  138                 if ((n == 0) && (euid != 0))
  139                     UNSHARE(CLONE_NEWNET);
  140 #endif
  141 #if defined(CLONE_NEWNS)
  142                 UNSHARE(CLONE_NEWNS);
  143 #endif
  144 #if defined(CLONE_NEWPID)
  145                 UNSHARE(CLONE_NEWPID);
  146 #endif
  147 #if defined(CLONE_NEWUSER)
  148                 UNSHARE(CLONE_NEWUSER);
  149 #endif
  150 #if defined(CLONE_NEWUTS)
  151                 UNSHARE(CLONE_NEWUTS);
  152 #endif
  153 #if defined(CLONE_SYSVSEM)
  154                 UNSHARE(CLONE_SYSVSEM);
  155 #endif
  156 #if defined(CLONE_THREAD)
  157                 UNSHARE(CLONE_THREAD);
  158 #endif
  159 #if defined(CLONE_SIGHAND)
  160                 UNSHARE(CLONE_SIGHAND);
  161 #endif
  162 #if defined(CLONE_VM)
  163                 UNSHARE(CLONE_VM);
  164 #endif
  165                 _exit(0);
  166             } else {
  167                 (void)setpgid(pids[n], g_pgrp);
  168             }
  169         }
  170         for (i = 0; i < n; i++) {
  171             int status;
  172 
  173             if (pids[i] > 0) {
  174                 int ret;
  175 
  176                 ret = kill(pids[i], SIGKILL);
  177                 if (ret == 0) {
  178                     if (waitpid(pids[i], &status, 0) < 0) {
  179                         if (errno != EINTR)
  180                             pr_err("%s: waitpid errno=%d (%s)\n",
  181                                 args->name, errno, strerror(errno));
  182                     }
  183                 }
  184             }
  185         }
  186         inc_counter(args);
  187     } while (keep_stressing());
  188 
  189     return EXIT_SUCCESS;
  190 }
  191 
  192 stressor_info_t stress_unshare_info = {
  193     .stressor = stress_unshare,
  194     .class = CLASS_OS
  195 };
  196 #else
  197 stressor_info_t stress_unshare_info = {
  198     .stressor = stress_not_implemented,
  199     .class = CLASS_OS
  200 };
  201 #endif