Viewing: libcfs_private.h
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*
* Copyright (c) 2011, 2014, Intel Corporation.
*/
/*
* This file is part of Lustre, http://www.lustre.org/
*
* Various defines for libcfs.
*/
#ifndef __LIBCFS_PRIVATE_H__
#define __LIBCFS_PRIVATE_H__
#ifndef DEBUG_SUBSYSTEM
# define DEBUG_SUBSYSTEM S_UNDEFINED
#endif
#include <linux/slab.h>
#include <lustre_compat/linux/vmalloc.h>
#ifdef LIBCFS_DEBUG
/*
* When this is on, LASSERT macro includes check for assignment used instead
* of equality check, but doesn't have unlikely(). Turn this on from time to
* time to make test-builds. This shouldn't be on for production release.
*/
#define LASSERT_CHECKED (0)
#if LASSERT_CHECKED
/*
* Assertion.
*
* Strange construction with empty "then" clause is used to trigger compiler
* warnings on the assertions of the form LASSERT(a = b);
*
* "warning: suggest parentheses around assignment used as truth value"
*
* requires -Wall. Unfortunately this rules out use of likely/unlikely.
*/
#define LASSERTF(cond, fmt, ...) \
do { \
if (cond) \
; \
else { \
LIBCFS_DEBUG_MSG_DATA_DECL(__msg_data, D_EMERG, NULL); \
libcfs_debug_msg(&__msg_data, \
"ASSERTION( %s ) failed: " fmt, #cond, \
## __VA_ARGS__); \
lbug_with_loc(&__msg_data); \
} \
} while (0)
#define LASSERT(cond) LASSERTF(cond, "\n")
#else /* !LASSERT_CHECKED */
#define LASSERTF(cond, fmt, ...) \
do { \
if (unlikely(!(cond))) { \
LIBCFS_DEBUG_MSG_DATA_DECL(__msg_data, D_EMERG, NULL); \
libcfs_debug_msg(&__msg_data, \
"ASSERTION( %s ) failed: " fmt, #cond, \
## __VA_ARGS__); \
lbug_with_loc(&__msg_data); \
} \
} while (0)
#define LASSERT(cond) LASSERTF(cond, "\n")
#endif /* !LASSERT_CHECKED */
#else /* !LIBCFS_DEBUG */
/* sizeof is to use expression without evaluating it. */
# define LASSERT(e) ((void)sizeof!!(e))
# define LASSERTF(cond, ...) ((void)sizeof!!(cond))
#endif /* !LIBCFS_DEBUG */
#ifdef CONFIG_LUSTRE_DEBUG_EXPENSIVE_CHECK
/**
* This is for more expensive checks that one doesn't want to be enabled all
* the time. LINVRNT() has to be explicitly enabled by --enable-invariants
* configure option.
*/
# define LINVRNT(exp) LASSERT(exp)
#else
# define LINVRNT(exp) ((void)sizeof!!(exp))
#endif
void
#ifdef HAVE_LBUG_WITH_LOC_IN_OBJTOOL
__noreturn
#endif
lbug_with_loc(struct libcfs_debug_msg_data *msg);
#define LBUG() \
do { \
LIBCFS_DEBUG_MSG_DATA_DECL(msgdata, D_EMERG, NULL); \
lbug_with_loc(&msgdata); \
break; \
} while(0)
/*
* Memory
*/
#ifdef LIBCFS_DEBUG
extern atomic64_t libcfs_kmem;
# define libcfs_kmem_inc(ptr, size) \
do { \
atomic64_add((size), &libcfs_kmem); \
} while (0)
# define libcfs_kmem_dec(ptr, size) \
do { \
atomic64_sub((size), &libcfs_kmem); \
} while (0)
# define libcfs_kmem_read() \
(long long)atomic64_read(&libcfs_kmem)
#else
# define libcfs_kmem_inc(ptr, size) do {} while (0)
# define libcfs_kmem_dec(ptr, size) do {} while (0)
# define libcfs_kmem_read() (0)
#endif /* LIBCFS_DEBUG */
#ifndef LIBCFS_VMALLOC_SIZE
#define LIBCFS_VMALLOC_SIZE (2 << PAGE_SHIFT) /* 2 pages */
#endif
#define LIBCFS_ALLOC_PRE(size, mask) \
do { \
LASSERT(!in_interrupt() || \
(((size) <= LIBCFS_VMALLOC_SIZE) && \
((mask) & GFP_ATOMIC) != 0)); \
} while (0)
/* message format here needs to match regexp in lustre/tests/leak_finder.pl */
#define LIBCFS_MEM_MSG(ptr, size, name) \
CDEBUG(D_MALLOC, name " '" #ptr "': %d at %p.\n", (int)(size), ptr)
#define LIBCFS_ALLOC_POST(ptr, size, name) \
do { \
if (unlikely((ptr) == NULL)) { \
CERROR("LNET: out of memory at %s:%d (tried to alloc '" \
#ptr "' = %d)\n", __FILE__, __LINE__, (int)(size)); \
CERROR("LNET: %lld total bytes allocated by lnet\n", \
libcfs_kmem_read()); \
} else { \
libcfs_kmem_inc((ptr), (size)); \
LIBCFS_MEM_MSG(ptr, (size), name); \
} \
} while (0)
#define LIBCFS_FREE_PRE(ptr, size, name) \
libcfs_kmem_dec((ptr), (size)); \
LIBCFS_MEM_MSG(ptr, (size), name)
/**
* allocate memory with GFP flags @mask
* The allocated memory is zeroed-out.
*/
#define LIBCFS_ALLOC_GFP(ptr, size, mask) \
do { \
LIBCFS_ALLOC_PRE((size), (mask)); \
(ptr) = (size) <= LIBCFS_VMALLOC_SIZE ? \
kzalloc((size), (mask)) : vzalloc(size); \
LIBCFS_ALLOC_POST((ptr), (size), "alloc"); \
} while (0)
/**
* default allocator
*/
#define LIBCFS_ALLOC(ptr, size) \
LIBCFS_ALLOC_GFP(ptr, (size), GFP_NOFS)
/**
* non-sleeping allocator
*/
#define LIBCFS_ALLOC_ATOMIC(ptr, size) \
LIBCFS_ALLOC_GFP(ptr, (size), GFP_ATOMIC)
/**
* allocate memory for specified CPU partition
* \a cptab != NULL, \a cpt is CPU partition id of \a cptab
* \a cptab == NULL, \a cpt is HW NUMA node id
* The allocated memory is zeroed-out.
*/
#define LIBCFS_CPT_ALLOC_GFP(ptr, cptab, cpt, size, mask) \
do { \
LIBCFS_ALLOC_PRE((size), (mask)); \
(ptr) = (size) <= LIBCFS_VMALLOC_SIZE ? \
cfs_cpt_malloc((cptab), (cpt), (size), (mask) | __GFP_ZERO) : \
cfs_cpt_vzalloc((cptab), (cpt), (size)); \
LIBCFS_ALLOC_POST((ptr), (size), "alloc"); \
} while (0)
/** default numa allocator */
#define LIBCFS_CPT_ALLOC(ptr, cptab, cpt, size) \
LIBCFS_CPT_ALLOC_GFP(ptr, (cptab), (cpt), (size), GFP_NOFS)
#define LIBCFS_FREE(ptr, size) \
do { \
size_t s = (size); \
if (likely(ptr)) { \
LIBCFS_FREE_PRE(ptr, (size), "kfreed"); \
if (unlikely(s > LIBCFS_VMALLOC_SIZE)) \
compat_vfree_atomic(ptr); \
else \
kfree(ptr); \
} \
} while (0)
/******************************************************************************/
void libcfs_debug_dumplog(void);
int libcfs_debug_init(unsigned long bufsize);
int libcfs_debug_cleanup(void);
int libcfs_debug_clear_buffer(void);
int libcfs_debug_mark_buffer(const char *text);
#define CFS_ALLOC_PTR(ptr) LIBCFS_ALLOC(ptr, sizeof(*(ptr)));
#define CFS_ALLOC_PTR_ARRAY(ptr, count) \
LIBCFS_ALLOC(ptr, (count) * sizeof(*(ptr)))
#define CFS_FREE_PTR(ptr) LIBCFS_FREE(ptr, sizeof(*(ptr)));
#define CFS_FREE_PTR_ARRAY(ptr, count) \
LIBCFS_FREE(ptr, (count) * sizeof(*(ptr)))
/* implication */
#define ergo(a, b) (!(a) || (b))
/* logical equivalence */
#define equi(a, b) (!!(a) == !!(b))
#endif