// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2005-2019 Junjiro R. Okajima */ /* * magic sysrq handler */ /* #include */ #include #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; struct inode *i; 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 /* reserved */ 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 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 (hlist_empty(&i->i_dentry)) au_dpri_inode(i); spin_unlock(&i->i_lock); } spin_unlock(&sb->s_inode_list_lock); 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); }