"Fossies" - the Fresh Open Source Software Archive

Member "stress-ng-0.09.56/stress-fcntl.c" (15 Mar 2019, 12082 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-fcntl.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 0.09.49_vs_0.09.50.

    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(F_DUPFD) ||     \
   28     defined(F_DUPFD_CLOEXEC) || \
   29     defined(F_GETFD) ||     \
   30     defined(F_SETFD) ||     \
   31     defined(F_GETFL) ||     \
   32     defined(F_SETFL) ||     \
   33     defined(F_GETOWN) ||    \
   34     defined(F_SETOWN) ||    \
   35     defined(F_GETOWN_EX) || \
   36     defined(F_SETOWN_EX) || \
   37     defined(F_GETSIG) ||    \
   38     defined(F_SETSIG) ||    \
   39     defined(F_GETOWNER_UIDS) || \
   40     defined(F_GETLEASE) ||  \
   41     (defined(F_GETLK) && defined(F_SETLK) && \
   42      defined(F_SETLKW) && defined(F_WRLCK) && \
   43      defined(F_UNLCK)) ||   \
   44     (defined(F_OFD_GETLK) && defined(F_OFD_SETLK) && \
   45      defined(F_OFD_SETLKW) && defined(F_WRLCK) && defined(F_UNLCK)) | \
   46     (defined(F_GET_FILE_RW_HINT) && defined(F_SET_FILE_RW_HINT)) | \
   47     (defined(F_GET_RW_HINT) && defined(F_SET_RW_HINT))
   48 
   49 /*
   50  *  check_return()
   51  *  sanity check fcntl() return for errors
   52  */
   53 static void check_return(const args_t *args, const int ret, const char *cmd)
   54 {
   55     if (ret < 0) {
   56         if (errno != EINVAL) {
   57             pr_fail("%s: fcntl %s failed: "
   58                 "errno=%d (%s)\n",
   59                 args->name, cmd, errno, strerror(errno));
   60         }
   61     }
   62 }
   63 
   64 #endif
   65 
   66 
   67 /*
   68  *  do_fcntl()
   69  */
   70 static int do_fcntl(const args_t *args, const int fd)
   71 {
   72 #if defined(F_DUPFD)
   73     {
   74         int ret;
   75 
   76         ret = fcntl(fd, F_DUPFD, 0);
   77         check_return(args, ret, "F_DUPFD");
   78         if (ret > -1)
   79             (void)close(ret);
   80     }
   81 #endif
   82 
   83 #if defined(F_DUPFD_CLOEXEC)
   84     {
   85         int ret;
   86 
   87         ret = fcntl(fd, F_DUPFD, F_DUPFD_CLOEXEC);
   88         check_return(args, ret, "F_DUPFD_CLOEXEC");
   89         if (ret > -1)
   90             (void)close(ret);
   91     }
   92 #endif
   93 
   94 #if defined(F_GETFD)
   95     {
   96         int old_flags;
   97 
   98         old_flags = fcntl(fd, F_GETFD);
   99         check_return(args, old_flags, "F_GETFD");
  100 
  101 #if defined(F_SETFD) && defined(O_CLOEXEC)
  102         if (old_flags > -1) {
  103             int new_flags, ret;
  104 
  105             new_flags = old_flags | O_CLOEXEC;
  106             ret = fcntl(fd, F_SETFD, new_flags);
  107             check_return(args, ret, "F_SETFD");
  108 
  109             new_flags &= ~O_CLOEXEC;
  110             ret = fcntl(fd, F_SETFD, new_flags);
  111             check_return(args, ret, "F_SETFD");
  112         }
  113 #endif
  114     }
  115 #endif
  116 
  117 #if defined(F_GETFL)
  118     {
  119         int old_flags;
  120 
  121         old_flags = fcntl(fd, F_GETFL);
  122         check_return(args, old_flags, "F_GETFL");
  123 
  124 #if defined(F_SETFL) && defined(O_APPEND)
  125         if (old_flags > -1) {
  126             int new_flags, ret;
  127 
  128             new_flags = old_flags | O_APPEND;
  129             ret = fcntl(fd, F_SETFL, new_flags);
  130             check_return(args, ret, "F_SETFL");
  131 
  132             new_flags &= ~O_APPEND;
  133             ret = fcntl(fd, F_SETFL, new_flags);
  134             check_return(args, ret, "F_SETFL");
  135         }
  136 #endif
  137     }
  138 #endif
  139 
  140 #if defined(F_SETOWN) && defined(__linux__)
  141     {
  142         int ret;
  143 
  144         ret = fcntl(fd, F_SETOWN, args->pid);
  145         check_return(args, ret, "F_SETOWN");
  146     }
  147 #endif
  148 
  149 #if defined(F_GETOWN) && defined(__linux__)
  150     {
  151         int ret;
  152 
  153         ret = fcntl(fd, F_GETOWN);
  154         check_return(args, ret, "F_GETOWN");
  155     }
  156 #endif
  157 
  158 #if defined(F_SETOWN_EX) && \
  159     (defined(F_OWNER_PID) ||    \
  160      defined(F_OWNER_GID) ||    \
  161      defined(F_OWNER_PGRP) ||   \
  162      (defined(F_OWNER_TID) && defined(__linux__)))
  163     {
  164         int ret;
  165         struct f_owner_ex owner;
  166 
  167 #if defined(F_OWNER_PID)
  168         owner.type = F_OWNER_PID;
  169         owner.pid = args->pid;
  170         ret = fcntl(fd, F_SETOWN_EX, &owner);
  171         check_return(args, ret, "F_SETOWN_EX, F_OWNER_PID");
  172 #endif
  173 #if defined(HAVE_GETPGRP) && defined(F_OWNER_PGRP)
  174         owner.type = F_OWNER_PGRP;
  175         owner.pid = getpgrp();
  176         ret = fcntl(fd, F_SETOWN_EX, &owner);
  177         check_return(args, ret, "F_SETOWN_EX, F_OWNER_PGRP");
  178 #endif
  179 #if defined(HAVE_GETPGRP) && defined(F_OWNER_GID)
  180         owner.type = F_OWNER_GID;
  181         owner.pid = getpgrp();
  182         ret = fcntl(fd, F_SETOWN_EX, &owner);
  183         check_return(args, ret, "F_SETOWN_EX, F_OWNER_GID");
  184 #endif
  185 #if defined(F_OWNER_TID) && defined(__linux__)
  186         owner.type = F_OWNER_TID;
  187         owner.pid = shim_gettid();
  188         ret = fcntl(fd, F_SETOWN_EX, &owner);
  189         check_return(args, ret, "F_SETOWN_EX, F_OWNER_TID");
  190 #endif
  191     }
  192 #endif
  193 
  194 #if defined(F_GETOWN_EX)
  195     {
  196         int ret;
  197         struct f_owner_ex owner;
  198 
  199         owner.type = F_OWNER_PID;
  200         ret = fcntl(fd, F_GETOWN_EX, &owner);
  201         check_return(args, ret, "F_GETOWN_EX, F_OWNER_PID");
  202 
  203 #if defined(F_OWNER_PGRP)
  204         owner.type = F_OWNER_PGRP;
  205         ret = fcntl(fd, F_GETOWN_EX, &owner);
  206         check_return(args, ret, "F_GETOWN_EX, F_OWNER_PGRP");
  207 #endif
  208 #if defined(F_OWNER_GID)
  209         owner.type = F_OWNER_GID;
  210         ret = fcntl(fd, F_GETOWN_EX, &owner);
  211         check_return(args, ret, "F_GETOWN_EX, F_OWNER_GID");
  212 #endif
  213 #if defined(F_OWNER_TID) && defined(__linux__)
  214         owner.type = F_OWNER_TID;
  215         ret = fcntl(fd, F_GETOWN_EX, &owner);
  216         check_return(args, ret, "F_GETOWN_EX, F_OWNER_TID");
  217 #endif
  218     }
  219 #endif
  220 
  221 #if defined(F_SETSIG)
  222     {
  223         int ret;
  224 
  225         ret = fcntl(fd, F_SETSIG, SIGKILL);
  226         check_return(args, ret, "F_SETSIG");
  227         ret = fcntl(fd, F_SETSIG, 0);
  228         check_return(args, ret, "F_SETSIG");
  229         ret = fcntl(fd, F_SETSIG, SIGIO);
  230         check_return(args, ret, "F_SETSIG");
  231     }
  232 #endif
  233 
  234 #if defined(F_GETSIG)
  235     {
  236         int ret;
  237 
  238         ret = fcntl(fd, F_GETSIG);
  239         check_return(args, ret, "F_GETSIG");
  240     }
  241 #endif
  242 
  243 #if defined(F_GETOWNER_UIDS)
  244     {
  245         int ret;
  246 
  247         ret = fcntl(fd, F_GETOWNER_UIDS);
  248         check_return(args, ret, "F_GETOWNER_UIDS");
  249     }
  250 #endif
  251 
  252 #if defined(F_GETLEASE)
  253     {
  254         int ret;
  255 
  256         ret = fcntl(fd, F_GETLEASE);
  257         check_return(args, ret, "F_GETLEASE");
  258     }
  259 #endif
  260 
  261 #if defined(F_GETLK) && defined(F_SETLK) && defined(F_SETLKW) && \
  262     defined(F_WRLCK) && defined(F_UNLCK)
  263     {
  264 #if defined (__linux__)
  265         struct flock64 f;
  266 #else
  267         struct flock f;
  268 #endif
  269         int ret;
  270         const off_t len = (mwc16() + 1) & 0x7fff;
  271         const off_t start = mwc16() & 0x7fff;
  272 
  273         if (ftruncate(fd, 65536) < 0) {
  274             pr_fail_err("ftruncate");
  275             goto lock_abort;
  276         }
  277 
  278         f.l_type = F_WRLCK;
  279         f.l_whence = SEEK_SET;
  280         f.l_start = start;
  281         f.l_len = len;
  282         f.l_pid = args->pid;
  283 
  284         ret = fcntl(fd, F_GETLK, &f);
  285         check_return(args, ret, "F_GETLK");
  286 
  287 #if 0
  288         if (f.l_type != F_UNLCK) {
  289             pr_fail_err("fcntl F_GETLK");
  290             goto lock_abort;
  291         }
  292 #endif
  293 
  294         f.l_type = F_WRLCK;
  295         f.l_whence = SEEK_SET;
  296         f.l_start = start;
  297         f.l_len = len;
  298         f.l_pid = args->pid;
  299 
  300         ret = fcntl(fd, F_SETLK, &f);
  301         if ((ret < 0) && (errno == EAGAIN))
  302             goto lock_abort;
  303         check_return(args, ret, "F_SETLK (F_WRLCK)");
  304 
  305         f.l_type = F_UNLCK;
  306         f.l_whence = SEEK_SET;
  307         f.l_start = start;
  308         f.l_len = len;
  309         f.l_pid = args->pid;
  310 
  311         ret = fcntl(fd, F_SETLK, &f);
  312         if ((ret < 0) && (errno == EAGAIN))
  313             goto lock_abort;
  314 
  315         check_return(args, ret, "F_SETLK (F_UNLCK)");
  316 
  317         f.l_type = F_WRLCK;
  318         f.l_whence = SEEK_SET;
  319         f.l_start = start;
  320         f.l_len = len;
  321         f.l_pid = args->pid;
  322 
  323         ret = fcntl(fd, F_SETLKW, &f);
  324         if ((ret < 0) && (errno == EAGAIN))
  325             goto lock_abort;
  326         check_return(args, ret, "F_SETLKW (F_WRLCK)");
  327 
  328         f.l_type = F_UNLCK;
  329         f.l_whence = SEEK_SET;
  330         f.l_start = start;
  331         f.l_len = len;
  332         f.l_pid = args->pid;
  333 
  334         ret = fcntl(fd, F_SETLK, &f);
  335         check_return(args, ret, "F_SETLK (F_UNLCK)");
  336 
  337 lock_abort: { /* Nowt */ }
  338     }
  339 #endif
  340 
  341 #if defined(F_OFD_GETLK) && defined(F_OFD_SETLK) && defined(F_OFD_SETLKW) && \
  342     defined(F_WRLCK) && defined(F_UNLCK)
  343     {
  344 #if defined (__linux__)
  345         struct flock64 f;
  346 #else
  347         struct flock f;
  348 #endif
  349         int ret;
  350         const off_t len = (mwc16() + 1) & 0x7fff;
  351         const off_t start = mwc16() & 0x7fff;
  352 
  353         if (ftruncate(fd, 65536) < 0) {
  354             pr_fail_err("ftruncate");
  355             goto ofd_lock_abort;
  356         }
  357 
  358         f.l_type = F_WRLCK;
  359         f.l_whence = SEEK_SET;
  360         f.l_start = start;
  361         f.l_len = len;
  362         f.l_pid = 0;
  363 
  364         ret = fcntl(fd, F_OFD_GETLK, &f);
  365 
  366         check_return(args, ret, "F_OFD_GETLK (F_WRLCK)");
  367 
  368         f.l_type = F_WRLCK;
  369         f.l_whence = SEEK_SET;
  370         f.l_start = start;
  371         f.l_len = len;
  372         f.l_pid = 0;
  373 
  374         ret = fcntl(fd, F_OFD_SETLK, &f);
  375         if ((ret < 0) && (errno == EAGAIN))
  376             goto ofd_lock_abort;
  377         check_return(args, ret, "F_OFD_SETLK (F_WRLCK)");
  378 
  379         f.l_type = F_UNLCK;
  380         f.l_whence = SEEK_SET;
  381         f.l_start = start;
  382         f.l_len = len;
  383         f.l_pid = 0;
  384 
  385         ret = fcntl(fd, F_OFD_SETLK, &f);
  386         if ((ret < 0) && (errno == EAGAIN))
  387             goto ofd_lock_abort;
  388         check_return(args, ret, "F_OFD_SETLK (F_UNLCK)");
  389 
  390         f.l_type = F_WRLCK;
  391         f.l_whence = SEEK_SET;
  392         f.l_start = start;
  393         f.l_len = len;
  394         f.l_pid = 0;
  395 
  396         ret = fcntl(fd, F_OFD_SETLKW, &f);
  397         if ((ret < 0) && (errno == EAGAIN))
  398             goto ofd_lock_abort;
  399         check_return(args, ret, "F_OFD_SETLKW (F_WRLCK)");
  400 
  401         f.l_type = F_UNLCK;
  402         f.l_whence = SEEK_SET;
  403         f.l_start = start;
  404         f.l_len = len;
  405         f.l_pid = 0;
  406 
  407         ret = fcntl(fd, F_OFD_SETLK, &f);
  408         if ((ret < 0) && (errno == EAGAIN))
  409             goto ofd_lock_abort;
  410         check_return(args, ret, "F_OFD_SETLK (F_UNLCK)");
  411 
  412 ofd_lock_abort: { /* Nowt */ }
  413     }
  414 #endif
  415 
  416 #if (defined(F_GET_FILE_RW_HINT) && defined(F_SET_FILE_RW_HINT)) | \
  417     (defined(F_GET_RW_HINT) && defined(F_SET_RW_HINT))
  418     {
  419         int ret;
  420         size_t i;
  421         unsigned long hint;
  422         static const unsigned long hints[] = {
  423 #if defined(RWH_WRITE_LIFE_EXTREME)
  424             RWH_WRITE_LIFE_EXTREME,
  425 #endif
  426 #if defined(RWH_WRITE_LIFE_LONG)
  427             RWH_WRITE_LIFE_LONG,
  428 #endif
  429 #if defined(RWH_WRITE_LIFE_MEDIUM)
  430             RWH_WRITE_LIFE_MEDIUM,
  431 #endif
  432 #if defined(RWH_WRITE_LIFE_SHORT)
  433             RWH_WRITE_LIFE_SHORT,
  434 #endif
  435 #if defined(RWH_WRITE_LIFE_NONE)
  436             RWH_WRITE_LIFE_NONE,
  437 #endif
  438 #if defined(RWF_WRITE_LIFE_NOT_SET)
  439             RWF_WRITE_LIFE_NOT_SET
  440 #endif
  441         };
  442 
  443 #if defined(F_GET_FILE_RW_HINT) && defined(F_SET_FILE_RW_HINT)
  444         ret = fcntl(fd, F_GET_FILE_RW_HINT, &hint);
  445         if (ret == 0) {
  446             for (i = 0; i < SIZEOF_ARRAY(hints); i++) {
  447                 hint = hints[i];
  448                 ret = fcntl(fd, F_SET_FILE_RW_HINT, &hint);
  449                 (void)ret;
  450             }
  451         }
  452 #endif
  453 #if defined(F_GET_RW_HINT) && defined(F_SET_RW_HINT)
  454         ret = fcntl(fd, F_GET_RW_HINT, &hint);
  455         if (ret == 0) {
  456             for (i = 0; i < SIZEOF_ARRAY(hints); i++) {
  457                 hint = hints[i];
  458                 ret = fcntl(fd, F_SET_RW_HINT, &hint);
  459                 (void)ret;
  460             }
  461         }
  462 #endif
  463 
  464     }
  465 #endif
  466 
  467     return 0;
  468 }
  469 
  470 /*
  471  *  stress_fcntl
  472  *  stress various fcntl calls
  473  */
  474 static int stress_fcntl(const args_t *args)
  475 {
  476     const pid_t ppid = getppid();
  477     int fd = -1, rc = EXIT_FAILURE, retries = 0;
  478     char filename[PATH_MAX], dirname[PATH_MAX];
  479 
  480     /*
  481      *  Allow for multiple workers to chmod the *same* file
  482      */
  483     stress_temp_dir(dirname, sizeof(dirname), args->name, ppid, 0);
  484     if (mkdir(dirname, S_IRWXU) < 0) {
  485         if (errno != EEXIST) {
  486             pr_fail_err("mkdir");
  487             return exit_status(errno);
  488         }
  489     }
  490     (void)stress_temp_filename(filename, sizeof(filename),
  491         args->name, ppid, 0, 0);
  492 
  493     do {
  494         errno = 0;
  495         /*
  496          *  Try and open the file, it may be impossible
  497          *  momentarily because other fcntl stressors have
  498          *  already created it
  499          */
  500         if ((fd = creat(filename, S_IRUSR | S_IWUSR)) < 0) {
  501             if ((errno == EPERM) || (errno == EACCES) ||
  502                 (errno == ENOMEM) || (errno == ENOSPC)) {
  503                 (void)shim_usleep(100000);
  504                 continue;
  505             }
  506             pr_fail_err("open");
  507             goto tidy;
  508         }
  509         break;
  510     } while (g_keep_stressing_flag && ++retries < 100);
  511 
  512     if (retries >= 100) {
  513         pr_err("%s: creat: file %s took %d "
  514             "retries to create (instance %" PRIu32 ")\n",
  515             args->name, filename, retries, args->instance);
  516         goto tidy;
  517     }
  518 
  519     do {
  520         do_fcntl(args, fd);
  521         inc_counter(args);
  522     } while (keep_stressing());
  523 
  524     rc = EXIT_SUCCESS;
  525 tidy:
  526     if (fd >= 0)
  527         (void)close(fd);
  528     (void)unlink(filename);
  529     (void)rmdir(dirname);
  530 
  531     return rc;
  532 }
  533 
  534 stressor_info_t stress_fcntl_info = {
  535     .stressor = stress_fcntl,
  536     .class = CLASS_FILESYSTEM | CLASS_OS
  537 };