"Fossies" - the Fresh Open Source Software Archive

Member "stress-ng-0.09.56/stress-getdent.c" (15 Mar 2019, 5799 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-getdent.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 #if defined(HAVE_GETDENTS64) || defined(HAVE_GETDENTS)
   28 
   29 #define BUF_SIZE    (256 * 1024)
   30 
   31 typedef int (getdents_func)(
   32     const args_t *args,
   33     const char *path,
   34     const bool recurse,
   35     const int depth,
   36     const size_t page_size);
   37 
   38 #if defined(HAVE_GETDENTS)
   39 static getdents_func stress_getdents_dir;
   40 #endif
   41 #if defined(HAVE_GETDENTS64)
   42 static getdents_func stress_getdents64_dir;
   43 #endif
   44 
   45 static getdents_func * getdents_funcs[] = {
   46 #if defined(HAVE_GETDENTS)
   47     stress_getdents_dir,
   48 #endif
   49 #if defined(HAVE_GETDENTS64)
   50     stress_getdents64_dir,
   51 #endif
   52 };
   53 
   54 static inline int stress_getdents_rand(
   55     const args_t *args,
   56     const char *path,
   57     const bool recurse,
   58     const int depth,
   59     const size_t page_size)
   60 {
   61     int ret = -ENOSYS;
   62     const size_t n = SIZEOF_ARRAY(getdents_funcs);
   63     size_t i, j = mwc32() % n;
   64 
   65     for (i = 0; i < n; i++) {
   66         getdents_func *func = getdents_funcs[j];
   67 
   68         if (func) {
   69             ret = func(args, path, recurse, depth, page_size);
   70             if (ret == -ENOSYS)
   71                 getdents_funcs[j] = NULL;
   72             else
   73                 return ret;
   74         }
   75         j++;
   76         j = j % n;
   77     }
   78     pr_fail("%s: getdents: errno=%d (%s)\n",
   79         args->name, -ret, strerror(-ret));
   80 
   81     return ret;
   82 }
   83 
   84 #if defined(HAVE_GETDENTS)
   85 /*
   86  *  stress_getdents_dir()
   87  *  read directory via the old 32 bit interface
   88  */
   89 static int stress_getdents_dir(
   90     const args_t *args,
   91     const char *path,
   92     const bool recurse,
   93     const int depth,
   94     const size_t page_size)
   95 {
   96     int fd, rc = 0;
   97     char *buf;
   98     size_t buf_sz;
   99 
  100     if (!keep_stressing())
  101         return 0;
  102 
  103     fd = open(path, O_RDONLY | O_DIRECTORY);
  104     if (fd < 0)
  105         return 0;
  106 
  107     buf_sz = ((mwc32() % BUF_SIZE) + page_size) & ~(page_size - 1);
  108     buf = malloc(buf_sz);
  109     if (!buf)
  110         goto exit_close;
  111 
  112     do {
  113         int nread;
  114         char *ptr = buf;
  115 
  116         nread = shim_getdents(fd, (struct shim_linux_dirent *)buf, buf_sz);
  117         if (nread < 0) {
  118             rc = -errno;
  119             goto exit_free;
  120         }
  121         if (nread == 0)
  122             break;
  123 
  124         inc_counter(args);
  125 
  126         if (!recurse || depth < 1)
  127             continue;
  128 
  129         while (ptr < buf + nread) {
  130             struct shim_linux_dirent *d = (struct shim_linux_dirent *)ptr;
  131             unsigned char d_type = *(ptr + d->d_reclen - 1);
  132 
  133             if (d_type == DT_DIR &&
  134                 stress_is_dot_filename(d->d_name)) {
  135                 char newpath[PATH_MAX];
  136 
  137                 (void)snprintf(newpath, sizeof(newpath), "%s/%s", path, d->d_name);
  138                 rc = stress_getdents_rand(args, newpath, recurse, depth - 1, page_size);
  139                 if (rc < 0)
  140                     goto exit_free;
  141             }
  142             ptr += d->d_reclen;
  143         }
  144     } while (keep_stressing());
  145 exit_free:
  146     free(buf);
  147 exit_close:
  148     (void)close(fd);
  149 
  150     return rc;
  151 }
  152 #endif
  153 
  154 #if defined(HAVE_GETDENTS64)
  155 /*
  156  *  stress_getdents64_dir()
  157  *  read directory via the 64 bit interface
  158  */
  159 static int stress_getdents64_dir(
  160     const args_t *args,
  161     const char *path,
  162     const bool recurse,
  163     const int depth,
  164     const size_t page_size)
  165 {
  166     int fd, rc = 0;
  167     char *buf;
  168     size_t buf_sz;
  169 
  170     if (!keep_stressing())
  171         return 0;
  172 
  173     fd = open(path, O_RDONLY | O_DIRECTORY);
  174     if (fd < 0)
  175         return 0;
  176 
  177     buf_sz = ((mwc32() % BUF_SIZE) + page_size) & ~(page_size - 1);
  178     buf = malloc(buf_sz);
  179     if (!buf)
  180         goto exit_close;
  181 
  182     do {
  183         int nread;
  184         char *ptr = buf;
  185 
  186         nread = shim_getdents64(fd, (struct shim_linux_dirent64 *)buf, buf_sz);
  187         if (nread < 0) {
  188             rc = -errno;
  189             goto exit_free;
  190         }
  191         if (nread == 0)
  192             break;
  193 
  194         inc_counter(args);
  195 
  196         if (!recurse || depth < 1)
  197             continue;
  198 
  199         while (ptr < buf + nread) {
  200             struct shim_linux_dirent64 *d = (struct shim_linux_dirent64 *)ptr;
  201 
  202             if (d->d_type == DT_DIR &&
  203                 stress_is_dot_filename(d->d_name)) {
  204                 char newpath[PATH_MAX];
  205 
  206                 (void)snprintf(newpath, sizeof(newpath), "%s/%s", path, d->d_name);
  207                 rc = stress_getdents_rand(args, newpath, recurse, depth - 1, page_size);
  208                 if (rc < 0)
  209                     goto exit_free;
  210             }
  211             ptr += d->d_reclen;
  212         }
  213     } while (keep_stressing());
  214 exit_free:
  215     free(buf);
  216 exit_close:
  217     (void)close(fd);
  218 
  219     return rc;
  220 }
  221 #endif
  222 
  223 /*
  224  *  stress_getdent
  225  *  stress reading directories
  226  */
  227 static int stress_getdent(const args_t *args)
  228 {
  229     const size_t page_size = args->page_size;
  230 
  231     do {
  232         int ret;
  233 
  234         ret = stress_getdents_rand(args, "/proc", true, 8, page_size);
  235         if (ret == -ENOSYS)
  236             break;
  237         ret = stress_getdents_rand(args, "/dev", true, 1, page_size);
  238         if (ret == -ENOSYS)
  239             break;
  240         ret = stress_getdents_rand(args, "/tmp", true, 4, page_size);
  241         if (ret == -ENOSYS)
  242             break;
  243         ret = stress_getdents_rand(args, "/sys", true, 8, page_size);
  244         if (ret == -ENOSYS)
  245             break;
  246         ret = stress_getdents_rand(args, "/run", true, 2, page_size);
  247         if (ret == -ENOSYS)
  248             break;
  249     } while (keep_stressing());
  250 
  251     return EXIT_SUCCESS;
  252 }
  253 
  254 stressor_info_t stress_getdent_info = {
  255     .stressor = stress_getdent,
  256     .class = CLASS_FILESYSTEM | CLASS_OS
  257 };
  258 #else
  259 stressor_info_t stress_getdent_info = {
  260     .stressor = stress_not_implemented,
  261     .class = CLASS_FILESYSTEM | CLASS_OS
  262 };
  263 #endif