"Fossies" - the Fresh Open Source Software Archive

Member "stress-ng-0.09.56/stress-iomix.c" (15 Mar 2019, 16419 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-iomix.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 typedef void (*stress_iomix_func)(const args_t *args, const int fd, const off_t iomix_bytes);
   28 
   29 int stress_set_iomix_bytes(const char *opt)
   30 {
   31     off_t iomix_bytes;
   32 
   33     iomix_bytes = (off_t)get_uint64_byte_filesystem(opt, 1);
   34     check_range_bytes("iomix-bytes", iomix_bytes,
   35         MIN_IOMIX_BYTES, MAX_IOMIX_BYTES);
   36     return set_setting("iomix-bytes", TYPE_ID_OFF_T, &iomix_bytes);
   37 }
   38 
   39 /*
   40  *  stress_iomix_wr_seq_bursts()
   41  *  bursty sequential writes
   42  */
   43 static void stress_iomix_wr_seq_bursts(
   44     const args_t *args,
   45     const int fd,
   46     const off_t iomix_bytes)
   47 {
   48     do {
   49         off_t ret, posn;
   50         const int n = mwc8();
   51         int i;
   52         struct timeval tv;
   53 
   54         posn = mwc64() % iomix_bytes;
   55         ret = lseek(fd, posn, SEEK_SET);
   56         if (ret < 0) {
   57             pr_fail("seek");
   58             return;
   59         }
   60         for (i = 0; (i < n) && (posn < iomix_bytes); i++) {
   61             char buffer[512];
   62             ssize_t rc;
   63             const size_t len = 1 + (mwc32() & (sizeof(buffer) - 1));
   64 
   65             stress_strnrnd(buffer, len);
   66 
   67             rc = write(fd, buffer, len);
   68             if (rc < 0) {
   69                 pr_fail("write");
   70                 return;
   71             }
   72             posn += rc;
   73             if (!keep_stressing())
   74                 return;
   75             inc_counter(args);
   76         }
   77         tv.tv_sec = 0;
   78         tv.tv_usec = mwc32() % 1000000;
   79         (void)select(0, NULL, NULL, NULL, &tv);
   80     } while (keep_stressing());
   81 }
   82 
   83 /*
   84  *  stress_iomix_wr_rnd_bursts()
   85  *  bursty random writes
   86  */
   87 static void stress_iomix_wr_rnd_bursts(
   88     const args_t *args,
   89     const int fd,
   90     const off_t iomix_bytes)
   91 {
   92     do {
   93         const int n = mwc8();
   94         int i;
   95         struct timeval tv;
   96 
   97         for (i = 0; i < n; i++) {
   98             char buffer[512];
   99             ssize_t rc;
  100             const size_t len = 1 + (mwc32() & (sizeof(buffer) - 1));
  101             off_t ret, posn;
  102 
  103             posn = mwc64() % iomix_bytes;
  104             ret = lseek(fd, posn, SEEK_SET);
  105             if (ret < 0) {
  106                 pr_fail("seek");
  107                 return;
  108             }
  109 
  110             stress_strnrnd(buffer, len);
  111             rc = write(fd, buffer, len);
  112             if (rc < 0) {
  113                 pr_fail("write");
  114                 return;
  115             }
  116             if (!keep_stressing())
  117                 return;
  118             inc_counter(args);
  119         }
  120         tv.tv_sec = mwc32() % 2;
  121         tv.tv_usec = mwc32() % 1000000;
  122         (void)select(0, NULL, NULL, NULL, &tv);
  123 
  124     } while (keep_stressing());
  125 }
  126 
  127 /*
  128  *  stress_iomix_wr_seq_slow()
  129  *  slow sequential writes
  130  */
  131 static void stress_iomix_wr_seq_slow(
  132     const args_t *args,
  133     const int fd,
  134     const off_t iomix_bytes)
  135 {
  136     do {
  137         off_t ret, posn = 0;
  138 
  139         ret = lseek(fd, 0, SEEK_SET);
  140         if (ret < 0) {
  141             pr_fail("seek");
  142             return;
  143         }
  144         while (posn < iomix_bytes) {
  145             char buffer[512];
  146             ssize_t rc;
  147             const size_t len = 1 + (mwc32() & (sizeof(buffer) - 1));
  148 
  149             stress_strnrnd(buffer, len);
  150 
  151             rc = write(fd, buffer, len);
  152             if (rc < 0) {
  153                 pr_fail("write");
  154                 return;
  155             }
  156             (void)shim_usleep(250000);
  157             posn += rc;
  158             if (!keep_stressing())
  159                 return;
  160             inc_counter(args);
  161         }
  162     } while (keep_stressing());
  163 }
  164 
  165 /*
  166  *  stress_iomix_rd_seq_bursts()
  167  *  bursty sequential reads
  168  */
  169 static void stress_iomix_rd_seq_bursts(
  170     const args_t *args,
  171     const int fd,
  172     const off_t iomix_bytes)
  173 {
  174     do {
  175         off_t ret, posn;
  176         const int n = mwc8();
  177         int i;
  178         struct timeval tv;
  179 
  180         posn = mwc64() % iomix_bytes;
  181         ret = lseek(fd, posn, SEEK_SET);
  182         if (ret < 0) {
  183             pr_fail("seek");
  184             return;
  185         }
  186 #if defined(HAVE_POSIX_FADVISE)
  187         (void)posix_fadvise(fd, posn, 1024 * 1024, POSIX_FADV_SEQUENTIAL);
  188 #endif
  189         for (i = 0; (i < n) && (posn < iomix_bytes); i++) {
  190             char buffer[512];
  191             ssize_t rc;
  192             const size_t len = 1 + (mwc32() & (sizeof(buffer) - 1));
  193 
  194             rc = read(fd, buffer, len);
  195             if (rc < 0) {
  196                 pr_fail("read");
  197                 return;
  198             }
  199             posn += rc;
  200             if (!keep_stressing())
  201                 return;
  202             inc_counter(args);
  203         }
  204         tv.tv_sec = 0;
  205         tv.tv_usec = mwc32() % 1000000;
  206         (void)select(0, NULL, NULL, NULL, &tv);
  207     } while (keep_stressing());
  208 }
  209 
  210 /*
  211  *  stress_iomix_rd_rnd_bursts()
  212  *  bursty random reads
  213  */
  214 static void stress_iomix_rd_rnd_bursts(
  215     const args_t *args,
  216     const int fd,
  217     const off_t iomix_bytes)
  218 {
  219     do {
  220         const int n = mwc8();
  221         int i;
  222         struct timeval tv;
  223 
  224         for (i = 0; i < n; i++) {
  225             char buffer[512];
  226             ssize_t rc;
  227             const size_t len = 1 + (mwc32() & (sizeof(buffer) - 1));
  228             off_t ret, posn;
  229 
  230             posn = mwc64() % iomix_bytes;
  231 #if defined(HAVE_POSIX_FADVISE)
  232             (void)posix_fadvise(fd, posn, len, POSIX_FADV_RANDOM);
  233 #endif
  234             ret = lseek(fd, posn, SEEK_SET);
  235             if (ret < 0) {
  236                 pr_fail("seek");
  237                 return;
  238             }
  239 
  240             rc = read(fd, buffer, len);
  241             if (rc < 0) {
  242                 pr_fail("read");
  243                 return;
  244             }
  245             if (!keep_stressing())
  246                 return;
  247             inc_counter(args);
  248         }
  249         tv.tv_sec = mwc32() % 3;
  250         tv.tv_usec = mwc32() % 1000000;
  251         (void)select(0, NULL, NULL, NULL, &tv);
  252     } while (keep_stressing());
  253 }
  254 
  255 /*
  256  *  stress_iomix_rd_seq_slow()
  257  *  slow sequential reads
  258  */
  259 static void stress_iomix_rd_seq_slow(
  260     const args_t *args,
  261     const int fd,
  262     const off_t iomix_bytes)
  263 {
  264     do {
  265         off_t ret, posn = 0;
  266 
  267         ret = lseek(fd, 0, SEEK_SET);
  268         if (ret < 0) {
  269             pr_fail("seek");
  270             return;
  271         }
  272         while (posn < iomix_bytes) {
  273             char buffer[512];
  274             ssize_t rc;
  275             const size_t len = 1 + (mwc32() & (sizeof(buffer) - 1));
  276 
  277 #if defined(HAVE_POSIX_FADVISE)
  278             (void)posix_fadvise(fd, posn, len, POSIX_FADV_SEQUENTIAL);
  279 #endif
  280             rc = read(fd, buffer, len);
  281             if (rc < 0) {
  282                 pr_fail("read");
  283                 return;
  284             }
  285             (void)shim_usleep(333333);
  286             posn += rc;
  287             if (!keep_stressing())
  288                 return;
  289             inc_counter(args);
  290         }
  291     } while (keep_stressing());
  292 }
  293 
  294 /*
  295  *  stress_iomix_sync()
  296  *  file syncs
  297  */
  298 static void stress_iomix_sync(
  299     const args_t *args,
  300     const int fd,
  301     const off_t iomix_bytes)
  302 {
  303     do {
  304         struct timeval tv;
  305 
  306         (void)shim_fsync(fd);
  307         if (!keep_stressing())
  308             break;
  309         inc_counter(args);
  310         tv.tv_sec = mwc32() % 4;
  311         tv.tv_usec = mwc32() % 1000000;
  312         (void)select(0, NULL, NULL, NULL, &tv);
  313         if (!keep_stressing())
  314             break;
  315 
  316 #if defined(HAVE_FDATASYNC)
  317         (void)shim_fdatasync(fd);
  318         if (!keep_stressing())
  319             break;
  320         tv.tv_sec = mwc32() % 4;
  321         tv.tv_usec = mwc32() % 1000000;
  322         (void)select(0, NULL, NULL, NULL, &tv);
  323         if (!keep_stressing())
  324             break;
  325 #endif
  326 #if defined(HAVE_SYNC_FILE_RANGE) &&    \
  327     defined(SYNC_FILE_RANGE_WRITE)
  328         (void)sync_file_range(fd, mwc64() % iomix_bytes, 65536, SYNC_FILE_RANGE_WRITE);
  329         if (!keep_stressing())
  330             break;
  331         tv.tv_sec = mwc32() % 4;
  332         tv.tv_usec = mwc32() % 1000000;
  333         (void)select(0, NULL, NULL, NULL, &tv);
  334 #else
  335         (void)iomix_bytes;
  336 #endif
  337     } while (keep_stressing());
  338 }
  339 
  340 #if defined(HAVE_POSIX_FADVISE)
  341 /*
  342  *  stress_iomix_bad_advise()
  343  *  bad fadvise hints
  344  */
  345 static void stress_iomix_bad_advise(
  346     const args_t *args,
  347     const int fd,
  348     const off_t iomix_bytes)
  349 {
  350     do {
  351         off_t posn = mwc64() % iomix_bytes;
  352 
  353         (void)posix_fadvise(fd, posn, 65536, POSIX_FADV_DONTNEED);
  354         (void)shim_usleep(100000);
  355     } while (keep_stressing());
  356 }
  357 #endif
  358 
  359 /*
  360  *  stress_iomix_rd_wr_mmap()
  361  *  random memory mapped read/writes
  362  */
  363 static void stress_iomix_rd_wr_mmap(
  364     const args_t *args,
  365     const int fd,
  366     const off_t iomix_bytes)
  367 {
  368     void *mmaps[128];
  369     size_t i;
  370     const size_t page_size = args->page_size;
  371     int flags = MAP_SHARED | MAP_ANONYMOUS;
  372 
  373 #if defined(MAP_POPULATE)
  374     flags |= MAP_POPULATE;
  375 #endif
  376 
  377     do {
  378         for (i = 0; i < SIZEOF_ARRAY(mmaps); i++) {
  379             off_t posn = (mwc64() % iomix_bytes) & ~(page_size - 1);
  380             mmaps[i] = mmap(NULL, page_size,
  381                     PROT_READ | PROT_WRITE, flags, fd, posn);
  382         }
  383         for (i = 0; i < SIZEOF_ARRAY(mmaps); i++) {
  384             if (mmaps[i] != MAP_FAILED) {
  385                 size_t j;
  386                 uint64_t sum = 0;
  387                 uint8_t *buffer =  (uint8_t *)mmaps[i];
  388 
  389                 /* Force page data to be read */
  390                 for (j = 0; j < page_size; j++)
  391                     sum += buffer[j];
  392                 uint64_put(sum);
  393 
  394                 stress_strnrnd(mmaps[i], page_size);
  395                 (void)shim_msync(mmaps[i], page_size,
  396                     mwc1() ? MS_ASYNC : MS_SYNC);
  397             }
  398         }
  399         (void)shim_usleep(100000);
  400         for (i = 0; i < SIZEOF_ARRAY(mmaps); i++) {
  401             if (mmaps[i] != MAP_FAILED)
  402                 (void)munmap(mmaps[i], page_size);
  403         }
  404     } while (keep_stressing());
  405 }
  406 
  407 /*
  408  *  stress_iomix_wr_bytes()
  409  *  lots of small 1 byte writes
  410  */
  411 static void stress_iomix_wr_bytes(
  412     const args_t *args,
  413     const int fd,
  414     const off_t iomix_bytes)
  415 {
  416     do {
  417         off_t ret, posn = 0;
  418 
  419         ret = lseek(fd, 0, SEEK_SET);
  420         if (ret < 0) {
  421             pr_fail("seek");
  422             return;
  423         }
  424         while (posn < iomix_bytes) {
  425             char buffer[1] = { (mwc8() % 26) + 'A' };
  426             ssize_t rc;
  427 
  428             rc = write(fd, buffer, sizeof(buffer));
  429             if (rc < 0) {
  430                 pr_fail("write");
  431                 return;
  432             }
  433             (void)shim_usleep(1000);
  434             posn += rc;
  435             if (!keep_stressing())
  436                 return;
  437             inc_counter(args);
  438         }
  439     } while (keep_stressing());
  440 }
  441 
  442 /*
  443  *  stress_iomix_rd_bytes()
  444  *  lots of small 1 byte reads
  445  */
  446 static void stress_iomix_rd_bytes(
  447     const args_t *args,
  448     const int fd,
  449     const off_t iomix_bytes)
  450 {
  451     do {
  452         off_t ret, posn = iomix_bytes;
  453 
  454         while (posn != 0) {
  455             char buffer[1];
  456             ssize_t rc;
  457 
  458             ret = lseek(fd, posn, SEEK_SET);
  459             if (ret < 0) {
  460                 pr_fail("seek");
  461                 return;
  462             }
  463 
  464             rc = read(fd, buffer, sizeof(buffer));
  465             if (rc < 0) {
  466                 pr_fail("write");
  467                 return;
  468             }
  469             (void)shim_usleep(1000);
  470             posn--;
  471             if (!keep_stressing())
  472                 return;
  473             inc_counter(args);
  474         }
  475     } while (keep_stressing());
  476 }
  477 
  478 #if defined(__linux__)
  479 
  480 #if defined(FS_APPEND_FL)   || \
  481     defined(FS_COMPR_FL)    || \
  482     defined(FS_IMMUTABLE_FL)    || \
  483     defined(FS_JOURNAL_DATA_FL) || \
  484     defined(FS_NOATIME_FL)  || \
  485     defined(FS_NOCOW_FL)    || \
  486     defined(FS_NODUMP_FL)   || \
  487     defined(FS_NOTAIL_FL)   || \
  488     defined(FS_SECRM_FL)    || \
  489     defined(FS_SYNC_FL)     || \
  490     defined(FS_UNRM_FL)
  491 /*
  492  *  stress_iomix_inode_ioctl()
  493  *  attempt to set and unset a file based inode flag
  494  */
  495 static void stress_iomix_inode_ioctl(const int fd, const int flag, bool *ok)
  496 {
  497     int ret, attr;
  498 
  499 #if defined(FS_IOC_GETFLAGS)
  500     ret = ioctl(fd, FS_IOC_GETFLAGS, &attr);
  501     if (ret < 0)
  502         return;
  503 #if defined(FS_IOC_SETFLAGS)
  504     attr |= flag;
  505     ret = ioctl(fd, FS_IOC_SETFLAGS, &attr);
  506     if (ret < 0)
  507         return;
  508 
  509     attr &= ~flag;
  510     ret = ioctl(fd, FS_IOC_SETFLAGS, &attr);
  511     if (ret < 0)
  512         return;
  513 #endif
  514 #endif
  515     *ok = true;
  516 }
  517 #endif
  518 
  519 /*
  520  *  stress_iomix_inode_flags()
  521  *  twiddle various inode flags
  522  */
  523 static void stress_iomix_inode_flags(
  524     const args_t *args,
  525     const int fd,
  526     const off_t iomix_bytes)
  527 {
  528     (void)args;
  529     (void)iomix_bytes;
  530 
  531     do {
  532         bool ok = false;
  533 #if defined(FS_APPEND_FL)
  534         stress_iomix_inode_ioctl(fd, FS_APPEND_FL, &ok);
  535 #endif
  536 #if defined(FS_COMPR_FL)
  537         stress_iomix_inode_ioctl(fd, FS_COMPR_FL, &ok);
  538 #endif
  539 #if defined(FS_IMMUTABLE_FL)
  540         stress_iomix_inode_ioctl(fd, FS_IMMUTABLE_FL, &ok);
  541 #endif
  542 #if defined(FS_JOURNAL_DATA_FL)
  543         stress_iomix_inode_ioctl(fd, FS_JOURNAL_DATA_FL, &ok);
  544 #endif
  545 #if defined(FS_NOATIME_FL)
  546         stress_iomix_inode_ioctl(fd, FS_NOATIME_FL, &ok);
  547 #endif
  548 #if defined(FS_NOCOW_FL)
  549         stress_iomix_inode_ioctl(fd, FS_NOCOW_FL, &ok);
  550 #endif
  551 #if defined(FS_NODUMP_FL)
  552         stress_iomix_inode_ioctl(fd, FS_NODUMP_FL, &ok);
  553 #endif
  554 #if defined(FS_NOTAIL_FL)
  555         stress_iomix_inode_ioctl(fd, FS_NOTAIL_FL, &ok);
  556 #endif
  557 #if defined(FS_SECRM_FL)
  558         stress_iomix_inode_ioctl(fd, FS_SECRM_FL, &ok);
  559 #endif
  560 #if defined(FS_SYNC_FL)
  561         stress_iomix_inode_ioctl(fd, FS_SYNC_FL, &ok);
  562 #endif
  563 #if defined(FS_UNRM_FL)
  564         stress_iomix_inode_ioctl(fd, FS_UNRM_FL, &ok);
  565 #endif
  566         if (!ok)
  567             _exit(EXIT_SUCCESS);
  568     } while (keep_stressing());
  569 }
  570 #endif
  571 
  572 #if defined(__linux__)
  573 /*
  574  *  stress_iomix_drop_caches()
  575  *  occasional file cache dropping
  576  */
  577 static void stress_iomix_drop_caches(
  578     const args_t *args,
  579     const int fd,
  580     const off_t iomix_bytes)
  581 {
  582     (void)fd;
  583     (void)iomix_bytes;
  584 
  585     do {
  586         (void)sync();
  587         if (system_write("/proc/sys/vm/drop_caches", "1", 1) < 0)
  588             (void)pause();
  589         (void)sleep(5);
  590         if (!keep_stressing())
  591             return;
  592         (void)sync();
  593         if (system_write("/proc/sys/vm/drop_caches", "2", 1) < 0)
  594             (void)pause();
  595         (void)sleep(5);
  596         if (!keep_stressing())
  597             return;
  598         (void)sync();
  599         if (system_write("/proc/sys/vm/drop_caches", "3", 1) < 0)
  600             (void)pause();
  601         (void)sleep(5);
  602     } while (keep_stressing());
  603 }
  604 #endif
  605 
  606 static stress_iomix_func iomix_funcs[] = {
  607     stress_iomix_wr_seq_bursts,
  608     stress_iomix_wr_rnd_bursts,
  609     stress_iomix_wr_seq_slow,
  610     stress_iomix_wr_seq_slow,
  611     stress_iomix_rd_seq_bursts,
  612     stress_iomix_rd_rnd_bursts,
  613     stress_iomix_rd_seq_slow,
  614     stress_iomix_rd_seq_slow,
  615     stress_iomix_sync,
  616 #if defined(HAVE_POSIX_FADVISE)
  617     stress_iomix_bad_advise,
  618 #endif
  619     stress_iomix_rd_wr_mmap,
  620     stress_iomix_wr_bytes,
  621     stress_iomix_rd_bytes,
  622 #if defined(__linux__)
  623     stress_iomix_inode_flags,
  624 #endif
  625 #if defined(__linux__)
  626     stress_iomix_drop_caches
  627 #endif
  628 };
  629 
  630 /*
  631  *  stress_iomix
  632  *  stress I/O via random mix of io ops
  633  */
  634 static int stress_iomix(const args_t *args)
  635 {
  636     int fd, ret;
  637     char filename[PATH_MAX];
  638     uint64_t *counters;
  639     off_t iomix_bytes = DEFAULT_IOMIX_BYTES;
  640     const size_t page_size = args->page_size;
  641     const size_t counters_sz = sizeof(uint64_t) * SIZEOF_ARRAY(iomix_funcs);
  642     const size_t sz = (counters_sz + page_size) & ~(page_size - 1);
  643     size_t i;
  644     int pids[SIZEOF_ARRAY(iomix_funcs)];
  645 
  646     counters = (void *)mmap(NULL, sz, PROT_READ | PROT_WRITE,
  647             MAP_SHARED | MAP_ANONYMOUS, -1, 0);
  648     if (counters == MAP_FAILED) {
  649         pr_fail_dbg("mmap");
  650         return EXIT_NO_RESOURCE;
  651     }
  652 
  653     if (!get_setting("iomix-bytes", &iomix_bytes)) {
  654         if (g_opt_flags & OPT_FLAGS_MAXIMIZE)
  655             iomix_bytes = MAX_FALLOCATE_BYTES;
  656         if (g_opt_flags & OPT_FLAGS_MINIMIZE)
  657             iomix_bytes = MIN_FALLOCATE_BYTES;
  658     }
  659     iomix_bytes /= args->num_instances;
  660     if (iomix_bytes < (off_t)MIN_IOMIX_BYTES)
  661         iomix_bytes = (off_t)MIN_IOMIX_BYTES;
  662     if (iomix_bytes < (off_t)page_size)
  663         iomix_bytes = page_size;
  664 
  665     ret = stress_temp_dir_mk_args(args);
  666     if (ret < 0) {
  667         ret = exit_status(-ret);
  668         goto unmap;
  669     }
  670 
  671     (void)stress_temp_filename_args(args,
  672         filename, sizeof(filename), mwc32());
  673     if ((fd = open(filename, O_CREAT | O_RDWR | O_SYNC, S_IRUSR | S_IWUSR)) < 0) {
  674         ret = exit_status(errno);
  675         pr_fail_err("open");
  676         goto unmap;
  677     }
  678     (void)unlink(filename);
  679 
  680 #if defined(FALLOC_FL_ZERO_RANGE)
  681     ret = shim_fallocate(fd, FALLOC_FL_ZERO_RANGE, 0, iomix_bytes);
  682 #else
  683     ret = shim_fallocate(fd, 0, 0, iomix_bytes);
  684 #endif
  685     if (ret < 0) {
  686         if (errno == ENOSPC) {
  687             ret = EXIT_NO_RESOURCE;
  688         } else {
  689             ret = EXIT_FAILURE;
  690             pr_fail_err("fallocate");
  691         }
  692         goto tidy;
  693     }
  694 
  695     (void)memset(pids, 0, sizeof(pids));
  696     (void)memset(counters, 0, sz);
  697 
  698     for (i = 0; i < SIZEOF_ARRAY(iomix_funcs); i++) {
  699         const args_t tmp_args = {
  700             .counter = &counters[i],
  701             .name = args->name,
  702             .max_ops = args->max_ops,
  703             .instance = args->instance,
  704             .num_instances = args->num_instances,
  705             .pid = args->pid,
  706             .ppid = args->ppid,
  707             .page_size = args->page_size
  708         };
  709 
  710         pids[i] = fork();
  711         if (pids[i] < 0) {
  712             goto reap;
  713         } else if (pids[i] == 0) {
  714             /* Child */
  715             iomix_funcs[i](&tmp_args, fd, iomix_bytes);
  716             _exit(EXIT_SUCCESS);
  717         }
  718     }
  719 
  720     do {
  721         uint64_t c = 0;
  722         (void)shim_usleep(5000);
  723         for (i = 0; i < SIZEOF_ARRAY(iomix_funcs); i++) {
  724             c += counters[i];
  725             if (UNLIKELY(args->max_ops && c >= args->max_ops)) {
  726                 set_counter(args, c);
  727                 goto reap;
  728             }
  729         }
  730     } while (keep_stressing());
  731 
  732     ret = EXIT_SUCCESS;
  733 reap:
  734     set_counter(args, 0);
  735     for (i = 0; i < SIZEOF_ARRAY(iomix_funcs); i++) {
  736         add_counter(args, counters[i]);
  737 
  738         if (pids[i]) {
  739             (void)kill(pids[i], SIGALRM);
  740             (void)kill(pids[i], SIGKILL);
  741         }
  742     }
  743     for (i = 0; i < SIZEOF_ARRAY(iomix_funcs); i++) {
  744         if (pids[i]) {
  745             int status;
  746 
  747             (void)waitpid(pids[i], &status, 0);
  748         }
  749     }
  750 
  751 tidy:
  752     (void)close(fd);
  753     (void)stress_temp_dir_rm_args(args);
  754 unmap:
  755     (void)munmap((void *)counters, sz);
  756 
  757     return ret;
  758 }
  759 
  760 stressor_info_t stress_iomix_info = {
  761     .stressor = stress_iomix,
  762     .class = CLASS_FILESYSTEM | CLASS_OS
  763 };