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