[PATCH 30/42] Unionfs: debugging infrastructure
Signed-off-by: Erez Zadok <[EMAIL PROTECTED]> --- fs/unionfs/debug.c | 532 1 files changed, 532 insertions(+), 0 deletions(-) create mode 100644 fs/unionfs/debug.c diff --git a/fs/unionfs/debug.c b/fs/unionfs/debug.c new file mode 100644 index 000..c2b8b58 --- /dev/null +++ b/fs/unionfs/debug.c @@ -0,0 +1,532 @@ +/* + * Copyright (c) 2003-2007 Erez Zadok + * Copyright (c) 2005-2007 Josef 'Jeff' Sipek + * Copyright (c) 2003-2007 Stony Brook University + * Copyright (c) 2003-2007 The Research Foundation of SUNY + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include "union.h" + +/* + * Helper debugging functions for maintainers (and for users to report back + * useful information back to maintainers) + */ + +/* it's always useful to know what part of the code called us */ +#define PRINT_CALLER(fname, fxn, line) \ + do {\ + if (!printed_caller) { \ + pr_debug("PC:%s:%s:%d\n", (fname), (fxn), (line)); \ + printed_caller = 1; \ + } \ + } while (0) + +/* + * __unionfs_check_{inode,dentry,file} perform exhaustive sanity checking on + * the fan-out of various Unionfs objects. We check that no lower objects + * exist outside the start/end branch range; that all objects within are + * non-NULL (with some allowed exceptions); that for every lower file + * there's a lower dentry+inode; that the start/end ranges match for all + * corresponding lower objects; that open files/symlinks have only one lower + * objects, but directories can have several; and more. + */ +void __unionfs_check_inode(const struct inode *inode, + const char *fname, const char *fxn, int line) +{ + int bindex; + int istart, iend; + struct inode *lower_inode; + struct super_block *sb; + int printed_caller = 0; + void *poison_ptr; + + /* for inodes now */ + BUG_ON(!inode); + sb = inode->i_sb; + istart = ibstart(inode); + iend = ibend(inode); + /* don't check inode if no lower branches */ + if (istart < 0 && iend < 0) + return; + if (unlikely(istart > iend)) { + PRINT_CALLER(fname, fxn, line); + pr_debug(" Ci0: inode=%p istart/end=%d:%d\n", +inode, istart, iend); + } + if (unlikely((istart == -1 && iend != -1) || +(istart != -1 && iend == -1))) { + PRINT_CALLER(fname, fxn, line); + pr_debug(" Ci1: inode=%p istart/end=%d:%d\n", +inode, istart, iend); + } + if (!S_ISDIR(inode->i_mode)) { + if (unlikely(iend != istart)) { + PRINT_CALLER(fname, fxn, line); + pr_debug(" Ci2: inode=%p istart=%d iend=%d\n", +inode, istart, iend); + } + } + + for (bindex = sbstart(sb); bindex < sbmax(sb); bindex++) { + if (unlikely(!UNIONFS_I(inode))) { + PRINT_CALLER(fname, fxn, line); + pr_debug(" Ci3: no inode_info %p\n", inode); + return; + } + if (unlikely(!UNIONFS_I(inode)->lower_inodes)) { + PRINT_CALLER(fname, fxn, line); + pr_debug(" Ci4: no lower_inodes %p\n", inode); + return; + } + lower_inode = unionfs_lower_inode_idx(inode, bindex); + if (lower_inode) { + memset(_ptr, POISON_INUSE, sizeof(void *)); + if (unlikely(bindex < istart || bindex > iend)) { + PRINT_CALLER(fname, fxn, line); + pr_debug(" Ci5: inode/linode=%p:%p bindex=%d " +"istart/end=%d:%d\n", inode, +lower_inode, bindex, istart, iend); + } else if (unlikely(lower_inode == poison_ptr)) { + /* freed inode! */ + PRINT_CALLER(fname, fxn, line); + pr_debug(" Ci6: inode/linode=%p:%p bindex=%d " +"istart/end=%d:%d\n", inode, +lower_inode, bindex, istart, iend); + } + continue; + } + /* if we get here, then lower_inode == NULL */ + if (bindex < istart || bindex >
[PATCH 30/42] Unionfs: debugging infrastructure
Signed-off-by: Erez Zadok [EMAIL PROTECTED] --- fs/unionfs/debug.c | 532 1 files changed, 532 insertions(+), 0 deletions(-) create mode 100644 fs/unionfs/debug.c diff --git a/fs/unionfs/debug.c b/fs/unionfs/debug.c new file mode 100644 index 000..c2b8b58 --- /dev/null +++ b/fs/unionfs/debug.c @@ -0,0 +1,532 @@ +/* + * Copyright (c) 2003-2007 Erez Zadok + * Copyright (c) 2005-2007 Josef 'Jeff' Sipek + * Copyright (c) 2003-2007 Stony Brook University + * Copyright (c) 2003-2007 The Research Foundation of SUNY + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include union.h + +/* + * Helper debugging functions for maintainers (and for users to report back + * useful information back to maintainers) + */ + +/* it's always useful to know what part of the code called us */ +#define PRINT_CALLER(fname, fxn, line) \ + do {\ + if (!printed_caller) { \ + pr_debug(PC:%s:%s:%d\n, (fname), (fxn), (line)); \ + printed_caller = 1; \ + } \ + } while (0) + +/* + * __unionfs_check_{inode,dentry,file} perform exhaustive sanity checking on + * the fan-out of various Unionfs objects. We check that no lower objects + * exist outside the start/end branch range; that all objects within are + * non-NULL (with some allowed exceptions); that for every lower file + * there's a lower dentry+inode; that the start/end ranges match for all + * corresponding lower objects; that open files/symlinks have only one lower + * objects, but directories can have several; and more. + */ +void __unionfs_check_inode(const struct inode *inode, + const char *fname, const char *fxn, int line) +{ + int bindex; + int istart, iend; + struct inode *lower_inode; + struct super_block *sb; + int printed_caller = 0; + void *poison_ptr; + + /* for inodes now */ + BUG_ON(!inode); + sb = inode-i_sb; + istart = ibstart(inode); + iend = ibend(inode); + /* don't check inode if no lower branches */ + if (istart 0 iend 0) + return; + if (unlikely(istart iend)) { + PRINT_CALLER(fname, fxn, line); + pr_debug( Ci0: inode=%p istart/end=%d:%d\n, +inode, istart, iend); + } + if (unlikely((istart == -1 iend != -1) || +(istart != -1 iend == -1))) { + PRINT_CALLER(fname, fxn, line); + pr_debug( Ci1: inode=%p istart/end=%d:%d\n, +inode, istart, iend); + } + if (!S_ISDIR(inode-i_mode)) { + if (unlikely(iend != istart)) { + PRINT_CALLER(fname, fxn, line); + pr_debug( Ci2: inode=%p istart=%d iend=%d\n, +inode, istart, iend); + } + } + + for (bindex = sbstart(sb); bindex sbmax(sb); bindex++) { + if (unlikely(!UNIONFS_I(inode))) { + PRINT_CALLER(fname, fxn, line); + pr_debug( Ci3: no inode_info %p\n, inode); + return; + } + if (unlikely(!UNIONFS_I(inode)-lower_inodes)) { + PRINT_CALLER(fname, fxn, line); + pr_debug( Ci4: no lower_inodes %p\n, inode); + return; + } + lower_inode = unionfs_lower_inode_idx(inode, bindex); + if (lower_inode) { + memset(poison_ptr, POISON_INUSE, sizeof(void *)); + if (unlikely(bindex istart || bindex iend)) { + PRINT_CALLER(fname, fxn, line); + pr_debug( Ci5: inode/linode=%p:%p bindex=%d +istart/end=%d:%d\n, inode, +lower_inode, bindex, istart, iend); + } else if (unlikely(lower_inode == poison_ptr)) { + /* freed inode! */ + PRINT_CALLER(fname, fxn, line); + pr_debug( Ci6: inode/linode=%p:%p bindex=%d +istart/end=%d:%d\n, inode, +lower_inode, bindex, istart, iend); + } + continue; + } + /* if we get here, then lower_inode == NULL */ + if (bindex istart || bindex iend) +