xfs: introduce CONFIG_XFS_WARN

Running a CONFIG_XFS_DEBUG kernel in production environments is not
the best idea as it introduces significant overhead, can change
the behaviour of algorithms (such as allocation) to improve test
coverage, and (most importantly) panic the machine on non-fatal
errors.

There are many cases where all we want to do is run a
kernel with more bounds checking enabled, such as is provided by the
ASSERT() statements throughout the code, but without all the
potential overhead and drawbacks.

This patch converts all the ASSERT statements to evaluate as
WARN_ON(1) statements and hence if they fail dump a warning and a
stack trace to the log. This has minimal overhead and does not
change any algorithms, and will allow us to find strange "out of
bounds" problems more easily on production machines.

There are a few places where assert statements contain debug only
code. These are converted to be debug-or-warn only code so that we
still get all the assert checks in the code.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Signed-off-by: Ben Myers <bpm@sgi.com>
This commit is contained in:
Dave Chinner 2013-04-30 21:39:34 +10:00 committed by Ben Myers
parent cab09a81fb
commit 742ae1e35b
13 changed files with 66 additions and 27 deletions

View File

@ -69,6 +69,19 @@ config XFS_RT
If unsure, say N. If unsure, say N.
config XFS_WARN
bool "XFS Verbose Warnings"
depends on XFS_FS && !XFS_DEBUG
help
Say Y here to get an XFS build with many additional warnings.
It converts ASSERT checks to WARN, so will log any out-of-bounds
conditions that occur that would otherwise be missed. It is much
lighter weight than XFS_DEBUG and does not modify algorithms and will
not cause the kernel to panic on non-fatal errors.
However, similar to XFS_DEBUG, it is only advisable to use this if you
are debugging a particular problem.
config XFS_DEBUG config XFS_DEBUG
bool "XFS Debugging support" bool "XFS Debugging support"
depends on XFS_FS depends on XFS_FS

View File

