summaryrefslogtreecommitdiff
path: root/fs/aufs/sysrq.c
blob: dcfa82462b2959e90bd025739508463c35925ab2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/*
 * Copyright (C) 2005-2015 Junjiro R. Okajima
 */

/*
 * magic sysrq hanlder
 */

/* #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 au_sphlhead *files;
	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(&inode_sb_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(&inode_sb_list_lock);
	}
#endif
	pr("files\n");
	files = &au_sbi(sb)->si_files;
	spin_lock(&files->spin);
	hlist_for_each_entry(finfo, &files->head, fi_hlist) {
		umode_t mode;

		file = finfo->fi_file;
		mode = file_inode(file)->i_mode;
		if (!special_file(mode))
			au_dpri_file(file);
	}
	spin_unlock(&files->spin);
	pr("done\n");

#undef pr
	au_plevel = plevel;
}

/* ---------------------------------------------------------------------- */

/* module parameter */
static char *aufs_sysrq_key = "a";
module_param_named(sysrq, aufs_sysrq_key, charp, S_IRUGO);
MODULE_PARM_DESC(sysrq, "MagicSysRq key for " AUFS_NAME);

static void au_sysrq(int key __maybe_unused)
{
	struct au_sbinfo *sbinfo;

	lockdep_off();
	au_sbilist_lock();
	list_for_each_entry(sbinfo, &au_sbilist.head, 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);
}