"Fossies" - the Fresh Open Source Software Archive

Member "stress-ng-0.09.56/stress-dev-shm.c" (15 Mar 2019, 5441 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-dev-shm.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(__linux__)
   28 
   29 /*
   30  *  stress_dev_shm_child()
   31  *  stress /dev/shm by filling it with data and mmap'ing
   32  *  to it once we hit the largest file size allowed.
   33  */
   34 static inline int stress_dev_shm_child(
   35     const args_t *args,
   36     const int fd)
   37 {
   38     int rc = EXIT_SUCCESS;
   39     const size_t page_size = args->page_size;
   40     const size_t page_thresh = 16 * MB;
   41     ssize_t sz = page_size;
   42     uint32_t *addr;
   43 
   44     /* Make sure this is killable by OOM killer */
   45     set_oom_adjustment(args->name, true);
   46 
   47     while (keep_stressing()) {
   48         size_t sz_delta = page_thresh;
   49         int ret;
   50 
   51         ret = ftruncate(fd, 0);
   52         if (ret < 0) {
   53             pr_err("%s: ftruncate failed, errno=%d (%s)\n",
   54                 args->name, errno, strerror(errno));
   55             return EXIT_FAILURE;
   56         }
   57 
   58         /*
   59          *  Try to allocate the largest file size
   60          *  possible using a fast rough binary search. We
   61          *  shouldn't make this exact as mmap'ing this
   62          *  can trip a SIGBUS
   63          */
   64         while (keep_stressing() && (sz_delta >= page_thresh)) {
   65             ret = shim_fallocate(fd, 0, 0, sz);
   66             if (ret < 0) {
   67                 sz -= (sz_delta >> 1);
   68                 break;
   69             } else {
   70                 sz += sz_delta;
   71                 sz_delta <<= 1;
   72                 inc_counter(args);
   73             }
   74         }
   75         if (sz > 0) {
   76             /*
   77              *  Now try to map this into our address space
   78              */
   79             if (!keep_stressing())
   80                 break;
   81             addr = mmap(NULL, sz, PROT_READ | PROT_WRITE,
   82                 MAP_SHARED, fd, 0);
   83             if (addr != MAP_FAILED)  {
   84                 const size_t words = page_size / sizeof(uint32_t);
   85                 uint32_t *ptr, *end = addr + (sz / sizeof(uint32_t));
   86 
   87                 (void)madvise_random(addr, sz);
   88 
   89                 /* Touch all pages with random data */
   90                 for (ptr = addr; ptr < end; ptr += words) {
   91                     *ptr = mwc32();
   92                 }
   93                 (void)msync(addr, sz, MS_INVALIDATE);
   94                 (void)munmap(addr, sz);
   95             }
   96             sz = page_size;
   97             sz_delta = page_size * 32;
   98             ret = ftruncate(fd, 0);
   99             if (ret < 0) {
  100                 pr_err("%s: ftruncate failed, errno=%d (%s)\n",
  101                     args->name, errno, strerror(errno));
  102                 return EXIT_FAILURE;
  103             }
  104         }
  105     }
  106     return rc;
  107 }
  108 
  109 /*
  110  *  stress_dev_shm()
  111  *  stress /dev/shm
  112  */
  113 static int stress_dev_shm(const args_t *args)
  114 {
  115     int fd, rc = EXIT_SUCCESS;
  116     char path[PATH_MAX];
  117     pid_t pid;
  118 
  119     /*
  120      *  Sanity check for existence and r/w permissions
  121      *  on /dev/shm, it may not be configure for the
  122      *  kernel, so don't make it a failure of it does
  123      *  not exist or we can't access it.
  124      */
  125     if (access("/dev/shm", R_OK | W_OK) < 0) {
  126         if (errno == ENOENT) {
  127             pr_inf("%s: /dev/shm does not exist, skipping test\n",
  128                 args->name);
  129             return EXIT_NO_RESOURCE;
  130         } else {
  131             pr_inf("%s: cannot access /dev/shm, errno=%d (%s), skipping test\n",
  132                 args->name, errno, strerror(errno));
  133             return EXIT_NO_RESOURCE;
  134         }
  135     }
  136 
  137     (void)snprintf(path, sizeof(path), "/dev/shm/stress-dev-shm-%d-%d-%" PRIu32,
  138         args->instance, getpid(), mwc32());
  139     fd = open(path, O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR);
  140     if (fd < 0) {
  141         pr_inf("%s: cannot create %s, errno=%d (%s)\n",
  142             args->name, path, errno, strerror(errno));
  143         return EXIT_SUCCESS;
  144     }
  145     (void)unlink(path);
  146 
  147     while (keep_stressing()) {
  148 fork_again:
  149         pid = fork();
  150         if (pid < 0) {
  151             /* Can't fork, retry? */
  152             if ((errno == EAGAIN) || (errno == ENOMEM))
  153                 goto fork_again;
  154             pr_err("%s: fork failed: errno=%d: (%s)\n",
  155                 args->name, errno, strerror(errno));
  156             /* Nope, give up! */
  157             (void)close(fd);
  158             return EXIT_FAILURE;
  159         } else if (pid > 0) {
  160             /* Parent */
  161             int ret, status = 0;
  162 
  163             (void)setpgid(pid, g_pgrp);
  164             ret = waitpid(pid, &status, 0);
  165             if (ret < 0) {
  166                 if (errno != EINTR)
  167                     pr_dbg("%s: waitpid(): errno=%d (%s)\n",
  168                         args->name, errno, strerror(errno));
  169                 (void)kill(pid, SIGTERM);
  170                 (void)kill(pid, SIGKILL);
  171                 (void)waitpid(pid, &status, 0);
  172             }
  173             if (WIFSIGNALED(status)) {
  174                 if ((WTERMSIG(status) == SIGKILL) ||
  175                     (WTERMSIG(status) == SIGKILL)) {
  176                     log_system_mem_info();
  177                     pr_dbg("%s: assuming killed by OOM killer, "
  178                         "restarting again (instance %d)\n",
  179                         args->name, args->instance);
  180                 }
  181             }
  182         } else if (pid == 0) {
  183             /* Child, stress memory */
  184             (void)setpgid(0, g_pgrp);
  185             stress_parent_died_alarm();
  186 
  187             rc = stress_dev_shm_child(args, fd);
  188             _exit(rc);
  189         }
  190     }
  191     (void)close(fd);
  192     return rc;
  193 }
  194 
  195 stressor_info_t stress_dev_shm_info = {
  196     .stressor = stress_dev_shm,
  197     .class = CLASS_VM | CLASS_OS
  198 };
  199 #else
  200 stressor_info_t stress_dev_shm_info = {
  201     .stressor = stress_not_implemented,
  202     .class = CLASS_VM | CLASS_OS
  203 };
  204 #endif