"Fossies" - the Fresh Open Source Software Archive

Member "stress-ng-0.09.56/stress-rawdev.c" (15 Mar 2019, 9874 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-rawdev.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 typedef void (*rawdev_func)(const args_t *args, const int fd,
   28                unsigned long blks, unsigned long blksz);
   29 
   30 #define MIN_BLKSZ   ((int)512)
   31 #define MAX_BLKSZ   ((int)(128 * KB))
   32 
   33 typedef struct {
   34     const char              *name;
   35     const rawdev_func       func;
   36 } stress_rawdev_method_info_t;
   37 
   38 #if defined(HAVE_SYS_SYSMACROS_H) &&    \
   39     defined(BLKGETSIZE) &&      \
   40     defined(BLKSSZGET)
   41 
   42 /*
   43  *  stress_rawdev_supported()
   44  *      check if we can run this as root
   45  */
   46 static int stress_rawdev_supported(void)
   47 {
   48     if (geteuid() != 0) {
   49         pr_inf("rawdev flood stressor will be skipped, "
   50             "need to be running as root for this stressor\n");
   51         return -1;
   52     }
   53     return 0;
   54 }
   55 
   56 static inline unsigned long shift_ul(unsigned long v, unsigned int shift)
   57 {
   58     v >>= shift;
   59     return (v == 0) ? 1 : v;
   60 }
   61 
   62 static char *stress_rawdev_path(const dev_t dev)
   63 {
   64     static char path[PATH_MAX];
   65     DIR *dir;
   66     struct dirent *d;
   67     const dev_t majdev = makedev(major(dev), 0);
   68 
   69     dir = opendir("/dev");
   70     if (!dir)
   71         return NULL;
   72 
   73     while ((d = readdir(dir)) != NULL) {
   74         int ret;
   75         struct stat stat_buf;
   76 
   77         (void)snprintf(path, sizeof(path), "/dev/%s", d->d_name);
   78         ret = stat(path, &stat_buf);
   79         if ((ret == 0) &&
   80             (S_ISBLK(stat_buf.st_mode)) &&
   81             (stat_buf.st_rdev == majdev)) {
   82             (void)closedir(dir);
   83             return path;
   84         }
   85     }
   86     (void)closedir(dir);
   87 
   88     return NULL;
   89 }
   90 
   91 static void stress_rawdev_sweep(
   92     const args_t *args,
   93     const int fd,
   94     unsigned long blks,
   95     unsigned long blksz)
   96 {
   97     unsigned long i;
   98     int ret;
   99     char buf[blksz << 1];
  100     char *aligned = stress_align_address(buf, blksz);
  101     off_t offset;
  102 
  103     for (i = 0; i < blks && keep_stressing(); i += shift_ul(blks, 8)) {
  104         offset = (off_t)i * (off_t)blksz;
  105         ret = pread(fd, aligned, (size_t)blksz, offset);
  106         if (ret < 0) {
  107             pr_err("%s: pread at %ju failed, errno=%d (%s)\n",
  108                 args->name, (intmax_t)offset, errno, strerror(errno));
  109         }
  110         inc_counter(args);
  111     }
  112     for (; i > 0 && keep_stressing(); i -= shift_ul(blks, 8)) {
  113         offset = (off_t)i * (off_t)blksz;
  114         ret = pread(fd, aligned, (size_t)blksz, offset);
  115         if (ret < 0) {
  116             pr_err("%s: pread at %ju failed, errno=%d (%s)\n",
  117                 args->name, (intmax_t)offset, errno, strerror(errno));
  118         }
  119         inc_counter(args);
  120     }
  121 }
  122 
  123 static void stress_rawdev_wiggle(
  124     const args_t *args,
  125     const int fd,
  126     unsigned long blks,
  127     unsigned long blksz)
  128 {
  129     unsigned long i;
  130     int ret;
  131     char buf[blksz << 1];
  132     char *aligned = stress_align_address(buf, blksz);
  133     off_t offset;
  134 
  135     for (i = shift_ul(blks, 8); i < blks && keep_stressing(); i += shift_ul(blks, 8)) {
  136         unsigned long j;
  137 
  138         for (j = 0; j < shift_ul(blks, 8) && keep_stressing(); j += shift_ul(blks, 10)) {
  139             offset = (off_t)(i - j) * (off_t)blksz;
  140             ret = pread(fd, aligned, (size_t)blksz, offset);
  141             if (ret < 0) {
  142                 pr_err("%s: pread at %ju failed, errno=%d (%s)\n",
  143                     args->name, (intmax_t)offset, errno, strerror(errno));
  144             }
  145             inc_counter(args);
  146         }
  147     }
  148 }
  149 
  150 static void stress_rawdev_ends(
  151     const args_t *args,
  152     const int fd,
  153     unsigned long blks,
  154     unsigned long blksz)
  155 {
  156     unsigned long i;
  157     char buf[blksz << 1];
  158     char *aligned = stress_align_address(buf, blksz);
  159     off_t offset;
  160 
  161     for (i = 0; i < 128; i++) {
  162         int ret;
  163 
  164         offset = (off_t)i * (off_t)blksz;
  165         ret = pread(fd, aligned, (size_t)blksz, offset);
  166         if (ret < 0) {
  167             pr_err("%s: pread at %ju failed, errno=%d (%s)\n",
  168                 args->name, (intmax_t)offset, errno, strerror(errno));
  169         }
  170         inc_counter(args);
  171 
  172         offset = (off_t)(blks - (i + 1)) * (off_t)blksz;
  173         ret = pread(fd, aligned, (size_t)blksz, offset);
  174         if (ret < 0) {
  175             pr_err("%s: pread at %ju failed, errno=%d (%s)\n",
  176                 args->name, (intmax_t)offset, errno, strerror(errno));
  177         }
  178         inc_counter(args);
  179     }
  180 }
  181 
  182 static void stress_rawdev_random(
  183     const args_t *args,
  184     const int fd,
  185     unsigned long blks,
  186     unsigned long blksz)
  187 {
  188     int i;
  189     char buf[blksz << 1];
  190     char *aligned = stress_align_address(buf, blksz);
  191 
  192     for (i = 0; i < 256 && keep_stressing(); i++) {
  193         int ret;
  194         off_t offset = (off_t)blksz * (mwc64() % blks);
  195 
  196         ret = pread(fd, aligned, (size_t)blksz, offset);
  197         if (ret < 0) {
  198             pr_err("%s: pread at %ju failed, errno=%d (%s)\n",
  199                 args->name, (intmax_t)offset, errno, strerror(errno));
  200         }
  201         inc_counter(args);
  202     }
  203 }
  204 
  205 static void stress_rawdev_burst(
  206     const args_t *args,
  207     const int fd,
  208     unsigned long blks,
  209     unsigned long blksz)
  210 {
  211     int i;
  212     char buf[blksz << 1];
  213     char *aligned = stress_align_address(buf, blksz);
  214     off_t blk = (mwc64() % blks);
  215 
  216     for (i = 0; i < 256 && keep_stressing(); i++) {
  217         int ret;
  218         off_t offset = blk * blksz;
  219 
  220         ret = pread(fd, aligned, (size_t)blksz, offset);
  221         if (ret < 0) {
  222             pr_err("%s: pread at %ju failed, errno=%d (%s)\n",
  223                 args->name, (intmax_t)offset, errno, strerror(errno));
  224         }
  225         blk++;
  226         blk %= blks;
  227         inc_counter(args);
  228     }
  229 }
  230 
  231 static const stress_rawdev_method_info_t rawdev_methods[];
  232 
  233 /*
  234  *  stress_rawdev_all()
  235  *      iterate over all rawdev methods
  236  */
  237 static void stress_rawdev_all(
  238     const args_t *args,
  239     const int fd,
  240     unsigned long blks,
  241     unsigned long blksz)
  242 {
  243     static int i = 1;       /* Skip over stress_rawdev_all */
  244 
  245     rawdev_methods[i++].func(args, fd, blks, blksz);
  246     if (!rawdev_methods[i].func)
  247         i = 1;
  248 }
  249 
  250 
  251 /*
  252  *  rawdev methods
  253  */
  254 static const stress_rawdev_method_info_t rawdev_methods[] = {
  255     { "all",    stress_rawdev_all },
  256     { "sweep",  stress_rawdev_sweep },
  257     { "wiggle", stress_rawdev_wiggle },
  258     { "ends",   stress_rawdev_ends },
  259     { "random", stress_rawdev_random },
  260     { "burst",  stress_rawdev_burst },
  261     { NULL,         NULL }
  262 };
  263 
  264 #endif
  265 
  266 #if defined(HAVE_SYS_SYSMACROS_H) &&    \
  267     defined(BLKGETSIZE) &&      \
  268     defined(BLKSSZGET)
  269 /*
  270  *  stress_set_rawdev_method()
  271  *  set the default rawdev method
  272  */
  273 int stress_set_rawdev_method(const char *name)
  274 {
  275     stress_rawdev_method_info_t const *info;
  276 
  277     for (info = rawdev_methods; info->func; info++) {
  278         if (!strcmp(info->name, name)) {
  279             set_setting("rawdev-method", TYPE_ID_UINTPTR_T, &info);
  280             return 0;
  281         }
  282     }
  283 
  284     (void)fprintf(stderr, "rawdev-method must be one of:");
  285     for (info = rawdev_methods; info->func; info++) {
  286         (void)fprintf(stderr, " %s", info->name);
  287     }
  288     (void)fprintf(stderr, "\n");
  289 
  290     return -1;
  291 }
  292 #else
  293 /*
  294  *  stress_set_rawdev_method()
  295  *  set the default rawdev method
  296  */
  297 int stress_set_rawdev_method(const char *name)
  298 {
  299     (void)name;
  300 
  301     (void)fprintf(stderr, "option --rawdev-method not supported\n");
  302     return -1;
  303 }
  304 #endif
  305 
  306 #if defined(HAVE_SYS_SYSMACROS_H) &&    \
  307     defined(BLKGETSIZE) &&      \
  308     defined(BLKSSZGET)
  309 
  310 static int stress_rawdev(const args_t *args)
  311 {
  312     int ret;
  313     char path[PATH_MAX], *devpath;
  314     struct stat stat_buf;
  315     int fd;
  316     int blksz = 0;
  317     unsigned long blks;
  318     const stress_rawdev_method_info_t *rawdev_method = &rawdev_methods[0];
  319     rawdev_func func;
  320 
  321     stress_temp_dir_args(args, path, sizeof(path));
  322 
  323     (void)get_setting("rawdev-method", &rawdev_method);
  324     func = rawdev_method->func;
  325 
  326     fd = open(path, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
  327     if (fd < 0) {
  328         ret = exit_status(errno);
  329         pr_err("%s: open failed: %d (%s)\n",
  330             args->name, errno, strerror(errno));
  331         return ret;
  332     }
  333 
  334     ret = fstat(fd, &stat_buf);
  335     if (ret <  0) {
  336         pr_err("%s: cannot stat %s: errno=%d (%s)\n",
  337             args->name, path, errno, strerror(errno));
  338         (void)unlink(path);
  339         (void)close(fd);
  340         return EXIT_FAILURE;
  341     }
  342     (void)unlink(path);
  343     (void)close(fd);
  344 
  345     devpath = stress_rawdev_path(stat_buf.st_dev);
  346     if (!devpath) {
  347         pr_inf("%s: cannot determine raw block device\n",
  348             args->name);
  349         return EXIT_NO_RESOURCE;
  350     }
  351 
  352     fd = open(devpath, O_RDONLY | O_NONBLOCK);
  353     if (fd < 0) {
  354         pr_inf("%s: cannot open raw block device: errno=%d (%s)\n",
  355             args->name, errno, strerror(errno));
  356         return EXIT_NO_RESOURCE;
  357     }
  358     ret = ioctl(fd, BLKGETSIZE, &blks);
  359     if (ret < 0) {
  360         pr_inf("%s: cannot get block size: errno=%d (%s)\n",
  361             args->name, errno, strerror(errno));
  362         (void)close(fd);
  363         return EXIT_NO_RESOURCE;
  364     }
  365     ret = ioctl(fd, BLKSSZGET, &blksz);
  366     if (ret < 0) {
  367         pr_inf("%s: cannot get block size: errno=%d (%s)\n",
  368             args->name, errno, strerror(errno));
  369         (void)close(fd);
  370         return EXIT_NO_RESOURCE;
  371     }
  372     /* Truncate if blksize looks too big */
  373     if (blksz > MAX_BLKSZ)
  374         blksz = MAX_BLKSZ;
  375     if (blksz < MIN_BLKSZ)
  376         blksz = MIN_BLKSZ;
  377 
  378     (void)close(fd);
  379     fd = open(devpath, O_RDONLY | O_DIRECT);
  380     if (fd < 0) {
  381         pr_inf("%s: cannot open raw block device: errno=%d (%s)\n",
  382             args->name, errno, strerror(errno));
  383         return EXIT_NO_RESOURCE;
  384     }
  385 
  386     if (args->instance == 0)
  387         pr_dbg("%s: exercising %s (%lu blocks of size %d bytes)\n",
  388             args->name, devpath, blks, blksz);
  389 
  390     do {
  391         func(args, fd, blks, (unsigned long)blksz);
  392     } while (keep_stressing());
  393 
  394     (void)close(fd);
  395 
  396     return EXIT_SUCCESS;
  397 }
  398 
  399 stressor_info_t stress_rawdev_info = {
  400     .stressor = stress_rawdev,
  401     .supported = stress_rawdev_supported,
  402     .class = CLASS_IO
  403 };
  404 #else
  405 stressor_info_t stress_rawdev_info = {
  406     .stressor = stress_not_implemented,
  407     .class = CLASS_IO
  408 };
  409 #endif