Print this page
    
2619 asynchronous destruction of ZFS file systems
2747 SPA versioning with zfs feature flags
Reviewed by: Matt Ahrens <mahrens@delphix.com>
Reviewed by: George Wilson <gwilson@delphix.com>
Reviewed by: Richard Lowe <richlowe@richlowe.net>
Reviewed by: Dan Kruchinin <dan.kruchinin@gmail.com>
Approved by: Dan McDonald <danmcd@nexenta.com>
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/lib/libc/port/threads/assfail.c
          +++ new/usr/src/lib/libc/port/threads/assfail.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  
    | 
      ↓ open down ↓ | 
    15 lines elided | 
    
      ↑ open up ↑ | 
  
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23   23   * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  24   24   * Use is subject to license terms.
  25   25   */
       26 +/*
       27 + * Copyright (c) 2012 by Delphix. All rights reserved.
       28 + */
  26   29  
  27   30  #include "lint.h"
  28   31  #include "thr_uberdata.h"
  29   32  
  30   33  const char *panicstr;
  31   34  ulwp_t *panic_thread;
  32   35  
  33   36  static mutex_t assert_lock = DEFAULTMUTEX;
  34   37  static ulwp_t *assert_thread = NULL;
  35   38  
  36   39  /*
  37   40   * Called from __assert() to set panicstr and panic_thread.
  38   41   */
  39   42  void
  40   43  __set_panicstr(const char *msg)
  41   44  {
  42   45          panicstr = msg;
  43   46          panic_thread = __curthread();
  44   47  }
  45   48  
  46   49  /*
  47   50   * Called from exit() (atexit function) to give precedence
  48   51   * to assertion failures and a core dump over _exit().
  49   52   */
  50   53  void
  51   54  grab_assert_lock()
  52   55  {
  53   56          (void) _lwp_mutex_lock(&assert_lock);
  54   57  }
  55   58  
  56   59  static void
  57   60  Abort(const char *msg)
  58   61  {
  59   62          ulwp_t *self;
  60   63          struct sigaction act;
  61   64          sigset_t sigmask;
  62   65          lwpid_t lwpid;
  63   66  
  64   67          /* to help with core file debugging */
  65   68          panicstr = msg;
  66   69          if ((self = __curthread()) != NULL) {
  67   70                  panic_thread = self;
  68   71                  lwpid = self->ul_lwpid;
  69   72          } else {
  70   73                  lwpid = _lwp_self();
  71   74          }
  72   75  
  73   76          /* set SIGABRT signal handler to SIG_DFL w/o grabbing any locks */
  74   77          (void) memset(&act, 0, sizeof (act));
  75   78          act.sa_sigaction = SIG_DFL;
  76   79          (void) __sigaction(SIGABRT, &act, NULL);
  77   80  
  78   81          /* delete SIGABRT from the signal mask */
  79   82          (void) sigemptyset(&sigmask);
  80   83          (void) sigaddset(&sigmask, SIGABRT);
  81   84          (void) __lwp_sigmask(SIG_UNBLOCK, &sigmask);
  82   85  
  83   86          (void) _lwp_kill(lwpid, SIGABRT);       /* never returns */
  84   87          (void) kill(getpid(), SIGABRT); /* if it does, try harder */
  85   88          _exit(127);
  86   89  }
  87   90  
  88   91  /*
  89   92   * Write a panic message w/o grabbing any locks other than assert_lock.
  90   93   * We have no idea what locks are held at this point.
  91   94   */
  92   95  static void
  93   96  common_panic(const char *head, const char *why)
  94   97  {
  95   98          char msg[400];  /* no panic() message in the library is this long */
  96   99          ulwp_t *self;
  97  100          size_t len1, len2;
  98  101  
  99  102          if ((self = __curthread()) != NULL)
 100  103                  enter_critical(self);
 101  104          (void) _lwp_mutex_lock(&assert_lock);
 102  105  
 103  106          (void) memset(msg, 0, sizeof (msg));
 104  107          (void) strcpy(msg, head);
 105  108          len1 = strlen(msg);
 106  109          len2 = strlen(why);
 107  110          if (len1 + len2 >= sizeof (msg))
 108  111                  len2 = sizeof (msg) - len1 - 1;
 109  112          (void) strncat(msg, why, len2);
 110  113          len1 = strlen(msg);
 111  114          if (msg[len1 - 1] != '\n')
 112  115                  msg[len1++] = '\n';
 113  116          (void) __write(2, msg, len1);
 114  117          Abort(msg);
 115  118  }
 116  119  
 117  120  void
 118  121  thr_panic(const char *why)
 119  122  {
 120  123          common_panic("*** libc thread failure: ", why);
 121  124  }
 122  125  
 123  126  void
 124  127  aio_panic(const char *why)
 125  128  {
 126  129          common_panic("*** libc aio system failure: ", why);
 127  130  }
 128  131  
 129  132  /*
 130  133   * Utility function for converting a long integer to a string, avoiding stdio.
 131  134   * 'base' must be one of 10 or 16
 132  135   */
 133  136  void
 134  137  ultos(uint64_t n, int base, char *s)
 135  138  {
 136  139          char lbuf[24];          /* 64 bits fits in 16 hex digits, 20 decimal */
 137  140          char *cp = lbuf;
 138  141  
 139  142          do {
 140  143                  *cp++ = "0123456789abcdef"[n%base];
 141  144                  n /= base;
 142  145          } while (n);
 143  146          if (base == 16) {
 144  147                  *s++ = '0';
 145  148                  *s++ = 'x';
 146  149          }
 147  150          do {
 148  151                  *s++ = *--cp;
 149  152          } while (cp > lbuf);
 150  153          *s = '\0';
 151  154  }
 152  155  
 153  156  /*
 154  157   * Report application lock usage error for mutexes and condvars.
 155  158   * Not called if _THREAD_ERROR_DETECTION=0.
 156  159   * Continue execution if _THREAD_ERROR_DETECTION=1.
 157  160   * Dump core if _THREAD_ERROR_DETECTION=2.
 158  161   */
 159  162  void
 160  163  lock_error(const mutex_t *mp, const char *who, void *cv, const char *msg)
 161  164  {
 162  165          mutex_t mcopy;
 163  166          char buf[800];
 164  167          uberdata_t *udp;
 165  168          ulwp_t *self;
 166  169          lwpid_t lwpid;
 167  170          pid_t pid;
 168  171  
 169  172          /*
 170  173           * Take a snapshot of the mutex before it changes (we hope!).
 171  174           * Use memcpy() rather than 'mcopy = *mp' in case mp is unaligned.
 172  175           */
 173  176          (void) memcpy(&mcopy, mp, sizeof (mcopy));
 174  177  
 175  178          /* avoid recursion deadlock */
 176  179          if ((self = __curthread()) != NULL) {
 177  180                  if (assert_thread == self)
 178  181                          _exit(127);
 179  182                  enter_critical(self);
 180  183                  (void) _lwp_mutex_lock(&assert_lock);
 181  184                  assert_thread = self;
 182  185                  lwpid = self->ul_lwpid;
 183  186                  udp = self->ul_uberdata;
 184  187                  pid = udp->pid;
 185  188          } else {
 186  189                  self = NULL;
 187  190                  (void) _lwp_mutex_lock(&assert_lock);
 188  191                  lwpid = _lwp_self();
 189  192                  udp = &__uberdata;
 190  193                  pid = getpid();
 191  194          }
 192  195  
 193  196          (void) strcpy(buf,
 194  197              "\n*** _THREAD_ERROR_DETECTION: lock usage error detected ***\n");
 195  198          (void) strcat(buf, who);
 196  199          (void) strcat(buf, "(");
 197  200          if (cv != NULL) {
 198  201                  ultos((uint64_t)(uintptr_t)cv, 16, buf + strlen(buf));
 199  202                  (void) strcat(buf, ", ");
 200  203          }
 201  204          ultos((uint64_t)(uintptr_t)mp, 16, buf + strlen(buf));
 202  205          (void) strcat(buf, ")");
 203  206          if (msg != NULL) {
 204  207                  (void) strcat(buf, ": ");
 205  208                  (void) strcat(buf, msg);
 206  209          } else if (!mutex_held(&mcopy)) {
 207  210                  (void) strcat(buf, ": calling thread does not own the lock");
 208  211          } else if (mcopy.mutex_rcount) {
 209  212                  (void) strcat(buf, ": mutex rcount = ");
 210  213                  ultos((uint64_t)mcopy.mutex_rcount, 10, buf + strlen(buf));
 211  214          } else {
 212  215                  (void) strcat(buf, ": calling thread already owns the lock");
 213  216          }
 214  217          (void) strcat(buf, "\ncalling thread is ");
 215  218          ultos((uint64_t)(uintptr_t)self, 16, buf + strlen(buf));
 216  219          (void) strcat(buf, " thread-id ");
 217  220          ultos((uint64_t)lwpid, 10, buf + strlen(buf));
 218  221          if (msg != NULL || mutex_held(&mcopy))
 219  222                  /* EMPTY */;
 220  223          else if (mcopy.mutex_lockw == 0)
 221  224                  (void) strcat(buf, "\nthe lock is unowned");
 222  225          else if (!(mcopy.mutex_type & USYNC_PROCESS)) {
 223  226                  (void) strcat(buf, "\nthe lock owner is ");
 224  227                  ultos((uint64_t)mcopy.mutex_owner, 16, buf + strlen(buf));
 225  228          } else {
 226  229                  (void) strcat(buf, " in process ");
 227  230                  ultos((uint64_t)pid, 10, buf + strlen(buf));
 228  231                  (void) strcat(buf, "\nthe lock owner is ");
 229  232                  ultos((uint64_t)mcopy.mutex_owner, 16, buf + strlen(buf));
 230  233                  (void) strcat(buf, " in process ");
 231  234                  ultos((uint64_t)mcopy.mutex_ownerpid, 10, buf + strlen(buf));
 232  235          }
 233  236          (void) strcat(buf, "\n\n");
 234  237          (void) __write(2, buf, strlen(buf));
 235  238          if (udp->uberflags.uf_thread_error_detection >= 2)
 236  239                  Abort(buf);
 237  240          assert_thread = NULL;
 238  241          (void) _lwp_mutex_unlock(&assert_lock);
 239  242          if (self != NULL)
 240  243                  exit_critical(self);
 241  244  }
 242  245  
 243  246  /*
 244  247   * Report application lock usage error for rwlocks.
 245  248   * Not called if _THREAD_ERROR_DETECTION=0.
 246  249   * Continue execution if _THREAD_ERROR_DETECTION=1.
 247  250   * Dump core if _THREAD_ERROR_DETECTION=2.
 248  251   */
 249  252  void
 250  253  rwlock_error(const rwlock_t *rp, const char *who, const char *msg)
 251  254  {
 252  255          rwlock_t rcopy;
 253  256          uint32_t rwstate;
 254  257          char buf[800];
 255  258          uberdata_t *udp;
 256  259          ulwp_t *self;
 257  260          lwpid_t lwpid;
 258  261          pid_t pid;
 259  262          int process;
 260  263  
 261  264          /*
 262  265           * Take a snapshot of the rwlock before it changes (we hope!).
 263  266           * Use memcpy() rather than 'rcopy = *rp' in case rp is unaligned.
 264  267           */
 265  268          (void) memcpy(&rcopy, rp, sizeof (rcopy));
 266  269  
 267  270          /* avoid recursion deadlock */
 268  271          if ((self = __curthread()) != NULL) {
 269  272                  if (assert_thread == self)
 270  273                          _exit(127);
 271  274                  enter_critical(self);
 272  275                  (void) _lwp_mutex_lock(&assert_lock);
 273  276                  assert_thread = self;
 274  277                  lwpid = self->ul_lwpid;
 275  278                  udp = self->ul_uberdata;
 276  279                  pid = udp->pid;
 277  280          } else {
 278  281                  self = NULL;
 279  282                  (void) _lwp_mutex_lock(&assert_lock);
 280  283                  lwpid = _lwp_self();
 281  284                  udp = &__uberdata;
 282  285                  pid = getpid();
 283  286          }
 284  287  
 285  288          rwstate = (uint32_t)rcopy.rwlock_readers;
 286  289          process = (rcopy.rwlock_type & USYNC_PROCESS);
 287  290  
 288  291          (void) strcpy(buf,
 289  292              "\n*** _THREAD_ERROR_DETECTION: lock usage error detected ***\n");
 290  293          (void) strcat(buf, who);
 291  294          (void) strcat(buf, "(");
 292  295          ultos((uint64_t)(uintptr_t)rp, 16, buf + strlen(buf));
 293  296          (void) strcat(buf, "): ");
 294  297          (void) strcat(buf, msg);
 295  298          (void) strcat(buf, "\ncalling thread is ");
 296  299          ultos((uint64_t)(uintptr_t)self, 16, buf + strlen(buf));
 297  300          (void) strcat(buf, " thread-id ");
 298  301          ultos((uint64_t)lwpid, 10, buf + strlen(buf));
 299  302          if (process) {
 300  303                  (void) strcat(buf, " in process ");
 301  304                  ultos((uint64_t)pid, 10, buf + strlen(buf));
 302  305          }
 303  306          if (rwstate & URW_WRITE_LOCKED) {
 304  307                  (void) strcat(buf, "\nthe writer lock owner is ");
 305  308                  ultos((uint64_t)rcopy.rwlock_owner, 16,
 306  309                      buf + strlen(buf));
 307  310                  if (process) {
 308  311                          (void) strcat(buf, " in process ");
 309  312                          ultos((uint64_t)rcopy.rwlock_ownerpid, 10,
 310  313                              buf + strlen(buf));
 311  314                  }
 312  315          } else if (rwstate & URW_READERS_MASK) {
 313  316                  (void) strcat(buf, "\nthe reader lock is held by ");
 314  317                  ultos((uint64_t)(rwstate & URW_READERS_MASK), 10,
 315  318                      buf + strlen(buf));
 316  319                  (void) strcat(buf, " readers");
 317  320          } else {
 318  321                  (void) strcat(buf, "\nthe lock is unowned");
 319  322          }
 320  323          if (rwstate & URW_HAS_WAITERS)
 321  324                  (void) strcat(buf, "\nand the lock appears to have waiters");
 322  325          (void) strcat(buf, "\n\n");
 323  326          (void) __write(2, buf, strlen(buf));
 324  327          if (udp->uberflags.uf_thread_error_detection >= 2)
 325  328                  Abort(buf);
 326  329          assert_thread = NULL;
 327  330          (void) _lwp_mutex_unlock(&assert_lock);
 328  331          if (self != NULL)
 329  332                  exit_critical(self);
 330  333  }
 331  334  
 332  335  /*
 333  336   * Report a thread usage error.
 334  337   * Not called if _THREAD_ERROR_DETECTION=0.
 335  338   * Writes message and continues execution if _THREAD_ERROR_DETECTION=1.
 336  339   * Writes message and dumps core if _THREAD_ERROR_DETECTION=2.
 337  340   */
 338  341  void
 339  342  thread_error(const char *msg)
 340  343  {
 341  344          char buf[800];
 342  345          uberdata_t *udp;
 343  346          ulwp_t *self;
 344  347          lwpid_t lwpid;
 345  348  
 346  349          /* avoid recursion deadlock */
 347  350          if ((self = __curthread()) != NULL) {
 348  351                  if (assert_thread == self)
 349  352                          _exit(127);
 350  353                  enter_critical(self);
 351  354                  (void) _lwp_mutex_lock(&assert_lock);
 352  355                  assert_thread = self;
 353  356                  lwpid = self->ul_lwpid;
 354  357                  udp = self->ul_uberdata;
 355  358          } else {
 356  359                  self = NULL;
 357  360                  (void) _lwp_mutex_lock(&assert_lock);
 358  361                  lwpid = _lwp_self();
 359  362                  udp = &__uberdata;
 360  363          }
 361  364  
 362  365          (void) strcpy(buf, "\n*** _THREAD_ERROR_DETECTION: "
 363  366              "thread usage error detected ***\n*** ");
 364  367          (void) strcat(buf, msg);
 365  368  
 366  369          (void) strcat(buf, "\n*** calling thread is ");
 367  370          ultos((uint64_t)(uintptr_t)self, 16, buf + strlen(buf));
 368  371          (void) strcat(buf, " thread-id ");
 369  372          ultos((uint64_t)lwpid, 10, buf + strlen(buf));
 370  373          (void) strcat(buf, "\n\n");
 371  374          (void) __write(2, buf, strlen(buf));
 372  375          if (udp->uberflags.uf_thread_error_detection >= 2)
 373  376                  Abort(buf);
 374  377          assert_thread = NULL;
 375  378          (void) _lwp_mutex_unlock(&assert_lock);
 376  379          if (self != NULL)
 377  380                  exit_critical(self);
 378  381  }
 379  382  
 380  383  /*
 381  384   * We use __assfail() because the libc __assert() calls
 382  385   * gettext() which calls malloc() which grabs a mutex.
 383  386   * We do everything without calling standard i/o.
 384  387   * assfail() and _assfail() are exported functions;
 385  388   * __assfail() is private to libc.
 386  389   */
 387  390  #pragma weak _assfail = __assfail
 388  391  void
 389  392  __assfail(const char *assertion, const char *filename, int line_num)
 390  393  {
 391  394          char buf[800];  /* no assert() message in the library is this long */
 392  395          ulwp_t *self;
 393  396          lwpid_t lwpid;
 394  397  
 395  398          /* avoid recursion deadlock */
 396  399          if ((self = __curthread()) != NULL) {
 397  400                  if (assert_thread == self)
 398  401                          _exit(127);
 399  402                  enter_critical(self);
 400  403                  (void) _lwp_mutex_lock(&assert_lock);
 401  404                  assert_thread = self;
 402  405                  lwpid = self->ul_lwpid;
 403  406          } else {
 404  407                  self = NULL;
 405  408                  (void) _lwp_mutex_lock(&assert_lock);
 406  409                  lwpid = _lwp_self();
 407  410          }
 408  411  
 409  412          (void) strcpy(buf, "assertion failed for thread ");
 410  413          ultos((uint64_t)(uintptr_t)self, 16, buf + strlen(buf));
 411  414          (void) strcat(buf, ", thread-id ");
 412  415          ultos((uint64_t)lwpid, 10, buf + strlen(buf));
 413  416          (void) strcat(buf, ": ");
 414  417          (void) strcat(buf, assertion);
 415  418          (void) strcat(buf, ", file ");
 416  419          (void) strcat(buf, filename);
 417  420          (void) strcat(buf, ", line ");
 418  421          ultos((uint64_t)line_num, 10, buf + strlen(buf));
 419  422          (void) strcat(buf, "\n");
 420  423          (void) __write(2, buf, strlen(buf));
 421  424          /*
 422  425           * We could replace the call to Abort() with the following code
 423  426           * if we want just to issue a warning message and not die.
 424  427           *      assert_thread = NULL;
 425  428           *      _lwp_mutex_unlock(&assert_lock);
 426  429           *      if (self != NULL)
 427  430           *              exit_critical(self);
 428  431           */
 429  432          Abort(buf);
 430  433  }
 431  434  
 432  435  /*
 433  436   * We define and export this version of assfail() just because libaio
  
    | 
      ↓ open down ↓ | 
    398 lines elided | 
    
      ↑ open up ↑ | 
  
 434  437   * used to define and export it, needlessly.  Now that libaio is folded
 435  438   * into libc, we need to continue this for ABI/version reasons.
 436  439   * We don't use "#pragma weak assfail __assfail" in order to avoid
 437  440   * warnings from the check_fnames utility at build time for libraries
 438  441   * that define their own version of assfail().
 439  442   */
 440  443  void
 441  444  assfail(const char *assertion, const char *filename, int line_num)
 442  445  {
 443  446          __assfail(assertion, filename, line_num);
      447 +}
      448 +
      449 +void
      450 +assfail3(const char *assertion, uintmax_t lv, const char *op, uintmax_t rv,
      451 +    const char *filename, int line_num)
      452 +{
      453 +        char buf[1000];
      454 +        (void) strcpy(buf, assertion);
      455 +        (void) strcat(buf, " (0x");
      456 +        ultos((uint64_t)lv, 16, buf + strlen(buf));
      457 +        (void) strcat(buf, " ");
      458 +        (void) strcat(buf, op);
      459 +        (void) strcat(buf, " 0x");
      460 +        ultos((uint64_t)rv, 16, buf + strlen(buf));
      461 +        (void) strcat(buf, ")");
      462 +        __assfail(buf, filename, line_num);
 444  463  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX