"Fossies" - the Fresh Open Source Software Archive

Member "stress-ng-0.09.56/stress-loop.c" (15 Mar 2019, 5066 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-loop.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_LINUX_LOOP_H) && \
   28     defined(LOOP_CTL_GET_FREE) && \
   29     defined(LOOP_SET_FD) && \
   30     defined(LOOP_CLR_FD) && \
   31     defined(LOOP_CTL_REMOVE)
   32 
   33 /*
   34  *  stress_loot_supported()
   35  *      check if we can run this as root
   36  */
   37 static int stress_loop_supported(void)
   38 {
   39     if (geteuid() != 0) {
   40         pr_inf("loop stressor will be skipped, "
   41             "need to be running as root for this stressor\n");
   42         return -1;
   43     }
   44     return 0;
   45 }
   46 
   47 /*
   48  *  stress_loop()
   49  *  stress loopback device
   50  */
   51 static int stress_loop(const args_t *args)
   52 {
   53     int ret, backing_fd, rc = EXIT_FAILURE;
   54     char backing_file[PATH_MAX];
   55     size_t backing_size = 2 * MB;
   56 
   57     ret = stress_temp_dir_mk_args(args);
   58     if (ret < 0)
   59         return exit_status(-ret);
   60 
   61     (void)stress_temp_filename_args(args,
   62         backing_file, sizeof(backing_file), mwc32());
   63 
   64     if ((backing_fd = open(backing_file, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR)) < 0) {
   65         pr_fail_err("open");
   66         goto tidy;
   67     }
   68     if (ftruncate(backing_fd, backing_size) < 0) {
   69         pr_fail_err("ftruncate");
   70         (void)close(backing_fd);
   71         goto tidy;
   72     }
   73     (void)unlink(backing_file);
   74 
   75     do {
   76         int ctrl_dev, loop_dev;
   77         int i;
   78         long dev_num;
   79         char dev_name[PATH_MAX];
   80         struct loop_info info;
   81 
   82         /*
   83          *  Open loop control device
   84          */
   85         ctrl_dev = open("/dev/loop-control", O_RDWR);
   86         if (ctrl_dev < 0) {
   87             pr_fail("%s: cannot open /dev/loop-control: %d (%s)\n",
   88                 args->name, errno, strerror(errno));
   89             break;
   90         }
   91 
   92         /*
   93          *  Attempt to get a free loop device
   94          */
   95         dev_num = ioctl(ctrl_dev, LOOP_CTL_GET_FREE);
   96         if (dev_num < 0)
   97             goto next;
   98 
   99         /*
  100          *  Open new loop device
  101          */
  102         (void)snprintf(dev_name, sizeof(dev_name), "/dev/loop%ld", dev_num);
  103         loop_dev = open(dev_name, O_RDWR);
  104         if (loop_dev < 0)
  105             goto destroy_loop;
  106 
  107         /*
  108          *  Associate loop device with backing storage
  109          */
  110         ret = ioctl(loop_dev, LOOP_SET_FD, backing_fd);
  111         if (ret < 0)
  112             goto close_loop;
  113 
  114 #if defined(LOOP_GET_STATUS)
  115         /*
  116          *  Fetch loop device status information
  117          */
  118         ret = ioctl(loop_dev, LOOP_GET_STATUS, &info);
  119         if (ret < 0)
  120             goto clr_loop;
  121 
  122         /*
  123          *  Try to set some flags
  124          */
  125         info.lo_flags |= (LO_FLAGS_AUTOCLEAR | LO_FLAGS_READ_ONLY);
  126 #if defined(LOOP_SET_STATUS)
  127         ret = ioctl(loop_dev, LOOP_SET_STATUS, &info);
  128         (void)ret;
  129 #endif
  130 #endif
  131 
  132 #if defined(LOOP_SET_CAPACITY)
  133         /*
  134          *  Resize command (even though we have not changed size)
  135          */
  136         ret = ftruncate(backing_fd, backing_size * 2);
  137         (void)ret;
  138         ret = ioctl(loop_dev, LOOP_SET_CAPACITY);
  139         (void)ret;
  140 #endif
  141 
  142 #if defined(LOOP_GET_STATUS)
  143 clr_loop:
  144 #endif
  145         /*
  146          *  Disassociate backing store from loop device
  147          */
  148         for (i = 0; i < 1000; i++) {
  149             ret = ioctl(loop_dev, LOOP_CLR_FD, backing_fd);
  150             if (ret < 0) {
  151                 if (errno == EBUSY) {
  152                     (void)shim_usleep(10);
  153                 } else {
  154                     pr_fail("%s: failed to disassociate %s from backing store, "
  155                         "errno=%d (%s)\n",
  156                         args->name, dev_name, errno, strerror(errno));
  157                     goto close_loop;
  158                 }
  159             } else {
  160                 break;
  161             }
  162         }
  163 close_loop:
  164         (void)close(loop_dev);
  165 
  166         /*
  167          *  Remove the loop device, may need several retries
  168          *  if we get EBUSY
  169          */
  170 destroy_loop:
  171         for (i = 0; i < 1000; i++) {
  172             ret = ioctl(ctrl_dev, LOOP_CTL_REMOVE, dev_num);
  173             if ((ret < 0) && (errno == EBUSY)) {
  174                 (void)shim_usleep(10);
  175             } else {
  176                 break;
  177             }
  178         }
  179 next:
  180         (void)close(ctrl_dev);
  181 #if defined(LOOP_SET_CAPACITY)
  182         ret = ftruncate(backing_fd, backing_size);
  183         (void)ret;
  184 #endif
  185 
  186         inc_counter(args);
  187     } while (keep_stressing());
  188 
  189     rc = EXIT_SUCCESS;
  190     (void)close(backing_fd);
  191 tidy:
  192     (void)stress_temp_dir_rm_args(args);
  193 
  194     return rc;
  195 }
  196 
  197 stressor_info_t stress_loop_info = {
  198     .stressor = stress_loop,
  199     .supported = stress_loop_supported,
  200     .class = CLASS_OS | CLASS_DEV,
  201 };
  202 #else
  203 
  204 static int stress_loop_supported(void)
  205 {
  206         pr_inf("loop stressor will be skipped, loop is not available\n");
  207         return -1;
  208 }
  209 
  210 stressor_info_t stress_loop_info = {
  211     .stressor = stress_not_implemented,
  212     .supported = stress_loop_supported,
  213     .class = CLASS_OS | CLASS_DEV,
  214 };
  215 #endif