"Fossies" - the Fresh Open Source Software Archive

Member "stress-ng-0.13.05/stress-iomix.c" (11 Oct 2021, 22082 Bytes) of package /linux/privat/stress-ng-0.13.05.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-iomix.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 0.13.04_vs_0.13.05.

    1 /*
    2  * Copyright (C) 2013-2021 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 typedef void (*stress_iomix_func)(const stress_args_t *args, const int fd, const off_t iomix_bytes);
   28 
   29 static const stress_help_t help[] = {
   30     { NULL, "iomix N",   "start N workers that have a mix of I/O operations" },
   31     { NULL, "iomix-bytes N", "write N bytes per iomix worker (default is 1GB)" },
   32     { NULL, "iomix-ops N",   "stop iomix workers after N iomix bogo operations" },
   33     { NULL, NULL,        NULL }
   34 };
   35 
   36 static int stress_set_iomix_bytes(const char *opt)
   37 {
   38     off_t iomix_bytes;
   39 
   40     iomix_bytes = (off_t)stress_get_uint64_byte_filesystem(opt, 1);
   41     stress_check_range_bytes("iomix-bytes", (uint64_t)iomix_bytes,
   42         MIN_IOMIX_BYTES, MAX_IOMIX_BYTES);
   43     return stress_set_setting("iomix-bytes", TYPE_ID_OFF_T, &iomix_bytes);
   44 }
   45 
   46 /*
   47  *  stress_iomix_rnd_offset()
   48  *  generate a random offset between 0..max-1
   49  */
   50 static off_t stress_iomix_rnd_offset(const off_t max)
   51 {
   52     return (off_t)(stress_mwc64() % max);
   53 }
   54 
   55 /*
   56  *  stress_iomix_fsync_min_1Hz()
   57  *  sync written data at most every once a second while
   58  *  trying to minimize the number time get calls
   59  */
   60 static void stress_iomix_fsync_min_1Hz(const int fd)
   61 {
   62     static double time_last = -1.0;
   63     static int counter = 0;
   64     static int counter_max = 1;
   65 
   66     if (time_last <= 0.0)
   67         time_last = stress_time_now() + 1.0;
   68 
   69     if (counter++ >= counter_max) {
   70         const double now = stress_time_now();
   71         const double delta = now - time_last;
   72 
   73         /* Less than 1Hz? try again */
   74         if (delta < 1.0)
   75             return;
   76 
   77         counter_max = (int)((double)counter / delta);
   78 
   79         counter = 0;
   80         time_last = now;
   81 
   82         switch (stress_mwc8() % 3) {
   83         case 0:
   84             (void)shim_fsync(fd);
   85             break;
   86         case 1:
   87             (void)shim_fdatasync(fd);
   88             break;
   89         case 2:
   90             (void)sync();
   91             break;
   92         }
   93     }
   94 }
   95 
   96 /*
   97  *  stress_iomix_wr_seq_bursts()
   98  *  bursty sequential writes
   99  */
  100 static void stress_iomix_wr_seq_bursts(
  101     const stress_args_t *args,
  102     const int fd,
  103     const off_t iomix_bytes)
  104 {
  105     do {
  106         off_t ret, posn;
  107         const int n = stress_mwc8();
  108         int i;
  109         struct timeval tv;
  110 
  111         posn = stress_iomix_rnd_offset(iomix_bytes);
  112         ret = lseek(fd, posn, SEEK_SET);
  113         if (ret < 0) {
  114             pr_fail("%s: lseek failed, errno=%d (%s)\n",
  115                 args->name, errno, strerror(errno));
  116             return;
  117         }
  118 #if defined(HAVE_POSIX_FADVISE) &&      \
  119     defined(POSIX_FADV_SEQUENTIAL)
  120         if (posn < iomix_bytes)
  121             (void)posix_fadvise(fd, posn, iomix_bytes - posn, POSIX_FADV_SEQUENTIAL);
  122 #endif
  123         for (i = 0; (i < n) && (posn < iomix_bytes); i++) {
  124             char buffer[512];
  125             ssize_t rc;
  126             const size_t len = 1 + (stress_mwc32() & (sizeof(buffer) - 1));
  127 
  128             stress_strnrnd(buffer, len);
  129 
  130             rc = write(fd, buffer, len);
  131             if (rc < 0) {
  132                 if (errno != EPERM) {
  133                     pr_fail("%s: write failed, errno=%d (%s)\n",
  134                         args->name, errno, strerror(errno));
  135                     return;
  136                 }
  137             }
  138             posn += rc;
  139             if (!keep_stressing(args))
  140                 return;
  141             inc_counter(args);
  142             stress_iomix_fsync_min_1Hz(fd);
  143         }
  144         tv.tv_sec = 0;
  145         tv.tv_usec = stress_mwc32() % 1000000;
  146         (void)select(0, NULL, NULL, NULL, &tv);
  147     } while (keep_stressing(args));
  148 }
  149 
  150 /*
  151  *  stress_iomix_wr_rnd_bursts()
  152  *  bursty random writes
  153  */
  154 static void stress_iomix_wr_rnd_bursts(
  155     const stress_args_t *args,
  156     const int fd,
  157     const off_t iomix_bytes)
  158 {
  159 #if defined(HAVE_POSIX_FADVISE) &&      \
  160     defined(POSIX_FADV_RANDOM)
  161     (void)posix_fadvise(fd, 0, iomix_bytes, POSIX_FADV_RANDOM);
  162 #endif
  163     do {
  164         const int n = stress_mwc8();
  165         int i;
  166         struct timeval tv;
  167 
  168         for (i = 0; i < n; i++) {
  169             char buffer[512];
  170             ssize_t rc;
  171             const size_t len = 1 + (stress_mwc32() & (sizeof(buffer) - 1));
  172             off_t ret, posn;
  173 
  174             posn = stress_iomix_rnd_offset(iomix_bytes);
  175             ret = lseek(fd, posn, SEEK_SET);
  176             if (ret < 0) {
  177                 pr_fail("%s: lseek failed, errno=%d (%s)\n",
  178                     args->name, errno, strerror(errno));
  179                 return;
  180             }
  181 
  182             stress_strnrnd(buffer, len);
  183             rc = write(fd, buffer, len);
  184             if (rc < 0) {
  185                 if (errno != EPERM) {
  186                     pr_fail("%s: write failed, errno=%d (%s)\n",
  187                         args->name, errno, strerror(errno));
  188                     return;
  189                 }
  190             }
  191             if (!keep_stressing(args))
  192                 return;
  193             inc_counter(args);
  194             stress_iomix_fsync_min_1Hz(fd);
  195         }
  196         tv.tv_sec = stress_mwc32() % 2;
  197         tv.tv_usec = stress_mwc32() % 1000000;
  198         (void)select(0, NULL, NULL, NULL, &tv);
  199 
  200     } while (keep_stressing(args));
  201 }
  202 
  203 /*
  204  *  stress_iomix_wr_seq_slow()
  205  *  slow sequential writes
  206  */
  207 static void stress_iomix_wr_seq_slow(
  208     const stress_args_t *args,
  209     const int fd,
  210     const off_t iomix_bytes)
  211 {
  212     do {
  213         off_t ret, posn = 0;
  214 
  215         ret = lseek(fd, 0, SEEK_SET);
  216         if (ret < 0) {
  217             pr_fail("%s: lseek failed, errno=%d (%s)\n",
  218                 args->name, errno, strerror(errno));
  219             return;
  220         }
  221 #if defined(HAVE_POSIX_FADVISE) &&      \
  222     defined(POSIX_FADV_SEQUENTIAL)
  223         if (posn < iomix_bytes)
  224             (void)posix_fadvise(fd, posn, iomix_bytes - posn, POSIX_FADV_SEQUENTIAL);
  225 #endif
  226         while (posn < iomix_bytes) {
  227             char buffer[512];
  228             ssize_t rc;
  229             const size_t len = 1 + (stress_mwc32() & (sizeof(buffer) - 1));
  230 
  231             stress_strnrnd(buffer, len);
  232 
  233             rc = write(fd, buffer, len);
  234             if (rc < 0) {
  235                 if (errno != EPERM) {
  236                     pr_fail("%s: write failed, errno=%d (%s)\n",
  237                         args->name, errno, strerror(errno));
  238                     return;
  239                 }
  240             }
  241             (void)shim_usleep(250000);
  242             posn += rc;
  243             if (!keep_stressing(args))
  244                 return;
  245             inc_counter(args);
  246             stress_iomix_fsync_min_1Hz(fd);
  247         }
  248     } while (keep_stressing(args));
  249 }
  250 
  251 /*
  252  *  stress_iomix_rd_seq_bursts()
  253  *  bursty sequential reads
  254  */
  255 static void stress_iomix_rd_seq_bursts(
  256     const stress_args_t *args,
  257     const int fd,
  258     const off_t iomix_bytes)
  259 {
  260     do {
  261         off_t ret, posn;
  262         const int n = stress_mwc8();
  263         int i;
  264         struct timeval tv;
  265 
  266         posn = stress_iomix_rnd_offset(iomix_bytes);
  267         ret = lseek(fd, posn, SEEK_SET);
  268         if (ret < 0) {
  269             pr_fail("%s: lseek failed, errno=%d (%s)\n",
  270                 args->name, errno, strerror(errno));
  271             return;
  272         }
  273 
  274 #if defined(HAVE_POSIX_FADVISE) &&      \
  275     defined(POSIX_FADV_SEQUENTIAL)
  276         if (posn < iomix_bytes)
  277             (void)posix_fadvise(fd, posn, iomix_bytes - posn, POSIX_FADV_SEQUENTIAL);
  278 #endif
  279         for (i = 0; (i < n) && (posn < iomix_bytes); i++) {
  280             char buffer[512];
  281             ssize_t rc;
  282             const size_t len = 1 + (stress_mwc32() & (sizeof(buffer) - 1));
  283 
  284             rc = read(fd, buffer, len);
  285             if (rc < 0) {
  286                 pr_fail("%s: read failed, errno=%d (%s)\n",
  287                     args->name, errno, strerror(errno));
  288                 return;
  289             }
  290             posn += rc;
  291             if (!keep_stressing(args))
  292                 return;
  293             inc_counter(args);
  294         }
  295         tv.tv_sec = 0;
  296         tv.tv_usec = stress_mwc32() % 1000000;
  297         (void)select(0, NULL, NULL, NULL, &tv);
  298     } while (keep_stressing(args));
  299 }
  300 
  301 /*
  302  *  stress_iomix_rd_rnd_bursts()
  303  *  bursty random reads
  304  */
  305 static void stress_iomix_rd_rnd_bursts(
  306     const stress_args_t *args,
  307     const int fd,
  308     const off_t iomix_bytes)
  309 {
  310     do {
  311         const int n = stress_mwc8();
  312         int i;
  313         struct timeval tv;
  314 
  315         for (i = 0; i < n; i++) {
  316             char buffer[512];
  317             ssize_t rc;
  318             const size_t len = 1 + (stress_mwc32() & (sizeof(buffer) - 1));
  319             off_t ret, posn;
  320 
  321             posn = stress_iomix_rnd_offset(iomix_bytes);
  322 #if defined(HAVE_POSIX_FADVISE) &&      \
  323     defined(POSIX_FADV_RANDOM)
  324             (void)posix_fadvise(fd, posn, (off_t)len, POSIX_FADV_RANDOM);
  325 #endif
  326             ret = lseek(fd, posn, SEEK_SET);
  327             if (ret < 0) {
  328                 pr_fail("%s: lseek failed, errno=%d (%s)\n",
  329                     args->name, errno, strerror(errno));
  330                 return;
  331             }
  332 
  333             rc = read(fd, buffer, len);
  334             if (rc < 0) {
  335                 pr_fail("%s: read failed, errno=%d (%s)\n",
  336                     args->name, errno, strerror(errno));
  337                 return;
  338             }
  339             if (!keep_stressing(args))
  340                 return;
  341             inc_counter(args);
  342         }
  343         tv.tv_sec = stress_mwc32() % 3;
  344         tv.tv_usec = stress_mwc32() % 1000000;
  345         (void)select(0, NULL, NULL, NULL, &tv);
  346     } while (keep_stressing(args));
  347 }
  348 
  349 /*
  350  *  stress_iomix_rd_seq_slow()
  351  *  slow sequential reads
  352  */
  353 static void stress_iomix_rd_seq_slow(
  354     const stress_args_t *args,
  355     const int fd,
  356     const off_t iomix_bytes)
  357 {
  358     do {
  359         off_t ret, posn = 0;
  360 
  361         ret = lseek(fd, 0, SEEK_SET);
  362         if (ret < 0) {
  363             pr_fail("%s: lseek failed, errno=%d (%s)\n",
  364                 args->name, errno, strerror(errno));
  365             return;
  366         }
  367 #if defined(HAVE_POSIX_FADVISE) &&      \
  368     defined(POSIX_FADV_SEQUENTIAL)
  369         if (posn < iomix_bytes)
  370             (void)posix_fadvise(fd, posn, iomix_bytes - posn, POSIX_FADV_SEQUENTIAL);
  371 #endif
  372         while (posn < iomix_bytes) {
  373             char buffer[512];
  374             ssize_t rc;
  375             const size_t len = 1 + (stress_mwc32() & (sizeof(buffer) - 1));
  376 
  377             rc = read(fd, buffer, len);
  378             if (rc < 0) {
  379                 pr_fail("%s: read failed, errno=%d (%s)\n",
  380                     args->name, errno, strerror(errno));
  381                 return;
  382             }
  383             (void)shim_usleep(333333);
  384             posn += rc;
  385             if (!keep_stressing(args))
  386                 return;
  387             inc_counter(args);
  388             stress_iomix_fsync_min_1Hz(fd);
  389         }
  390     } while (keep_stressing(args));
  391 }
  392 
  393 /*
  394  *  stress_iomix_sync()
  395  *  file syncs
  396  */
  397 static void stress_iomix_sync(
  398     const stress_args_t *args,
  399     const int fd,
  400     const off_t iomix_bytes)
  401 {
  402     do {
  403         struct timeval tv;
  404 
  405         (void)shim_fsync(fd);
  406         if (!keep_stressing(args))
  407             break;
  408         inc_counter(args);
  409         tv.tv_sec = stress_mwc32() % 4;
  410         tv.tv_usec = stress_mwc32() % 1000000;
  411         (void)select(0, NULL, NULL, NULL, &tv);
  412         if (!keep_stressing(args))
  413             break;
  414 
  415 #if defined(HAVE_FDATASYNC)
  416         (void)shim_fdatasync(fd);
  417         /* Exercise illegal fdatasync */
  418         (void)shim_fdatasync(-1);
  419         if (!keep_stressing(args))
  420             break;
  421         tv.tv_sec = stress_mwc32() % 4;
  422         tv.tv_usec = stress_mwc32() % 1000000;
  423         (void)select(0, NULL, NULL, NULL, &tv);
  424         if (!keep_stressing(args))
  425             break;
  426 #endif
  427 #if defined(HAVE_SYNC_FILE_RANGE) &&    \
  428     defined(SYNC_FILE_RANGE_WRITE)
  429         (void)sync_file_range(fd, stress_iomix_rnd_offset(iomix_bytes),
  430                 65536, SYNC_FILE_RANGE_WRITE);
  431         if (!keep_stressing(args))
  432             break;
  433         tv.tv_sec = stress_mwc32() % 4;
  434         tv.tv_usec = stress_mwc32() % 1000000;
  435         (void)select(0, NULL, NULL, NULL, &tv);
  436 #else
  437         (void)iomix_bytes;
  438 #endif
  439     } while (keep_stressing(args));
  440 }
  441 
  442 #if defined(HAVE_POSIX_FADVISE) &&  \
  443     defined(POSIX_FADV_DONTNEED)
  444 /*
  445  *  stress_iomix_bad_advise()
  446  *  bad fadvise hints
  447  */
  448 static void stress_iomix_bad_advise(
  449     const stress_args_t *args,
  450     const int fd,
  451     const off_t iomix_bytes)
  452 {
  453     do {
  454         off_t posn = stress_iomix_rnd_offset(iomix_bytes);
  455 
  456         (void)posix_fadvise(fd, posn, 65536, POSIX_FADV_DONTNEED);
  457         (void)shim_usleep(100000);
  458         (void)posix_fadvise(fd, posn, 65536, POSIX_FADV_NORMAL);
  459         (void)shim_usleep(100000);
  460     } while (keep_stressing(args));
  461 }
  462 #endif
  463 
  464 /*
  465  *  stress_iomix_rd_wr_mmap()
  466  *  random memory mapped read/writes
  467  */
  468 static void stress_iomix_rd_wr_mmap(
  469     const stress_args_t *args,
  470     const int fd,
  471     const off_t iomix_bytes)
  472 {
  473     void *mmaps[128];
  474     size_t i;
  475     const size_t page_size = args->page_size;
  476     int flags = MAP_SHARED | MAP_ANONYMOUS;
  477 
  478 #if defined(MAP_POPULATE)
  479     flags |= MAP_POPULATE;
  480 #endif
  481 
  482     do {
  483         for (i = 0; i < SIZEOF_ARRAY(mmaps); i++) {
  484             const off_t posn = stress_iomix_rnd_offset(iomix_bytes) & ~((off_t)page_size - 1);
  485 
  486             mmaps[i] = mmap(NULL, page_size,
  487                     PROT_READ | PROT_WRITE, flags, fd, posn);
  488         }
  489         for (i = 0; i < SIZEOF_ARRAY(mmaps); i++) {
  490             if (mmaps[i] != MAP_FAILED) {
  491                 size_t j;
  492                 uint64_t sum = 0;
  493                 uint8_t *buffer = (uint8_t *)mmaps[i];
  494 
  495                 /* Force page data to be read */
  496                 for (j = 0; j < page_size; j++)
  497                     sum += buffer[j];
  498                 stress_uint64_put(sum);
  499 
  500                 stress_strnrnd(mmaps[i], page_size);
  501                 (void)shim_msync(mmaps[i], page_size,
  502                     stress_mwc1() ? MS_ASYNC : MS_SYNC);
  503             }
  504         }
  505         (void)shim_usleep(100000);
  506         for (i = 0; i < SIZEOF_ARRAY(mmaps); i++) {
  507             if (mmaps[i] != MAP_FAILED)
  508                 (void)munmap(mmaps[i], page_size);
  509         }
  510     } while (keep_stressing(args));
  511 }
  512 
  513 /*
  514  *  stress_iomix_wr_bytes()
  515  *  lots of small 1 byte writes
  516  */
  517 static void stress_iomix_wr_bytes(
  518     const stress_args_t *args,
  519     const int fd,
  520     const off_t iomix_bytes)
  521 {
  522     do {
  523         off_t ret, posn = 0;
  524 
  525         ret = lseek(fd, 0, SEEK_SET);
  526         if (ret < 0) {
  527             pr_fail("%s: lseek failed, errno=%d (%s)\n",
  528                 args->name, errno, strerror(errno));
  529             return;
  530         }
  531         while (posn < iomix_bytes) {
  532             char buffer[1] = { (stress_mwc8() % 26) + 'A' };
  533             ssize_t rc;
  534 
  535             rc = write(fd, buffer, sizeof(buffer));
  536             if (rc < 0) {
  537                 if (errno != EPERM) {
  538                     pr_fail("%s: write failed, errno=%d (%s)\n",
  539                         args->name, errno, strerror(errno));
  540                     return;
  541             }   }
  542             (void)shim_usleep(1000);
  543             posn += rc;
  544             if (!keep_stressing(args))
  545                 return;
  546             inc_counter(args);
  547             stress_iomix_fsync_min_1Hz(fd);
  548         }
  549     } while (keep_stressing(args));
  550 }
  551 
  552 /*
  553  *  stress_iomix_wr_rev_bytes()
  554  *  lots of small 1 byte writes in reverse order
  555  */
  556 static void stress_iomix_wr_rev_bytes(
  557     const stress_args_t *args,
  558     const int fd,
  559     const off_t iomix_bytes)
  560 {
  561     do {
  562         off_t ret, posn = iomix_bytes;
  563 
  564         ret = lseek(fd, 0, SEEK_SET);
  565         if (ret < 0) {
  566             pr_fail("%s: lseek failed, errno=%d (%s)\n",
  567                 args->name, errno, strerror(errno));
  568             return;
  569         }
  570         while (posn != 0) {
  571             char buffer[1] = { (stress_mwc8() % 26) + 'A' };
  572             ssize_t rc;
  573 
  574             rc = write(fd, buffer, sizeof(buffer));
  575             if (rc < 0) {
  576                 if (errno != EPERM) {
  577                     pr_fail("%s: write failed, errno=%d (%s)\n",
  578                         args->name, errno, strerror(errno));
  579                     return;
  580             }   }
  581             (void)shim_usleep(1000);
  582             posn--;
  583             if (!keep_stressing(args))
  584                 return;
  585             inc_counter(args);
  586             stress_iomix_fsync_min_1Hz(fd);
  587         }
  588     } while (keep_stressing(args));
  589 }
  590 
  591 /*
  592  *  stress_iomix_rd_bytes()
  593  *  lots of small 1 byte reads
  594  */
  595 static void stress_iomix_rd_bytes(
  596     const stress_args_t *args,
  597     const int fd,
  598     const off_t iomix_bytes)
  599 {
  600     do {
  601         off_t ret, posn = iomix_bytes;
  602 
  603         while (posn != 0) {
  604             char buffer[1];
  605             ssize_t rc;
  606 
  607             ret = lseek(fd, posn, SEEK_SET);
  608             if (ret < 0) {
  609                 pr_fail("%s: lseek failed, errno=%d (%s)\n",
  610                     args->name, errno, strerror(errno));
  611                 return;
  612             }
  613 
  614             rc = read(fd, buffer, sizeof(buffer));
  615             if (rc < 0) {
  616                 if (errno != EPERM) {
  617                     pr_fail("%s: write failed, errno=%d (%s)\n",
  618                         args->name, errno, strerror(errno));
  619                     return;
  620                 }
  621             }
  622             (void)shim_usleep(1000);
  623             posn--;
  624             if (!keep_stressing(args))
  625                 return;
  626             inc_counter(args);
  627         }
  628     } while (keep_stressing(args));
  629 }
  630 
  631 #if defined(__linux__)
  632 
  633 #if defined(FS_APPEND_FL)   || \
  634     defined(FS_COMPR_FL)    || \
  635     defined(FS_IMMUTABLE_FL)    || \
  636     defined(FS_JOURNAL_DATA_FL) || \
  637     defined(FS_NOATIME_FL)  || \
  638     defined(FS_NOCOW_FL)    || \
  639     defined(FS_NODUMP_FL)   || \
  640     defined(FS_NOTAIL_FL)   || \
  641     defined(FS_SECRM_FL)    || \
  642     defined(FS_SYNC_FL)     || \
  643     defined(FS_UNRM_FL)
  644 /*
  645  *  stress_iomix_inode_ioctl()
  646  *  attempt to set and unset a file based inode flag
  647  */
  648 static void stress_iomix_inode_ioctl(
  649     const stress_args_t *args,
  650     const int fd,
  651     const int flag,
  652     bool *ok)
  653 {
  654     int ret, attr;
  655 
  656     if (!keep_stressing(args))
  657         return;
  658 
  659 #if defined(FS_IOC_GETFLAGS)
  660     ret = ioctl(fd, FS_IOC_GETFLAGS, &attr);
  661     if (ret < 0)
  662         return;
  663 #if defined(FS_IOC_SETFLAGS)
  664     attr |= flag;
  665     ret = ioctl(fd, FS_IOC_SETFLAGS, &attr);
  666     if (ret < 0)
  667         return;
  668 
  669     attr &= ~flag;
  670     ret = ioctl(fd, FS_IOC_SETFLAGS, &attr);
  671     if (ret < 0)
  672         return;
  673 #endif
  674 #endif
  675     *ok = true;
  676 }
  677 #endif
  678 
  679 /*
  680  *  stress_iomix_inode_flags()
  681  *  twiddle various inode flags
  682  */
  683 static void stress_iomix_inode_flags(
  684     const stress_args_t *args,
  685     const int fd,
  686     const off_t iomix_bytes)
  687 {
  688     (void)args;
  689     (void)fd;
  690     (void)iomix_bytes;
  691 
  692     do {
  693         bool ok = false;
  694 #if defined(FS_APPEND_FL)
  695         stress_iomix_inode_ioctl(args, fd, FS_APPEND_FL, &ok);
  696 #endif
  697 #if defined(FS_COMPR_FL)
  698         stress_iomix_inode_ioctl(args, fd, FS_COMPR_FL, &ok);
  699 #endif
  700 #if defined(FS_IMMUTABLE_FL)
  701         stress_iomix_inode_ioctl(args, fd, FS_IMMUTABLE_FL, &ok);
  702 #endif
  703 #if defined(FS_JOURNAL_DATA_FL)
  704         stress_iomix_inode_ioctl(args, fd, FS_JOURNAL_DATA_FL, &ok);
  705 #endif
  706 #if defined(FS_NOATIME_FL)
  707         stress_iomix_inode_ioctl(args, fd, FS_NOATIME_FL, &ok);
  708 #endif
  709 #if defined(FS_NOCOW_FL)
  710         stress_iomix_inode_ioctl(args, fd, FS_NOCOW_FL, &ok);
  711 #endif
  712 #if defined(FS_NODUMP_FL)
  713         stress_iomix_inode_ioctl(args, fd, FS_NODUMP_FL, &ok);
  714 #endif
  715 #if defined(FS_NOTAIL_FL)
  716         stress_iomix_inode_ioctl(args, fd, FS_NOTAIL_FL, &ok);
  717 #endif
  718 #if defined(FS_SECRM_FL)
  719         stress_iomix_inode_ioctl(args, fd, FS_SECRM_FL, &ok);
  720 #endif
  721 #if defined(FS_SYNC_FL)
  722         stress_iomix_inode_ioctl(args, fd, FS_SYNC_FL, &ok);
  723 #endif
  724 #if defined(FS_UNRM_FL)
  725         stress_iomix_inode_ioctl(args, fd, FS_UNRM_FL, &ok);
  726 #endif
  727         if (!ok)
  728             _exit(EXIT_SUCCESS);
  729         stress_iomix_fsync_min_1Hz(fd);
  730     } while (keep_stressing(args));
  731 }
  732 #endif
  733 
  734 #if defined(__linux__)
  735 /*
  736  *  stress_iomix_drop_caches()
  737  *  occasional file cache dropping
  738  */
  739 static void stress_iomix_drop_caches(
  740     const stress_args_t *args,
  741     const int fd,
  742     const off_t iomix_bytes)
  743 {
  744     (void)fd;
  745     (void)iomix_bytes;
  746 
  747     do {
  748         (void)sync();
  749         if (system_write("/proc/sys/vm/drop_caches", "1", 1) < 0)
  750             (void)pause();
  751         (void)sleep(5);
  752         if (!keep_stressing(args))
  753             return;
  754         (void)sync();
  755         if (system_write("/proc/sys/vm/drop_caches", "2", 1) < 0)
  756             (void)pause();
  757         (void)sleep(5);
  758         if (!keep_stressing(args))
  759             return;
  760         (void)sync();
  761         if (system_write("/proc/sys/vm/drop_caches", "3", 1) < 0)
  762             (void)pause();
  763         (void)sleep(5);
  764     } while (keep_stressing(args));
  765 }
  766 #endif
  767 
  768 static stress_iomix_func iomix_funcs[] = {
  769     stress_iomix_wr_seq_bursts,
  770     stress_iomix_wr_rnd_bursts,
  771     stress_iomix_wr_seq_slow,
  772     stress_iomix_wr_seq_slow,
  773     stress_iomix_rd_seq_bursts,
  774     stress_iomix_rd_rnd_bursts,
  775     stress_iomix_rd_seq_slow,
  776     stress_iomix_rd_seq_slow,
  777     stress_iomix_sync,
  778 #if defined(HAVE_POSIX_FADVISE)
  779     stress_iomix_bad_advise,
  780 #endif
  781     stress_iomix_rd_wr_mmap,
  782     stress_iomix_wr_bytes,
  783     stress_iomix_wr_rev_bytes,
  784     stress_iomix_rd_bytes,
  785 #if defined(__linux__)
  786     stress_iomix_inode_flags,
  787 #endif
  788 #if defined(__linux__)
  789     stress_iomix_drop_caches
  790 #endif
  791 };
  792 
  793 /*
  794  *  stress_iomix
  795  *  stress I/O via random mix of io ops
  796  */
  797 static int stress_iomix(const stress_args_t *args)
  798 {
  799     int fd, ret;
  800     char filename[PATH_MAX];
  801     uint64_t *counters;
  802     off_t iomix_bytes = DEFAULT_IOMIX_BYTES;
  803     const size_t page_size = args->page_size;
  804     const size_t counters_sz = sizeof(uint64_t) * SIZEOF_ARRAY(iomix_funcs);
  805     const size_t sz = (counters_sz + page_size) & ~(page_size - 1);
  806     size_t i;
  807     int pids[SIZEOF_ARRAY(iomix_funcs)];
  808 
  809     counters = (void *)mmap(NULL, sz, PROT_READ | PROT_WRITE,
  810             MAP_SHARED | MAP_ANONYMOUS, -1, 0);
  811     if (counters == MAP_FAILED) {
  812         pr_fail("%s: mmap failed, errno=%d (%s)\n",
  813             args->name, errno, strerror(errno));
  814         return EXIT_NO_RESOURCE;
  815     }
  816 
  817     if (!stress_get_setting("iomix-bytes", &iomix_bytes)) {
  818         if (g_opt_flags & OPT_FLAGS_MAXIMIZE)
  819             iomix_bytes = MAXIMIZED_FILE_SIZE;
  820         if (g_opt_flags & OPT_FLAGS_MINIMIZE)
  821             iomix_bytes = MIN_IOMIX_BYTES;
  822     }
  823     iomix_bytes /= args->num_instances;
  824     if (iomix_bytes < (off_t)MIN_IOMIX_BYTES)
  825         iomix_bytes = (off_t)MIN_IOMIX_BYTES;
  826     if (iomix_bytes < (off_t)page_size)
  827         iomix_bytes = (off_t)page_size;
  828 
  829     ret = stress_temp_dir_mk_args(args);
  830     if (ret < 0) {
  831         ret = exit_status(-ret);
  832         goto unmap;
  833     }
  834 
  835     (void)stress_temp_filename_args(args,
  836         filename, sizeof(filename), stress_mwc32());
  837     if ((fd = open(filename, O_CREAT | O_RDWR | O_SYNC, S_IRUSR | S_IWUSR)) < 0) {
  838         ret = exit_status(errno);
  839         pr_fail("%s: open %s failed, errno=%d (%s)\n",
  840             args->name, filename, errno, strerror(errno));
  841         goto unmap;
  842     }
  843     (void)unlink(filename);
  844 
  845 #if defined(FALLOC_FL_ZERO_RANGE)
  846     ret = shim_fallocate(fd, FALLOC_FL_ZERO_RANGE, 0, iomix_bytes);
  847 #else
  848     ret = shim_fallocate(fd, 0, 0, iomix_bytes);
  849 #endif
  850     if (ret < 0) {
  851         if (errno == ENOSPC) {
  852             ret = EXIT_NO_RESOURCE;
  853         } else {
  854             ret = EXIT_FAILURE;
  855             pr_fail("%s: fallocate failed, errno=%d (%s)\n",
  856                 args->name, errno, strerror(errno));
  857         }
  858         goto tidy;
  859     }
  860 
  861     (void)memset(pids, 0, sizeof(pids));
  862     (void)memset(counters, 0, sz);
  863 
  864     stress_set_proc_state(args->name, STRESS_STATE_RUN);
  865 
  866     for (i = 0; i < SIZEOF_ARRAY(iomix_funcs); i++) {
  867         stress_args_t tmp_args = *args;
  868 
  869         tmp_args.counter = &counters[i];
  870 
  871         pids[i] = fork();
  872         if (pids[i] < 0) {
  873             goto reap;
  874         } else if (pids[i] == 0) {
  875             /* Child */
  876             (void)sched_settings_apply(true);
  877             iomix_funcs[i](&tmp_args, fd, iomix_bytes);
  878             _exit(EXIT_SUCCESS);
  879         }
  880     }
  881 
  882     do {
  883         uint64_t c = 0;
  884         (void)shim_usleep(5000);
  885         for (i = 0; i < SIZEOF_ARRAY(iomix_funcs); i++) {
  886             c += counters[i];
  887             if (UNLIKELY(args->max_ops && c >= args->max_ops)) {
  888                 set_counter(args, c);
  889                 goto reap;
  890             }
  891         }
  892     } while (keep_stressing(args));
  893 
  894     ret = EXIT_SUCCESS;
  895 reap:
  896     set_counter(args, 0);
  897     for (i = 0; i < SIZEOF_ARRAY(iomix_funcs); i++) {
  898         add_counter(args, counters[i]);
  899 
  900         if (pids[i]) {
  901             (void)kill(pids[i], SIGALRM);
  902             (void)kill(pids[i], SIGKILL);
  903         }
  904     }
  905     for (i = 0; i < SIZEOF_ARRAY(iomix_funcs); i++) {
  906         if (pids[i]) {
  907             int status;
  908 
  909             (void)shim_waitpid(pids[i], &status, 0);
  910         }
  911     }
  912 
  913 tidy:
  914     stress_set_proc_state(args->name, STRESS_STATE_DEINIT);
  915     (void)close(fd);
  916     (void)stress_temp_dir_rm_args(args);
  917 unmap:
  918     stress_set_proc_state(args->name, STRESS_STATE_DEINIT);
  919     (void)munmap((void *)counters, sz);
  920 
  921     return ret;
  922 }
  923 
  924 static const stress_opt_set_func_t opt_set_funcs[] = {
  925     { OPT_iomix_bytes,  stress_set_iomix_bytes },
  926     { 0,            NULL }
  927 };
  928 
  929 stressor_info_t stress_iomix_info = {
  930     .stressor = stress_iomix,
  931     .class = CLASS_FILESYSTEM | CLASS_OS,
  932     .opt_set_funcs = opt_set_funcs,
  933     .help = help
  934 };