"Fossies" - the Fresh Open Source Software Archive

Member "stress-ng-0.09.56/stress-dentry.c" (15 Mar 2019, 7021 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-dentry.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 #define ORDER_FORWARD   0x00
   28 #define ORDER_REVERSE   0x01
   29 #define ORDER_STRIDE    0x02
   30 #define ORDER_RANDOM    0x03
   31 #define ORDER_NONE  0x04
   32 
   33 typedef struct {
   34     const char *name;
   35     const uint8_t denty_order;
   36 } dentry_removal_t;
   37 
   38 static const dentry_removal_t dentry_removals[] = {
   39     { "forward",    ORDER_FORWARD },
   40     { "reverse",    ORDER_REVERSE },
   41     { "stride", ORDER_STRIDE },
   42     { "random", ORDER_RANDOM },
   43     { NULL,     ORDER_NONE },
   44 };
   45 
   46 int stress_set_dentries(const char *opt)
   47 {
   48     uint64_t dentries;
   49 
   50     dentries = get_uint64(opt);
   51     check_range("dentries", dentries,
   52         MIN_DENTRIES, MAX_DENTRIES);
   53     return set_setting("dentries", TYPE_ID_UINT64, &dentries);
   54 }
   55 
   56 /*
   57  *  stress_set_dentry_order()
   58  *  set dentry ordering from give option
   59  */
   60 int stress_set_dentry_order(const char *opt)
   61 {
   62     const dentry_removal_t *dr;
   63 
   64     for (dr = dentry_removals; dr->name; dr++) {
   65         if (!strcmp(dr->name, opt)) {
   66             uint8_t dentry_order = dr->denty_order;
   67 
   68             set_setting("dentry-order",
   69                 TYPE_ID_UINT8, &dentry_order);
   70             return 0;
   71         }
   72     }
   73 
   74     (void)fprintf(stderr, "dentry-order must be one of:");
   75     for (dr = dentry_removals; dr->name; dr++) {
   76         (void)fprintf(stderr, " %s", dr->name);
   77     }
   78     (void)fprintf(stderr, "\n");
   79 
   80     return -1;
   81 }
   82 
   83 /*
   84  *  stress_dentry_unlink()
   85  *  remove all dentries
   86  */
   87 static void stress_dentry_unlink(
   88     const args_t *args,
   89     const uint64_t n,
   90     const uint8_t dentry_order)
   91 {
   92     uint64_t i, j;
   93     uint64_t prime;
   94     const uint8_t ord = (dentry_order == ORDER_RANDOM) ?
   95                 mwc32() % 3 : dentry_order;
   96 
   97     switch (ord) {
   98     case ORDER_REVERSE:
   99         for (i = 0; i < n; i++) {
  100             char path[PATH_MAX];
  101             uint64_t gray_code;
  102 
  103             j = (n - 1) - i;
  104             gray_code = (j >> 1) ^ j;
  105 
  106             stress_temp_filename_args(args,
  107                 path, sizeof(path), gray_code * 2);
  108             (void)unlink(path);
  109         }
  110         break;
  111     case ORDER_STRIDE:
  112         prime = stress_get_prime64(n);
  113         for (i = 0, j = prime; i < n; i++, j += prime) {
  114             char path[PATH_MAX];
  115             uint64_t k = j % n;
  116             uint64_t gray_code = (k >> 1) ^ k;
  117 
  118             stress_temp_filename_args(args,
  119                 path, sizeof(path), gray_code * 2);
  120             (void)unlink(path);
  121         }
  122         break;
  123     case ORDER_FORWARD:
  124     default:
  125         for (i = 0; i < n; i++) {
  126             char path[PATH_MAX];
  127             uint64_t gray_code = (i >> 1) ^ i;
  128 
  129             stress_temp_filename_args(args,
  130                 path, sizeof(path), gray_code * 2);
  131             (void)unlink(path);
  132         }
  133         break;
  134     }
  135     (void)sync();
  136 }
  137 
  138 /*
  139  *  stress_dentry_misc()
  140  *  misc ways to exercise a directory file
  141  */
  142 static void stress_dentry_misc(const char *path)
  143 {
  144     int fd, flags = O_RDONLY, ret;
  145     off_t offset;
  146     struct stat statbuf;
  147     struct timeval timeout;
  148     fd_set rdfds;
  149     char buf[1024];
  150 
  151 #if defined(O_DIRECTORY)
  152     flags |= O_DIRECTORY;
  153 #endif
  154 
  155     fd = open(path, flags);
  156     if (fd < 0)
  157         return;
  158 
  159     ret = fstat(fd, &statbuf);
  160     (void)ret;
  161 
  162     /* Not really legal */
  163     offset = lseek(fd, 0, SEEK_END);
  164     (void)offset;
  165 
  166     offset = lseek(fd, 0, SEEK_SET);
  167     (void)offset;
  168 
  169     /* Not allowed */
  170     ret = read(fd, buf, sizeof(buf));
  171     (void)ret;
  172 
  173     FD_ZERO(&rdfds);
  174     FD_SET(fd, &rdfds);
  175     timeout.tv_sec = 0;
  176     timeout.tv_usec = 0;
  177     ret = select(fd + 1, &rdfds, NULL, NULL, &timeout);
  178     (void)ret;
  179 
  180 #if defined(HAVE_FLOCK) && defined(LOCK_EX) && defined(LOCK_UN)
  181     /*
  182      *  flock capable systems..
  183      */
  184     ret = flock(fd, LOCK_EX);
  185     if (ret == 0) {
  186         ret = flock(fd, LOCK_UN);
  187         (void)ret;
  188     }
  189 #elif defined(F_SETLKW) && defined(F_RDLCK) && defined(F_UNLCK)
  190     /*
  191      *  ..otherwise fall back to fcntl (e.g. Solaris)
  192      */
  193     {
  194         struct flock lock;
  195 
  196         lock.l_start = 0;
  197         lock.l_len = 0;
  198         lock.l_whence = SEEK_SET;
  199         lock.l_type = F_RDLCK;
  200         ret = fcntl(fd, F_SETLKW, &lock);
  201         if (ret == 0) {
  202             lock.l_start = 0;
  203             lock.l_len = 0;
  204             lock.l_whence = SEEK_SET;
  205             lock.l_type = F_UNLCK;
  206             ret = fcntl(fd, F_SETLKW, &lock);
  207             (void)ret;
  208         }
  209     }
  210 #endif
  211 
  212 #if defined(F_GETFL)
  213     {
  214         int flag;
  215 
  216         ret = fcntl(fd, F_GETFL, &flag);
  217         (void)ret;
  218     }
  219 #endif
  220     (void)close(fd);
  221 
  222 }
  223 
  224 /*
  225  *  stress_dentry
  226  *  stress dentries.  file names are based
  227  *  on a gray-coded value multiplied by two.
  228  *  Even numbered files exist, odd don't exist.
  229  */
  230 static int stress_dentry(const args_t *args)
  231 {
  232     int ret;
  233     uint64_t dentries = DEFAULT_DENTRIES;
  234     uint8_t dentry_order = ORDER_RANDOM;
  235     char dir_path[PATH_MAX];
  236 
  237     if (!get_setting("dentries", &dentries)) {
  238         if (g_opt_flags & OPT_FLAGS_MAXIMIZE)
  239             dentries = MAX_DENTRIES;
  240         if (g_opt_flags & OPT_FLAGS_MINIMIZE)
  241             dentries = MIN_DENTRIES;
  242     }
  243     (void)get_setting("dentry-order", &dentry_order);
  244 
  245     ret = stress_temp_dir_mk_args(args);
  246     if (ret < 0)
  247         return exit_status(-ret);
  248 
  249     (void)stress_temp_dir(dir_path, sizeof(dir_path), args->name, args->pid, args->instance);
  250 
  251     do {
  252         uint64_t i, n = dentries;
  253         char path[PATH_MAX];
  254 
  255         for (i = 0; i < n; i++) {
  256             const uint64_t gray_code = (i >> 1) ^ i;
  257             int fd;
  258 
  259             stress_temp_filename_args(args,
  260                 path, sizeof(path), gray_code * 2);
  261 
  262             if ((fd = open(path, O_CREAT | O_RDWR,
  263                     S_IRUSR | S_IWUSR)) < 0) {
  264                 if (errno != ENOSPC)
  265                     pr_fail_err("open");
  266                 n = i;
  267                 break;
  268             }
  269             (void)close(fd);
  270 
  271             if (!keep_stressing())
  272                 goto abort;
  273 
  274             inc_counter(args);
  275         }
  276 
  277         stress_dentry_misc(dir_path);
  278 
  279         /*
  280          *  Now look up some bogus names to exercise
  281          *  lookup failures
  282          */
  283         for (i = 0; i < n; i++) {
  284             const uint64_t gray_code = (i >> 1) ^ i;
  285             int rc;
  286 
  287             if (!keep_stressing())
  288                 goto abort;
  289 
  290             stress_temp_filename_args(args,
  291                 path, sizeof(path), (gray_code * 2) + 1);
  292 
  293             /* The following should fail, ignore error return */
  294             rc = access(path, R_OK);
  295             (void)rc;
  296         }
  297 
  298         /*
  299          *  And remove
  300          */
  301         stress_dentry_unlink(args, n, dentry_order);
  302         stress_dentry_misc(dir_path);
  303 
  304         if (!g_keep_stressing_flag)
  305             break;
  306         (void)sync();
  307     } while (keep_stressing());
  308 
  309 abort:
  310     /* force unlink of all files */
  311     pr_tidy("%s: removing %" PRIu64 " entries\n",
  312         args->name, dentries);
  313     stress_dentry_unlink(args, dentries, dentry_order);
  314     (void)stress_temp_dir_rm_args(args);
  315 
  316     return EXIT_SUCCESS;
  317 }
  318 
  319 stressor_info_t stress_dentry_info = {
  320     .stressor = stress_dentry,
  321     .class = CLASS_FILESYSTEM | CLASS_OS
  322 };