"Fossies" - the Fresh Open Source Software Archive

Member "stress-ng-0.09.56/stress-msync.c" (15 Mar 2019, 6303 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-msync.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_MSYNC)
   28 static sigjmp_buf jmp_env;
   29 static uint64_t sigbus_count;
   30 #endif
   31 
   32 int stress_set_msync_bytes(const char *opt)
   33 {
   34     size_t msync_bytes;
   35 
   36     msync_bytes = (size_t)get_uint64_byte_memory(opt, 1);
   37     check_range_bytes("msync-bytes", msync_bytes,
   38         MIN_MSYNC_BYTES, MAX_MEM_LIMIT);
   39     return set_setting("msync-bytes", TYPE_ID_SIZE_T, &msync_bytes);
   40 }
   41 
   42 #if defined(HAVE_MSYNC)
   43 /*
   44  *  stress_page_check()
   45  *  check if mmap'd data is sane
   46  */
   47 static int stress_page_check(
   48     uint8_t *buf,
   49     const uint8_t val,
   50     const size_t sz)
   51 {
   52     size_t i;
   53 
   54     for (i = 0; i < sz; i++) {
   55         if (buf[i] != val)
   56             return -1;
   57     }
   58     return 0;
   59 }
   60 
   61 /*
   62  *  stress_sigbus_handler()
   63  *     SIGBUS handler
   64  */
   65 static void MLOCKED_TEXT stress_sigbus_handler(int signum)
   66 {
   67     (void)signum;
   68 
   69     sigbus_count++;
   70 
   71     siglongjmp(jmp_env, 1); /* bounce back */
   72 }
   73 
   74 /*
   75  *  stress_msync()
   76  *  stress msync
   77  */
   78 static int stress_msync(const args_t *args)
   79 {
   80     uint8_t *buf = NULL;
   81     const size_t page_size = args->page_size;
   82     const size_t min_size = 2 * page_size;
   83     size_t msync_bytes = DEFAULT_MSYNC_BYTES;
   84     NOCLOBBER size_t sz;
   85     ssize_t ret;
   86     NOCLOBBER ssize_t rc = EXIT_SUCCESS;
   87 
   88     int fd = -1;
   89     char filename[PATH_MAX];
   90 
   91     ret = sigsetjmp(jmp_env, 1);
   92     if (ret) {
   93         pr_fail_err("sigsetjmp");
   94         return EXIT_FAILURE;
   95     }
   96     if (stress_sighandler(args->name, SIGBUS, stress_sigbus_handler, NULL) < 0)
   97         return EXIT_FAILURE;
   98 
   99     if (!get_setting("msync-bytes", &msync_bytes)) {
  100         if (g_opt_flags & OPT_FLAGS_MAXIMIZE)
  101             msync_bytes = MAX_MSYNC_BYTES;
  102         if (g_opt_flags & OPT_FLAGS_MINIMIZE)
  103             msync_bytes = MIN_MSYNC_BYTES;
  104     }
  105     msync_bytes /= args->num_instances;
  106     if (msync_bytes < MIN_MSYNC_BYTES)
  107         msync_bytes = MIN_MSYNC_BYTES;
  108     if (msync_bytes < page_size)
  109         msync_bytes = page_size;
  110     sz = msync_bytes & ~(page_size - 1);
  111     if (sz < min_size)
  112         sz = min_size;
  113 
  114     /* Make sure this is killable by OOM killer */
  115     set_oom_adjustment(args->name, true);
  116 
  117     rc = stress_temp_dir_mk_args(args);
  118     if (rc < 0)
  119         return exit_status(-rc);
  120 
  121     (void)stress_temp_filename_args(args,
  122         filename, sizeof(filename), mwc32());
  123 
  124     if ((fd = open(filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR)) < 0) {
  125         rc = exit_status(errno);
  126         pr_fail_err("open");
  127         (void)unlink(filename);
  128         (void)stress_temp_dir_rm_args(args);
  129 
  130         return rc;
  131     }
  132     (void)unlink(filename);
  133 
  134     if (ftruncate(fd, sz) < 0) {
  135         pr_err("%s: ftruncate failed, errno=%d (%s)\n",
  136             args->name, errno, strerror(errno));
  137         (void)close(fd);
  138         (void)stress_temp_dir_rm_args(args);
  139 
  140         return EXIT_FAILURE;
  141     }
  142 
  143     buf = (uint8_t *)mmap(NULL, sz,
  144         PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
  145     if (buf == MAP_FAILED) {
  146         pr_err("%s: failed to mmap memory, errno=%d (%s)\n",
  147             args->name, errno, strerror(errno));
  148         rc = EXIT_NO_RESOURCE;
  149         goto err;
  150     }
  151 
  152     do {
  153         off_t offset;
  154         uint8_t val, data[page_size];
  155 
  156         ret = sigsetjmp(jmp_env, 1);
  157         if (ret) {
  158             /* Try again */
  159             continue;
  160         }
  161         /*
  162          *  Change data in memory, msync to disk
  163          */
  164         offset = (mwc64() % (sz - page_size)) & ~(page_size - 1);
  165         val = mwc8();
  166 
  167         (void)memset(buf + offset, val, page_size);
  168         ret = shim_msync(buf + offset, page_size, MS_SYNC);
  169         if (ret < 0) {
  170             pr_fail("%s: msync MS_SYNC on "
  171                 "offset %jd failed, errno=%d (%s)\n",
  172                 args->name, (intmax_t)offset, errno,
  173                 strerror(errno));
  174             goto do_invalidate;
  175         }
  176         ret = lseek(fd, offset, SEEK_SET);
  177         if (ret == (off_t)-1) {
  178             pr_err("%s: cannot seet to offset %jd, "
  179                 "errno=%d (%s)\n",
  180                 args->name, (intmax_t)offset, errno,
  181                 strerror(errno));
  182             rc = EXIT_NO_RESOURCE;
  183             break;
  184         }
  185         ret = read(fd, data, sizeof(data));
  186         if (ret < (ssize_t)sizeof(data)) {
  187             pr_fail_err("read");
  188             goto do_invalidate;
  189         }
  190         if (stress_page_check(data, val, sizeof(data)) < 0) {
  191             pr_fail("%s: msync'd data in file different "
  192                 "to data in memory\n", args->name);
  193         }
  194 
  195 do_invalidate:
  196         /*
  197          *  Now change data on disc, msync invalidate
  198          */
  199         offset = (mwc64() % (sz - page_size)) & ~(page_size - 1);
  200         val = mwc8();
  201 
  202         (void)memset(buf + offset, val, page_size);
  203 
  204         ret = lseek(fd, offset, SEEK_SET);
  205         if (ret == (off_t)-1) {
  206             pr_err("%s: cannot seet to offset %jd, errno=%d (%s)\n",
  207                 args->name, (intmax_t)offset, errno,
  208                 strerror(errno));
  209             rc = EXIT_NO_RESOURCE;
  210             break;
  211         }
  212         ret = read(fd, data, sizeof(data));
  213         if (ret < (ssize_t)sizeof(data)) {
  214             pr_fail_err("read");
  215             goto do_next;
  216         }
  217         ret = shim_msync(buf + offset, page_size, MS_INVALIDATE);
  218         if (ret < 0) {
  219             pr_fail("%s: msync MS_INVALIDATE on "
  220                 "offset %jd failed, errno=%d (%s)\n",
  221                 args->name, (intmax_t)offset, errno,
  222                 strerror(errno));
  223             goto do_next;
  224         }
  225         if (stress_page_check(buf + offset, val, sizeof(data)) < 0) {
  226             pr_fail("%s: msync'd data in memory "
  227                 "different to data in file\n", args->name);
  228         }
  229 do_next:
  230         inc_counter(args);
  231     } while (keep_stressing());
  232 
  233     (void)munmap((void *)buf, sz);
  234 err:
  235     (void)close(fd);
  236     (void)stress_temp_dir_rm_args(args);
  237 
  238     if (sigbus_count)
  239         pr_inf("%s: caught %" PRIu64 " SIGBUS signals\n",
  240             args->name, sigbus_count);
  241     return rc;
  242 }
  243 
  244 stressor_info_t stress_msync_info = {
  245     .stressor = stress_msync,
  246     .class = CLASS_VM | CLASS_OS
  247 };
  248 #else
  249 stressor_info_t stress_msync_info = {
  250     .stressor = stress_not_implemented,
  251     .class = CLASS_VM | CLASS_OS
  252 };
  253 #endif