"Fossies" - the Fresh Open Source Software Archive

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

    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 #define BUF_ALIGNMENT       (4096)
   28 #define BUF_SIZE        (512)
   29 #define MAX_OFFSETS     (16)
   30 
   31 int stress_set_readahead_bytes(const char *opt)
   32 {
   33     uint64_t readahead_bytes;
   34 
   35     readahead_bytes = get_uint64_byte_filesystem(opt, 1);
   36     check_range_bytes("readahead-bytes", readahead_bytes,
   37         MIN_HDD_BYTES, MAX_HDD_BYTES);
   38     return set_setting("readahead-bytes", TYPE_ID_UINT64, &readahead_bytes);
   39 }
   40 
   41 #if defined(__linux__) && NEED_GLIBC(2,3,0)
   42 
   43 static int do_readahead(
   44     const args_t *args,
   45     const int fd,
   46     off_t *offsets,
   47     const uint64_t rounded_readahead_bytes)
   48 {
   49     int i;
   50 
   51     for (i = 0; i < MAX_OFFSETS; i++) {
   52         offsets[i] = (mwc64() % (rounded_readahead_bytes - BUF_SIZE)) & ~511;
   53         if (readahead(fd, offsets[i], BUF_SIZE) < 0) {
   54             pr_fail_err("ftruncate");
   55             return -1;
   56         }
   57     }
   58     return 0;
   59 }
   60 
   61 /*
   62  *  stress_readahead
   63  *  stress file system cache via readahead calls
   64  */
   65 static int stress_readahead(const args_t *args)
   66 {
   67     uint8_t *buf = NULL;
   68     uint64_t rounded_readahead_bytes, i;
   69     uint64_t readahead_bytes = DEFAULT_READAHEAD_BYTES;
   70     uint64_t misreads = 0;
   71     uint64_t baddata = 0;
   72     int ret, rc = EXIT_FAILURE;
   73     char filename[PATH_MAX];
   74     int flags = O_CREAT | O_RDWR | O_TRUNC;
   75     int fd;
   76     struct stat statbuf;
   77 
   78     if (!get_setting("readahead-bytes", &readahead_bytes)) {
   79         if (g_opt_flags & OPT_FLAGS_MAXIMIZE)
   80             readahead_bytes = MAX_HDD_BYTES;
   81         if (g_opt_flags & OPT_FLAGS_MINIMIZE)
   82             readahead_bytes = MIN_HDD_BYTES;
   83     }
   84     readahead_bytes /= args->num_instances;
   85     if (readahead_bytes < MIN_HDD_BYTES)
   86         readahead_bytes = MIN_HDD_BYTES;
   87 
   88     if (stress_temp_dir_mk_args(args) < 0)
   89         return EXIT_FAILURE;
   90 
   91     ret = posix_memalign((void **)&buf, BUF_ALIGNMENT, BUF_SIZE);
   92     if (ret || !buf) {
   93         rc = exit_status(errno);
   94         pr_err("%s: cannot allocate buffer\n", args->name);
   95         (void)stress_temp_dir_rm_args(args);
   96         return rc;
   97     }
   98 
   99     (void)stress_temp_filename_args(args,
  100         filename, sizeof(filename), mwc32());
  101 
  102     if ((fd = open(filename, flags, S_IRUSR | S_IWUSR)) < 0) {
  103         rc = exit_status(errno);
  104         pr_fail_err("open");
  105         goto finish;
  106     }
  107     if (ftruncate(fd, (off_t)0) < 0) {
  108         rc = exit_status(errno);
  109         pr_fail_err("ftruncate");
  110         goto close_finish;
  111     }
  112     (void)unlink(filename);
  113 
  114 #if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_DONTNEED)
  115     if (posix_fadvise(fd, 0, readahead_bytes, POSIX_FADV_DONTNEED) < 0) {
  116         pr_fail_err("posix_fadvise");
  117         goto close_finish;
  118     }
  119 #endif
  120 
  121     /* Sequential Write */
  122     for (i = 0; i < readahead_bytes; i += BUF_SIZE) {
  123         ssize_t pret;
  124         size_t j;
  125         off_t o = i / BUF_SIZE;
  126 seq_wr_retry:
  127         if (!g_keep_stressing_flag) {
  128             pr_inf("%s: test expired during test setup "
  129                 "(writing of data file)\n", args->name);
  130             rc = EXIT_SUCCESS;
  131             goto close_finish;
  132         }
  133 
  134         for (j = 0; j < BUF_SIZE; j++)
  135             buf[j] = (o + j) & 0xff;
  136 
  137         pret = pwrite(fd, buf, BUF_SIZE, i);
  138         if (pret <= 0) {
  139             if ((errno == EAGAIN) || (errno == EINTR))
  140                 goto seq_wr_retry;
  141             if (errno == ENOSPC)
  142                 break;
  143             if (errno) {
  144                 pr_fail_err("pwrite");
  145                 goto close_finish;
  146             }
  147             continue;
  148         }
  149     }
  150 
  151     if (fstat(fd, &statbuf) < 0) {
  152         pr_fail_err("fstat");
  153         goto close_finish;
  154     }
  155 
  156     /* Round to write size to get no partial reads */
  157     rounded_readahead_bytes = (uint64_t)statbuf.st_size -
  158         (statbuf.st_size % BUF_SIZE);
  159 
  160     do {
  161         off_t offsets[MAX_OFFSETS];
  162 
  163         if (do_readahead(args, fd, offsets, rounded_readahead_bytes) < 0)
  164             goto close_finish;
  165 
  166         for (i = 0; i < MAX_OFFSETS; i++) {
  167 rnd_rd_retry:
  168             if (!keep_stressing())
  169                 break;
  170             ret = pread(fd, buf, BUF_SIZE, offsets[i]);
  171             if (ret <= 0) {
  172                 if ((errno == EAGAIN) || (errno == EINTR))
  173                     goto rnd_rd_retry;
  174                 if (errno) {
  175                     pr_fail_err("read");
  176                     goto close_finish;
  177                 }
  178                 continue;
  179             }
  180             if (ret != BUF_SIZE)
  181                 misreads++;
  182 
  183             if (g_opt_flags & OPT_FLAGS_VERIFY) {
  184                 size_t j;
  185                 off_t o = offsets[i] / BUF_SIZE;
  186 
  187                 for (j = 0; j < BUF_SIZE; j++) {
  188                     uint8_t v = (o + j) & 0xff;
  189                     if (buf[j] != v)
  190                         baddata++;
  191                 }
  192                 if (baddata) {
  193                     pr_fail("error in data between %ju and %ju\n",
  194                         (intmax_t)offsets[i],
  195                         (intmax_t)offsets[i] + BUF_SIZE - 1);
  196                 }
  197             }
  198             inc_counter(args);
  199         }
  200     } while (keep_stressing());
  201 
  202     rc = EXIT_SUCCESS;
  203 close_finish:
  204     (void)close(fd);
  205 finish:
  206     free(buf);
  207     (void)stress_temp_dir_rm_args(args);
  208 
  209     if (misreads)
  210         pr_dbg("%s: %" PRIu64 " incomplete random reads\n",
  211             args->name, misreads);
  212 
  213     return rc;
  214 }
  215 
  216 stressor_info_t stress_readahead_info = {
  217     .stressor = stress_readahead,
  218     .class = CLASS_IO | CLASS_OS
  219 };
  220 #else
  221 stressor_info_t stress_readahead_info = {
  222     .stressor = stress_not_implemented,
  223     .class = CLASS_IO | CLASS_OS
  224 };
  225 #endif