@ -22,12 +22,12 @@
typedef struct { typedef struct {
struct rw_semaphore mr_lock; struct rw_semaphore mr_lock;
#ifdef DEBUG #if defined(DEBUG) || defined(XFS_WARN)
int mr_writer; int mr_writer;
#endif #endif
} mrlock_t; } mrlock_t;
#ifdef DEBUG #if defined(DEBUG) || defined(XFS_WARN)
#define mrinit(mrp, name) \ #define mrinit(mrp, name) \
do { (mrp)->mr_writer = 0; init_rwsem(&(mrp)->mr_lock); } while (0) do { (mrp)->mr_writer = 0; init_rwsem(&(mrp)->mr_lock); } while (0)
#else #else
@ -46,7 +46,7 @@ static inline void mraccess_nested(mrlock_t *mrp, int subclass)
static inline void mrupdate_nested(mrlock_t *mrp, int subclass) static inline void mrupdate_nested(mrlock_t *mrp, int subclass)
{ {
down_write_nested(&mrp->mr_lock, subclass); down_write_nested(&mrp->mr_lock, subclass);
#ifdef DEBUG #if defined(DEBUG) || defined(XFS_WARN)
mrp->mr_writer = 1; mrp->mr_writer = 1;
#endif #endif
} }
@ -60,7 +60,7 @@ static inline int mrtryupdate(mrlock_t *mrp)
{ {
if (!down_write_trylock(&mrp->mr_lock)) if (!down_write_trylock(&mrp->mr_lock))
return 0; return 0;
#ifdef DEBUG #if defined(DEBUG) || defined(XFS_WARN)
mrp->mr_writer = 1; mrp->mr_writer = 1;
#endif #endif
return 1; return 1;
@ -68,7 +68,7 @@ static inline int mrtryupdate(mrlock_t *mrp)
static inline void mrunlock_excl(mrlock_t *mrp) static inline void mrunlock_excl(mrlock_t *mrp)
{ {
#ifdef DEBUG #if defined(DEBUG) || defined(XFS_WARN)
mrp->mr_writer = 0; mrp->mr_writer = 0;
#endif #endif
up_write(&mrp->mr_lock); up_write(&mrp->mr_lock);
@ -81,7 +81,7 @@ static inline void mrunlock_shared(mrlock_t *mrp)
static inline void mrdemote(mrlock_t *mrp) static inline void mrdemote(mrlock_t *mrp)
{ {
#ifdef DEBUG #if defined(DEBUG) || defined(XFS_WARN)
mrp->mr_writer = 0; mrp->mr_writer = 0;
#endif #endif
downgrade_write(&mrp->mr_lock); downgrade_write(&mrp->mr_lock);

View File

@ -24,6 +24,11 @@
#define XFS_BUF_LOCK_TRACKING 1 #define XFS_BUF_LOCK_TRACKING 1
#endif #endif
#ifdef CONFIG_XFS_WARN
#define XFS_WARN 1
#endif
#include "xfs_linux.h" #include "xfs_linux.h"
#endif /* __XFS_H__ */ #endif /* __XFS_H__ */

View File

@ -386,7 +386,7 @@ const struct xfs_buf_ops xfs_allocbt_buf_ops = {
}; };
#ifdef DEBUG #if defined(DEBUG) || defined(XFS_WARN)
STATIC int STATIC int
xfs_allocbt_keys_inorder( xfs_allocbt_keys_inorder(
struct xfs_btree_cur *cur, struct xfs_btree_cur *cur,
@ -442,7 +442,7 @@ static const struct xfs_btree_ops xfs_allocbt_ops = {
.init_ptr_from_cur = xfs_allocbt_init_ptr_from_cur, .init_ptr_from_cur = xfs_allocbt_init_ptr_from_cur,
.key_diff = xfs_allocbt_key_diff, .key_diff = xfs_allocbt_key_diff,
.buf_ops = &xfs_allocbt_buf_ops, .buf_ops = &xfs_allocbt_buf_ops,
#ifdef DEBUG #if defined(DEBUG) || defined(XFS_WARN)
.keys_inorder = xfs_allocbt_keys_inorder, .keys_inorder = xfs_allocbt_keys_inorder,
.recs_inorder = xfs_allocbt_recs_inorder, .recs_inorder = xfs_allocbt_recs_inorder,
#endif #endif

View File

@ -813,7 +813,7 @@ const struct xfs_buf_ops xfs_bmbt_buf_ops = {
}; };
#ifdef DEBUG #if defined(DEBUG) || defined(XFS_WARN)
STATIC int STATIC int
xfs_bmbt_keys_inorder( xfs_bmbt_keys_inorder(
struct xfs_btree_cur *cur, struct xfs_btree_cur *cur,
@ -853,7 +853,7 @@ static const struct xfs_btree_ops xfs_bmbt_ops = {
.init_ptr_from_cur = xfs_bmbt_init_ptr_from_cur, .init_ptr_from_cur = xfs_bmbt_init_ptr_from_cur,
.key_diff = xfs_bmbt_key_diff, .key_diff = xfs_bmbt_key_diff,
.buf_ops = &xfs_bmbt_buf_ops, .buf_ops = &xfs_bmbt_buf_ops,
#ifdef DEBUG #if defined(DEBUG) || defined(XFS_WARN)
.keys_inorder = xfs_bmbt_keys_inorder, .keys_inorder = xfs_bmbt_keys_inorder,
.recs_inorder = xfs_bmbt_recs_inorder, .recs_inorder = xfs_bmbt_recs_inorder,
#endif #endif

View File

@ -215,7 +215,7 @@ struct xfs_btree_ops {
const struct xfs_buf_ops *buf_ops; const struct xfs_buf_ops *buf_ops;
#ifdef DEBUG #if defined(DEBUG) || defined(XFS_WARN)
/* check that k1 is lower than k2 */ /* check that k1 is lower than k2 */
int (*keys_inorder)(struct xfs_btree_cur *cur, int (*keys_inorder)(struct xfs_btree_cur *cur,
union xfs_btree_key *k1, union xfs_btree_key *k1,

View File

@ -993,7 +993,7 @@ xfs_dir2_leafn_rebalance(
xfs_dir2_leaf_t *leaf1; /* first leaf structure */ xfs_dir2_leaf_t *leaf1; /* first leaf structure */
xfs_dir2_leaf_t *leaf2; /* second leaf structure */ xfs_dir2_leaf_t *leaf2; /* second leaf structure */
int mid; /* midpoint leaf index */ int mid; /* midpoint leaf index */
#ifdef DEBUG #if defined(DEBUG) || defined(XFS_WARN)
int oldstale; /* old count of stale leaves */ int oldstale; /* old count of stale leaves */
#endif #endif
int oldsum; /* old total leaf count */ int oldsum; /* old total leaf count */
@ -1022,7 +1022,7 @@ xfs_dir2_leafn_rebalance(
ents2 = xfs_dir3_leaf_ents_p(leaf2); ents2 = xfs_dir3_leaf_ents_p(leaf2);
oldsum = hdr1.count + hdr2.count; oldsum = hdr1.count + hdr2.count;
#ifdef DEBUG #if defined(DEBUG) || defined(XFS_WARN)
oldstale = hdr1.stale + hdr2.stale; oldstale = hdr1.stale + hdr2.stale;
#endif #endif
mid = oldsum >> 1; mid = oldsum >> 1;

View File

@ -272,7 +272,7 @@ const struct xfs_buf_ops xfs_inobt_buf_ops = {
.verify_write = xfs_inobt_write_verify, .verify_write = xfs_inobt_write_verify,
}; };
#ifdef DEBUG #if defined(DEBUG) || defined(XFS_WARN)
STATIC int STATIC int
xfs_inobt_keys_inorder( xfs_inobt_keys_inorder(
struct xfs_btree_cur *cur, struct xfs_btree_cur *cur,
@ -310,7 +310,7 @@ static const struct xfs_btree_ops xfs_inobt_ops = {
.init_ptr_from_cur = xfs_inobt_init_ptr_from_cur, .init_ptr_from_cur = xfs_inobt_init_ptr_from_cur,
.key_diff = xfs_inobt_key_diff, .key_diff = xfs_inobt_key_diff,
.buf_ops = &xfs_inobt_buf_ops, .buf_ops = &xfs_inobt_buf_ops,
#ifdef DEBUG #if defined(DEBUG) || defined(XFS_WARN)
.keys_inorder = xfs_inobt_keys_inorder, .keys_inorder = xfs_inobt_keys_inorder,
.recs_inorder = xfs_inobt_recs_inorder, .recs_inorder = xfs_inobt_recs_inorder,
#endif #endif

View File

@ -287,7 +287,7 @@ xfs_ilock_demote(
trace_xfs_ilock_demote(ip, lock_flags, _RET_IP_); trace_xfs_ilock_demote(ip, lock_flags, _RET_IP_);
} }
#ifdef DEBUG #if defined(DEBUG) || defined(XFS_WARN)
int int
xfs_isilocked( xfs_isilocked(
xfs_inode_t *ip, xfs_inode_t *ip,

View File

@ -293,15 +293,7 @@ static inline __uint64_t howmany_64(__uint64_t x, __uint32_t y)
#define ASSERT_ALWAYS(expr) \ #define ASSERT_ALWAYS(expr) \
(unlikely(expr) ? (void)0 : assfail(#expr, __FILE__, __LINE__)) (unlikely(expr) ? (void)0 : assfail(#expr, __FILE__, __LINE__))
#ifndef DEBUG #ifdef DEBUG
#define ASSERT(expr) ((void)0)
#ifndef STATIC
# define STATIC static noinline
#endif
#else /* DEBUG */
#define ASSERT(expr) \ #define ASSERT(expr) \
(unlikely(expr) ? (void)0 : assfail(#expr, __FILE__, __LINE__)) (unlikely(expr) ? (void)0 : assfail(#expr, __FILE__, __LINE__))
@ -309,6 +301,26 @@ static inline __uint64_t howmany_64(__uint64_t x, __uint32_t y)
# define STATIC noinline # define STATIC noinline
#endif #endif
#else /* !DEBUG */
#ifdef XFS_WARN
#define ASSERT(expr) \
(unlikely(expr) ? (void)0 : asswarn(#expr, __FILE__, __LINE__))
#ifndef STATIC
# define STATIC static noinline
#endif
#else /* !DEBUG && !XFS_WARN */
#define ASSERT(expr) ((void)0)
#ifndef STATIC
# define STATIC static noinline
#endif
#endif /* XFS_WARN */
#endif /* DEBUG */ #endif /* DEBUG */
#endif /* __XFS_LINUX__ */ #endif /* __XFS_LINUX__ */

View File

@ -92,6 +92,14 @@ xfs_alert_tag(
BUG_ON(do_panic); BUG_ON(do_panic);
} }
void
asswarn(char *expr, char *file, int line)
{
xfs_warn(NULL, "Assertion failed: %s, file: %s, line: %d",
expr, file, line);
WARN_ON(1);
}
void void
assfail(char *expr, char *file, int line) assfail(char *expr, char *file, int line)
{ {

View File

@ -57,6 +57,7 @@ do { \
xfs_printk_ratelimited(xfs_debug, dev, fmt, ##__VA_ARGS__) xfs_printk_ratelimited(xfs_debug, dev, fmt, ##__VA_ARGS__)
extern void assfail(char *expr, char *f, int l); extern void assfail(char *expr, char *f, int l);
extern void asswarn(char *expr, char *f, int l);
extern void xfs_hex_dump(void *p, int length); extern void xfs_hex_dump(void *p, int length);

View File

@ -405,7 +405,7 @@ typedef struct xfs_trans {
int64_t t_res_fdblocks_delta; /* on-disk only chg */ int64_t t_res_fdblocks_delta; /* on-disk only chg */
int64_t t_frextents_delta;/* superblock freextents chg*/ int64_t t_frextents_delta;/* superblock freextents chg*/
int64_t t_res_frextents_delta; /* on-disk only chg */ int64_t t_res_frextents_delta; /* on-disk only chg */
#ifdef DEBUG #if defined(DEBUG) || defined(XFS_WARN)
int64_t t_ag_freeblks_delta; /* debugging counter */ int64_t t_ag_freeblks_delta; /* debugging counter */
int64_t t_ag_flist_delta; /* debugging counter */ int64_t t_ag_flist_delta; /* debugging counter */
int64_t t_ag_btree_delta; /* debugging counter */ int64_t t_ag_btree_delta; /* debugging counter */
@ -433,7 +433,7 @@ typedef struct xfs_trans {
#define xfs_trans_get_block_res(tp) ((tp)->t_blk_res) #define xfs_trans_get_block_res(tp) ((tp)->t_blk_res)
#define xfs_trans_set_sync(tp) ((tp)->t_flags |= XFS_TRANS_SYNC) #define xfs_trans_set_sync(tp) ((tp)->t_flags |= XFS_TRANS_SYNC)
#ifdef DEBUG #if defined(DEBUG) || defined(XFS_WARN)
#define xfs_trans_agblocks_delta(tp, d) ((tp)->t_ag_freeblks_delta += (int64_t)d) #define xfs_trans_agblocks_delta(tp, d) ((tp)->t_ag_freeblks_delta += (int64_t)d)
#define xfs_trans_agflist_delta(tp, d) ((tp)->t_ag_flist_delta += (int64_t)d) #define xfs_trans_agflist_delta(tp, d) ((tp)->t_ag_flist_delta += (int64_t)d)
#define xfs_trans_agbtree_delta(tp, d) ((tp)->t_ag_btree_delta += (int64_t)d) #define xfs_trans_agbtree_delta(tp, d) ((tp)->t_ag_btree_delta += (int64_t)d)