Print this page
    
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/test/os-tests/tests/file-locking/runtests.c
          +++ new/usr/src/test/os-tests/tests/file-locking/runtests.c
   1    1  /*
   2    2   * This file and its contents are supplied under the terms of the
   3    3   * Common Development and Distribution License ("CDDL"), version 1.0.
   4    4   * You may only use this file in accordance with the terms of version
   5    5   * 1.0 of the CDDL.
   6    6   *
   7    7   * A full copy of the text of the CDDL should have accompanied this
   8    8   * source.  A copy of the CDDL is also available via the Internet at
   9    9   * http://www.illumos.org/license/CDDL.
  10   10   */
  11   11  
  12   12  /*
  13   13   * Copyright 2016 Joyent, Inc.
  14   14   */
  15   15  
  16   16  /*
  17   17   * Validate various fcntl(2) and flock(3C) operations.
  18   18   */
  19   19  
  20   20  #include "util.h"
  21   21  #include <err.h>
  22   22  #include <errno.h>
  23   23  #include <fcntl.h>
  24   24  #include <libgen.h>
  25   25  #include <signal.h>
  26   26  #include <stdlib.h>
  27   27  #include <strings.h>
  28   28  #include <sys/debug.h>
  29   29  #include <sys/file.h>
  30   30  #include <sys/stat.h>
  31   31  #include <sys/wait.h>
  32   32  #include <unistd.h>
  33   33  
  34   34  
  35   35  #define LOCKFILE_FMT    "/tmp/.lockfile-%s-%ld"
  36   36  #define LOCKDIR_FMT     "/tmp/.lockdir-%s-%ld"
  37   37  
  38   38  typedef struct lockinfo {
  39   39          char *lf_name;
  40   40          char *lf_path;
  41   41          int lf_fd;
  42   42  } lockinfo_t;
  43   43  
  44   44  
  45   45  static  void    assert_write_locked_by(lockinfo_t *, pid_t);
  46   46  static  void    assert_read_locked_by(lockinfo_t *, pid_t);
  47   47  static  void    assert_unlocked(lockinfo_t *);
  48   48  static  void    assert_all_unlocked(void);
  49   49  
  50   50  static  int     flock_copyfil(lockinfo_t *, lockinfo_t *);
  51   51  static  int     flock_mkfil(lockinfo_t *);
  52   52  static  int     flock_mkdir(lockinfo_t *);
  53   53  static  void    flock_rminfo(lockinfo_t *);
  54   54  
  55   55  static  void    flock_fcntl(lockinfo_t *lf, int cmd, struct flock *fl);
  56   56  static  void    flock_run(lock_style_t, boolean_t, lockinfo_t *,
  57   57                      pid_t *, int[]);
  58   58  static  int     flock_wait(pid_t pid);
  59   59  static  void    flock_cleanup_child(pid_t, int []);
  60   60  
  61   61  static  void    flock_test_invalid(lockinfo_t *, int, short, short,
  62   62                      off_t, off_t);
  63   63  static  void    flock_test_exclusive(lock_style_t, lock_style_t,
  64   64                      lockinfo_t *, lockinfo_t *, boolean_t);
  65   65  static  void    flock_test_shared(lock_style_t, lock_style_t, lockinfo_t *,
  66   66                      lockinfo_t *, boolean_t);
  67   67  static  void    flock_test_upgrade_downgrade(void);
  68   68  
  69   69  static char *acqprog = NULL;
  70   70  
  71   71  static lockinfo_t flock_fileA = { "a", NULL, -1 };
  72   72  static lockinfo_t flock_fileB = { "b", NULL, -1 };
  73   73  static lockinfo_t flock_dirA = { "a", NULL, -1 };
  74   74  static lockinfo_t flock_dirB = { "b", NULL, -1 };
  75   75  
  76   76  
  77   77  static short cmds[8] = {
  78   78          F_SETLK, F_SETLKW, F_GETLK,
  79   79          F_OFD_SETLK, F_OFD_SETLKW, F_OFD_GETLK,
  80   80          F_FLOCK, F_FLOCKW
  81   81  };
  82   82  
  83   83  
  84   84  static void
  85   85  flock_kill(pid_t pid)
  86   86  {
  87   87          while (kill(pid, SIGKILL) == -1) {
  88   88                  if (errno == EINTR)
  89   89                          continue;
  90   90  
  91   91                  err(EXIT_FAILURE, "kill failed");
  92   92          }
  93   93  }
  94   94  
  95   95  
  96   96  static void
  97   97  flock_fcntl(lockinfo_t *lf, int cmd, struct flock *fl)
  98   98  {
  99   99          if (fcntl(lf->lf_fd, cmd, fl) == -1) {
 100  100                  err(EXIT_FAILURE, "fcntl failed");
 101  101          }
 102  102  }
 103  103  
 104  104  
 105  105  static void
 106  106  assert_write_locked_by(lockinfo_t *lf, pid_t pid)
 107  107  {
 108  108          struct flock fl;
 109  109  
 110  110          flock_reinit(&fl, F_WRLCK);
 111  111          flock_fcntl(lf, F_GETLK, &fl);
 112  112          VERIFY3_IMPL(fl.l_type, ==, F_WRLCK, short);
 113  113          VERIFY3_IMPL(fl.l_sysid, ==, 0, int);
 114  114          VERIFY3_IMPL(fl.l_pid, ==, pid, pid_t);
 115  115  
 116  116          flock_reinit(&fl, F_WRLCK);
 117  117          flock_fcntl(lf, F_OFD_GETLK, &fl);
 118  118          VERIFY3_IMPL(fl.l_type, ==, F_WRLCK, short);
 119  119          VERIFY3_IMPL(fl.l_sysid, ==, 0, int);
 120  120          VERIFY3_IMPL(fl.l_pid, ==, pid, pid_t);
 121  121  
 122  122          flock_reinit(&fl, F_RDLCK);
 123  123          flock_fcntl(lf, F_GETLK, &fl);
 124  124          VERIFY3_IMPL(fl.l_type, ==, F_WRLCK, short);
 125  125          VERIFY3_IMPL(fl.l_sysid, ==, 0, int);
 126  126          VERIFY3_IMPL(fl.l_pid, ==, pid, pid_t);
 127  127  
 128  128          flock_reinit(&fl, F_RDLCK);
 129  129          flock_fcntl(lf, F_OFD_GETLK, &fl);
 130  130          VERIFY3_IMPL(fl.l_type, ==, F_WRLCK, short);
 131  131          VERIFY3_IMPL(fl.l_sysid, ==, 0, int);
 132  132          VERIFY3_IMPL(fl.l_pid, ==, pid, pid_t);
 133  133  }
 134  134  
 135  135  
 136  136  static void
 137  137  assert_read_locked_by(lockinfo_t *lf, pid_t pid)
 138  138  {
 139  139          struct flock fl;
 140  140  
 141  141          flock_reinit(&fl, F_WRLCK);
 142  142          flock_fcntl(lf, F_GETLK, &fl);
 143  143          VERIFY3_IMPL(fl.l_type, ==, F_RDLCK, short);
 144  144          VERIFY3_IMPL(fl.l_sysid, ==, 0, int);
 145  145          VERIFY3_IMPL(fl.l_pid, ==, pid, pid_t);
 146  146  
 147  147          flock_reinit(&fl, F_WRLCK);
 148  148          flock_fcntl(lf, F_OFD_GETLK, &fl);
 149  149          VERIFY3_IMPL(fl.l_type, ==, F_RDLCK, short);
 150  150          VERIFY3_IMPL(fl.l_sysid, ==, 0, int);
 151  151          VERIFY3_IMPL(fl.l_pid, ==, pid, pid_t);
 152  152  
 153  153          flock_reinit(&fl, F_RDLCK);
 154  154          flock_fcntl(lf, F_GETLK, &fl);
 155  155          VERIFY3_IMPL(fl.l_type, ==, F_UNLCK, short);
 156  156          VERIFY3_IMPL(fl.l_sysid, ==, 0, int);
 157  157          VERIFY3_IMPL(fl.l_pid, ==, 0, pid_t);
 158  158  
 159  159          flock_reinit(&fl, F_RDLCK);
 160  160          flock_fcntl(lf, F_OFD_GETLK, &fl);
 161  161          VERIFY3_IMPL(fl.l_type, ==, F_UNLCK, short);
 162  162          VERIFY3_IMPL(fl.l_sysid, ==, 0, int);
 163  163          VERIFY3_IMPL(fl.l_pid, ==, 0, pid_t);
 164  164  }
 165  165  
 166  166  static void
 167  167  assert_unlocked(lockinfo_t *lf)
 168  168  {
 169  169          struct flock fl;
 170  170  
 171  171          flock_reinit(&fl, F_WRLCK);
 172  172          flock_fcntl(lf, F_GETLK, &fl);
 173  173          VERIFY3_IMPL(fl.l_type, ==, F_UNLCK, short);
 174  174          VERIFY3_IMPL(fl.l_sysid, ==, 0, int);
 175  175          VERIFY3_IMPL(fl.l_pid, ==, 0, pid_t);
 176  176  
 177  177          flock_reinit(&fl, F_WRLCK);
 178  178          flock_fcntl(lf, F_OFD_GETLK, &fl);
 179  179          VERIFY3_IMPL(fl.l_type, ==, F_UNLCK, short);
 180  180          VERIFY3_IMPL(fl.l_sysid, ==, 0, int);
 181  181          VERIFY3_IMPL(fl.l_pid, ==, 0, pid_t);
 182  182  
 183  183          flock_reinit(&fl, F_RDLCK);
 184  184          flock_fcntl(lf, F_GETLK, &fl);
 185  185          VERIFY3_IMPL(fl.l_type, ==, F_UNLCK, short);
 186  186          VERIFY3_IMPL(fl.l_sysid, ==, 0, int);
 187  187          VERIFY3_IMPL(fl.l_pid, ==, 0, pid_t);
 188  188  
 189  189          flock_reinit(&fl, F_RDLCK);
 190  190          flock_fcntl(lf, F_OFD_GETLK, &fl);
 191  191          VERIFY3_IMPL(fl.l_type, ==, F_UNLCK, short);
 192  192          VERIFY3_IMPL(fl.l_sysid, ==, 0, int);
 193  193          VERIFY3_IMPL(fl.l_pid, ==, 0, pid_t);
 194  194  }
 195  195  
 196  196  
 197  197  static void
 198  198  assert_all_unlocked(void)
 199  199  {
 200  200          assert_unlocked(&flock_fileA);
 201  201          assert_unlocked(&flock_fileB);
 202  202          assert_unlocked(&flock_dirA);
 203  203          assert_unlocked(&flock_dirB);
 204  204  }
 205  205  
 206  206  
 207  207  static int
 208  208  flock_copyfil(lockinfo_t *src, lockinfo_t *dst)
 209  209  {
 210  210          dst->lf_name = NULL;
 211  211          dst->lf_path = NULL;
 212  212          if ((dst->lf_fd = open(src->lf_path, O_RDWR)) == -1) {
 213  213                  warn("Failed to open %s", src->lf_path);
 214  214                  return (-1);
 215  215          }
 216  216  
 217  217          return (0);
 218  218  }
 219  219  
 220  220  
 221  221  static int
 222  222  flock_mkfil(lockinfo_t *lf)
 223  223  {
 224  224          if (asprintf(&lf->lf_path, LOCKFILE_FMT, lf->lf_name, getpid()) < 0) {
 225  225                  warnx("Failed to generate lockfile name");
 226  226                  return (-1);
 227  227          }
 228  228  
 229  229          if ((lf->lf_fd = open(lf->lf_path, O_RDWR|O_CREAT, 0600)) == -1)  {
 230  230                  warn("Failed to open %s", lf->lf_path);
 231  231                  return (-1);
 232  232          }
 233  233  
 234  234          return (0);
 235  235  }
 236  236  
 237  237  
 238  238  static int
 239  239  flock_mkdir(lockinfo_t *lf)
 240  240  {
 241  241          if (asprintf(&lf->lf_path, LOCKDIR_FMT, lf->lf_name, getpid()) < 0) {
 242  242                  warnx("Failed to generate lockfile name");
 243  243                  return (-1);
 244  244          }
 245  245  
 246  246          if (mkdir(lf->lf_path, 0700) == -1)  {
 247  247                  warn("Failed to make %s", lf->lf_path);
 248  248                  return (-1);
 249  249          }
 250  250  
 251  251          if ((lf->lf_fd = open(lf->lf_path, O_RDONLY)) == -1)  {
 252  252                  warn("Failed to open %s", lf->lf_path);
 253  253                  return (-1);
 254  254          }
 255  255  
 256  256          return (0);
 257  257  }
 258  258  
 259  259  
 260  260  static void
 261  261  flock_rminfo(lockinfo_t *lf)
 262  262  {
 263  263          if (lf->lf_fd != -1) {
 264  264                  (void) close(lf->lf_fd);
 265  265          }
 266  266          if (lf->lf_path != NULL) {
 267  267                  (void) unlink(lf->lf_path);
 268  268                  free(lf->lf_path);
 269  269          }
 270  270  }
 271  271  
 272  272  
 273  273  static void
 274  274  flock_run(lock_style_t style, boolean_t is_exclusive, lockinfo_t *lf,
 275  275      pid_t *pid, int fds[])
 276  276  {
 277  277          char *stylestr = flock_stylestr(style);
 278  278          char *modestr = is_exclusive ? "exclusive" : "shared";
 279  279          char *argv[5] = { acqprog, stylestr, modestr, lf->lf_path, NULL };
 280  280          int ret = pipe(fds);
 281  281          if (ret == -1) {
 282  282                  err(EXIT_FAILURE, "pipe failed");
 283  283          }
 284  284  
 285  285          *pid = fork();
 286  286          if (*pid == (pid_t)-1) {
 287  287                  err(EXIT_FAILURE, "fork failed");
 288  288          } else if (*pid == (pid_t)0) {
 289  289                  /* Set up pipe for communicating with child */
 290  290                  ret = dup2(fds[1], 0);
 291  291                  if (ret == -1) {
 292  292                          err(EXIT_FAILURE, "dup2 failed");
 293  293                  }
 294  294                  ret = dup2(fds[1], 1);
 295  295                  if (ret == -1) {
 296  296                          err(EXIT_FAILURE, "dup2 failed");
 297  297                  }
 298  298                  closefrom(3);
 299  299  
 300  300                  (void) execv(acqprog, argv);
 301  301                  err(EXIT_FAILURE, "Failed to execute %s", acqprog);
 302  302          }
 303  303  }
 304  304  
 305  305  
 306  306  static int
 307  307  flock_wait(pid_t pid)
 308  308  {
 309  309          int childstat = 0;
 310  310  
 311  311          while (waitpid(pid, &childstat, 0) == -1) {
 312  312                  if (errno == EINTR)
 313  313                          continue;
 314  314  
 315  315                  err(EXIT_FAILURE, "Failed to wait on child");
 316  316          }
 317  317  
 318  318          if (WIFEXITED(childstat)) {
 319  319                  return (WEXITSTATUS(childstat));
 320  320          } else if (WIFSIGNALED(childstat)) {
 321  321                  return (1);
 322  322          } else {
 323  323                  abort();
 324  324                  return (1);
 325  325          }
 326  326  }
 327  327  
 328  328  
 329  329  static void
 330  330  flock_cleanup_child(pid_t pid, int fds[])
 331  331  {
 332  332          (void) flock_wait(pid);
 333  333          (void) close(fds[0]);
 334  334          (void) close(fds[1]);
 335  335  }
 336  336  
 337  337  
 338  338  static void
 339  339  flock_test_upgrade_downgrade(void)
 340  340  {
 341  341          lockinfo_t afd1, afd2, afd3;
 342  342          pid_t pid;
 343  343          int fds[2];
 344  344  
 345  345          VERIFY3S(flock_copyfil(&flock_fileA, &afd1), ==, 0);
 346  346          VERIFY3S(flock_copyfil(&flock_fileA, &afd2), ==, 0);
 347  347          VERIFY3S(flock_copyfil(&flock_fileA, &afd3), ==, 0);
 348  348  
 349  349          flock_log("Acquiring shared locks 1, 2 and 3...");
 350  350          VERIFY3S(flock(afd1.lf_fd, LOCK_SH), ==, 0);
 351  351          VERIFY3S(flock(afd2.lf_fd, LOCK_SH), ==, 0);
 352  352          VERIFY3S(flock(afd3.lf_fd, LOCK_SH), ==, 0);
 353  353          assert_read_locked_by(&flock_fileA, -1);
 354  354          flock_log(" ok\n");
 355  355  
 356  356          flock_log("Upgrading lock 3 should fail w/ EWOULDBLOCK...");
 357  357          VERIFY3S(flock(afd3.lf_fd, LOCK_EX|LOCK_NB), ==, -1);
 358  358          VERIFY3U(errno, ==, EWOULDBLOCK);
 359  359          assert_read_locked_by(&flock_fileA, -1);
 360  360          flock_log(" ok\n");
 361  361  
 362  362          flock_log("Upgrading 3 should succeed after releasing locks 1 & 2...");
 363  363          VERIFY3S(flock(afd1.lf_fd, LOCK_UN), ==, 0);
 364  364          VERIFY3S(flock(afd2.lf_fd, LOCK_UN), ==, 0);
 365  365          VERIFY3S(flock(afd3.lf_fd, LOCK_EX), ==, 0);
 366  366          assert_write_locked_by(&flock_fileA, -1);
 367  367          flock_log(" ok\n");
 368  368  
 369  369  
 370  370          flock_log("Starting up child, then downgrading lock 3 to shared...");
 371  371          flock_run(LSTYLE_FLOCK, B_FALSE, &flock_fileA, &pid, fds);
 372  372          VERIFY3_IMPL(flock_nodata(fds[0]), ==, B_TRUE, boolean_t);
 373  373          VERIFY3S(flock(afd3.lf_fd, LOCK_SH), ==, 0);
 374  374          flock_block(fds[0]);
 375  375          assert_read_locked_by(&flock_fileA, -1);
 376  376          flock_log(" ok\n");
 377  377  
 378  378          flock_log("Releasing child and upgrading...");
 379  379          flock_alert(fds[0]);
 380  380          flock_cleanup_child(pid, fds);
 381  381          assert_read_locked_by(&flock_fileA, -1);
 382  382          VERIFY3S(flock(afd3.lf_fd, LOCK_EX), ==, 0);
 383  383          assert_write_locked_by(&flock_fileA, -1);
 384  384          flock_log(" ok\n");
 385  385  
 386  386          flock_log("Releasing lock 3...");
 387  387          VERIFY3S(flock(afd3.lf_fd, LOCK_UN), ==, 0);
 388  388          flock_rminfo(&afd1);
 389  389          flock_rminfo(&afd2);
 390  390          flock_rminfo(&afd3);
 391  391          assert_all_unlocked();
 392  392          flock_log(" ok\n");
 393  393  }
 394  394  
 395  395  
 396  396  static void
 397  397  flock_test_invalid(lockinfo_t *lf, int cmd, short l_type, short l_whence,
 398  398      off_t l_start, off_t l_len)
 399  399  {
 400  400          struct flock fl = {
 401  401                  .l_type = l_type,
 402  402                  .l_whence = l_whence,
 403  403                  .l_start = l_start,
 404  404                  .l_len = l_len
 405  405          };
 406  406  
 407  407          flock_log("fcntl(fd, %s, { %hd, %hd, %ld, %ld, ... })...",
 408  408              flock_cmdname(cmd), l_type, l_whence, l_start, l_len);
 409  409          VERIFY3S(fcntl(lf->lf_fd, cmd, &fl), ==, -1);
 410  410          VERIFY3U(errno, ==, EINVAL);
 411  411          flock_log(" ok\n");
 412  412  }
 413  413  
 414  414  
 415  415  static void
 416  416  flock_test_exclusive(lock_style_t styleA, lock_style_t styleB,
 417  417      lockinfo_t *lock1, lockinfo_t *lock2, boolean_t kill_firstborn)
 418  418  {
 419  419          pid_t pidA, pidB;
 420  420          int fdsA[2], fdsB[2];
 421  421  
 422  422          flock_log("Running %s + %s tests (%s)...",
 423  423              flock_stylename(styleA), flock_stylename(styleB),
 424  424              kill_firstborn ? "kill child" : "child exits");
 425  425  
 426  426          /* Create child, and wait for it to acquire the lock */
 427  427          flock_run(styleA, B_TRUE, lock1, &pidA, fdsA);
 428  428          flock_block(fdsA[0]);
 429  429  
 430  430          /* Create second child, which shouldn't acquire & signal */
 431  431          flock_run(styleB, B_TRUE, lock1, &pidB, fdsB);
 432  432          VERIFY3_IMPL(flock_nodata(fdsB[0]), ==, B_TRUE, boolean_t);
 433  433  
 434  434          /* lock1 is blocked for reading and writing */
 435  435          assert_write_locked_by(lock1, styleA == LSTYLE_POSIX ? pidA : -1);
 436  436          assert_unlocked(lock2);
 437  437  
 438  438          /* Tell pidA to exit */
 439  439          if (kill_firstborn) {
 440  440                  flock_kill(pidA);
 441  441          } else {
 442  442                  flock_alert(fdsA[0]);
 443  443          }
 444  444          flock_cleanup_child(pidA, fdsA);
 445  445  
 446  446          /* Wait for pidB to signal us */
 447  447          flock_block(fdsB[0]);
 448  448  
 449  449          /* lock1 is blocked for reading and writing */
 450  450          assert_write_locked_by(lock1, styleB == LSTYLE_POSIX ? pidB : -1);
 451  451          assert_unlocked(lock2);
 452  452  
 453  453          /* Tell pidB to exit */
 454  454          flock_alert(fdsB[0]);
 455  455  
 456  456          flock_cleanup_child(pidB, fdsB);
 457  457  
 458  458          /*
 459  459           * Tests after child has released lock
 460  460           */
 461  461          assert_all_unlocked();
 462  462  
 463  463          flock_log(" ok\n");
 464  464  }
 465  465  
 466  466  
 467  467  static void
 468  468  flock_test_shared(lock_style_t styleA, lock_style_t styleB,
 469  469      lockinfo_t *lock1, lockinfo_t *lock2, boolean_t kill_firstborn)
 470  470  {
 471  471          pid_t pidA, pidB;
 472  472          int fdsA[2], fdsB[2];
 473  473  
 474  474          flock_log("Running %s + %s tests (%s)...",
 475  475              flock_stylename(styleA), flock_stylename(styleB),
 476  476              kill_firstborn ? "kill child" : "child exits");
 477  477  
 478  478          /* Create children, and wait for it to acquire the lock */
 479  479          flock_run(styleB, B_FALSE, lock1, &pidB, fdsB);
 480  480          flock_block(fdsB[0]);
 481  481          flock_run(styleA, B_FALSE, lock1, &pidA, fdsA);
 482  482          flock_block(fdsA[0]);
 483  483  
 484  484          /* testfileA is only blocked for writing */
 485  485          assert_read_locked_by(lock1, styleA == LSTYLE_POSIX ? pidA : -1);
 486  486          assert_unlocked(lock2);
 487  487  
 488  488          /* Tell pidA to exit */
 489  489          if (kill_firstborn) {
 490  490                  flock_kill(pidA);
 491  491          } else {
 492  492                  flock_alert(fdsA[0]);
 493  493          }
 494  494          flock_cleanup_child(pidA, fdsA);
 495  495  
 496  496          /* testfileA is still blocked for writing by pidB */
 497  497          assert_read_locked_by(lock1, styleB == LSTYLE_POSIX ? pidB : -1);
 498  498          assert_unlocked(lock2);
 499  499  
 500  500          /* Tell pidB to exit */
 501  501          flock_alert(fdsB[0]);
 502  502          flock_cleanup_child(pidB, fdsB);
 503  503  
 504  504          assert_all_unlocked();
 505  505  
 506  506          flock_log(" ok\n");
 507  507  }
 508  508  
 509  509  
 510  510  static void
 511  511  flock_test_ofd_sameproc(void)
 512  512  {
 513  513          lockinfo_t afd1, afd2, afd3;
 514  514  
 515  515          VERIFY3S(flock_copyfil(&flock_fileA, &afd1), ==, 0);
 516  516          VERIFY3S(flock_copyfil(&flock_fileA, &afd2), ==, 0);
 517  517          VERIFY3S(flock_copyfil(&flock_fileA, &afd3), ==, 0);
 518  518  
 519  519          flock_log("Acquiring first two shared locks...");
 520  520          VERIFY3S(flock(afd1.lf_fd, LOCK_SH), ==, 0);
 521  521          VERIFY3S(flock(afd2.lf_fd, LOCK_SH), ==, 0);
 522  522          assert_read_locked_by(&flock_fileA, -1);
 523  523          flock_log(" ok\n");
 524  524  
 525  525          flock_log("Acquiring an exclusive lock should fail w/ EWOULDBLOCK...");
 526  526          VERIFY3S(flock(afd3.lf_fd, LOCK_EX|LOCK_NB), ==, -1);
 527  527          VERIFY3U(errno, ==, EWOULDBLOCK);
 528  528          flock_log(" ok\n");
 529  529  
 530  530          flock_log("Releasing to acquire an exclusive lock...");
 531  531          VERIFY3S(flock(afd1.lf_fd, LOCK_UN), ==, 0);
 532  532          VERIFY3S(flock(afd2.lf_fd, LOCK_UN), ==, 0);
 533  533          flock_log(" ok\n");
 534  534  
 535  535          flock_log("Acquiring an exclusive lock...");
 536  536          VERIFY3S(flock(afd3.lf_fd, LOCK_EX), ==, 0);
 537  537          assert_write_locked_by(&flock_fileA, -1);
 538  538          flock_log(" ok\n");
 539  539  
 540  540          flock_log("Acquiring a shared lock should fail w/ EWOULDBLOCK...");
 541  541          VERIFY3S(flock(afd1.lf_fd, LOCK_EX|LOCK_NB), ==, -1);
 542  542          VERIFY3U(errno, ==, EWOULDBLOCK);
 543  543          VERIFY3S(flock(afd2.lf_fd, LOCK_EX|LOCK_NB), ==, -1);
 544  544          VERIFY3U(errno, ==, EWOULDBLOCK);
 545  545          flock_log(" ok\n");
 546  546  
 547  547          flock_log("Releasing exclusive lock...");
 548  548          VERIFY3S(flock(afd3.lf_fd, LOCK_UN), ==, 0);
 549  549          assert_all_unlocked();
 550  550          flock_log(" ok\n");
 551  551  
 552  552          flock_rminfo(&afd1);
 553  553          flock_rminfo(&afd2);
 554  554          flock_rminfo(&afd3);
 555  555  }
 556  556  
 557  557  
 558  558  static void
 559  559  flock_runtests(void)
 560  560  {
 561  561          lock_style_t first, second;
 562  562          int i;
 563  563  
 564  564          flock_log("# Exclusive lock tests\n");
 565  565          for (first = (lock_style_t)0; first < LSTYLE_LAST; first++) {
 566  566                  for (second = (lock_style_t)0; second < LSTYLE_LAST; second++) {
 567  567                          flock_test_exclusive(first, second,
 568  568                              &flock_fileA, &flock_fileB, B_TRUE);
 569  569                          flock_test_exclusive(first, second,
 570  570                              &flock_fileA, &flock_fileB, B_FALSE);
 571  571                  }
 572  572          }
 573  573  
 574  574          flock_log("# Shared lock tests\n");
 575  575          for (first = (lock_style_t)0; first < LSTYLE_LAST; first++) {
 576  576                  for (second = (lock_style_t)0; second < LSTYLE_LAST; second++) {
 577  577                          flock_test_shared(first, second,
 578  578                              &flock_fileA, &flock_fileB, B_TRUE);
 579  579                          flock_test_shared(first, second,
 580  580                              &flock_fileA, &flock_fileB, B_FALSE);
 581  581                  }
 582  582          }
 583  583  
 584  584          flock_log("# flock(3C) directory lock tests\n");
 585  585          flock_test_exclusive(LSTYLE_FLOCK, LSTYLE_FLOCK,
 586  586              &flock_dirA, &flock_dirB, B_TRUE);
 587  587          flock_test_exclusive(LSTYLE_FLOCK, LSTYLE_FLOCK,
 588  588              &flock_dirA, &flock_dirB, B_FALSE);
 589  589          flock_test_shared(LSTYLE_FLOCK, LSTYLE_FLOCK,
 590  590              &flock_dirA, &flock_dirB, B_TRUE);
 591  591          flock_test_shared(LSTYLE_FLOCK, LSTYLE_FLOCK,
 592  592              &flock_dirA, &flock_dirB, B_FALSE);
 593  593  
 594  594  
 595  595          flock_log("# Invalid fcntl(2) parameters tests\n");
 596  596          for (i = 0; i < sizeof (cmds) / sizeof (short); i++) {
 597  597                  flock_test_invalid(&flock_fileA, cmds[i], 200, 0, 0, 0);
 598  598                  flock_test_invalid(&flock_fileA, cmds[i], -1, 0, 0, 0);
 599  599          }
 600  600          for (i = 3; i < sizeof (cmds) / sizeof (short); i++) {
 601  601                  flock_test_invalid(&flock_fileA, cmds[i], F_WRLCK, 1, 0, 0);
 602  602                  flock_test_invalid(&flock_fileA, cmds[i], F_WRLCK, 0, 1, 0);
 603  603                  flock_test_invalid(&flock_fileA, cmds[i], F_WRLCK, 0, 0, 1);
 604  604          }
 605  605  
 606  606          flock_log("# Testing that multiple OFD locks work in a process\n");
 607  607          flock_test_ofd_sameproc();
 608  608  
 609  609          flock_log("# Testing flock(3C) upgrade/downgrade tests\n");
 610  610          flock_test_upgrade_downgrade();
 611  611  }
 612  612  
 613  613  
 614  614  int
 615  615  main(int argc, char *argv[])
 616  616  {
 617  617          char *basestr, *suffix, *dirstr, *dirpath;
 618  618          pid_t testrunner;
 619  619          int exval;
 620  620  
 621  621          LOG = B_TRUE;
 622  622  
 623  623          if (argc < 1) {
 624  624                  errx(EXIT_FAILURE, "Can't find program name!");
 625  625          }
 626  626  
 627  627          dirstr = strdup(argv[0]);
 628  628          dirpath = dirname(dirstr);
 629  629          basestr = strdup(argv[0]);
 630  630          suffix = basename(basestr);
 631  631  
 632  632          while (*suffix != '.' && *suffix != '\0') {
 633  633                  suffix += 1;
 634  634          }
 635  635  
 636  636          if (asprintf(&acqprog, "%s/acquire-lock%s", dirpath, suffix) < 0) {
 637  637                  errx(EXIT_FAILURE,
 638  638                      "Can't generate lock acquisition program name!");
 639  639          }
 640  640  
 641  641          if (access(acqprog, X_OK) != 0) {
 642  642                  err(EXIT_FAILURE,
 643  643                      "Can't run lock acquisition program %s", acqprog);
 644  644          }
 645  645  
 646  646          /* Create several lockfiles for testing */
 647  647          if (flock_mkfil(&flock_fileA) != 0 ||
 648  648              flock_mkfil(&flock_fileB) != 0 ||
 649  649              flock_mkdir(&flock_dirA) != 0 ||
 650  650              flock_mkdir(&flock_dirB) != 0) {
 651  651                  exval = 1;
 652  652                  goto cleanup;
 653  653          }
 654  654  
 655  655          /*
 656  656           * We run the tests in a child process so that when tests fail
 657  657           * we can still clean up our temporary files.
 658  658           */
 659  659          testrunner = fork();
 660  660          if (testrunner == (pid_t)-1) {
 661  661                  err(EXIT_FAILURE, "Unable to fork to run tests");
 662  662          } else if (testrunner == (pid_t)0) {
 663  663                  flock_runtests();
 664  664                  return (0);
 665  665          }
 666  666  
 667  667          exval = flock_wait(testrunner);
 668  668  
 669  669  cleanup:
 670  670          free(basestr);
 671  671          free(dirstr);
 672  672          flock_rminfo(&flock_fileA);
 673  673          flock_rminfo(&flock_fileB);
 674  674          flock_rminfo(&flock_dirA);
 675  675          flock_rminfo(&flock_dirB);
 676  676          return (exval);
 677  677  }
  
    | 
      ↓ open down ↓ | 
    677 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX