"Fossies" - the Fresh Open Source Software Archive

Member "stress-ng-0.09.56/stress-aio-linux.c" (15 Mar 2019, 6794 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-aio-linux.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 BUFFER_SZ       (4096)
   28 #define DEFAULT_AIO_MAX_NR  (65536)
   29 
   30 int stress_set_aio_linux_requests(const char *opt)
   31 {
   32     uint64_t aio_linux_requests;
   33 
   34     aio_linux_requests = get_uint32(opt);
   35     check_range("aiol-requests", aio_linux_requests,
   36         MIN_AIO_LINUX_REQUESTS, MAX_AIO_LINUX_REQUESTS);
   37     return set_setting("aiol-requests", TYPE_ID_UINT64, &aio_linux_requests);
   38 }
   39 
   40 #if defined(HAVE_LIB_AIO) &&        \
   41     defined(HAVE_LIBAIO_H) &&       \
   42     defined(HAVE_CLOCK_GETTIME) &&  \
   43     defined(__NR_io_setup) &&       \
   44     defined(__NR_io_destroy) &&     \
   45     defined(__NR_io_submit) &&      \
   46     defined(__NR_io_getevents)
   47 
   48 /*
   49  *  aio_linux_fill_buffer()
   50  *  fill buffer with some known pattern
   51  */
   52 static inline void aio_linux_fill_buffer(
   53     const int request,
   54     uint8_t *const buffer,
   55     const size_t size)
   56 {
   57     register size_t i;
   58 
   59     for (i = 0; i < size; i++)
   60         buffer[i] = (uint8_t)(request + i);
   61 }
   62 
   63 /*
   64  *  stress_aiol
   65  *  stress asynchronous I/O using the linux specific aio ABI
   66  */
   67 static int stress_aiol(const args_t *args)
   68 {
   69     int fd, ret, rc = EXIT_FAILURE;
   70     char filename[PATH_MAX];
   71     char buf[64];
   72     io_context_t ctx = 0;
   73     uint64_t aio_linux_requests = DEFAULT_AIO_LINUX_REQUESTS;
   74     uint8_t *buffer;
   75     uint64_t aio_max_nr = DEFAULT_AIO_MAX_NR;
   76 
   77     if (!get_setting("aiol-requests", &aio_linux_requests)) {
   78         if (g_opt_flags & OPT_FLAGS_MAXIMIZE)
   79             aio_linux_requests = MAX_AIO_REQUESTS;
   80         if (g_opt_flags & OPT_FLAGS_MINIMIZE)
   81             aio_linux_requests = MIN_AIO_REQUESTS;
   82     }
   83     if ((aio_linux_requests < MIN_AIO_REQUESTS) ||
   84         (aio_linux_requests > MAX_AIO_REQUESTS)) {
   85         pr_err("%s: iol_requests out of range", args->name);
   86         return EXIT_FAILURE;
   87     }
   88 
   89     ret = system_read("/proc/sys/fs/aio-max-nr", buf, sizeof(buf));
   90     if (ret > 0) {
   91         if (sscanf(buf, "%" SCNu64, &aio_max_nr) != 1) {
   92             /* Guess max */
   93             aio_max_nr = DEFAULT_AIO_MAX_NR;
   94         }
   95     } else {
   96         /* Guess max */
   97         aio_max_nr = DEFAULT_AIO_MAX_NR;
   98     }
   99 
  100     aio_max_nr /= (args->num_instances == 0) ? 1 : args->num_instances;
  101 
  102     if (aio_max_nr < 1)
  103         aio_max_nr = 1;
  104     if (aio_linux_requests > aio_max_nr) {
  105         aio_linux_requests = aio_max_nr;
  106         if (args->instance == 0)
  107             pr_inf("%s: Limiting AIO requests to "
  108                 "%" PRIu64 " per stressor (avoids running out of resources)\n",
  109                 args->name, aio_linux_requests);
  110     }
  111 
  112     ret = posix_memalign((void **)&buffer, 4096,
  113         aio_linux_requests * BUFFER_SZ);
  114     if (ret) {
  115         pr_inf("%s: Out of memory allocating buffers, errno=%d (%s)",
  116             args->name, errno, strerror(errno));
  117         return EXIT_NO_RESOURCE;
  118     }
  119     ret = io_setup(aio_linux_requests, &ctx);
  120     if (ret < 0) {
  121         /*
  122          *  The libaio interface returns -errno in the
  123          *  return value, so set errno accordingly
  124          */
  125         errno = -ret;
  126         if ((errno == EAGAIN) || (errno == EACCES)) {
  127             pr_err("%s: io_setup failed, ran out of "
  128                 "available events, consider increasing "
  129                 "/proc/sys/fs/aio-max-nr, errno=%d (%s)\n",
  130                 args->name, errno, strerror(errno));
  131             rc = EXIT_NO_RESOURCE;
  132             goto free_buffer;
  133         } else if (errno == ENOMEM) {
  134             pr_err("%s: io_setup failed, ran out of "
  135                 "memory, errno=%d (%s)\n",
  136                 args->name, errno, strerror(errno));
  137             rc = EXIT_NO_RESOURCE;
  138             goto free_buffer;
  139         } else if (errno == ENOSYS) {
  140             pr_err("%s: io_setup failed, no io_setup "
  141                 "system call with this kernel, "
  142                 "errno=%d (%s)\n",
  143                 args->name, errno, strerror(errno));
  144             rc = EXIT_NO_RESOURCE;
  145             goto free_buffer;
  146         } else {
  147             pr_fail_err("io_setup");
  148             rc = EXIT_FAILURE;
  149             goto free_buffer;
  150         }
  151     }
  152     ret = stress_temp_dir_mk_args(args);
  153     if (ret < 0) {
  154         rc = exit_status(-ret);
  155         goto free_buffer;
  156     }
  157 
  158     (void)stress_temp_filename_args(args,
  159         filename, sizeof(filename), mwc32());
  160 
  161     if ((fd = open(filename, O_CREAT | O_RDWR | O_DIRECT, S_IRUSR | S_IWUSR)) < 0) {
  162         rc = exit_status(errno);
  163         pr_fail_err("open");
  164         goto finish;
  165     }
  166     (void)unlink(filename);
  167 
  168     do {
  169         struct iocb cb[aio_linux_requests];
  170         struct iocb *cbs[aio_linux_requests];
  171         struct io_event events[aio_linux_requests];
  172         uint8_t *buffers[aio_linux_requests];
  173         uint8_t *bufptr = buffer;
  174         uint64_t i;
  175         long n;
  176 
  177         for (i = 0; i < aio_linux_requests; i++, bufptr += BUFFER_SZ) {
  178             buffers[i] = bufptr;
  179             aio_linux_fill_buffer(i, buffers[i], BUFFER_SZ);
  180         }
  181 
  182         (void)memset(cb, 0, sizeof(cb));
  183         for (i = 0; i < aio_linux_requests; i++) {
  184             cb[i].aio_fildes = fd;
  185             cb[i].aio_lio_opcode = IO_CMD_PWRITE;
  186             cb[i].u.c.buf = buffers[i];
  187             cb[i].u.c.offset = mwc16() * BUFFER_SZ;
  188             cb[i].u.c.nbytes = BUFFER_SZ;
  189             cbs[i] = &cb[i];
  190         }
  191         ret = io_submit(ctx, (long)aio_linux_requests, cbs);
  192         if (ret < 0) {
  193             errno = -ret;
  194             if (errno == EAGAIN)
  195                 continue;
  196             pr_fail_err("io_submit");
  197             break;
  198         }
  199 
  200         n = aio_linux_requests;
  201         do {
  202             struct timespec timeout, *timeout_ptr;
  203 
  204             if (clock_gettime(CLOCK_REALTIME, &timeout) < 0) {
  205                 timeout_ptr = NULL;
  206             } else {
  207                 timeout.tv_nsec += 1000000;
  208                 if (timeout.tv_nsec > 1000000000) {
  209                     timeout.tv_nsec -= 1000000000;
  210                     timeout.tv_sec++;
  211                 }
  212                 timeout_ptr = &timeout;
  213             }
  214 
  215             ret = io_getevents(ctx, 1, n, events, timeout_ptr);
  216             if (ret < 0) {
  217                 errno = -ret;
  218                 if (errno == EINTR) {
  219                     if (g_keep_stressing_flag)
  220                         continue;
  221                     else
  222                         break;
  223                 }
  224                 pr_fail_err("io_getevents");
  225                 break;
  226             } else {
  227                 n -= ret;
  228             }
  229         } while ((n > 0) && g_keep_stressing_flag);
  230         inc_counter(args);
  231     } while (keep_stressing());
  232 
  233     rc = EXIT_SUCCESS;
  234     (void)close(fd);
  235 finish:
  236     (void)io_destroy(ctx);
  237     (void)stress_temp_dir_rm_args(args);
  238 
  239 free_buffer:
  240     free(buffer);
  241     return rc;
  242 }
  243 
  244 stressor_info_t stress_aiol_info = {
  245     .stressor = stress_aiol,
  246     .class = CLASS_IO | CLASS_INTERRUPT | CLASS_OS
  247 };
  248 #else
  249 stressor_info_t stress_aiol_info = {
  250     .stressor = stress_not_implemented,
  251     .class = CLASS_IO | CLASS_INTERRUPT | CLASS_OS
  252 };
  253 #endif