diff --git a/cmd/zed/zed_log.h b/cmd/zed/zed_log.h index ed88ad41d7e2..18ab0553ea40 100644 --- a/cmd/zed/zed_log.h +++ b/cmd/zed/zed_log.h @@ -1,44 +1,45 @@ /* * This file is part of the ZFS Event Daemon (ZED). * * Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049). * Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC. * Refer to the OpenZFS git commit log for authoritative copyright attribution. * * The contents of this file are subject to the terms of the * Common Development and Distribution License Version 1.0 (CDDL-1.0). * You can obtain a copy of the license from the top-level file * "OPENSOLARIS.LICENSE" or at . * You may not use this file except in compliance with the license. */ #ifndef ZED_LOG_H #define ZED_LOG_H #include void zed_log_init(const char *identity); void zed_log_fini(void); void zed_log_pipe_open(void); void zed_log_pipe_close_reads(void); void zed_log_pipe_close_writes(void); void zed_log_pipe_wait(void); void zed_log_stderr_open(int priority); void zed_log_stderr_close(void); void zed_log_syslog_open(int facility); void zed_log_syslog_close(void); void zed_log_msg(int priority, const char *fmt, ...); +__attribute__((format(printf, 1, 2), __noreturn__)) void zed_log_die(const char *fmt, ...); #endif /* !ZED_LOG_H */ diff --git a/contrib/coverity/model.c b/contrib/coverity/model.c index d27abd038767..8baa3a7e2d31 100644 --- a/contrib/coverity/model.c +++ b/contrib/coverity/model.c @@ -1,422 +1,359 @@ /* * Coverity Scan model * https://scan.coverity.com/models * * This is a modeling file for Coverity Scan. * Modeling helps to avoid false positives. * * - Modeling doesn't need full structs and typedefs. Rudimentary structs * and similar types are sufficient. * - An uninitialized local pointer is not an error. It signifies that the * variable could be either NULL or have some data. * * Coverity Scan doesn't pick up modifications automatically. The model file * must be uploaded by an admin in the analysis settings. * * Some of this initially cribbed from: * * https://github.com/kees/coverity-linux/blob/trunk/model.c * * The below model was based on the original model by Brian Behlendorf for the * original zfsonlinux/zfs repository. Some inspiration was taken from * kees/coverity-linux, specifically involving memory copies. */ #include #define UMEM_DEFAULT 0x0000 /* normal -- may fail */ #define UMEM_NOFAIL 0x0100 /* Never fails */ #define NULL (0) int condition0, condition1; -void -abort() -{ - __coverity_panic__(); -} - -void -exit(int status) -{ - (void) status; - - __coverity_panic__(); -} - -void -_exit(int status) -{ - (void) status; - - __coverity_panic__(); -} - -void -zed_log_die(const char *fmt, ...) -{ - __coverity_format_string_sink__(fmt); - __coverity_panic__(); -} - -void -panic(const char *fmt, ...) -{ - __coverity_format_string_sink__(fmt); - __coverity_panic__(); -} - -void -vpanic(const char *fmt, va_list adx) -{ - (void) adx; - - __coverity_format_string_sink__(fmt); - __coverity_panic__(); -} - -void -uu_panic(const char *format, ...) -{ - __coverity_format_string_sink__(format); - __coverity_panic__(); -} - -int -libspl_assertf(const char *file, const char *func, int line, - const char *format, ...) -{ - __coverity_format_string_sink__(format); - __coverity_panic__(); -} - int ddi_copyin(const void *from, void *to, size_t len, int flags) { __coverity_tainted_data_argument__(from); __coverity_tainted_data_argument__(to); __coverity_writeall__(to); } void * memset(void *dst, int c, size_t len) { __coverity_writeall__(dst); return (dst); } void * memmove(void *dst, void *src, size_t len) { __coverity_writeall__(dst); return (dst); } void * memcpy(void *dst, void *src, size_t len) { __coverity_writeall__(dst); return (dst); } void * umem_alloc_aligned(size_t size, size_t align, int kmflags) { (void) align; - if (UMEM_NOFAIL & kmflags == UMEM_NOFAIL) + if ((UMEM_NOFAIL & kmflags) == UMEM_NOFAIL) return (__coverity_alloc__(size)); else if (condition0) return (__coverity_alloc__(size)); else return (NULL); } void * umem_alloc(size_t size, int kmflags) { - if (UMEM_NOFAIL & kmflags == UMEM_NOFAIL) + if ((UMEM_NOFAIL & kmflags) == UMEM_NOFAIL) return (__coverity_alloc__(size)); else if (condition0) return (__coverity_alloc__(size)); else return (NULL); } void * umem_zalloc(size_t size, int kmflags) { - if (UMEM_NOFAIL & kmflags == UMEM_NOFAIL) + if ((UMEM_NOFAIL & kmflags) == UMEM_NOFAIL) return (__coverity_alloc__(size)); else if (condition0) return (__coverity_alloc__(size)); else return (NULL); } void umem_free(void *buf, size_t size) { (void) size; __coverity_free__(buf); } +typedef struct {} umem_cache_t; + +void * +umem_cache_alloc(umem_cache_t *skc, int flags) +{ + (void) skc; + + if (condition1) + __coverity_sleep__(); + + if ((UMEM_NOFAIL & flags) == UMEM_NOFAIL) + return (__coverity_alloc_nosize__()); + else if (condition0) + return (__coverity_alloc_nosize__()); + else + return (NULL); +} + +void +umem_cache_free(umem_cache_t *skc, void *obj) +{ + (void) skc; + + __coverity_free__(obj); +} + void * spl_kmem_alloc(size_t sz, int fl, const char *func, int line) { (void) func; (void) line; if (condition1) __coverity_sleep__(); if (fl == 0) { return (__coverity_alloc__(sz)); } else if (condition0) return (__coverity_alloc__(sz)); else return (NULL); } void * spl_kmem_zalloc(size_t sz, int fl, const char *func, int line) { (void) func; (void) line; if (condition1) __coverity_sleep__(); if (fl == 0) { return (__coverity_alloc__(sz)); } else if (condition0) return (__coverity_alloc__(sz)); else return (NULL); } void spl_kmem_free(const void *ptr, size_t sz) { (void) sz; __coverity_free__(ptr); } typedef struct {} spl_kmem_cache_t; void * spl_kmem_cache_alloc(spl_kmem_cache_t *skc, int flags) { (void) skc; if (condition1) __coverity_sleep__(); if (flags == 0) { return (__coverity_alloc_nosize__()); } else if (condition0) return (__coverity_alloc_nosize__()); else return (NULL); } void spl_kmem_cache_free(spl_kmem_cache_t *skc, void *obj) { (void) skc; __coverity_free__(obj); } void malloc(size_t size) { __coverity_alloc__(size); } void free(void *buf) { __coverity_free__(buf); } -int -spl_panic(const char *file, const char *func, int line, const char *fmt, ...) -{ - __coverity_format_string_sink__(fmt); - __coverity_panic__(); -} - int sched_yield(void) { __coverity_sleep__(); } typedef struct {} kmutex_t; typedef struct {} krwlock_t; typedef int krw_t; /* * Coverty reportedly does not support macros, so this only works for * userspace. */ void mutex_enter(kmutex_t *mp) { if (condition0) __coverity_sleep__(); __coverity_exclusive_lock_acquire__(mp); } int mutex_tryenter(kmutex_t *mp) { if (condition0) { __coverity_exclusive_lock_acquire__(mp); return (1); } return (0); } void mutex_exit(kmutex_t *mp) { __coverity_exclusive_lock_release__(mp); } void rw_enter(krwlock_t *rwlp, krw_t rw) { (void) rw; if (condition0) __coverity_sleep__(); __coverity_recursive_lock_acquire__(rwlp); } void rw_exit(krwlock_t *rwlp) { __coverity_recursive_lock_release__(rwlp); } int rw_tryenter(krwlock_t *rwlp, krw_t rw) { if (condition0) { __coverity_recursive_lock_acquire__(rwlp); return (1); } return (0); } /* Thus, we fallback to the Linux kernel locks */ struct {} mutex; struct {} rw_semaphore; void mutex_lock(struct mutex *lock) { if (condition0) { __coverity_sleep__(); } __coverity_exclusive_lock_acquire__(lock); } void mutex_unlock(struct mutex *lock) { __coverity_exclusive_lock_release__(lock); } void down_read(struct rw_semaphore *sem) { if (condition0) { __coverity_sleep__(); } __coverity_recursive_lock_acquire__(sem); } void down_write(struct rw_semaphore *sem) { if (condition0) { __coverity_sleep__(); } __coverity_recursive_lock_acquire__(sem); } int down_read_trylock(struct rw_semaphore *sem) { if (condition0) { __coverity_recursive_lock_acquire__(sem); return (1); } return (0); } int down_write_trylock(struct rw_semaphore *sem) { if (condition0) { __coverity_recursive_lock_acquire__(sem); return (1); } return (0); } void up_read(struct rw_semaphore *sem) { __coverity_recursive_lock_release__(sem); } void up_write(struct rw_semaphore *sem) { __coverity_recursive_lock_release__(sem); } int __cond_resched(void) { if (condition0) { __coverity_sleep__(); } } - -/* - * An endian-independent filesystem must support doing byte swaps on data. We - * attempt to suppress taint warnings, which are false positives for us. - */ -void -byteswap_uint64_array(void *vbuf, size_t size) -{ - __coverity_tainted_data_sanitize__(vbuf); -} - -void -byteswap_uint32_array(void *vbuf, size_t size) -{ - __coverity_tainted_data_sanitize__(vbuf); -} - -void -byteswap_uint16_array(void *vbuf, size_t size) -{ - __coverity_tainted_data_sanitize__(vbuf); -} diff --git a/include/libuutil_impl.h b/include/libuutil_impl.h index b9907447afd9..7aa8f0cedf15 100644 --- a/include/libuutil_impl.h +++ b/include/libuutil_impl.h @@ -1,174 +1,175 @@ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or https://opensource.org/licenses/CDDL-1.0. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _LIBUUTIL_IMPL_H #define _LIBUUTIL_IMPL_H #include #include #include #include #ifdef __cplusplus extern "C" { #endif void uu_set_error(uint_t); -void uu_panic(const char *format, ...) __attribute__((format(printf, 1, 2))); +__attribute__((format(printf, 1, 2), __noreturn__)) +void uu_panic(const char *format, ...); /* * For debugging purposes, libuutil keeps around linked lists of all uu_lists * and uu_avls, along with pointers to their parents. These can cause false * negatives when looking for memory leaks, so we encode the pointers by * storing them with swapped endianness; this is not perfect, but it's about * the best we can do without wasting a lot of space. */ #ifdef _LP64 #define UU_PTR_ENCODE(ptr) BSWAP_64((uintptr_t)(void *)(ptr)) #else #define UU_PTR_ENCODE(ptr) BSWAP_32((uintptr_t)(void *)(ptr)) #endif #define UU_PTR_DECODE(ptr) ((void *)UU_PTR_ENCODE(ptr)) /* * uu_list structures */ typedef struct uu_list_node_impl { struct uu_list_node_impl *uln_next; struct uu_list_node_impl *uln_prev; } uu_list_node_impl_t; struct uu_list_walk { uu_list_walk_t *ulw_next; uu_list_walk_t *ulw_prev; uu_list_t *ulw_list; int8_t ulw_dir; uint8_t ulw_robust; uu_list_node_impl_t *ulw_next_result; }; struct uu_list { uintptr_t ul_next_enc; uintptr_t ul_prev_enc; uu_list_pool_t *ul_pool; uintptr_t ul_parent_enc; /* encoded parent pointer */ size_t ul_offset; size_t ul_numnodes; uint8_t ul_debug; uint8_t ul_sorted; uint8_t ul_index; /* mark for uu_list_index_ts */ uu_list_node_impl_t ul_null_node; uu_list_walk_t ul_null_walk; /* for robust walkers */ }; #define UU_LIST_PTR(ptr) ((uu_list_t *)UU_PTR_DECODE(ptr)) #define UU_LIST_POOL_MAXNAME 64 struct uu_list_pool { uu_list_pool_t *ulp_next; uu_list_pool_t *ulp_prev; char ulp_name[UU_LIST_POOL_MAXNAME]; size_t ulp_nodeoffset; size_t ulp_objsize; uu_compare_fn_t *ulp_cmp; uint8_t ulp_debug; uint8_t ulp_last_index; pthread_mutex_t ulp_lock; /* protects null_list */ uu_list_t ulp_null_list; }; /* * uu_avl structures */ typedef struct avl_node uu_avl_node_impl_t; struct uu_avl_walk { uu_avl_walk_t *uaw_next; uu_avl_walk_t *uaw_prev; uu_avl_t *uaw_avl; void *uaw_next_result; int8_t uaw_dir; uint8_t uaw_robust; }; struct uu_avl { uintptr_t ua_next_enc; uintptr_t ua_prev_enc; uu_avl_pool_t *ua_pool; uintptr_t ua_parent_enc; uint8_t ua_debug; uint8_t ua_index; /* mark for uu_avl_index_ts */ struct avl_tree ua_tree; uu_avl_walk_t ua_null_walk; }; #define UU_AVL_PTR(x) ((uu_avl_t *)UU_PTR_DECODE(x)) #define UU_AVL_POOL_MAXNAME 64 struct uu_avl_pool { uu_avl_pool_t *uap_next; uu_avl_pool_t *uap_prev; char uap_name[UU_AVL_POOL_MAXNAME]; size_t uap_nodeoffset; size_t uap_objsize; uu_compare_fn_t *uap_cmp; uint8_t uap_debug; uint8_t uap_last_index; pthread_mutex_t uap_lock; /* protects null_avl */ uu_avl_t uap_null_avl; }; /* * atfork() handlers */ void uu_avl_lockup(void); void uu_avl_release(void); void uu_list_lockup(void); void uu_list_release(void); #ifdef __cplusplus } #endif #endif /* _LIBUUTIL_IMPL_H */ diff --git a/include/os/freebsd/spl/sys/byteorder.h b/include/os/freebsd/spl/sys/byteorder.h index 4ea56094cea5..0c09757c8e15 100644 --- a/include/os/freebsd/spl/sys/byteorder.h +++ b/include/os/freebsd/spl/sys/byteorder.h @@ -1,109 +1,123 @@ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or https://opensource.org/licenses/CDDL-1.0. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END * * $FreeBSD$ */ /* * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ /* * University Copyright- Copyright (c) 1982, 1986, 1988 * The Regents of the University of California * All Rights Reserved * * University Acknowledgment- Portions of this document are derived from * software developed by the University of California, Berkeley, and its * contributors. */ #ifndef _OPENSOLARIS_SYS_BYTEORDER_H_ #define _OPENSOLARIS_SYS_BYTEORDER_H_ #include +#ifdef __COVERITY__ +/* + * Coverity's taint warnings from byteswapping are false positives for us. + * Suppress them by hiding byteswapping from Coverity. + */ +#define BSWAP_8(x) ((x) & 0xff) +#define BSWAP_16(x) ((x) & 0xffff) +#define BSWAP_32(x) ((x) & 0xffffffff) +#define BSWAP_64(x) (x) + +#else /* __COVERITY__ */ + /* * Macros to reverse byte order */ #define BSWAP_8(x) ((x) & 0xff) #define BSWAP_16(x) ((BSWAP_8(x) << 8) | BSWAP_8((x) >> 8)) #define BSWAP_32(x) ((BSWAP_16(x) << 16) | BSWAP_16((x) >> 16)) #define BSWAP_64(x) ((BSWAP_32(x) << 32) | BSWAP_32((x) >> 32)) +#endif /* __COVERITY__ */ + #define BMASK_8(x) ((x) & 0xff) #define BMASK_16(x) ((x) & 0xffff) #define BMASK_32(x) ((x) & 0xffffffff) #define BMASK_64(x) (x) /* * Macros to convert from a specific byte order to/from native byte order */ #if BYTE_ORDER == _BIG_ENDIAN #define BE_8(x) BMASK_8(x) #define BE_16(x) BMASK_16(x) #define BE_32(x) BMASK_32(x) #define BE_64(x) BMASK_64(x) #define LE_8(x) BSWAP_8(x) #define LE_16(x) BSWAP_16(x) #define LE_32(x) BSWAP_32(x) #define LE_64(x) BSWAP_64(x) #else #define LE_8(x) BMASK_8(x) #define LE_16(x) BMASK_16(x) #define LE_32(x) BMASK_32(x) #define LE_64(x) BMASK_64(x) #define BE_8(x) BSWAP_8(x) #define BE_16(x) BSWAP_16(x) #define BE_32(x) BSWAP_32(x) #define BE_64(x) BSWAP_64(x) #endif #if !defined(_STANDALONE) #if BYTE_ORDER == _BIG_ENDIAN #define htonll(x) BMASK_64(x) #define ntohll(x) BMASK_64(x) #else /* BYTE_ORDER == _LITTLE_ENDIAN */ #ifndef __LP64__ static __inline__ uint64_t htonll(uint64_t n) { return ((((uint64_t)htonl(n)) << 32) + htonl(n >> 32)); } static __inline__ uint64_t ntohll(uint64_t n) { return ((((uint64_t)ntohl(n)) << 32) + ntohl(n >> 32)); } #else /* !__LP64__ */ #define htonll(x) BSWAP_64(x) #define ntohll(x) BSWAP_64(x) #endif /* __LP64__ */ #endif /* BYTE_ORDER */ #endif /* _STANDALONE */ #define BE_IN32(xa) htonl(*((uint32_t *)(void *)(xa))) #endif /* _OPENSOLARIS_SYS_BYTEORDER_H_ */ diff --git a/include/os/freebsd/spl/sys/cmn_err.h b/include/os/freebsd/spl/sys/cmn_err.h index 88132337f038..a8f9a88247cd 100644 --- a/include/os/freebsd/spl/sys/cmn_err.h +++ b/include/os/freebsd/spl/sys/cmn_err.h @@ -1,82 +1,82 @@ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or https://opensource.org/licenses/CDDL-1.0. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ /* * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _SYS_CMN_ERR_H #define _SYS_CMN_ERR_H #if !defined(_ASM) #include #endif #ifdef __cplusplus extern "C" { #endif /* Common error handling severity levels */ #define CE_CONT 0 /* continuation */ #define CE_NOTE 1 /* notice */ #define CE_WARN 2 /* warning */ #define CE_PANIC 3 /* panic */ #define CE_IGNORE 4 /* print nothing */ #ifndef _ASM extern void cmn_err(int, const char *, ...) __attribute__((format(printf, 2, 3))); extern void vzcmn_err(zoneid_t, int, const char *, __va_list) __attribute__((format(printf, 3, 0))); extern void vcmn_err(int, const char *, __va_list) __attribute__((format(printf, 2, 0))); extern void zcmn_err(zoneid_t, int, const char *, ...) __attribute__((format(printf, 3, 4))); extern void vzprintf(zoneid_t, const char *, __va_list) __attribute__((format(printf, 2, 0))); extern void zprintf(zoneid_t, const char *, ...) __attribute__((format(printf, 2, 3))); extern void vuprintf(const char *, __va_list) __attribute__((format(printf, 1, 0))); extern void panic(const char *, ...) - __attribute__((format(printf, 1, 2))); + __attribute__((format(printf, 1, 2), __noreturn__)); #endif /* !_ASM */ #ifdef __cplusplus } #endif #endif /* _SYS_CMN_ERR_H */ diff --git a/include/os/freebsd/spl/sys/debug.h b/include/os/freebsd/spl/sys/debug.h index 86fad18e17d2..a5bd677b16d4 100644 --- a/include/os/freebsd/spl/sys/debug.h +++ b/include/os/freebsd/spl/sys/debug.h @@ -1,171 +1,179 @@ /* * Copyright (c) 2020 iXsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ /* * Available Solaris debug functions. All of the ASSERT() macros will be * compiled out when NDEBUG is defined, this is the default behavior for * the SPL. To enable assertions use the --enable-debug with configure. * The VERIFY() functions are never compiled out and cannot be disabled. * * PANIC() - Panic the node and print message. * ASSERT() - Assert X is true, if not panic. * ASSERT3B() - Assert boolean X OP Y is true, if not panic. * ASSERT3S() - Assert signed X OP Y is true, if not panic. * ASSERT3U() - Assert unsigned X OP Y is true, if not panic. * ASSERT3P() - Assert pointer X OP Y is true, if not panic. * ASSERT0() - Assert value is zero, if not panic. * VERIFY() - Verify X is true, if not panic. * VERIFY3B() - Verify boolean X OP Y is true, if not panic. * VERIFY3S() - Verify signed X OP Y is true, if not panic. * VERIFY3U() - Verify unsigned X OP Y is true, if not panic. * VERIFY3P() - Verify pointer X OP Y is true, if not panic. * VERIFY0() - Verify value is zero, if not panic. */ #ifndef _SPL_DEBUG_H #define _SPL_DEBUG_H /* * Common DEBUG functionality. */ -int spl_panic(const char *file, const char *func, int line, - const char *fmt, ...); -void spl_dumpstack(void); +extern void spl_panic(const char *file, const char *func, int line, + const char *fmt, ...) __attribute__((__noreturn__)); +extern void spl_dumpstack(void); + +static inline int +spl_assert(const char *buf, const char *file, const char *func, int line) +{ + spl_panic(file, func, line, "%s", buf); + return (0); +} #ifndef expect #define expect(expr, value) (__builtin_expect((expr), (value))) #endif #define likely(expr) expect((expr) != 0, 1) #define unlikely(expr) expect((expr) != 0, 0) #define PANIC(fmt, a...) \ spl_panic(__FILE__, __FUNCTION__, __LINE__, fmt, ## a) #define VERIFY(cond) \ (void) (unlikely(!(cond)) && \ - spl_panic(__FILE__, __FUNCTION__, __LINE__, \ - "%s", "VERIFY(" #cond ") failed\n")) + spl_assert("VERIFY(" #cond ") failed\n", \ + __FILE__, __FUNCTION__, __LINE__)) #define VERIFY3B(LEFT, OP, RIGHT) do { \ const boolean_t _verify3_left = (boolean_t)(LEFT); \ const boolean_t _verify3_right = (boolean_t)(RIGHT); \ if (unlikely(!(_verify3_left OP _verify3_right))) \ spl_panic(__FILE__, __FUNCTION__, __LINE__, \ "VERIFY3(" #LEFT " " #OP " " #RIGHT ") " \ "failed (%d " #OP " %d)\n", \ (boolean_t)(_verify3_left), \ (boolean_t)(_verify3_right)); \ } while (0) #define VERIFY3S(LEFT, OP, RIGHT) do { \ const int64_t _verify3_left = (int64_t)(LEFT); \ const int64_t _verify3_right = (int64_t)(RIGHT); \ if (unlikely(!(_verify3_left OP _verify3_right))) \ spl_panic(__FILE__, __FUNCTION__, __LINE__, \ "VERIFY3(" #LEFT " " #OP " " #RIGHT ") " \ "failed (%lld " #OP " %lld)\n", \ (long long) (_verify3_left), \ (long long) (_verify3_right)); \ } while (0) #define VERIFY3U(LEFT, OP, RIGHT) do { \ const uint64_t _verify3_left = (uint64_t)(LEFT); \ const uint64_t _verify3_right = (uint64_t)(RIGHT); \ if (unlikely(!(_verify3_left OP _verify3_right))) \ spl_panic(__FILE__, __FUNCTION__, __LINE__, \ "VERIFY3(" #LEFT " " #OP " " #RIGHT ") " \ "failed (%llu " #OP " %llu)\n", \ (unsigned long long) (_verify3_left), \ (unsigned long long) (_verify3_right)); \ } while (0) #define VERIFY3P(LEFT, OP, RIGHT) do { \ const uintptr_t _verify3_left = (uintptr_t)(LEFT); \ const uintptr_t _verify3_right = (uintptr_t)(RIGHT); \ if (unlikely(!(_verify3_left OP _verify3_right))) \ spl_panic(__FILE__, __FUNCTION__, __LINE__, \ "VERIFY3(" #LEFT " " #OP " " #RIGHT ") " \ "failed (%px " #OP " %px)\n", \ (void *) (_verify3_left), \ (void *) (_verify3_right)); \ } while (0) #define VERIFY0(RIGHT) do { \ const int64_t _verify3_left = (int64_t)(0); \ const int64_t _verify3_right = (int64_t)(RIGHT); \ if (unlikely(!(_verify3_left == _verify3_right))) \ spl_panic(__FILE__, __FUNCTION__, __LINE__, \ "VERIFY3(0 == " #RIGHT ") " \ "failed (0 == %lld)\n", \ (long long) (_verify3_right)); \ } while (0) /* * Debugging disabled (--disable-debug) */ #ifdef NDEBUG #define ASSERT(x) ((void) sizeof ((uintptr_t)(x))) #define ASSERT3B(x, y, z) \ ((void) sizeof ((uintptr_t)(x)), (void) sizeof ((uintptr_t)(z))) #define ASSERT3S(x, y, z) \ ((void) sizeof ((uintptr_t)(x)), (void) sizeof ((uintptr_t)(z))) #define ASSERT3U(x, y, z) \ ((void) sizeof ((uintptr_t)(x)), (void) sizeof ((uintptr_t)(z))) #define ASSERT3P(x, y, z) \ ((void) sizeof ((uintptr_t)(x)), (void) sizeof ((uintptr_t)(z))) #define ASSERT0(x) ((void) sizeof ((uintptr_t)(x))) #define IMPLY(A, B) \ ((void) sizeof ((uintptr_t)(A)), (void) sizeof ((uintptr_t)(B))) #define EQUIV(A, B) \ ((void) sizeof ((uintptr_t)(A)), (void) sizeof ((uintptr_t)(B))) /* * Debugging enabled (--enable-debug) */ #else #define ASSERT3B VERIFY3B #define ASSERT3S VERIFY3S #define ASSERT3U VERIFY3U #define ASSERT3P VERIFY3P #define ASSERT0 VERIFY0 #define ASSERT VERIFY #define IMPLY(A, B) \ - ((void)(likely((!(A)) || (B)) || \ - spl_panic(__FILE__, __FUNCTION__, __LINE__, \ - "(" #A ") implies (" #B ")"))) + ((void)(likely((!(A)) || (B)) || \ + spl_assert("(" #A ") implies (" #B ")", \ + __FILE__, __FUNCTION__, __LINE__))) #define EQUIV(A, B) \ - ((void)(likely(!!(A) == !!(B)) || \ - spl_panic(__FILE__, __FUNCTION__, __LINE__, \ - "(" #A ") is equivalent to (" #B ")"))) + ((void)(likely(!!(A) == !!(B)) || \ + spl_assert("(" #A ") is equivalent to (" #B ")", \ + __FILE__, __FUNCTION__, __LINE__))) + #endif /* NDEBUG */ #endif /* SPL_DEBUG_H */ diff --git a/include/os/freebsd/spl/sys/kmem.h b/include/os/freebsd/spl/sys/kmem.h index a81cb1fb521d..ae2941b80912 100644 --- a/include/os/freebsd/spl/sys/kmem.h +++ b/include/os/freebsd/spl/sys/kmem.h @@ -1,107 +1,110 @@ /* * Copyright (c) 2007 Pawel Jakub Dawidek * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _OPENSOLARIS_SYS_KMEM_H_ #define _OPENSOLARIS_SYS_KMEM_H_ #ifdef _KERNEL #include #include #include #include #include #include #include MALLOC_DECLARE(M_SOLARIS); #define POINTER_IS_VALID(p) (!((uintptr_t)(p) & 0x3)) #define POINTER_INVALIDATE(pp) (*(pp) = (void *)((uintptr_t)(*(pp)) | 0x1)) #define KM_SLEEP M_WAITOK #define KM_PUSHPAGE M_WAITOK #define KM_NOSLEEP M_NOWAIT #define KM_NORMALPRI 0 #define KMC_NODEBUG UMA_ZONE_NODUMP typedef struct vmem vmem_t; -extern char *kmem_asprintf(const char *, ...); -extern char *kmem_vasprintf(const char *fmt, va_list ap); +extern char *kmem_asprintf(const char *, ...) + __attribute__((format(printf, 1, 2))); +extern char *kmem_vasprintf(const char *fmt, va_list ap) + __attribute__((format(printf, 1, 0))); typedef struct kmem_cache { char kc_name[32]; #if !defined(KMEM_DEBUG) uma_zone_t kc_zone; #else size_t kc_size; #endif int (*kc_constructor)(void *, void *, int); void (*kc_destructor)(void *, void *); void *kc_private; } kmem_cache_t; extern uint64_t spl_kmem_cache_inuse(kmem_cache_t *cache); extern uint64_t spl_kmem_cache_entry_size(kmem_cache_t *cache); +__attribute__((alloc_size(1))) void *zfs_kmem_alloc(size_t size, int kmflags); void zfs_kmem_free(void *buf, size_t size); uint64_t kmem_size(void); kmem_cache_t *kmem_cache_create(const char *name, size_t bufsize, size_t align, int (*constructor)(void *, void *, int), void (*destructor)(void *, void *), void (*reclaim)(void *) __unused, void *private, vmem_t *vmp, int cflags); void kmem_cache_destroy(kmem_cache_t *cache); void *kmem_cache_alloc(kmem_cache_t *cache, int flags); void kmem_cache_free(kmem_cache_t *cache, void *buf); boolean_t kmem_cache_reap_active(void); void kmem_cache_reap_soon(kmem_cache_t *); void kmem_reap(void); int kmem_debugging(void); void *calloc(size_t n, size_t s); #define kmem_cache_reap_now kmem_cache_reap_soon #define freemem vm_free_count() #define minfree vm_cnt.v_free_min #define kmem_alloc(size, kmflags) zfs_kmem_alloc((size), (kmflags)) #define kmem_zalloc(size, kmflags) \ zfs_kmem_alloc((size), (kmflags) | M_ZERO) #define kmem_free(buf, size) zfs_kmem_free((buf), (size)) #endif /* _KERNEL */ #ifdef _STANDALONE /* * At the moment, we just need it for the type. We redirect the alloc/free * routines to the usual Free and Malloc in that environment. */ typedef int kmem_cache_t; #endif /* _STANDALONE */ #endif /* _OPENSOLARIS_SYS_KMEM_H_ */ diff --git a/include/os/linux/spl/sys/byteorder.h b/include/os/linux/spl/sys/byteorder.h index bb5e173ce5e4..e9406b4c0b86 100644 --- a/include/os/linux/spl/sys/byteorder.h +++ b/include/os/linux/spl/sys/byteorder.h @@ -1,86 +1,101 @@ /* * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. * Copyright (C) 2007 The Regents of the University of California. * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). * Written by Brian Behlendorf . * UCRL-CODE-235197 * * This file is part of the SPL, Solaris Porting Layer. * * The SPL is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * The SPL is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * You should have received a copy of the GNU General Public License along * with the SPL. If not, see . */ #ifndef _SPL_BYTEORDER_H #define _SPL_BYTEORDER_H #include #if defined(__BIG_ENDIAN) && !defined(_ZFS_BIG_ENDIAN) #define _ZFS_BIG_ENDIAN #endif #if defined(__LITTLE_ENDIAN) && !defined(_ZFS_LITTLE_ENDIAN) #define _ZFS_LITTLE_ENDIAN #endif #include +#ifdef __COVERITY__ +/* + * Coverity's taint warnings from byteswapping are false positives for us. + * Suppress them by hiding byteswapping from Coverity. + */ + +#define BSWAP_8(x) ((x) & 0xff) +#define BSWAP_16(x) ((x) & 0xffff) +#define BSWAP_32(x) ((x) & 0xffffffff) +#define BSWAP_64(x) (x) + +#else /* __COVERITY__ */ + #define BSWAP_8(x) ((x) & 0xff) #define BSWAP_16(x) ((BSWAP_8(x) << 8) | BSWAP_8((x) >> 8)) #define BSWAP_32(x) ((BSWAP_16(x) << 16) | BSWAP_16((x) >> 16)) #define BSWAP_64(x) ((BSWAP_32(x) << 32) | BSWAP_32((x) >> 32)) +#endif /* __COVERITY__ */ + #define LE_16(x) cpu_to_le16(x) #define LE_32(x) cpu_to_le32(x) #define LE_64(x) cpu_to_le64(x) #define BE_16(x) cpu_to_be16(x) #define BE_32(x) cpu_to_be32(x) #define BE_64(x) cpu_to_be64(x) #define BE_IN8(xa) \ *((uint8_t *)(xa)) #define BE_IN16(xa) \ (((uint16_t)BE_IN8(xa) << 8) | BE_IN8((uint8_t *)(xa)+1)) #define BE_IN32(xa) \ (((uint32_t)BE_IN16(xa) << 16) | BE_IN16((uint8_t *)(xa)+2)) #ifdef _ZFS_BIG_ENDIAN static __inline__ uint64_t htonll(uint64_t n) { return (n); } static __inline__ uint64_t ntohll(uint64_t n) { return (n); } #else static __inline__ uint64_t htonll(uint64_t n) { return ((((uint64_t)htonl(n)) << 32) + htonl(n >> 32)); } static __inline__ uint64_t ntohll(uint64_t n) { return ((((uint64_t)ntohl(n)) << 32) + ntohl(n >> 32)); } #endif #endif /* SPL_BYTEORDER_H */ diff --git a/include/os/linux/spl/sys/cmn_err.h b/include/os/linux/spl/sys/cmn_err.h index d2088371c6bc..161bcf9b3a46 100644 --- a/include/os/linux/spl/sys/cmn_err.h +++ b/include/os/linux/spl/sys/cmn_err.h @@ -1,48 +1,48 @@ /* * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. * Copyright (C) 2007 The Regents of the University of California. * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). * Written by Brian Behlendorf . * UCRL-CODE-235197 * * This file is part of the SPL, Solaris Porting Layer. * * The SPL is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * The SPL is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * You should have received a copy of the GNU General Public License along * with the SPL. If not, see . */ #ifndef _SPL_CMN_ERR_H #define _SPL_CMN_ERR_H #if defined(_KERNEL) && defined(HAVE_STANDALONE_LINUX_STDARG) #include #else #include #endif #define CE_CONT 0 /* continuation */ #define CE_NOTE 1 /* notice */ #define CE_WARN 2 /* warning */ #define CE_PANIC 3 /* panic */ #define CE_IGNORE 4 /* print nothing */ extern void cmn_err(int, const char *, ...) __attribute__((format(printf, 2, 3))); extern void vcmn_err(int, const char *, va_list) __attribute__((format(printf, 2, 0))); extern void vpanic(const char *, va_list) - __attribute__((format(printf, 1, 0))); + __attribute__((format(printf, 1, 0), __noreturn__)); #define fm_panic panic #endif /* SPL_CMN_ERR_H */ diff --git a/include/os/linux/spl/sys/debug.h b/include/os/linux/spl/sys/debug.h index 9c013370c5f0..8ad199808633 100644 --- a/include/os/linux/spl/sys/debug.h +++ b/include/os/linux/spl/sys/debug.h @@ -1,165 +1,172 @@ /* * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. * Copyright (C) 2007 The Regents of the University of California. * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). * Written by Brian Behlendorf . * UCRL-CODE-235197 * * This file is part of the SPL, Solaris Porting Layer. * * The SPL is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * The SPL is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * You should have received a copy of the GNU General Public License along * with the SPL. If not, see . */ /* * Available Solaris debug functions. All of the ASSERT() macros will be * compiled out when NDEBUG is defined, this is the default behavior for * the SPL. To enable assertions use the --enable-debug with configure. * The VERIFY() functions are never compiled out and cannot be disabled. * * PANIC() - Panic the node and print message. * ASSERT() - Assert X is true, if not panic. * ASSERT3B() - Assert boolean X OP Y is true, if not panic. * ASSERT3S() - Assert signed X OP Y is true, if not panic. * ASSERT3U() - Assert unsigned X OP Y is true, if not panic. * ASSERT3P() - Assert pointer X OP Y is true, if not panic. * ASSERT0() - Assert value is zero, if not panic. * VERIFY() - Verify X is true, if not panic. * VERIFY3B() - Verify boolean X OP Y is true, if not panic. * VERIFY3S() - Verify signed X OP Y is true, if not panic. * VERIFY3U() - Verify unsigned X OP Y is true, if not panic. * VERIFY3P() - Verify pointer X OP Y is true, if not panic. * VERIFY0() - Verify value is zero, if not panic. */ #ifndef _SPL_DEBUG_H #define _SPL_DEBUG_H /* * Common DEBUG functionality. */ #define __printflike(a, b) __printf(a, b) #ifndef __maybe_unused #define __maybe_unused __attribute__((unused)) #endif -int spl_panic(const char *file, const char *func, int line, - const char *fmt, ...); -void spl_dumpstack(void); +extern void spl_panic(const char *file, const char *func, int line, + const char *fmt, ...) __attribute__((__noreturn__)); +extern void spl_dumpstack(void); + +static inline int +spl_assert(const char *buf, const char *file, const char *func, int line) +{ + spl_panic(file, func, line, "%s", buf); + return (0); +} #define PANIC(fmt, a...) \ spl_panic(__FILE__, __FUNCTION__, __LINE__, fmt, ## a) #define VERIFY(cond) \ (void) (unlikely(!(cond)) && \ - spl_panic(__FILE__, __FUNCTION__, __LINE__, \ - "%s", "VERIFY(" #cond ") failed\n")) + spl_assert("VERIFY(" #cond ") failed\n", \ + __FILE__, __FUNCTION__, __LINE__)) #define VERIFY3B(LEFT, OP, RIGHT) do { \ const boolean_t _verify3_left = (boolean_t)(LEFT); \ const boolean_t _verify3_right = (boolean_t)(RIGHT); \ if (unlikely(!(_verify3_left OP _verify3_right))) \ spl_panic(__FILE__, __FUNCTION__, __LINE__, \ "VERIFY3(" #LEFT " " #OP " " #RIGHT ") " \ "failed (%d " #OP " %d)\n", \ (boolean_t)(_verify3_left), \ (boolean_t)(_verify3_right)); \ } while (0) #define VERIFY3S(LEFT, OP, RIGHT) do { \ const int64_t _verify3_left = (int64_t)(LEFT); \ const int64_t _verify3_right = (int64_t)(RIGHT); \ if (unlikely(!(_verify3_left OP _verify3_right))) \ spl_panic(__FILE__, __FUNCTION__, __LINE__, \ "VERIFY3(" #LEFT " " #OP " " #RIGHT ") " \ "failed (%lld " #OP " %lld)\n", \ (long long)(_verify3_left), \ (long long)(_verify3_right)); \ } while (0) #define VERIFY3U(LEFT, OP, RIGHT) do { \ const uint64_t _verify3_left = (uint64_t)(LEFT); \ const uint64_t _verify3_right = (uint64_t)(RIGHT); \ if (unlikely(!(_verify3_left OP _verify3_right))) \ spl_panic(__FILE__, __FUNCTION__, __LINE__, \ "VERIFY3(" #LEFT " " #OP " " #RIGHT ") " \ "failed (%llu " #OP " %llu)\n", \ (unsigned long long)(_verify3_left), \ (unsigned long long)(_verify3_right)); \ } while (0) #define VERIFY3P(LEFT, OP, RIGHT) do { \ const uintptr_t _verify3_left = (uintptr_t)(LEFT); \ const uintptr_t _verify3_right = (uintptr_t)(RIGHT); \ if (unlikely(!(_verify3_left OP _verify3_right))) \ spl_panic(__FILE__, __FUNCTION__, __LINE__, \ "VERIFY3(" #LEFT " " #OP " " #RIGHT ") " \ "failed (%px " #OP " %px)\n", \ (void *) (_verify3_left), \ (void *) (_verify3_right)); \ } while (0) #define VERIFY0(RIGHT) do { \ const int64_t _verify3_left = (int64_t)(0); \ const int64_t _verify3_right = (int64_t)(RIGHT); \ if (unlikely(!(_verify3_left == _verify3_right))) \ spl_panic(__FILE__, __FUNCTION__, __LINE__, \ "VERIFY3(0 == " #RIGHT ") " \ "failed (0 == %lld)\n", \ (long long) (_verify3_right)); \ } while (0) /* * Debugging disabled (--disable-debug) */ #ifdef NDEBUG #define ASSERT(x) ((void) sizeof ((uintptr_t)(x))) #define ASSERT3B(x, y, z) \ ((void) sizeof ((uintptr_t)(x)), (void) sizeof ((uintptr_t)(z))) #define ASSERT3S(x, y, z) \ ((void) sizeof ((uintptr_t)(x)), (void) sizeof ((uintptr_t)(z))) #define ASSERT3U(x, y, z) \ ((void) sizeof ((uintptr_t)(x)), (void) sizeof ((uintptr_t)(z))) #define ASSERT3P(x, y, z) \ ((void) sizeof ((uintptr_t)(x)), (void) sizeof ((uintptr_t)(z))) #define ASSERT0(x) ((void) sizeof ((uintptr_t)(x))) #define IMPLY(A, B) \ ((void) sizeof ((uintptr_t)(A)), (void) sizeof ((uintptr_t)(B))) #define EQUIV(A, B) \ ((void) sizeof ((uintptr_t)(A)), (void) sizeof ((uintptr_t)(B))) /* * Debugging enabled (--enable-debug) */ #else #define ASSERT3B VERIFY3B #define ASSERT3S VERIFY3S #define ASSERT3U VERIFY3U #define ASSERT3P VERIFY3P #define ASSERT0 VERIFY0 #define ASSERT VERIFY #define IMPLY(A, B) \ - ((void)(likely((!(A)) || (B)) || \ - spl_panic(__FILE__, __FUNCTION__, __LINE__, \ - "(" #A ") implies (" #B ")"))) + ((void)(likely((!(A)) || (B)) || \ + spl_assert("(" #A ") implies (" #B ")", \ + __FILE__, __FUNCTION__, __LINE__))) #define EQUIV(A, B) \ - ((void)(likely(!!(A) == !!(B)) || \ - spl_panic(__FILE__, __FUNCTION__, __LINE__, \ - "(" #A ") is equivalent to (" #B ")"))) + ((void)(likely(!!(A) == !!(B)) || \ + spl_assert("(" #A ") is equivalent to (" #B ")", \ + __FILE__, __FUNCTION__, __LINE__))) #endif /* NDEBUG */ #endif /* SPL_DEBUG_H */ diff --git a/include/os/linux/spl/sys/kmem.h b/include/os/linux/spl/sys/kmem.h index a93e87df8069..86e872fa2492 100644 --- a/include/os/linux/spl/sys/kmem.h +++ b/include/os/linux/spl/sys/kmem.h @@ -1,210 +1,214 @@ /* * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. * Copyright (C) 2007 The Regents of the University of California. * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). * Written by Brian Behlendorf . * UCRL-CODE-235197 * * This file is part of the SPL, Solaris Porting Layer. * * The SPL is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * The SPL is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * You should have received a copy of the GNU General Public License along * with the SPL. If not, see . */ #ifndef _SPL_KMEM_H #define _SPL_KMEM_H #include #include #include #include #include extern int kmem_debugging(void); -extern char *kmem_vasprintf(const char *fmt, va_list ap); -extern char *kmem_asprintf(const char *fmt, ...); +extern char *kmem_vasprintf(const char *fmt, va_list ap) + __attribute__((format(printf, 1, 0))); +extern char *kmem_asprintf(const char *fmt, ...) + __attribute__((format(printf, 1, 2))); extern char *kmem_strdup(const char *str); extern void kmem_strfree(char *str); /* * Memory allocation interfaces */ #define KM_SLEEP 0x0000 /* can block for memory; success guaranteed */ #define KM_NOSLEEP 0x0001 /* cannot block for memory; may fail */ #define KM_PUSHPAGE 0x0004 /* can block for memory; may use reserve */ #define KM_ZERO 0x1000 /* zero the allocation */ #define KM_VMEM 0x2000 /* caller is vmem_* wrapper */ #define KM_PUBLIC_MASK (KM_SLEEP | KM_NOSLEEP | KM_PUSHPAGE) static int spl_fstrans_check(void); void *spl_kvmalloc(size_t size, gfp_t flags); /* * Convert a KM_* flags mask to its Linux GFP_* counterpart. The conversion * function is context aware which means that KM_SLEEP allocations can be * safely used in syncing contexts which have set PF_FSTRANS. */ static inline gfp_t kmem_flags_convert(int flags) { gfp_t lflags = __GFP_NOWARN | __GFP_COMP; if (flags & KM_NOSLEEP) { lflags |= GFP_ATOMIC | __GFP_NORETRY; } else { lflags |= GFP_KERNEL; if (spl_fstrans_check()) lflags &= ~(__GFP_IO|__GFP_FS); } if (flags & KM_PUSHPAGE) lflags |= __GFP_HIGH; if (flags & KM_ZERO) lflags |= __GFP_ZERO; return (lflags); } typedef struct { struct task_struct *fstrans_thread; unsigned int saved_flags; } fstrans_cookie_t; /* * Introduced in Linux 3.9, however this cannot be solely relied on before * Linux 3.18 as it doesn't turn off __GFP_FS as it should. */ #ifdef PF_MEMALLOC_NOIO #define __SPL_PF_MEMALLOC_NOIO (PF_MEMALLOC_NOIO) #else #define __SPL_PF_MEMALLOC_NOIO (0) #endif /* * PF_FSTRANS is removed from Linux 4.12 */ #ifdef PF_FSTRANS #define __SPL_PF_FSTRANS (PF_FSTRANS) #else #define __SPL_PF_FSTRANS (0) #endif #define SPL_FSTRANS (__SPL_PF_FSTRANS|__SPL_PF_MEMALLOC_NOIO) static inline fstrans_cookie_t spl_fstrans_mark(void) { fstrans_cookie_t cookie; BUILD_BUG_ON(SPL_FSTRANS == 0); cookie.fstrans_thread = current; cookie.saved_flags = current->flags & SPL_FSTRANS; current->flags |= SPL_FSTRANS; return (cookie); } static inline void spl_fstrans_unmark(fstrans_cookie_t cookie) { ASSERT3P(cookie.fstrans_thread, ==, current); ASSERT((current->flags & SPL_FSTRANS) == SPL_FSTRANS); current->flags &= ~SPL_FSTRANS; current->flags |= cookie.saved_flags; } static inline int spl_fstrans_check(void) { return (current->flags & SPL_FSTRANS); } /* * specifically used to check PF_FSTRANS flag, cannot be relied on for * checking spl_fstrans_mark(). */ static inline int __spl_pf_fstrans_check(void) { return (current->flags & __SPL_PF_FSTRANS); } /* * Kernel compatibility for GFP flags */ /* < 4.13 */ #ifndef __GFP_RETRY_MAYFAIL #define __GFP_RETRY_MAYFAIL __GFP_REPEAT #endif /* < 4.4 */ #ifndef __GFP_RECLAIM #define __GFP_RECLAIM __GFP_WAIT #endif #ifdef HAVE_ATOMIC64_T #define kmem_alloc_used_add(size) atomic64_add(size, &kmem_alloc_used) #define kmem_alloc_used_sub(size) atomic64_sub(size, &kmem_alloc_used) #define kmem_alloc_used_read() atomic64_read(&kmem_alloc_used) #define kmem_alloc_used_set(size) atomic64_set(&kmem_alloc_used, size) extern atomic64_t kmem_alloc_used; extern unsigned long long kmem_alloc_max; #else /* HAVE_ATOMIC64_T */ #define kmem_alloc_used_add(size) atomic_add(size, &kmem_alloc_used) #define kmem_alloc_used_sub(size) atomic_sub(size, &kmem_alloc_used) #define kmem_alloc_used_read() atomic_read(&kmem_alloc_used) #define kmem_alloc_used_set(size) atomic_set(&kmem_alloc_used, size) extern atomic_t kmem_alloc_used; extern unsigned long long kmem_alloc_max; #endif /* HAVE_ATOMIC64_T */ extern unsigned int spl_kmem_alloc_warn; extern unsigned int spl_kmem_alloc_max; #define kmem_alloc(sz, fl) spl_kmem_alloc((sz), (fl), __func__, __LINE__) #define kmem_zalloc(sz, fl) spl_kmem_zalloc((sz), (fl), __func__, __LINE__) #define kmem_free(ptr, sz) spl_kmem_free((ptr), (sz)) #define kmem_cache_reap_active spl_kmem_cache_reap_active -extern void *spl_kmem_alloc(size_t sz, int fl, const char *func, int line); -extern void *spl_kmem_zalloc(size_t sz, int fl, const char *func, int line); +extern void *spl_kmem_alloc(size_t sz, int fl, const char *func, int line) + __attribute__((alloc_size(1))); +extern void *spl_kmem_zalloc(size_t sz, int fl, const char *func, int line) + __attribute__((alloc_size(1))); extern void spl_kmem_free(const void *ptr, size_t sz); /* * 5.8 API change, pgprot_t argument removed. */ #ifdef HAVE_VMALLOC_PAGE_KERNEL #define spl_vmalloc(size, flags) __vmalloc(size, flags, PAGE_KERNEL) #else #define spl_vmalloc(size, flags) __vmalloc(size, flags) #endif /* * The following functions are only available for internal use. */ extern void *spl_kmem_alloc_impl(size_t size, int flags, int node); extern void *spl_kmem_alloc_debug(size_t size, int flags, int node); extern void *spl_kmem_alloc_track(size_t size, int flags, const char *func, int line, int node); extern void spl_kmem_free_impl(const void *buf, size_t size); extern void spl_kmem_free_debug(const void *buf, size_t size); extern void spl_kmem_free_track(const void *buf, size_t size); extern int spl_kmem_init(void); extern void spl_kmem_fini(void); extern int spl_kmem_cache_reap_active(void); #endif /* _SPL_KMEM_H */ diff --git a/include/sys/zfs_context.h b/include/sys/zfs_context.h index 1f7e8bffabdb..d29d7118ff00 100644 --- a/include/sys/zfs_context.h +++ b/include/sys/zfs_context.h @@ -1,779 +1,783 @@ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or https://opensource.org/licenses/CDDL-1.0. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2011 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2012, 2018 by Delphix. All rights reserved. * Copyright (c) 2012, Joyent, Inc. All rights reserved. */ #ifndef _SYS_ZFS_CONTEXT_H #define _SYS_ZFS_CONTEXT_H #ifdef __cplusplus extern "C" { #endif /* * This code compiles in three different contexts. When __KERNEL__ is defined, * the code uses "unix-like" kernel interfaces. When _STANDALONE is defined, the * code is running in a reduced capacity environment of the boot loader which is * generally a subset of both POSIX and kernel interfaces (with a few unique * interfaces too). When neither are defined, it's in a userland POSIX or * similar environment. */ #if defined(__KERNEL__) || defined(_STANDALONE) #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #else /* _KERNEL || _STANDALONE */ #define _SYS_MUTEX_H #define _SYS_RWLOCK_H #define _SYS_CONDVAR_H #define _SYS_VNODE_H #define _SYS_VFS_H #define _SYS_SUNDDI_H #define _SYS_CALLB_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* * Stack */ #define noinline __attribute__((noinline)) #define likely(x) __builtin_expect((x), 1) #define unlikely(x) __builtin_expect((x), 0) /* * Debugging */ /* * Note that we are not using the debugging levels. */ #define CE_CONT 0 /* continuation */ #define CE_NOTE 1 /* notice */ #define CE_WARN 2 /* warning */ #define CE_PANIC 3 /* panic */ #define CE_IGNORE 4 /* print nothing */ /* * ZFS debugging */ extern void dprintf_setup(int *argc, char **argv); -extern void cmn_err(int, const char *, ...); -extern void vcmn_err(int, const char *, va_list); -extern __attribute__((noreturn)) void panic(const char *, ...); -extern __attribute__((noreturn)) void vpanic(const char *, va_list); +extern void cmn_err(int, const char *, ...) + __attribute__((format(printf, 2, 3))); +extern void vcmn_err(int, const char *, va_list) + __attribute__((format(printf, 2, 0))); +extern void panic(const char *, ...) + __attribute__((format(printf, 1, 2), noreturn)); +extern void vpanic(const char *, va_list) + __attribute__((format(printf, 1, 0), noreturn)); #define fm_panic panic /* * DTrace SDT probes have different signatures in userland than they do in * the kernel. If they're being used in kernel code, re-define them out of * existence for their counterparts in libzpool. * * Here's an example of how to use the set-error probes in userland: * zfs$target:::set-error /arg0 == EBUSY/ {stack();} * * Here's an example of how to use DTRACE_PROBE probes in userland: * If there is a probe declared as follows: * DTRACE_PROBE2(zfs__probe_name, uint64_t, blkid, dnode_t *, dn); * Then you can use it as follows: * zfs$target:::probe2 /copyinstr(arg0) == "zfs__probe_name"/ * {printf("%u %p\n", arg1, arg2);} */ #ifdef DTRACE_PROBE #undef DTRACE_PROBE #endif /* DTRACE_PROBE */ #define DTRACE_PROBE(a) #ifdef DTRACE_PROBE1 #undef DTRACE_PROBE1 #endif /* DTRACE_PROBE1 */ #define DTRACE_PROBE1(a, b, c) #ifdef DTRACE_PROBE2 #undef DTRACE_PROBE2 #endif /* DTRACE_PROBE2 */ #define DTRACE_PROBE2(a, b, c, d, e) #ifdef DTRACE_PROBE3 #undef DTRACE_PROBE3 #endif /* DTRACE_PROBE3 */ #define DTRACE_PROBE3(a, b, c, d, e, f, g) #ifdef DTRACE_PROBE4 #undef DTRACE_PROBE4 #endif /* DTRACE_PROBE4 */ #define DTRACE_PROBE4(a, b, c, d, e, f, g, h, i) /* * Tunables. */ typedef struct zfs_kernel_param { const char *name; /* unused stub */ } zfs_kernel_param_t; #define ZFS_MODULE_PARAM(scope_prefix, name_prefix, name, type, perm, desc) #define ZFS_MODULE_PARAM_ARGS void #define ZFS_MODULE_PARAM_CALL(scope_prefix, name_prefix, name, setfunc, \ getfunc, perm, desc) /* * Threads. */ typedef pthread_t kthread_t; #define TS_RUN 0x00000002 #define TS_JOINABLE 0x00000004 #define curthread ((void *)(uintptr_t)pthread_self()) #define getcomm() "unknown" #define thread_create_named(name, stk, stksize, func, arg, len, \ pp, state, pri) \ zk_thread_create(func, arg, stksize, state) #define thread_create(stk, stksize, func, arg, len, pp, state, pri) \ zk_thread_create(func, arg, stksize, state) #define thread_exit() pthread_exit(NULL) #define thread_join(t) pthread_join((pthread_t)(t), NULL) #define newproc(f, a, cid, pri, ctp, pid) (ENOSYS) /* in libzpool, p0 exists only to have its address taken */ typedef struct proc { uintptr_t this_is_never_used_dont_dereference_it; } proc_t; extern struct proc p0; #define curproc (&p0) #define PS_NONE -1 extern kthread_t *zk_thread_create(void (*func)(void *), void *arg, size_t stksize, int state); #define issig(why) (FALSE) #define ISSIG(thr, why) (FALSE) #define KPREEMPT_SYNC (-1) #define kpreempt(x) sched_yield() #define kpreempt_disable() ((void)0) #define kpreempt_enable() ((void)0) /* * Mutexes */ typedef struct kmutex { pthread_mutex_t m_lock; pthread_t m_owner; } kmutex_t; #define MUTEX_DEFAULT 0 #define MUTEX_NOLOCKDEP MUTEX_DEFAULT #define MUTEX_HELD(mp) pthread_equal((mp)->m_owner, pthread_self()) #define MUTEX_NOT_HELD(mp) !MUTEX_HELD(mp) extern void mutex_init(kmutex_t *mp, char *name, int type, void *cookie); extern void mutex_destroy(kmutex_t *mp); extern void mutex_enter(kmutex_t *mp); extern void mutex_exit(kmutex_t *mp); extern int mutex_tryenter(kmutex_t *mp); #define NESTED_SINGLE 1 #define mutex_enter_nested(mp, class) mutex_enter(mp) /* * RW locks */ typedef struct krwlock { pthread_rwlock_t rw_lock; pthread_t rw_owner; uint_t rw_readers; } krwlock_t; typedef int krw_t; #define RW_READER 0 #define RW_WRITER 1 #define RW_DEFAULT RW_READER #define RW_NOLOCKDEP RW_READER #define RW_READ_HELD(rw) ((rw)->rw_readers > 0) #define RW_WRITE_HELD(rw) pthread_equal((rw)->rw_owner, pthread_self()) #define RW_LOCK_HELD(rw) (RW_READ_HELD(rw) || RW_WRITE_HELD(rw)) extern void rw_init(krwlock_t *rwlp, char *name, int type, void *arg); extern void rw_destroy(krwlock_t *rwlp); extern void rw_enter(krwlock_t *rwlp, krw_t rw); extern int rw_tryenter(krwlock_t *rwlp, krw_t rw); extern int rw_tryupgrade(krwlock_t *rwlp); extern void rw_exit(krwlock_t *rwlp); #define rw_downgrade(rwlp) do { } while (0) /* * Credentials */ extern uid_t crgetuid(cred_t *cr); extern uid_t crgetruid(cred_t *cr); extern gid_t crgetgid(cred_t *cr); extern int crgetngroups(cred_t *cr); extern gid_t *crgetgroups(cred_t *cr); /* * Condition variables */ typedef pthread_cond_t kcondvar_t; #define CV_DEFAULT 0 #define CALLOUT_FLAG_ABSOLUTE 0x2 extern void cv_init(kcondvar_t *cv, char *name, int type, void *arg); extern void cv_destroy(kcondvar_t *cv); extern void cv_wait(kcondvar_t *cv, kmutex_t *mp); extern int cv_wait_sig(kcondvar_t *cv, kmutex_t *mp); extern int cv_timedwait(kcondvar_t *cv, kmutex_t *mp, clock_t abstime); extern int cv_timedwait_hires(kcondvar_t *cvp, kmutex_t *mp, hrtime_t tim, hrtime_t res, int flag); extern void cv_signal(kcondvar_t *cv); extern void cv_broadcast(kcondvar_t *cv); #define cv_timedwait_io(cv, mp, at) cv_timedwait(cv, mp, at) #define cv_timedwait_idle(cv, mp, at) cv_timedwait(cv, mp, at) #define cv_timedwait_sig(cv, mp, at) cv_timedwait(cv, mp, at) #define cv_wait_io(cv, mp) cv_wait(cv, mp) #define cv_wait_idle(cv, mp) cv_wait(cv, mp) #define cv_wait_io_sig(cv, mp) cv_wait_sig(cv, mp) #define cv_timedwait_sig_hires(cv, mp, t, r, f) \ cv_timedwait_hires(cv, mp, t, r, f) #define cv_timedwait_idle_hires(cv, mp, t, r, f) \ cv_timedwait_hires(cv, mp, t, r, f) /* * Thread-specific data */ #define tsd_get(k) pthread_getspecific(k) #define tsd_set(k, v) pthread_setspecific(k, v) #define tsd_create(kp, d) pthread_key_create((pthread_key_t *)kp, d) #define tsd_destroy(kp) /* nothing */ #ifdef __FreeBSD__ typedef off_t loff_t; #endif /* * kstat creation, installation and deletion */ extern kstat_t *kstat_create(const char *, int, const char *, const char *, uchar_t, ulong_t, uchar_t); extern void kstat_install(kstat_t *); extern void kstat_delete(kstat_t *); extern void kstat_set_raw_ops(kstat_t *ksp, int (*headers)(char *buf, size_t size), int (*data)(char *buf, size_t size, void *data), void *(*addr)(kstat_t *ksp, loff_t index)); /* * procfs list manipulation */ typedef struct procfs_list { void *pl_private; kmutex_t pl_lock; list_t pl_list; uint64_t pl_next_id; size_t pl_node_offset; } procfs_list_t; #ifndef __cplusplus struct seq_file { }; void seq_printf(struct seq_file *m, const char *fmt, ...); typedef struct procfs_list_node { list_node_t pln_link; uint64_t pln_id; } procfs_list_node_t; void procfs_list_install(const char *module, const char *submodule, const char *name, mode_t mode, procfs_list_t *procfs_list, int (*show)(struct seq_file *f, void *p), int (*show_header)(struct seq_file *f), int (*clear)(procfs_list_t *procfs_list), size_t procfs_list_node_off); void procfs_list_uninstall(procfs_list_t *procfs_list); void procfs_list_destroy(procfs_list_t *procfs_list); void procfs_list_add(procfs_list_t *procfs_list, void *p); #endif /* * Kernel memory */ #define KM_SLEEP UMEM_NOFAIL #define KM_PUSHPAGE KM_SLEEP #define KM_NOSLEEP UMEM_DEFAULT #define KM_NORMALPRI 0 /* not needed with UMEM_DEFAULT */ #define KMC_NODEBUG UMC_NODEBUG #define KMC_KVMEM 0x0 #define kmem_alloc(_s, _f) umem_alloc(_s, _f) #define kmem_zalloc(_s, _f) umem_zalloc(_s, _f) #define kmem_free(_b, _s) umem_free(_b, _s) #define vmem_alloc(_s, _f) kmem_alloc(_s, _f) #define vmem_zalloc(_s, _f) kmem_zalloc(_s, _f) #define vmem_free(_b, _s) kmem_free(_b, _s) #define kmem_cache_create(_a, _b, _c, _d, _e, _f, _g, _h, _i) \ umem_cache_create(_a, _b, _c, _d, _e, _f, _g, _h, _i) #define kmem_cache_destroy(_c) umem_cache_destroy(_c) #define kmem_cache_alloc(_c, _f) umem_cache_alloc(_c, _f) #define kmem_cache_free(_c, _b) umem_cache_free(_c, _b) #define kmem_debugging() 0 #define kmem_cache_reap_now(_c) umem_cache_reap_now(_c); #define kmem_cache_set_move(_c, _cb) /* nothing */ #define POINTER_INVALIDATE(_pp) /* nothing */ #define POINTER_IS_VALID(_p) 0 typedef umem_cache_t kmem_cache_t; typedef enum kmem_cbrc { KMEM_CBRC_YES, KMEM_CBRC_NO, KMEM_CBRC_LATER, KMEM_CBRC_DONT_NEED, KMEM_CBRC_DONT_KNOW } kmem_cbrc_t; /* * Task queues */ #define TASKQ_NAMELEN 31 typedef uintptr_t taskqid_t; typedef void (task_func_t)(void *); typedef struct taskq_ent { struct taskq_ent *tqent_next; struct taskq_ent *tqent_prev; task_func_t *tqent_func; void *tqent_arg; uintptr_t tqent_flags; } taskq_ent_t; typedef struct taskq { char tq_name[TASKQ_NAMELEN + 1]; kmutex_t tq_lock; krwlock_t tq_threadlock; kcondvar_t tq_dispatch_cv; kcondvar_t tq_wait_cv; kthread_t **tq_threadlist; int tq_flags; int tq_active; int tq_nthreads; int tq_nalloc; int tq_minalloc; int tq_maxalloc; kcondvar_t tq_maxalloc_cv; int tq_maxalloc_wait; taskq_ent_t *tq_freelist; taskq_ent_t tq_task; } taskq_t; #define TQENT_FLAG_PREALLOC 0x1 /* taskq_dispatch_ent used */ #define TASKQ_PREPOPULATE 0x0001 #define TASKQ_CPR_SAFE 0x0002 /* Use CPR safe protocol */ #define TASKQ_DYNAMIC 0x0004 /* Use dynamic thread scheduling */ #define TASKQ_THREADS_CPU_PCT 0x0008 /* Scale # threads by # cpus */ #define TASKQ_DC_BATCH 0x0010 /* Mark threads as batch */ #define TQ_SLEEP KM_SLEEP /* Can block for memory */ #define TQ_NOSLEEP KM_NOSLEEP /* cannot block for memory; may fail */ #define TQ_NOQUEUE 0x02 /* Do not enqueue if can't dispatch */ #define TQ_FRONT 0x08 /* Queue in front */ #define TASKQID_INVALID ((taskqid_t)0) extern taskq_t *system_taskq; extern taskq_t *system_delay_taskq; extern taskq_t *taskq_create(const char *, int, pri_t, int, int, uint_t); #define taskq_create_proc(a, b, c, d, e, p, f) \ (taskq_create(a, b, c, d, e, f)) #define taskq_create_sysdc(a, b, d, e, p, dc, f) \ ((void) sizeof (dc), taskq_create(a, b, maxclsyspri, d, e, f)) extern taskqid_t taskq_dispatch(taskq_t *, task_func_t, void *, uint_t); extern taskqid_t taskq_dispatch_delay(taskq_t *, task_func_t, void *, uint_t, clock_t); extern void taskq_dispatch_ent(taskq_t *, task_func_t, void *, uint_t, taskq_ent_t *); extern int taskq_empty_ent(taskq_ent_t *); extern void taskq_init_ent(taskq_ent_t *); extern void taskq_destroy(taskq_t *); extern void taskq_wait(taskq_t *); extern void taskq_wait_id(taskq_t *, taskqid_t); extern void taskq_wait_outstanding(taskq_t *, taskqid_t); extern int taskq_member(taskq_t *, kthread_t *); extern taskq_t *taskq_of_curthread(void); extern int taskq_cancel_id(taskq_t *, taskqid_t); extern void system_taskq_init(void); extern void system_taskq_fini(void); #define XVA_MAPSIZE 3 #define XVA_MAGIC 0x78766174 extern char *vn_dumpdir; #define AV_SCANSTAMP_SZ 32 /* length of anti-virus scanstamp */ typedef struct xoptattr { inode_timespec_t xoa_createtime; /* Create time of file */ uint8_t xoa_archive; uint8_t xoa_system; uint8_t xoa_readonly; uint8_t xoa_hidden; uint8_t xoa_nounlink; uint8_t xoa_immutable; uint8_t xoa_appendonly; uint8_t xoa_nodump; uint8_t xoa_settable; uint8_t xoa_opaque; uint8_t xoa_av_quarantined; uint8_t xoa_av_modified; uint8_t xoa_av_scanstamp[AV_SCANSTAMP_SZ]; uint8_t xoa_reparse; uint8_t xoa_offline; uint8_t xoa_sparse; } xoptattr_t; typedef struct vattr { uint_t va_mask; /* bit-mask of attributes */ u_offset_t va_size; /* file size in bytes */ } vattr_t; typedef struct xvattr { vattr_t xva_vattr; /* Embedded vattr structure */ uint32_t xva_magic; /* Magic Number */ uint32_t xva_mapsize; /* Size of attr bitmap (32-bit words) */ uint32_t *xva_rtnattrmapp; /* Ptr to xva_rtnattrmap[] */ uint32_t xva_reqattrmap[XVA_MAPSIZE]; /* Requested attrs */ uint32_t xva_rtnattrmap[XVA_MAPSIZE]; /* Returned attrs */ xoptattr_t xva_xoptattrs; /* Optional attributes */ } xvattr_t; typedef struct vsecattr { uint_t vsa_mask; /* See below */ int vsa_aclcnt; /* ACL entry count */ void *vsa_aclentp; /* pointer to ACL entries */ int vsa_dfaclcnt; /* default ACL entry count */ void *vsa_dfaclentp; /* pointer to default ACL entries */ size_t vsa_aclentsz; /* ACE size in bytes of vsa_aclentp */ } vsecattr_t; #define AT_MODE 0x00002 #define AT_UID 0x00004 #define AT_GID 0x00008 #define AT_FSID 0x00010 #define AT_NODEID 0x00020 #define AT_NLINK 0x00040 #define AT_SIZE 0x00080 #define AT_ATIME 0x00100 #define AT_MTIME 0x00200 #define AT_CTIME 0x00400 #define AT_RDEV 0x00800 #define AT_BLKSIZE 0x01000 #define AT_NBLOCKS 0x02000 #define AT_SEQ 0x08000 #define AT_XVATTR 0x10000 #define CRCREAT 0 #define F_FREESP 11 #define FIGNORECASE 0x80000 /* request case-insensitive lookups */ /* * Random stuff */ #define ddi_get_lbolt() (gethrtime() >> 23) #define ddi_get_lbolt64() (gethrtime() >> 23) #define hz 119 /* frequency when using gethrtime() >> 23 for lbolt */ #define ddi_time_before(a, b) (a < b) #define ddi_time_after(a, b) ddi_time_before(b, a) #define ddi_time_before_eq(a, b) (!ddi_time_after(a, b)) #define ddi_time_after_eq(a, b) ddi_time_before_eq(b, a) #define ddi_time_before64(a, b) (a < b) #define ddi_time_after64(a, b) ddi_time_before64(b, a) #define ddi_time_before_eq64(a, b) (!ddi_time_after64(a, b)) #define ddi_time_after_eq64(a, b) ddi_time_before_eq64(b, a) extern void delay(clock_t ticks); #define SEC_TO_TICK(sec) ((sec) * hz) #define MSEC_TO_TICK(msec) (howmany((hrtime_t)(msec) * hz, MILLISEC)) #define USEC_TO_TICK(usec) (howmany((hrtime_t)(usec) * hz, MICROSEC)) #define NSEC_TO_TICK(nsec) (howmany((hrtime_t)(nsec) * hz, NANOSEC)) #define max_ncpus 64 #define boot_ncpus (sysconf(_SC_NPROCESSORS_ONLN)) /* * Process priorities as defined by setpriority(2) and getpriority(2). */ #define minclsyspri 19 #define maxclsyspri -20 #define defclsyspri 0 #define CPU_SEQID ((uintptr_t)pthread_self() & (max_ncpus - 1)) #define CPU_SEQID_UNSTABLE CPU_SEQID #define kcred NULL #define CRED() NULL #define ptob(x) ((x) * PAGESIZE) #define NN_DIVISOR_1000 (1U << 0) #define NN_NUMBUF_SZ (6) extern uint64_t physmem; extern const char *random_path; extern const char *urandom_path; extern int highbit64(uint64_t i); extern int lowbit64(uint64_t i); extern int random_get_bytes(uint8_t *ptr, size_t len); extern int random_get_pseudo_bytes(uint8_t *ptr, size_t len); static __inline__ uint32_t random_in_range(uint32_t range) { uint32_t r; ASSERT(range != 0); if (range == 1) return (0); (void) random_get_pseudo_bytes((uint8_t *)&r, sizeof (r)); return (r % range); } extern void kernel_init(int mode); extern void kernel_fini(void); extern void random_init(void); extern void random_fini(void); struct spa; extern void show_pool_stats(struct spa *); extern int set_global_var(char const *arg); typedef struct callb_cpr { kmutex_t *cc_lockp; } callb_cpr_t; #define CALLB_CPR_INIT(cp, lockp, func, name) { \ (cp)->cc_lockp = lockp; \ } #define CALLB_CPR_SAFE_BEGIN(cp) { \ ASSERT(MUTEX_HELD((cp)->cc_lockp)); \ } #define CALLB_CPR_SAFE_END(cp, lockp) { \ ASSERT(MUTEX_HELD((cp)->cc_lockp)); \ } #define CALLB_CPR_EXIT(cp) { \ ASSERT(MUTEX_HELD((cp)->cc_lockp)); \ mutex_exit((cp)->cc_lockp); \ } #define zone_dataset_visible(x, y) (1) #define INGLOBALZONE(z) (1) extern uint32_t zone_get_hostid(void *zonep); extern char *kmem_vasprintf(const char *fmt, va_list adx); extern char *kmem_asprintf(const char *fmt, ...); #define kmem_strfree(str) kmem_free((str), strlen(str) + 1) #define kmem_strdup(s) strdup(s) /* * Hostname information */ extern int ddi_strtoull(const char *str, char **nptr, int base, u_longlong_t *result); typedef struct utsname utsname_t; extern utsname_t *utsname(void); /* ZFS Boot Related stuff. */ struct _buf { intptr_t _fd; }; struct bootstat { uint64_t st_size; }; typedef struct ace_object { uid_t a_who; uint32_t a_access_mask; uint16_t a_flags; uint16_t a_type; uint8_t a_obj_type[16]; uint8_t a_inherit_obj_type[16]; } ace_object_t; #define ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE 0x05 #define ACE_ACCESS_DENIED_OBJECT_ACE_TYPE 0x06 #define ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE 0x07 #define ACE_SYSTEM_ALARM_OBJECT_ACE_TYPE 0x08 extern int zfs_secpolicy_snapshot_perms(const char *name, cred_t *cr); extern int zfs_secpolicy_rename_perms(const char *from, const char *to, cred_t *cr); extern int zfs_secpolicy_destroy_perms(const char *name, cred_t *cr); extern int secpolicy_zfs(const cred_t *cr); extern int secpolicy_zfs_proc(const cred_t *cr, proc_t *proc); extern zoneid_t getzoneid(void); /* SID stuff */ typedef struct ksiddomain { uint_t kd_ref; uint_t kd_len; char *kd_name; } ksiddomain_t; ksiddomain_t *ksid_lookupdomain(const char *); void ksiddomain_rele(ksiddomain_t *); #define DDI_SLEEP KM_SLEEP #define ddi_log_sysevent(_a, _b, _c, _d, _e, _f, _g) \ sysevent_post_event(_c, _d, _b, "libzpool", _e, _f) #define zfs_sleep_until(wakeup) \ do { \ hrtime_t delta = wakeup - gethrtime(); \ struct timespec ts; \ ts.tv_sec = delta / NANOSEC; \ ts.tv_nsec = delta % NANOSEC; \ (void) nanosleep(&ts, NULL); \ } while (0) typedef int fstrans_cookie_t; extern fstrans_cookie_t spl_fstrans_mark(void); extern void spl_fstrans_unmark(fstrans_cookie_t); extern int __spl_pf_fstrans_check(void); extern int kmem_cache_reap_active(void); /* * Kernel modules */ #define __init #define __exit #endif /* _KERNEL || _STANDALONE */ #ifdef __cplusplus }; #endif #endif /* _SYS_ZFS_CONTEXT_H */ diff --git a/lib/libspl/assert.c b/lib/libspl/assert.c index 207da3a1d860..9d44740d4e3c 100644 --- a/lib/libspl/assert.c +++ b/lib/libspl/assert.c @@ -1,52 +1,55 @@ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or https://opensource.org/licenses/CDDL-1.0. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include static boolean_t libspl_assert_ok = B_FALSE; void libspl_set_assert_ok(boolean_t val) { libspl_assert_ok = val; } /* printf version of libspl_assert */ void libspl_assertf(const char *file, const char *func, int line, const char *format, ...) { va_list args; va_start(args, format); vfprintf(stderr, format, args); fprintf(stderr, "\n"); fprintf(stderr, "ASSERT at %s:%d:%s()", file, line, func); va_end(args); + +#if !__has_feature(attribute_analyzer_noreturn) && !defined(__COVERITY__) if (libspl_assert_ok) { return; } +#endif abort(); } diff --git a/lib/libspl/include/assert.h b/lib/libspl/include/assert.h index aaaa0af096ef..c5bf0f0cc8f1 100644 --- a/lib/libspl/include/assert.h +++ b/lib/libspl/include/assert.h @@ -1,150 +1,162 @@ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or https://opensource.org/licenses/CDDL-1.0. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include_next #ifndef _LIBSPL_ASSERT_H #define _LIBSPL_ASSERT_H #include #include #include #include +/* Workaround for non-Clang compilers */ +#ifndef __has_feature +#define __has_feature(x) 0 +#endif + +/* We need to workaround libspl_set_assert_ok() that we have for zdb */ +#if __has_feature(attribute_analyzer_noreturn) || defined(__COVERITY__) +#define NORETURN __attribute__((__noreturn__)) +#else +#define NORETURN +#endif + /* Set to non-zero to avoid abort()ing on an assertion failure */ extern void libspl_set_assert_ok(boolean_t val); /* printf version of libspl_assert */ extern void libspl_assertf(const char *file, const char *func, int line, - const char *format, ...); + const char *format, ...) NORETURN __attribute__((format(printf, 4, 5))); static inline int libspl_assert(const char *buf, const char *file, const char *func, int line) { libspl_assertf(file, func, line, "%s", buf); return (0); } #ifdef verify #undef verify #endif #define VERIFY(cond) \ (void) ((!(cond)) && \ libspl_assert(#cond, __FILE__, __FUNCTION__, __LINE__)) #define verify(cond) \ (void) ((!(cond)) && \ libspl_assert(#cond, __FILE__, __FUNCTION__, __LINE__)) #define VERIFY3B(LEFT, OP, RIGHT) \ do { \ const boolean_t __left = (boolean_t)(LEFT); \ const boolean_t __right = (boolean_t)(RIGHT); \ if (!(__left OP __right)) \ libspl_assertf(__FILE__, __FUNCTION__, __LINE__, \ "%s %s %s (0x%llx %s 0x%llx)", #LEFT, #OP, #RIGHT, \ (u_longlong_t)__left, #OP, (u_longlong_t)__right); \ } while (0) #define VERIFY3S(LEFT, OP, RIGHT) \ do { \ const int64_t __left = (int64_t)(LEFT); \ const int64_t __right = (int64_t)(RIGHT); \ if (!(__left OP __right)) \ libspl_assertf(__FILE__, __FUNCTION__, __LINE__, \ "%s %s %s (0x%llx %s 0x%llx)", #LEFT, #OP, #RIGHT, \ (u_longlong_t)__left, #OP, (u_longlong_t)__right); \ } while (0) #define VERIFY3U(LEFT, OP, RIGHT) \ do { \ const uint64_t __left = (uint64_t)(LEFT); \ const uint64_t __right = (uint64_t)(RIGHT); \ if (!(__left OP __right)) \ libspl_assertf(__FILE__, __FUNCTION__, __LINE__, \ "%s %s %s (0x%llx %s 0x%llx)", #LEFT, #OP, #RIGHT, \ (u_longlong_t)__left, #OP, (u_longlong_t)__right); \ } while (0) #define VERIFY3P(LEFT, OP, RIGHT) \ do { \ const uintptr_t __left = (uintptr_t)(LEFT); \ const uintptr_t __right = (uintptr_t)(RIGHT); \ if (!(__left OP __right)) \ libspl_assertf(__FILE__, __FUNCTION__, __LINE__, \ "%s %s %s (0x%llx %s 0x%llx)", #LEFT, #OP, #RIGHT, \ (u_longlong_t)__left, #OP, (u_longlong_t)__right); \ } while (0) #define VERIFY0(LEFT) \ do { \ const uint64_t __left = (uint64_t)(LEFT); \ if (!(__left == 0)) \ libspl_assertf(__FILE__, __FUNCTION__, __LINE__, \ "%s == 0 (0x%llx == 0)", #LEFT, \ (u_longlong_t)__left); \ } while (0) #ifdef assert #undef assert #endif #ifdef NDEBUG #define ASSERT3B(x, y, z) \ ((void) sizeof ((uintptr_t)(x)), (void) sizeof ((uintptr_t)(z))) #define ASSERT3S(x, y, z) \ ((void) sizeof ((uintptr_t)(x)), (void) sizeof ((uintptr_t)(z))) #define ASSERT3U(x, y, z) \ ((void) sizeof ((uintptr_t)(x)), (void) sizeof ((uintptr_t)(z))) #define ASSERT3P(x, y, z) \ ((void) sizeof ((uintptr_t)(x)), (void) sizeof ((uintptr_t)(z))) #define ASSERT0(x) ((void) sizeof ((uintptr_t)(x))) #define ASSERT(x) ((void) sizeof ((uintptr_t)(x))) #define assert(x) ((void) sizeof ((uintptr_t)(x))) #define IMPLY(A, B) \ ((void) sizeof ((uintptr_t)(A)), (void) sizeof ((uintptr_t)(B))) #define EQUIV(A, B) \ ((void) sizeof ((uintptr_t)(A)), (void) sizeof ((uintptr_t)(B))) #else #define ASSERT3B VERIFY3B #define ASSERT3S VERIFY3S #define ASSERT3U VERIFY3U #define ASSERT3P VERIFY3P #define ASSERT0 VERIFY0 #define ASSERT VERIFY #define assert VERIFY #define IMPLY(A, B) \ ((void)(((!(A)) || (B)) || \ libspl_assert("(" #A ") implies (" #B ")", \ __FILE__, __FUNCTION__, __LINE__))) #define EQUIV(A, B) \ ((void)((!!(A) == !!(B)) || \ libspl_assert("(" #A ") is equivalent to (" #B ")", \ __FILE__, __FUNCTION__, __LINE__))) #endif /* NDEBUG */ #endif /* _LIBSPL_ASSERT_H */ diff --git a/lib/libspl/include/os/freebsd/sys/byteorder.h b/lib/libspl/include/os/freebsd/sys/byteorder.h index 8de1104dc8a2..bd6728820ed4 100644 --- a/lib/libspl/include/os/freebsd/sys/byteorder.h +++ b/lib/libspl/include/os/freebsd/sys/byteorder.h @@ -1,192 +1,206 @@ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or https://opensource.org/licenses/CDDL-1.0. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ /* * University Copyright- Copyright (c) 1982, 1986, 1988 * The Regents of the University of California * All Rights Reserved * * University Acknowledgment- Portions of this document are derived from * software developed by the University of California, Berkeley, and its * contributors. */ #ifndef _SYS_BYTEORDER_H #define _SYS_BYTEORDER_H #include #include #include #include #if defined(__GNUC__) && defined(_ASM_INLINES) && \ (defined(__i386) || defined(__amd64)) #include #endif #ifdef __cplusplus extern "C" { #endif /* * macros for conversion between host and (internet) network byte order */ #if !defined(_XPG4_2) || defined(__EXTENSIONS__) +#ifdef __COVERITY__ +/* + * Coverity's taint warnings from byteswapping are false positives for us. + * Suppress them by hiding byteswapping from Coverity. + */ +#define BSWAP_8(x) ((x) & 0xff) +#define BSWAP_16(x) ((x) & 0xffff) +#define BSWAP_32(x) ((x) & 0xffffffff) +#define BSWAP_64(x) (x) + +#else /* __COVERITY__ */ + /* * Macros to reverse byte order */ #define BSWAP_8(x) ((x) & 0xff) #define BSWAP_16(x) ((BSWAP_8(x) << 8) | BSWAP_8((x) >> 8)) #define BSWAP_32(x) ((BSWAP_16(x) << 16) | BSWAP_16((x) >> 16)) #define BSWAP_64(x) ((BSWAP_32(x) << 32) | BSWAP_32((x) >> 32)) +#endif /* __COVERITY__ */ + #define BMASK_8(x) ((x) & 0xff) #define BMASK_16(x) ((x) & 0xffff) #define BMASK_32(x) ((x) & 0xffffffff) #define BMASK_64(x) (x) /* * Macros to convert from a specific byte order to/from native byte order */ #ifdef _ZFS_BIG_ENDIAN #define BE_8(x) BMASK_8(x) #define BE_16(x) BMASK_16(x) #define BE_32(x) BMASK_32(x) #define BE_64(x) BMASK_64(x) #define LE_8(x) BSWAP_8(x) #define LE_16(x) BSWAP_16(x) #define LE_32(x) BSWAP_32(x) #define LE_64(x) BSWAP_64(x) #else #define LE_8(x) BMASK_8(x) #define LE_16(x) BMASK_16(x) #define LE_32(x) BMASK_32(x) #define LE_64(x) BMASK_64(x) #define BE_8(x) BSWAP_8(x) #define BE_16(x) BSWAP_16(x) #define BE_32(x) BSWAP_32(x) #define BE_64(x) BSWAP_64(x) #endif #ifdef _ZFS_BIG_ENDIAN static __inline__ uint64_t htonll(uint64_t n) { return (n); } static __inline__ uint64_t ntohll(uint64_t n) { return (n); } #else static __inline__ uint64_t htonll(uint64_t n) { return ((((uint64_t)htonl(n)) << 32) + htonl(n >> 32)); } static __inline__ uint64_t ntohll(uint64_t n) { return ((((uint64_t)ntohl(n)) << 32) + ntohl(n >> 32)); } #endif /* * Macros to read unaligned values from a specific byte order to * native byte order */ #define BE_IN8(xa) \ *((uint8_t *)(xa)) #define BE_IN16(xa) \ (((uint16_t)BE_IN8(xa) << 8) | BE_IN8((uint8_t *)(xa)+1)) #define BE_IN32(xa) \ (((uint32_t)BE_IN16(xa) << 16) | BE_IN16((uint8_t *)(xa)+2)) #define BE_IN64(xa) \ (((uint64_t)BE_IN32(xa) << 32) | BE_IN32((uint8_t *)(xa)+4)) #define LE_IN8(xa) \ *((uint8_t *)(xa)) #define LE_IN16(xa) \ (((uint16_t)LE_IN8((uint8_t *)(xa) + 1) << 8) | LE_IN8(xa)) #define LE_IN32(xa) \ (((uint32_t)LE_IN16((uint8_t *)(xa) + 2) << 16) | LE_IN16(xa)) #define LE_IN64(xa) \ (((uint64_t)LE_IN32((uint8_t *)(xa) + 4) << 32) | LE_IN32(xa)) /* * Macros to write unaligned values from native byte order to a specific byte * order. */ #define BE_OUT8(xa, yv) *((uint8_t *)(xa)) = (uint8_t)(yv); #define BE_OUT16(xa, yv) \ BE_OUT8((uint8_t *)(xa) + 1, yv); \ BE_OUT8((uint8_t *)(xa), (yv) >> 8); #define BE_OUT32(xa, yv) \ BE_OUT16((uint8_t *)(xa) + 2, yv); \ BE_OUT16((uint8_t *)(xa), (yv) >> 16); #define BE_OUT64(xa, yv) \ BE_OUT32((uint8_t *)(xa) + 4, yv); \ BE_OUT32((uint8_t *)(xa), (yv) >> 32); #define LE_OUT8(xa, yv) *((uint8_t *)(xa)) = (uint8_t)(yv); #define LE_OUT16(xa, yv) \ LE_OUT8((uint8_t *)(xa), yv); \ LE_OUT8((uint8_t *)(xa) + 1, (yv) >> 8); #define LE_OUT32(xa, yv) \ LE_OUT16((uint8_t *)(xa), yv); \ LE_OUT16((uint8_t *)(xa) + 2, (yv) >> 16); #define LE_OUT64(xa, yv) \ LE_OUT32((uint8_t *)(xa), yv); \ LE_OUT32((uint8_t *)(xa) + 4, (yv) >> 32); #endif /* !defined(_XPG4_2) || defined(__EXTENSIONS__) */ #ifdef __cplusplus } #endif #endif /* _SYS_BYTEORDER_H */ diff --git a/lib/libspl/include/os/linux/sys/byteorder.h b/lib/libspl/include/os/linux/sys/byteorder.h index c8413ea76352..50f0f1e77936 100644 --- a/lib/libspl/include/os/linux/sys/byteorder.h +++ b/lib/libspl/include/os/linux/sys/byteorder.h @@ -1,223 +1,237 @@ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or https://opensource.org/licenses/CDDL-1.0. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ /* * University Copyright- Copyright (c) 1982, 1986, 1988 * The Regents of the University of California * All Rights Reserved * * University Acknowledgment- Portions of this document are derived from * software developed by the University of California, Berkeley, and its * contributors. */ #ifndef _SYS_BYTEORDER_H #define _SYS_BYTEORDER_H #if defined(__GNUC__) && defined(_ASM_INLINES) && \ (defined(__i386) || defined(__amd64)) #include #endif #include #include #ifdef __cplusplus extern "C" { #endif /* * macros for conversion between host and (internet) network byte order */ #if defined(_ZFS_BIG_ENDIAN) && !defined(ntohl) && !defined(__lint) /* big-endian */ #define ntohl(x) (x) #define ntohs(x) (x) #define htonl(x) (x) #define htons(x) (x) #elif !defined(ntohl) /* little-endian */ #ifndef _IN_PORT_T #define _IN_PORT_T typedef uint16_t in_port_t; #endif #ifndef _IN_ADDR_T #define _IN_ADDR_T typedef uint32_t in_addr_t; #endif #if !defined(_XPG4_2) || defined(__EXTENSIONS__) || defined(_XPG5) extern uint32_t htonl(uint32_t); extern uint16_t htons(uint16_t); extern uint32_t ntohl(uint32_t); extern uint16_t ntohs(uint16_t); #else extern in_addr_t htonl(in_addr_t); extern in_port_t htons(in_port_t); extern in_addr_t ntohl(in_addr_t); extern in_port_t ntohs(in_port_t); #endif /* !defined(_XPG4_2) || defined(__EXTENSIONS__) || defined(_XPG5) */ #endif #if !defined(_XPG4_2) || defined(__EXTENSIONS__) +#ifdef __COVERITY__ +/* + * Coverity's taint warnings from byteswapping are false positives for us. + * Suppress them by hiding byteswapping from Coverity. + */ +#define BSWAP_8(x) ((x) & 0xff) +#define BSWAP_16(x) ((x) & 0xffff) +#define BSWAP_32(x) ((x) & 0xffffffff) +#define BSWAP_64(x) (x) + +#else /* __COVERITY__ */ + /* * Macros to reverse byte order */ #define BSWAP_8(x) ((x) & 0xff) #define BSWAP_16(x) ((BSWAP_8(x) << 8) | BSWAP_8((x) >> 8)) #define BSWAP_32(x) ((BSWAP_16(x) << 16) | BSWAP_16((x) >> 16)) #define BSWAP_64(x) ((BSWAP_32(x) << 32) | BSWAP_32((x) >> 32)) +#endif /* __COVERITY__ */ + #define BMASK_8(x) ((x) & 0xff) #define BMASK_16(x) ((x) & 0xffff) #define BMASK_32(x) ((x) & 0xffffffff) #define BMASK_64(x) (x) /* * Macros to convert from a specific byte order to/from native byte order */ #ifdef _ZFS_BIG_ENDIAN #define BE_8(x) BMASK_8(x) #define BE_16(x) BMASK_16(x) #define BE_32(x) BMASK_32(x) #define BE_64(x) BMASK_64(x) #define LE_8(x) BSWAP_8(x) #define LE_16(x) BSWAP_16(x) #define LE_32(x) BSWAP_32(x) #define LE_64(x) BSWAP_64(x) #else #define LE_8(x) BMASK_8(x) #define LE_16(x) BMASK_16(x) #define LE_32(x) BMASK_32(x) #define LE_64(x) BMASK_64(x) #define BE_8(x) BSWAP_8(x) #define BE_16(x) BSWAP_16(x) #define BE_32(x) BSWAP_32(x) #define BE_64(x) BSWAP_64(x) #endif #ifdef _ZFS_BIG_ENDIAN static __inline__ uint64_t htonll(uint64_t n) { return (n); } static __inline__ uint64_t ntohll(uint64_t n) { return (n); } #else static __inline__ uint64_t htonll(uint64_t n) { return ((((uint64_t)htonl(n)) << 32) + htonl(n >> 32)); } static __inline__ uint64_t ntohll(uint64_t n) { return ((((uint64_t)ntohl(n)) << 32) + ntohl(n >> 32)); } #endif /* * Macros to read unaligned values from a specific byte order to * native byte order */ #define BE_IN8(xa) \ *((uint8_t *)(xa)) #define BE_IN16(xa) \ (((uint16_t)BE_IN8(xa) << 8) | BE_IN8((uint8_t *)(xa)+1)) #define BE_IN32(xa) \ (((uint32_t)BE_IN16(xa) << 16) | BE_IN16((uint8_t *)(xa)+2)) #define BE_IN64(xa) \ (((uint64_t)BE_IN32(xa) << 32) | BE_IN32((uint8_t *)(xa)+4)) #define LE_IN8(xa) \ *((uint8_t *)(xa)) #define LE_IN16(xa) \ (((uint16_t)LE_IN8((uint8_t *)(xa) + 1) << 8) | LE_IN8(xa)) #define LE_IN32(xa) \ (((uint32_t)LE_IN16((uint8_t *)(xa) + 2) << 16) | LE_IN16(xa)) #define LE_IN64(xa) \ (((uint64_t)LE_IN32((uint8_t *)(xa) + 4) << 32) | LE_IN32(xa)) /* * Macros to write unaligned values from native byte order to a specific byte * order. */ #define BE_OUT8(xa, yv) *((uint8_t *)(xa)) = (uint8_t)(yv); #define BE_OUT16(xa, yv) \ BE_OUT8((uint8_t *)(xa) + 1, yv); \ BE_OUT8((uint8_t *)(xa), (yv) >> 8); #define BE_OUT32(xa, yv) \ BE_OUT16((uint8_t *)(xa) + 2, yv); \ BE_OUT16((uint8_t *)(xa), (yv) >> 16); #define BE_OUT64(xa, yv) \ BE_OUT32((uint8_t *)(xa) + 4, yv); \ BE_OUT32((uint8_t *)(xa), (yv) >> 32); #define LE_OUT8(xa, yv) *((uint8_t *)(xa)) = (uint8_t)(yv); #define LE_OUT16(xa, yv) \ LE_OUT8((uint8_t *)(xa), yv); \ LE_OUT8((uint8_t *)(xa) + 1, (yv) >> 8); #define LE_OUT32(xa, yv) \ LE_OUT16((uint8_t *)(xa), yv); \ LE_OUT16((uint8_t *)(xa) + 2, (yv) >> 16); #define LE_OUT64(xa, yv) \ LE_OUT32((uint8_t *)(xa), yv); \ LE_OUT32((uint8_t *)(xa) + 4, (yv) >> 32); #endif /* !defined(_XPG4_2) || defined(__EXTENSIONS__) */ #ifdef __cplusplus } #endif #endif /* _SYS_BYTEORDER_H */ diff --git a/lib/libspl/include/umem.h b/lib/libspl/include/umem.h index 2a366e29472d..82976f756b73 100644 --- a/lib/libspl/include/umem.h +++ b/lib/libspl/include/umem.h @@ -1,208 +1,211 @@ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or https://opensource.org/licenses/CDDL-1.0. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _LIBSPL_UMEM_H #define _LIBSPL_UMEM_H /* * XXX: We should use the real portable umem library if it is detected * at configure time. However, if the library is not available, we can * use a trivial malloc based implementation. This obviously impacts * performance, but unless you are using a full userspace build of zpool for * something other than ztest, you are likely not going to notice or care. * * https://labs.omniti.com/trac/portableumem */ #include #include #include #include #ifdef __cplusplus extern "C" { #endif typedef void vmem_t; /* * Flags for umem_alloc/umem_free */ #define UMEM_DEFAULT 0x0000 /* normal -- may fail */ #define UMEM_NOFAIL 0x0100 /* Never fails */ /* * Flags for umem_cache_create() */ #define UMC_NODEBUG 0x00020000 #define UMEM_CACHE_NAMELEN 31 typedef int umem_nofail_callback_t(void); typedef int umem_constructor_t(void *, void *, int); typedef void umem_destructor_t(void *, void *); typedef void umem_reclaim_t(void *); typedef struct umem_cache { char cache_name[UMEM_CACHE_NAMELEN + 1]; size_t cache_bufsize; size_t cache_align; umem_constructor_t *cache_constructor; umem_destructor_t *cache_destructor; umem_reclaim_t *cache_reclaim; void *cache_private; void *cache_arena; int cache_cflags; } umem_cache_t; /* Prototypes for functions to provide defaults for umem envvars */ const char *_umem_debug_init(void); const char *_umem_options_init(void); const char *_umem_logging_init(void); +__attribute__((alloc_size(1))) static inline void * umem_alloc(size_t size, int flags) { void *ptr = NULL; do { ptr = malloc(size); } while (ptr == NULL && (flags & UMEM_NOFAIL)); return (ptr); } +__attribute__((alloc_size(1))) static inline void * umem_alloc_aligned(size_t size, size_t align, int flags) { void *ptr = NULL; int rc = EINVAL; do { rc = posix_memalign(&ptr, align, size); } while (rc == ENOMEM && (flags & UMEM_NOFAIL)); if (rc == EINVAL) { fprintf(stderr, "%s: invalid memory alignment (%zd)\n", __func__, align); if (flags & UMEM_NOFAIL) abort(); return (NULL); } return (ptr); } +__attribute__((alloc_size(1))) static inline void * umem_zalloc(size_t size, int flags) { void *ptr = NULL; ptr = umem_alloc(size, flags); if (ptr) memset(ptr, 0, size); return (ptr); } static inline void umem_free(const void *ptr, size_t size __maybe_unused) { free((void *)ptr); } static inline void umem_nofail_callback(umem_nofail_callback_t *cb __maybe_unused) {} static inline umem_cache_t * umem_cache_create( const char *name, size_t bufsize, size_t align, umem_constructor_t *constructor, umem_destructor_t *destructor, umem_reclaim_t *reclaim, void *priv, void *vmp, int cflags) { umem_cache_t *cp; cp = (umem_cache_t *)umem_alloc(sizeof (umem_cache_t), UMEM_DEFAULT); if (cp) { strlcpy(cp->cache_name, name, UMEM_CACHE_NAMELEN); cp->cache_bufsize = bufsize; cp->cache_align = align; cp->cache_constructor = constructor; cp->cache_destructor = destructor; cp->cache_reclaim = reclaim; cp->cache_private = priv; cp->cache_arena = vmp; cp->cache_cflags = cflags; } return (cp); } static inline void umem_cache_destroy(umem_cache_t *cp) { umem_free(cp, sizeof (umem_cache_t)); } static inline void * umem_cache_alloc(umem_cache_t *cp, int flags) { void *ptr = NULL; if (cp->cache_align != 0) ptr = umem_alloc_aligned( cp->cache_bufsize, cp->cache_align, flags); else ptr = umem_alloc(cp->cache_bufsize, flags); if (ptr && cp->cache_constructor) cp->cache_constructor(ptr, cp->cache_private, UMEM_DEFAULT); return (ptr); } static inline void umem_cache_free(umem_cache_t *cp, void *ptr) { if (cp->cache_destructor) cp->cache_destructor(ptr, cp->cache_private); umem_free(ptr, cp->cache_bufsize); } static inline void umem_cache_reap_now(umem_cache_t *cp __maybe_unused) { } #ifdef __cplusplus } #endif #endif diff --git a/module/os/freebsd/spl/spl_misc.c b/module/os/freebsd/spl/spl_misc.c index e46271a039de..e3653167323b 100644 --- a/module/os/freebsd/spl/spl_misc.c +++ b/module/os/freebsd/spl/spl_misc.c @@ -1,109 +1,109 @@ /* * Copyright (c) 2007 Pawel Jakub Dawidek * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include static struct opensolaris_utsname hw_utsname = { .machine = MACHINE }; utsname_t * utsname(void) { return (&hw_utsname); } static void opensolaris_utsname_init(void *arg) { hw_utsname.sysname = ostype; hw_utsname.nodename = prison0.pr_hostname; hw_utsname.release = osrelease; snprintf(hw_utsname.version, sizeof (hw_utsname.version), "%d", osreldate); } char * kmem_strdup(const char *s) { char *buf; buf = kmem_alloc(strlen(s) + 1, KM_SLEEP); strcpy(buf, s); return (buf); } int ddi_copyin(const void *from, void *to, size_t len, int flags) { /* Fake ioctl() issued by kernel, 'from' is a kernel address */ if (flags & FKIOCTL) { memcpy(to, from, len); return (0); } return (copyin(from, to, len)); } int ddi_copyout(const void *from, void *to, size_t len, int flags) { /* Fake ioctl() issued by kernel, 'from' is a kernel address */ if (flags & FKIOCTL) { memcpy(to, from, len); return (0); } return (copyout(from, to, len)); } -int +void spl_panic(const char *file, const char *func, int line, const char *fmt, ...) { va_list ap; va_start(ap, fmt); vpanic(fmt, ap); va_end(ap); } SYSINIT(opensolaris_utsname_init, SI_SUB_TUNABLES, SI_ORDER_ANY, opensolaris_utsname_init, NULL); diff --git a/module/os/linux/spl/spl-err.c b/module/os/linux/spl/spl-err.c index c84c39b56bf7..7d3f6127c4af 100644 --- a/module/os/linux/spl/spl-err.c +++ b/module/os/linux/spl/spl-err.c @@ -1,125 +1,124 @@ /* * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. * Copyright (C) 2007 The Regents of the University of California. * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). * Written by Brian Behlendorf . * UCRL-CODE-235197 * * This file is part of the SPL, Solaris Porting Layer. * * The SPL is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * The SPL is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * You should have received a copy of the GNU General Public License along * with the SPL. If not, see . * * Solaris Porting Layer (SPL) Error Implementation. */ #include #include /* * It is often useful to actually have the panic crash the node so you * can then get notified of the event, get the crashdump for later * analysis and other such goodies. * But we would still default to the current default of not to do that. */ unsigned int spl_panic_halt; /* CSTYLED */ module_param(spl_panic_halt, uint, 0644); MODULE_PARM_DESC(spl_panic_halt, "Cause kernel panic on assertion failures"); void spl_dumpstack(void) { printk("Showing stack for process %d\n", current->pid); dump_stack(); } EXPORT_SYMBOL(spl_dumpstack); -int +void spl_panic(const char *file, const char *func, int line, const char *fmt, ...) { const char *newfile; char msg[MAXMSGLEN]; va_list ap; newfile = strrchr(file, '/'); if (newfile != NULL) newfile = newfile + 1; else newfile = file; va_start(ap, fmt); (void) vsnprintf(msg, sizeof (msg), fmt, ap); va_end(ap); printk(KERN_EMERG "%s", msg); printk(KERN_EMERG "PANIC at %s:%d:%s()\n", newfile, line, func); if (spl_panic_halt) panic("%s", msg); spl_dumpstack(); /* Halt the thread to facilitate further debugging */ set_current_state(TASK_UNINTERRUPTIBLE); while (1) schedule(); /* Unreachable */ - return (1); } EXPORT_SYMBOL(spl_panic); void vcmn_err(int ce, const char *fmt, va_list ap) { char msg[MAXMSGLEN]; vsnprintf(msg, MAXMSGLEN, fmt, ap); switch (ce) { case CE_IGNORE: break; case CE_CONT: printk("%s", msg); break; case CE_NOTE: printk(KERN_NOTICE "NOTICE: %s\n", msg); break; case CE_WARN: printk(KERN_WARNING "WARNING: %s\n", msg); break; case CE_PANIC: printk(KERN_EMERG "PANIC: %s\n", msg); if (spl_panic_halt) panic("%s", msg); spl_dumpstack(); /* Halt the thread to facilitate further debugging */ set_current_state(TASK_UNINTERRUPTIBLE); while (1) schedule(); } } /* vcmn_err() */ EXPORT_SYMBOL(vcmn_err); void cmn_err(int ce, const char *fmt, ...) { va_list ap; va_start(ap, fmt); vcmn_err(ce, fmt, ap); va_end(ap); } /* cmn_err() */ EXPORT_SYMBOL(cmn_err);