"Fossies" - the Fresh Open Source Software Archive

Member "stress-ng-0.09.56/stress-inotify.c" (15 Mar 2019, 18666 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-inotify.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) 2012-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  * stress-inotify.c is derived from the eCryptfs inotify tests
   25  * that I authored in 2012.
   26  */
   27 #include "stress-ng.h"
   28 
   29 #if defined(HAVE_INOTIFY) &&        \
   30     defined(HAVE_SYS_INOTIFY_H) &&  \
   31     defined(HAVE_SYS_SELECT_H) &&   \
   32     NEED_GLIBC(2,9,0)
   33 
   34 #define DIR_FLAGS   (S_IRWXU | S_IRWXG)
   35 #define FILE_FLAGS  (S_IRUSR | S_IWUSR)
   36 
   37 #define TIME_OUT    (10)    /* Secs for inotify to report back */
   38 #define BUF_SIZE    (4096)
   39 
   40 typedef int (*inotify_helper)(const args_t *args, const char *path, const void *private);
   41 typedef void (*inotify_func)(const args_t *args, const char *path);
   42 
   43 typedef struct {
   44     const inotify_func func;
   45     const char* description;
   46 } inotify_stress_t;
   47 
   48 /*
   49  *  inotify_exercise()
   50  *  run a given test helper function 'func' and see if this triggers the
   51  *  required inotify event flags 'flags'.
   52  */
   53 static void inotify_exercise(
   54     const args_t *args, /* Stressor args */
   55     const char *filename,   /* Filename in test */
   56     const char *watchname,  /* File or directory to watch using inotify */
   57     const char *matchname,  /* Filename we expect inotify event to report */
   58     const inotify_helper func,  /* Helper func */
   59     const int flags,    /* IN_* flags to watch for */
   60     void *private)      /* Helper func private data */
   61 {
   62     int fd, wd, check_flags = flags, n = 0;
   63     char buffer[1024];
   64 retry:
   65     n++;
   66     if ((fd = inotify_init()) < 0) {
   67         if (!g_keep_stressing_flag)
   68             return;
   69 
   70         /* This is just so wrong... */
   71         if (n < 10000 && errno == EMFILE) {
   72             /*
   73              * inotify cleanup may be still running from a previous
   74              * iteration, in which case we've run out of resources
   75              * temporarily, so sleep a short while and retry.
   76              */
   77             (void)shim_usleep(10000);
   78             goto retry;
   79         }
   80         /* Nope, give up */
   81         pr_fail("%s: inotify_init failed: errno=%d (%s) after %" PRIu32 " calls\n",
   82             args->name, errno, strerror(errno), n);
   83         return;
   84     }
   85 
   86     if ((wd = inotify_add_watch(fd, watchname, flags)) < 0) {
   87         (void)close(fd);
   88         pr_fail_err("inotify_add_watch");
   89         return;
   90     }
   91 
   92     if (func(args, filename, private) < 0)
   93         goto cleanup;
   94 
   95     while (check_flags) {
   96         ssize_t len, i = 0;
   97         struct timeval tv;
   98         fd_set rfds;
   99         int err, nbytes;
  100 
  101         /* We give inotify TIME_OUT seconds to report back */
  102         tv.tv_sec = TIME_OUT;
  103         tv.tv_usec = 0;
  104 
  105         FD_ZERO(&rfds);
  106         FD_SET(fd, &rfds);
  107 
  108         /* Wait for an inotify event ... */
  109         err = select(fd + 1, &rfds, NULL, NULL, &tv);
  110         if (err == -1) {
  111             if (errno != EINTR)
  112                 pr_err("%s: select error: errno=%d (%s)\n",
  113                     args->name, errno, strerror(errno));
  114             break;
  115         } else if (err == 0) {
  116             if (g_opt_flags & OPT_FLAGS_VERIFY)
  117                 pr_fail("%s: timed waiting for event flags 0x%x\n", args->name, flags);
  118             break;
  119         }
  120 
  121 redo:
  122         if (!g_keep_stressing_flag)
  123             break;
  124         /*
  125          *  Exercise FIOREAD to get inotify code coverage up
  126          */
  127         if (ioctl(fd, FIONREAD, &nbytes) < 0) {
  128             if (g_opt_flags & OPT_FLAGS_VERIFY) {
  129                 pr_fail("%s: data is ready, but ioctl FIONREAD failed\n", args->name);
  130                 break;
  131             }
  132         }
  133         if (nbytes <= 0) {
  134             pr_fail("%s: data is ready, but ioctl FIONREAD "
  135                 "reported %d bytes available\n", args->name, nbytes);
  136             break;
  137         }
  138 
  139         len = read(fd, buffer, sizeof(buffer));
  140 
  141         if ((len <= 0) || (len > (ssize_t)sizeof(buffer))) {
  142             if ((errno == EAGAIN) || (errno == EINTR))
  143                 goto redo;
  144             if (errno) {
  145                 pr_fail_err("error reading inotify");
  146                 break;
  147             }
  148         }
  149 
  150         /* Scan through inotify events */
  151         while ((i >= 0) && (i <= len - (ssize_t)sizeof(struct inotify_event))) {
  152             struct inotify_event *event =
  153                 (struct inotify_event *)&buffer[i];
  154             int f = event->mask & (IN_DELETE_SELF | IN_MOVE_SELF |
  155                            IN_MOVED_TO | IN_MOVED_FROM |
  156                            IN_ATTRIB);
  157             if (event->len &&
  158                 strcmp(event->name, matchname) == 0 &&
  159                 flags & event->mask)
  160                 check_flags &= ~(flags & event->mask);
  161             else if (flags & f)
  162                 check_flags &= ~(flags & event->mask);
  163 
  164             i += sizeof(struct inotify_event) + event->len;
  165         }
  166     }
  167 
  168 cleanup:
  169     (void)inotify_rm_watch(fd, wd);
  170     if (close(fd) < 0) {
  171         pr_err("%s: close error: errno=%d (%s)\n",
  172             args->name, errno, strerror(errno));
  173     }
  174 }
  175 
  176 /*
  177  *  rm_file()
  178  *  remove a file
  179  */
  180 static int rm_file(const args_t *args, const char *path)
  181 {
  182     if ((unlink(path) < 0) && errno != ENOENT) {
  183         pr_err("%s: cannot remove file %s: errno=%d (%s)\n",
  184             args->name, path, errno, strerror(errno));
  185         return -1;
  186     }
  187     return 0;
  188 }
  189 
  190 /*
  191  *  rm_dir()
  192  *  clean files in directory and directory
  193  */
  194 static int rm_dir(const args_t *args, const char *path)
  195 {
  196     DIR *dp;
  197     int ret;
  198 
  199     dp = opendir(path);
  200     if (dp != NULL) {
  201         struct dirent *d;
  202 
  203         while ((d = readdir(dp)) != NULL) {
  204             char filename[PATH_MAX];
  205 
  206             if (stress_is_dot_filename(d->d_name))
  207                 continue;
  208             (void)snprintf(filename, sizeof(filename), "%s/%s",
  209                 path, d->d_name);
  210             (void)rm_file(args, filename);
  211         }
  212         (void)closedir(dp);
  213     }
  214     ret = rmdir(path);
  215     if (ret < 0 && errno != ENOENT)
  216         pr_err("%s: cannot remove directory %s: errno=%d (%s)\n",
  217             args->name, path, errno, strerror(errno));
  218     return ret;
  219 }
  220 
  221 /*
  222  *  mk_dir()
  223  *  make a directory
  224  */
  225 static int mk_dir(const args_t *args, const char *path)
  226 {
  227     if (mkdir(path, DIR_FLAGS) < 0) {
  228         pr_err("%s: cannot mkdir %s: errno=%d (%s)\n",
  229             args->name, path, errno, strerror(errno));
  230         return -1;
  231     }
  232     return 0;
  233 }
  234 
  235 /*
  236  *  mk_filename()
  237  *  simple helper to create a filename
  238  */
  239 static inline void mk_filename(
  240     char *filename,
  241     const size_t len,
  242     const char *path,
  243     const char *name)
  244 {
  245     (void)snprintf(filename, len, "%s/%s", path, name);
  246 }
  247 
  248 /*
  249  *  mk_file()
  250  *  create file of length len bytes
  251  */
  252 static int mk_file(const args_t *args, const char *filename, const size_t len)
  253 {
  254     int fd;
  255     size_t sz = len;
  256 
  257     char buffer[BUF_SIZE];
  258 
  259     (void)rm_file(args, filename);
  260     if ((fd = open(filename, O_CREAT | O_RDWR, FILE_FLAGS)) < 0) {
  261         pr_err("%s: cannot create file %s: errno=%d (%s)\n",
  262             args->name, filename, errno, strerror(errno));
  263         return -1;
  264     }
  265 
  266     (void)memset(buffer, 'x', BUF_SIZE);
  267     while (sz > 0) {
  268         size_t n = (sz > BUF_SIZE) ? BUF_SIZE : sz;
  269         int ret;
  270 
  271         if ((ret = write(fd, buffer, n)) < 0) {
  272             pr_err("%s: error writing to file %s: errno=%d (%s)\n",
  273                 args->name, filename, errno, strerror(errno));
  274             (void)close(fd);
  275             return -1;
  276         }
  277         sz -= ret;
  278     }
  279 
  280     if (close(fd) < 0) {
  281         pr_err("%s: cannot close file %s: errno=%d (%s)\n",
  282             args->name, filename, errno, strerror(errno));
  283         return -1;
  284     }
  285     return 0;
  286 }
  287 
  288 #if defined(IN_ATTRIB)
  289 static int inotify_attrib_helper(
  290     const args_t *args,
  291     const char *path,
  292     const void *signum)
  293 {
  294     (void)signum;
  295     if (chmod(path, S_IRUSR | S_IWUSR) < 0) {
  296         pr_err("%s: cannot chmod file %s: errno=%d (%s)\n",
  297             args->name, path, errno, strerror(errno));
  298         return -1;
  299     }
  300     return 0;
  301 }
  302 
  303 static void inotify_attrib_file(const args_t *args, const char *path)
  304 {
  305     char filepath[PATH_MAX];
  306 
  307     mk_filename(filepath, sizeof(filepath), path, "inotify_file");
  308     if (mk_file(args, filepath, 4096) < 0)
  309         return;
  310 
  311     inotify_exercise(args, filepath, path, "inotify_file",
  312         inotify_attrib_helper, IN_ATTRIB, NULL);
  313     (void)rm_file(args, filepath);
  314 }
  315 #endif
  316 
  317 #if defined(IN_ACCESS)
  318 static int inotify_access_helper(
  319     const args_t *args,
  320     const char *path,
  321     const void *signum)
  322 {
  323     int fd;
  324     char buffer[1];
  325     int rc = 0;
  326 
  327     (void)signum;
  328     if ((fd = open(path, O_RDONLY)) < 0) {
  329         pr_err("%s: cannot open file %s: errno=%d (%s)\n",
  330             args->name, path, errno, strerror(errno));
  331         return -1;
  332     }
  333 
  334     /* Just want to force an access */
  335 do_access:
  336     if (g_keep_stressing_flag && (read(fd, buffer, 1) < 0)) {
  337         if ((errno == EAGAIN) || (errno == EINTR))
  338             goto do_access;
  339         pr_err("%s: cannot read file %s: errno=%d (%s)\n",
  340             args->name, path, errno, strerror(errno));
  341         rc = -1;
  342     }
  343     (void)close(fd);
  344     return rc;
  345 }
  346 
  347 static void inotify_access_file(const args_t *args, const char *path)
  348 {
  349     char filepath[PATH_MAX];
  350 
  351     mk_filename(filepath, sizeof(filepath), path, "inotify_file");
  352     if (mk_file(args, filepath, 4096) < 0)
  353         return;
  354 
  355     inotify_exercise(args, filepath, path, "inotify_file",
  356         inotify_access_helper, IN_ACCESS, NULL);
  357     (void)rm_file(args, filepath);
  358 }
  359 #endif
  360 
  361 #if defined(IN_MODIFY)
  362 static int inotify_modify_helper(
  363     const args_t *args,
  364     const char *path,
  365     const void *signum)
  366 {
  367     int fd, rc = 0;
  368     char buffer[1] = { 0 };
  369 
  370     (void)signum;
  371     if (mk_file(args, path, 4096) < 0)
  372         return -1;
  373     if ((fd = open(path, O_RDWR)) < 0) {
  374         pr_err("%s: cannot open file %s: errno=%d (%s)\n",
  375             args->name, path, errno, strerror(errno));
  376         rc = -1;
  377         goto remove;
  378     }
  379 do_modify:
  380     if (g_keep_stressing_flag && (write(fd, buffer, 1) < 0)) {
  381         if ((errno == EAGAIN) || (errno == EINTR))
  382             goto do_modify;
  383         pr_err("%s: cannot write to file %s: errno=%d (%s)\n",
  384             args->name, path, errno, strerror(errno));
  385         rc = -1;
  386     }
  387     (void)close(fd);
  388 remove:
  389     (void)rm_file(args, path);
  390     return rc;
  391 }
  392 
  393 static void inotify_modify_file(const args_t *args, const char *path)
  394 {
  395     char filepath[PATH_MAX];
  396 
  397     mk_filename(filepath, sizeof(filepath), path, "inotify_file");
  398     inotify_exercise(args, filepath, path, "inotify_file",
  399         inotify_modify_helper, IN_MODIFY, NULL);
  400 }
  401 #endif
  402 
  403 #if defined(IN_CREATE)
  404 static int inotify_creat_helper(
  405     const args_t *args,
  406     const char *path,
  407     const void *signum)
  408 {
  409     (void)signum;
  410     int fd;
  411     if ((fd = creat(path, FILE_FLAGS)) < 0) {
  412         pr_err("%s: cannot create file %s: errno=%d (%s)\n",
  413             args->name, path, errno, strerror(errno));
  414         return -1;
  415     }
  416     (void)close(fd);
  417     return 0;
  418 }
  419 
  420 static void inotify_creat_file(const args_t *args, const char *path)
  421 {
  422     char filepath[PATH_MAX];
  423 
  424     mk_filename(filepath, sizeof(filepath), path, "inotify_file");
  425     inotify_exercise(args, filepath, path, "inotify_file",
  426         inotify_creat_helper, IN_CREATE, NULL);
  427     (void)rm_file(args, filepath);
  428 }
  429 #endif
  430 
  431 #if defined(IN_OPEN)
  432 static int inotify_open_helper(
  433     const args_t *args,
  434     const char *path,
  435     const void *signum)
  436 {
  437     int fd;
  438 
  439     (void)signum;
  440     if ((fd = open(path, O_RDONLY)) < 0) {
  441         pr_err("%s: cannot open file %s: errno=%d (%s)\n",
  442             args->name, path, errno, strerror(errno));
  443         return -1;
  444     }
  445     (void)close(fd);
  446     return 0;
  447 }
  448 
  449 static void inotify_open_file(const args_t *args, const char *path)
  450 {
  451     char filepath[PATH_MAX];
  452 
  453     mk_filename(filepath, sizeof(filepath), path, "inotify_file");
  454     if (mk_file(args, filepath, 4096) < 0)
  455         return;
  456     inotify_exercise(args, filepath, path, "inotify_file",
  457         inotify_open_helper, IN_OPEN, NULL);
  458     (void)rm_file(args, filepath);
  459 }
  460 #endif
  461 
  462 #if defined(IN_DELETE)
  463 static int inotify_delete_helper(
  464     const args_t *args,
  465     const char *path,
  466     const void *signum)
  467 {
  468     (void)signum;
  469 
  470     return rm_file(args, path);
  471 }
  472 
  473 static void inotify_delete_file(const args_t *args, const char *path)
  474 {
  475     char filepath[PATH_MAX];
  476 
  477     mk_filename(filepath, sizeof(filepath), path, "inotify_file");
  478     if (mk_file(args, filepath, 4096) < 0)
  479         return;
  480     inotify_exercise(args, filepath, path, "inotify_file",
  481         inotify_delete_helper, IN_DELETE, NULL);
  482     /* We remove (again) it just in case the test failed */
  483     (void)rm_file(args, filepath);
  484 }
  485 #endif
  486 
  487 #if defined(IN_DELETE_SELF)
  488 static int inotify_delete_self_helper(
  489     const args_t *args,
  490     const char *path,
  491     const void *signum)
  492 {
  493     (void)signum;
  494 
  495     return rm_dir(args, path);
  496 }
  497 
  498 static void inotify_delete_self(const args_t *args, const char *path)
  499 {
  500     char filepath[PATH_MAX];
  501 
  502     mk_filename(filepath, sizeof(filepath), path, "inotify_dir");
  503     if (mk_dir(args, filepath) < 0)
  504         return;
  505     inotify_exercise(args, filepath, filepath, "inotify_dir",
  506         inotify_delete_self_helper, IN_DELETE_SELF, NULL);
  507     /* We remove (again) in case the test failed */
  508     (void)rm_dir(args, filepath);
  509 }
  510 #endif
  511 
  512 #if defined(IN_MOVE_SELF)
  513 static int inotify_move_self_helper(
  514     const args_t *args,
  515     const char *oldpath,
  516     const void *private)
  517 {
  518     const char *newpath = (const char *)private;
  519 
  520     if (rename(oldpath, newpath) < 0) {
  521         pr_err("%s: cannot rename %s to %s: errno=%d (%s)\n",
  522             args->name, oldpath, newpath, errno, strerror(errno));
  523         return -1;
  524     }
  525     return 0;
  526 }
  527 #endif
  528 
  529 static void inotify_move_self(const args_t *args, const char *path)
  530 {
  531     char filepath[PATH_MAX], newpath[PATH_MAX];
  532 
  533     mk_filename(filepath, sizeof(filepath), path, "inotify_dir");
  534     if (mk_dir(args, filepath) < 0)
  535         return;
  536     mk_filename(newpath, sizeof(newpath), path, "renamed_dir");
  537 
  538     inotify_exercise(args, filepath, filepath, "inotify_dir",
  539         inotify_move_self_helper, IN_MOVE_SELF, newpath);
  540     (void)rm_dir(args, newpath);
  541     (void)rm_dir(args, filepath);   /* In case rename failed */
  542 }
  543 
  544 #if defined(IN_MOVED_TO)
  545 static int inotify_moved_to_helper(
  546     const args_t *args,
  547     const char *newpath,
  548     const void *private)
  549 {
  550     const char *oldpath = (const char *)private;
  551 
  552     if (rename(oldpath, newpath) < 0) {
  553         pr_err("%s: cannot rename %s to %s: errno=%d (%s)\n",
  554             args->name, oldpath, newpath, errno, strerror(errno));
  555         return -1;
  556     }
  557     return 0;
  558 }
  559 
  560 static void inotify_moved_to(const args_t *args, const char *path)
  561 {
  562     char olddir[PATH_MAX - 16], oldfile[PATH_MAX], newfile[PATH_MAX];
  563 
  564     mk_filename(olddir, sizeof(olddir), path, "new_dir");
  565     (void)rm_dir(args, olddir);
  566     if (mk_dir(args, olddir) < 0)
  567         return;
  568     mk_filename(oldfile, sizeof(oldfile), olddir, "inotify_file");
  569     if (mk_file(args, oldfile, 4096) < 0)
  570         return;
  571 
  572     mk_filename(newfile, sizeof(newfile), path, "inotify_file");
  573     inotify_exercise(args, newfile, path, "inotify_dir",
  574         inotify_moved_to_helper, IN_MOVED_TO, oldfile);
  575     (void)rm_file(args, newfile);
  576     (void)rm_dir(args, olddir);
  577 }
  578 #endif
  579 
  580 #if defined(IN_MOVED_FROM)
  581 static int inotify_moved_from_helper(
  582     const args_t *args,
  583     const char *oldpath,
  584     const void *private)
  585 {
  586     const char *newpath = (const char *)private;
  587 
  588     if (rename(oldpath, newpath) < 0) {
  589         pr_err("%s: cannot rename %s to %s: errno=%d (%s)\n",
  590             args->name, oldpath, newpath, errno, strerror(errno));
  591         return -1;
  592     }
  593     return 0;
  594 }
  595 
  596 static void inotify_moved_from(const args_t *args, const char *path)
  597 {
  598     char oldfile[PATH_MAX], newdir[PATH_MAX - 16], newfile[PATH_MAX];
  599 
  600     mk_filename(oldfile, sizeof(oldfile), path, "inotify_file");
  601     if (mk_file(args, oldfile, 4096) < 0)
  602         return;
  603     mk_filename(newdir, sizeof(newdir), path, "new_dir");
  604     (void)rm_dir(args, newdir);
  605     if (mk_dir(args, newdir) < 0)
  606         return;
  607     mk_filename(newfile, sizeof(newfile), newdir, "inotify_file");
  608     inotify_exercise(args, oldfile, path, "inotify_dir",
  609         inotify_moved_from_helper, IN_MOVED_FROM, newfile);
  610     (void)rm_file(args, newfile);
  611     (void)rm_file(args, oldfile);   /* In case rename failed */
  612     (void)rm_dir(args, newdir);
  613 }
  614 #endif
  615 
  616 #if defined(IN_CLOSE_WRITE)
  617 static int inotify_close_write_helper(
  618     const args_t *args,
  619     const char *path,
  620     const void *fdptr)
  621 {
  622     (void)args;
  623     (void)path;
  624 
  625     (void)close(*(const int *)fdptr);
  626     return 0;
  627 }
  628 
  629 static void inotify_close_write_file(const args_t *args, const char *path)
  630 {
  631     char filepath[PATH_MAX];
  632     int fd;
  633 
  634     mk_filename(filepath, sizeof(filepath), path, "inotify_file");
  635     if (mk_file(args, filepath, 4096) < 0)
  636         return;
  637 
  638     if ((fd = open(filepath, O_RDWR)) < 0) {
  639         pr_err("%s: cannot re-open %s: errno=%d (%s)\n",
  640             args->name, filepath, errno, strerror(errno));
  641         return;
  642     }
  643 
  644     inotify_exercise(args, filepath, path, "inotify_file",
  645         inotify_close_write_helper, IN_CLOSE_WRITE, (void*)&fd);
  646     (void)rm_file(args, filepath);
  647     (void)close(fd);
  648 }
  649 #endif
  650 
  651 #if defined(IN_CLOSE_NOWRITE)
  652 static int inotify_close_nowrite_helper(
  653     const args_t *args,
  654     const char *path,
  655     const void *fdptr)
  656 {
  657     (void)args;
  658     (void)path;
  659 
  660     (void)close(*(const int *)fdptr);
  661     return 0;
  662 }
  663 
  664 static void inotify_close_nowrite_file(const args_t *args, const char *path)
  665 {
  666     char filepath[PATH_MAX];
  667     int fd;
  668 
  669     mk_filename(filepath, sizeof(filepath), path, "inotify_file");
  670     if (mk_file(args, filepath, 4096) < 0)
  671         return;
  672 
  673     if ((fd = open(filepath, O_RDONLY)) < 0) {
  674         pr_err("%s: cannot re-open %s: errno=%d (%s)\n",
  675             args->name, filepath, errno, strerror(errno));
  676         (void)rm_file(args, filepath);
  677         return;
  678     }
  679 
  680     inotify_exercise(args, filepath, path, "inotify_file",
  681         inotify_close_nowrite_helper, IN_CLOSE_NOWRITE, (void*)&fd);
  682     (void)rm_file(args, filepath);
  683     (void)close(fd);
  684 }
  685 #endif
  686 
  687 static const inotify_stress_t inotify_stressors[] = {
  688 #if defined(IN_ACCESS)
  689     { inotify_access_file,      "IN_ACCESS" },
  690 #endif
  691 #if defined(IN_MODIFY)
  692     { inotify_modify_file,      "IN_MODIFY" },
  693 #endif
  694 #if defined(IN_ATTRIB)
  695     { inotify_attrib_file,      "IN_ATTRIB" },
  696 #endif
  697 #if defined(IN_CLOSE_WRITE)
  698     { inotify_close_write_file, "IN_CLOSE_WRITE" },
  699 #endif
  700 #if defined(IN_CLOSE_NOWRITE)
  701     { inotify_close_nowrite_file,   "IN_CLOSE_NOWRITE" },
  702 #endif
  703 #if defined(IN_OPEN)
  704     { inotify_open_file,        "IN_OPEN" },
  705 #endif
  706 #if defined(IN_MOVED_FROM)
  707     { inotify_moved_from,       "IN_MOVED_FROM" },
  708 #endif
  709 #if defined(IN_MOVED_TO)
  710     { inotify_moved_to,     "IN_MOVED_TO" },
  711 #endif
  712 #if defined(IN_CREATE)
  713     { inotify_creat_file,       "IN_CREATE" },
  714 #endif
  715 #if defined(IN_DELETE)
  716     { inotify_delete_file,      "IN_DELETE" },
  717 #endif
  718 #if defined(IN_DELETE_SELF)
  719     { inotify_delete_self,      "IN_DELETE_SELF" },
  720 #endif
  721 #if defined(IN_MOVE_SELF)
  722     { inotify_move_self,        "IN_MOVE_SELF" },
  723 #endif
  724     { NULL,             NULL }
  725 };
  726 
  727 /*
  728  *  stress_inotify()
  729  *  stress inotify
  730  */
  731 static int stress_inotify(const args_t *args)
  732 {
  733     char dirname[PATH_MAX - 16];
  734     int ret, i;
  735 
  736     stress_temp_dir_args(args, dirname, sizeof(dirname));
  737     ret = stress_temp_dir_mk_args(args);
  738     if (ret < 0)
  739         return exit_status(-ret);
  740     do {
  741         for (i = 0; g_keep_stressing_flag && inotify_stressors[i].func; i++)
  742             inotify_stressors[i].func(args, dirname);
  743         inc_counter(args);
  744     } while (keep_stressing());
  745     (void)stress_temp_dir_rm_args(args);
  746 
  747     return EXIT_SUCCESS;
  748 }
  749 
  750 stressor_info_t stress_inotify_info = {
  751     .stressor = stress_inotify,
  752     .class = CLASS_FILESYSTEM | CLASS_SCHEDULER | CLASS_OS
  753 };
  754 #else
  755 stressor_info_t stress_inotify_info = {
  756     .stressor = stress_not_implemented,
  757     .class = CLASS_FILESYSTEM | CLASS_SCHEDULER | CLASS_OS
  758 };
  759 #endif