Commit b41567b1 authored by J. R. Okajima's avatar J. R. Okajima
Browse files

aufs: debug print by MagicSysRq



Print the current data status for debugging.
The trigger key is a module parameter and you can freely change. The
default is 'a' of course.
Signed-off-by: default avatarJ. R. Okajima <hooanon05g@gmail.com>
parent a38028d6
......@@ -46,7 +46,7 @@ endchoice
config AUFS_SBILIST
bool
depends on PROC_FS
depends on AUFS_MAGIC_SYSRQ || PROC_FS
default y
help
Automatic configuration for internal use.
......@@ -122,4 +122,12 @@ config AUFS_DEBUG
help
Enable this to compile aufs internal debug code.
It will have a negative impact to the performance.
config AUFS_MAGIC_SYSRQ
bool
depends on AUFS_DEBUG && MAGIC_SYSRQ
default y
help
Automatic configuration for internal use.
When aufs supports Magic SysRq, enabled automatically.
endif
......@@ -30,3 +30,4 @@ aufs-$(CONFIG_AUFS_XATTR) += xattr.o
aufs-$(CONFIG_FS_POSIX_ACL) += posix_acl.o
aufs-$(CONFIG_AUFS_DIRREN) += dirren.o
aufs-$(CONFIG_AUFS_DEBUG) += debug.o
aufs-$(CONFIG_AUFS_MAGIC_SYSRQ) += sysrq.o
......@@ -467,12 +467,14 @@ static void au_br_do_add(struct super_block *sb, struct au_branch *br,
bbot = au_sbbot(sb);
amount = bbot + 1 - bindex;
h_dentry = au_br_dentry(br);
au_sbilist_lock();
au_br_do_add_brp(au_sbi(sb), bindex, br, bbot, amount);
au_br_do_add_hdp(au_di(root), bindex, bbot, amount);
au_br_do_add_hip(au_ii(root_inode), bindex, bbot, amount);
au_set_h_dptr(root, bindex, dget(h_dentry));
h_inode = d_inode(h_dentry);
au_set_h_iptr(root_inode, bindex, au_igrab(h_inode), /*flags*/0);
au_sbilist_unlock();
}
int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount)
......@@ -950,9 +952,11 @@ static void au_br_do_del(struct super_block *sb, aufs_bindex_t bindex,
h_inode = au_igrab(hinode->hi_inode);
au_hiput(hinode);
au_sbilist_lock();
au_br_do_del_brp(sbinfo, bindex, bbot);
au_br_do_del_hdp(au_di(root), bindex, bbot);
au_br_do_del_hip(au_ii(inode), bindex, bbot);
au_sbilist_unlock();
/* ignore an error */
au_dr_br_fin(sb, br); /* always, regardless the mount option */
......
......@@ -398,7 +398,7 @@ void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen)
void au_dbg_verify_kthread(void)
{
if (au_wkq_test()) {
/* au_dbg_blocked(); re-commit later */
au_dbg_blocked();
/*
* It may be recursive, but udba=notify between two aufs mounts,
* where a single ro branch is shared, is not a problem.
......
......@@ -15,6 +15,7 @@
#include <linux/atomic.h>
#include <linux/module.h>
#include <linux/kallsyms.h>
#include <linux/sysrq.h>
#ifdef CONFIG_AUFS_DEBUG
#define AuDebugOn(a) BUG_ON(a)
......@@ -187,5 +188,26 @@ AuStubInt0(__init au_debug_init, void)
#define AuDbgSym(addr) do {} while (0)
#endif /* CONFIG_AUFS_DEBUG */
/* ---------------------------------------------------------------------- */
#ifdef CONFIG_AUFS_MAGIC_SYSRQ
int __init au_sysrq_init(void);
void au_sysrq_fin(void);
#ifdef CONFIG_HW_CONSOLE
#define au_dbg_blocked() do { \
WARN_ON(1); \
handle_sysrq('w'); \
} while (0)
#else
AuStubVoid(au_dbg_blocked, void)
#endif
#else
AuStubInt0(__init au_sysrq_init, void)
AuStubVoid(au_sysrq_fin, void)
AuStubVoid(au_dbg_blocked, void)
#endif /* CONFIG_AUFS_MAGIC_SYSRQ */
#endif /* __KERNEL__ */
#endif /* __AUFS_DEBUG_H__ */
......@@ -196,9 +196,12 @@ static int __init aufs_init(void)
err = au_hnotify_init();
if (unlikely(err))
goto out_wkq;
err = au_cache_init();
err = au_sysrq_init();
if (unlikely(err))
goto out_hin;
err = au_cache_init();
if (unlikely(err))
goto out_sysrq;
err = register_filesystem(&aufs_fs_type);
if (unlikely(err))
......@@ -210,6 +213,8 @@ static int __init aufs_init(void)
out_cache:
au_cache_fin();
out_sysrq:
au_sysrq_fin();
out_hin:
au_hnotify_fin();
out_wkq:
......
......@@ -314,11 +314,28 @@ static inline void au_sbilist_del(struct super_block *sb)
au_hbl_del(&au_sbi(sb)->si_list, &au_sbilist);
}
#ifdef CONFIG_AUFS_MAGIC_SYSRQ
static inline void au_sbilist_lock(void)
{
hlist_bl_lock(&au_sbilist);
}
static inline void au_sbilist_unlock(void)
{
hlist_bl_unlock(&au_sbilist);
}
#define AuGFP_SBILIST GFP_ATOMIC
#else
AuStubVoid(au_sbilist_lock, void)
AuStubVoid(au_sbilist_unlock, void)
#define AuGFP_SBILIST GFP_NOFS
#endif /* CONFIG_AUFS_MAGIC_SYSRQ */
#else
AuStubVoid(au_sbilist_init, void)
AuStubVoid(au_sbilist_add, struct super_block *sb)
AuStubVoid(au_sbilist_del, struct super_block *sb)
AuStubVoid(au_sbilist_lock, void)
AuStubVoid(au_sbilist_unlock, void)
#define AuGFP_SBILIST GFP_NOFS
#endif
......
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2005-2019 Junjiro R. Okajima
*/
/*
* magic sysrq handler
*/
/* #include <linux/sysrq.h> */
#include <linux/writeback.h>
#include "aufs.h"
/* ---------------------------------------------------------------------- */
static void sysrq_sb(struct super_block *sb)
{
char *plevel;
struct au_sbinfo *sbinfo;
struct file *file;
struct hlist_bl_head *files;
struct hlist_bl_node *pos;
struct au_finfo *finfo;
plevel = au_plevel;
au_plevel = KERN_WARNING;
/* since we define pr_fmt, call printk directly */
#define pr(str) printk(KERN_WARNING AUFS_NAME ": " str)
sbinfo = au_sbi(sb);
printk(KERN_WARNING "si=%lx\n", sysaufs_si_id(sbinfo));
pr("superblock\n");
au_dpri_sb(sb);
#if 0
pr("root dentry\n");
au_dpri_dentry(sb->s_root);
pr("root inode\n");
au_dpri_inode(d_inode(sb->s_root));
#endif
#if 0
do {
int err, i, j, ndentry;
struct au_dcsub_pages dpages;
struct au_dpage *dpage;
err = au_dpages_init(&dpages, GFP_ATOMIC);
if (unlikely(err))
break;
err = au_dcsub_pages(&dpages, sb->s_root, NULL, NULL);
if (!err)
for (i = 0; i < dpages.ndpage; i++) {
dpage = dpages.dpages + i;
ndentry = dpage->ndentry;
for (j = 0; j < ndentry; j++)
au_dpri_dentry(dpage->dentries[j]);
}
au_dpages_free(&dpages);
} while (0);
#endif
#if 1
{
struct inode *i;
pr("isolated inode\n");
spin_lock(&sb->s_inode_list_lock);
list_for_each_entry(i, &sb->s_inodes, i_sb_list) {
spin_lock(&i->i_lock);
if (1 || hlist_empty(&i->i_dentry))
au_dpri_inode(i);
spin_unlock(&i->i_lock);
}
spin_unlock(&sb->s_inode_list_lock);
}
#endif
pr("files\n");
files = &au_sbi(sb)->si_files;
hlist_bl_lock(files);
hlist_bl_for_each_entry(finfo, pos, files, fi_hlist) {
umode_t mode;
file = finfo->fi_file;
mode = file_inode(file)->i_mode;
if (!special_file(mode))
au_dpri_file(file);
}
hlist_bl_unlock(files);
pr("done\n");
#undef pr
au_plevel = plevel;
}
/* ---------------------------------------------------------------------- */
/* module parameter */
static char *aufs_sysrq_key = "a";
module_param_named(sysrq, aufs_sysrq_key, charp, 0444);
MODULE_PARM_DESC(sysrq, "MagicSysRq key for " AUFS_NAME);
static void au_sysrq(int key __maybe_unused)
{
struct au_sbinfo *sbinfo;
struct hlist_bl_node *pos;
lockdep_off();
au_sbilist_lock();
hlist_bl_for_each_entry(sbinfo, pos, &au_sbilist, si_list)
sysrq_sb(sbinfo->si_sb);
au_sbilist_unlock();
lockdep_on();
}
static struct sysrq_key_op au_sysrq_op = {
.handler = au_sysrq,
.help_msg = "Aufs",
.action_msg = "Aufs",
.enable_mask = SYSRQ_ENABLE_DUMP
};
/* ---------------------------------------------------------------------- */
int __init au_sysrq_init(void)
{
int err;
char key;
err = -1;
key = *aufs_sysrq_key;
if ('a' <= key && key <= 'z')
err = register_sysrq_key(key, &au_sysrq_op);
if (unlikely(err))
pr_err("err %d, sysrq=%c\n", err, key);
return err;
}
void au_sysrq_fin(void)
{
int err;
err = unregister_sysrq_key(*aufs_sysrq_key, &au_sysrq_op);
if (unlikely(err))
pr_err("err %d (ignored)\n", err);
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment