aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ubifs
diff options
context:
space:
mode:
authorArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2011-05-31 11:16:34 -0400
committerArtem Bityutskiy <dedekind1@gmail.com>2011-07-04 03:54:28 -0400
commit81e79d38df5a17bb1c738a14f8e5f3412fb33afa (patch)
tree88f88631a6e10ec9fd83261ceee195e283be57eb /fs/ubifs
parent8d7819b4af697eec45339cc24db7c3fe45fea0e7 (diff)
UBIFS: switch self-check knobs to debugfs
UBIFS has many built-in self-check functions which can be enabled using the debug_chks module parameter or the corresponding sysfs file (/sys/module/ubifs/parameters/debug_chks). However, this is not flexible enough because it is not per-filesystem. This patch moves this to debugfs interfaces. We already have debugfs support, so this patch just adds more debugfs files. While looking at debugfs support I've noticed that it is racy WRT file-system unmount, and added a TODO entry for that. This problem has been there for long time and it is quite standard debugfs PITA. The plan is to fix this later. This patch is simple, but it is large because it changes many places where we check if a particular type of checks is enabled or disabled. Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Diffstat (limited to 'fs/ubifs')
-rw-r--r--fs/ubifs/debug.c140
-rw-r--r--fs/ubifs/debug.h72
2 files changed, 159 insertions, 53 deletions
diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c
index a967d6800ead..fdfa5dea5b95 100644
--- a/fs/ubifs/debug.c
+++ b/fs/ubifs/debug.c
@@ -31,9 +31,9 @@
31 31
32#include "ubifs.h" 32#include "ubifs.h"
33#include <linux/module.h> 33#include <linux/module.h>
34#include <linux/moduleparam.h>
35#include <linux/debugfs.h> 34#include <linux/debugfs.h>
36#include <linux/math64.h> 35#include <linux/math64.h>
36#include <linux/uaccess.h>
37 37
38#ifdef CONFIG_UBIFS_FS_DEBUG 38#ifdef CONFIG_UBIFS_FS_DEBUG
39 39
@@ -42,15 +42,6 @@ DEFINE_SPINLOCK(dbg_lock);
42static char dbg_key_buf0[128]; 42static char dbg_key_buf0[128];
43static char dbg_key_buf1[128]; 43static char dbg_key_buf1[128];
44 44
45unsigned int ubifs_chk_flags;
46unsigned int ubifs_tst_flags;
47
48module_param_named(debug_chks, ubifs_chk_flags, uint, S_IRUGO | S_IWUSR);
49module_param_named(debug_tsts, ubifs_tst_flags, uint, S_IRUGO | S_IWUSR);
50
51MODULE_PARM_DESC(debug_chks, "Debug check flags");
52MODULE_PARM_DESC(debug_tsts, "Debug special test flags");
53
54static const char *get_key_fmt(int fmt) 45static const char *get_key_fmt(int fmt)
55{ 46{
56 switch (fmt) { 47 switch (fmt) {
@@ -2886,21 +2877,93 @@ static int open_debugfs_file(struct inode *inode, struct file *file)
2886 return nonseekable_open(inode, file); 2877 return nonseekable_open(inode, file);
2887} 2878}
2888 2879
2889static ssize_t write_debugfs_file(struct file *file, const char __user *buf, 2880static ssize_t dfs_file_read(struct file *file, char __user *u, size_t count,
2890 size_t count, loff_t *ppos) 2881 loff_t *ppos)
2882{
2883 struct dentry *dent = file->f_path.dentry;
2884 struct ubifs_info *c = file->private_data;
2885 struct ubifs_debug_info *d = c->dbg;
2886 char buf[3];
2887 int val;
2888
2889 if (dent == d->dfs_chk_gen)
2890 val = d->chk_gen;
2891 else if (dent == d->dfs_chk_index)
2892 val = d->chk_index;
2893 else if (dent == d->dfs_chk_orph)
2894 val = d->chk_orph;
2895 else if (dent == d->dfs_chk_lprops)
2896 val = d->chk_lprops;
2897 else if (dent == d->dfs_chk_fs)
2898 val = d->chk_fs;
2899 else if (dent == d->dfs_tst_rcvry)
2900 val = d->tst_rcvry;
2901 else
2902 return -EINVAL;
2903
2904 if (val)
2905 buf[0] = '1';
2906 else
2907 buf[0] = '0';
2908 buf[1] = '\n';
2909 buf[2] = 0x00;
2910
2911 return simple_read_from_buffer(u, count, ppos, buf, 2);
2912}
2913
2914static ssize_t dfs_file_write(struct file *file, const char __user *u,
2915 size_t count, loff_t *ppos)
2891{ 2916{
2892 struct ubifs_info *c = file->private_data; 2917 struct ubifs_info *c = file->private_data;
2893 struct ubifs_debug_info *d = c->dbg; 2918 struct ubifs_debug_info *d = c->dbg;
2919 struct dentry *dent = file->f_path.dentry;
2920 size_t buf_size;
2921 char buf[8];
2922 int val;
2894 2923
2895 if (file->f_path.dentry == d->dfs_dump_lprops) 2924 /*
2925 * FIXME: this is racy - the file-system might have already been
2926 * unmounted and we'd oops in this case.
2927 */
2928 if (file->f_path.dentry == d->dfs_dump_lprops) {
2896 dbg_dump_lprops(c); 2929 dbg_dump_lprops(c);
2897 else if (file->f_path.dentry == d->dfs_dump_budg) 2930 return count;
2931 }
2932 if (file->f_path.dentry == d->dfs_dump_budg) {
2898 dbg_dump_budg(c, &c->bi); 2933 dbg_dump_budg(c, &c->bi);
2899 else if (file->f_path.dentry == d->dfs_dump_tnc) { 2934 return count;
2935 }
2936 if (file->f_path.dentry == d->dfs_dump_tnc) {
2900 mutex_lock(&c->tnc_mutex); 2937 mutex_lock(&c->tnc_mutex);
2901 dbg_dump_tnc(c); 2938 dbg_dump_tnc(c);
2902 mutex_unlock(&c->tnc_mutex); 2939 mutex_unlock(&c->tnc_mutex);
2903 } else 2940 return count;
2941 }
2942
2943 buf_size = min_t(size_t, count, (sizeof(buf) - 1));
2944 if (copy_from_user(buf, u, buf_size))
2945 return -EFAULT;
2946
2947 if (buf[0] == '1')
2948 val = 1;
2949 else if (buf[0] == '0')
2950 val = 0;
2951 else
2952 return -EINVAL;
2953
2954 if (dent == d->dfs_chk_gen)
2955 d->chk_gen = val;
2956 else if (dent == d->dfs_chk_index)
2957 d->chk_index = val;
2958 else if (dent == d->dfs_chk_orph)
2959 d->chk_orph = val;
2960 else if (dent == d->dfs_chk_lprops)
2961 d->chk_lprops = val;
2962 else if (dent == d->dfs_chk_fs)
2963 d->chk_fs = val;
2964 else if (dent == d->dfs_tst_rcvry)
2965 d->tst_rcvry = val;
2966 else
2904 return -EINVAL; 2967 return -EINVAL;
2905 2968
2906 return count; 2969 return count;
@@ -2908,7 +2971,8 @@ static ssize_t write_debugfs_file(struct file *file, const char __user *buf,
2908 2971
2909static const struct file_operations dfs_fops = { 2972static const struct file_operations dfs_fops = {
2910 .open = open_debugfs_file, 2973 .open = open_debugfs_file,
2911 .write = write_debugfs_file, 2974 .read = dfs_file_read,
2975 .write = dfs_file_write,
2912 .owner = THIS_MODULE, 2976 .owner = THIS_MODULE,
2913 .llseek = no_llseek, 2977 .llseek = no_llseek,
2914}; 2978};
@@ -2965,6 +3029,48 @@ int dbg_debugfs_init_fs(struct ubifs_info *c)
2965 goto out_remove; 3029 goto out_remove;
2966 d->dfs_dump_tnc = dent; 3030 d->dfs_dump_tnc = dent;
2967 3031
3032 fname = "chk_general";
3033 dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, d->dfs_dir, c,
3034 &dfs_fops);
3035 if (IS_ERR_OR_NULL(dent))
3036 goto out_remove;
3037 d->dfs_chk_gen = dent;
3038
3039 fname = "chk_index";
3040 dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, d->dfs_dir, c,
3041 &dfs_fops);
3042 if (IS_ERR_OR_NULL(dent))
3043 goto out_remove;
3044 d->dfs_chk_index = dent;
3045
3046 fname = "chk_orphans";
3047 dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, d->dfs_dir, c,
3048 &dfs_fops);
3049 if (IS_ERR_OR_NULL(dent))
3050 goto out_remove;
3051 d->dfs_chk_orph = dent;
3052
3053 fname = "chk_lprops";
3054 dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, d->dfs_dir, c,
3055 &dfs_fops);
3056 if (IS_ERR_OR_NULL(dent))
3057 goto out_remove;
3058 d->dfs_chk_lprops = dent;
3059
3060 fname = "chk_fs";
3061 dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, d->dfs_dir, c,
3062 &dfs_fops);
3063 if (IS_ERR_OR_NULL(dent))
3064 goto out_remove;
3065 d->dfs_chk_fs = dent;
3066
3067 fname = "tst_recovery";
3068 dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, d->dfs_dir, c,
3069 &dfs_fops);
3070 if (IS_ERR_OR_NULL(dent))
3071 goto out_remove;
3072 d->dfs_tst_rcvry = dent;
3073
2968 return 0; 3074 return 0;
2969 3075
2970out_remove: 3076out_remove:
diff --git a/fs/ubifs/debug.h b/fs/ubifs/debug.h
index 44265a3a08ce..8c3bdd378037 100644
--- a/fs/ubifs/debug.h
+++ b/fs/ubifs/debug.h
@@ -43,11 +43,13 @@ typedef int (*dbg_znode_callback)(struct ubifs_info *c,
43 * @old_zroot: old index root - used by 'dbg_check_old_index()' 43 * @old_zroot: old index root - used by 'dbg_check_old_index()'
44 * @old_zroot_level: old index root level - used by 'dbg_check_old_index()' 44 * @old_zroot_level: old index root level - used by 'dbg_check_old_index()'
45 * @old_zroot_sqnum: old index root sqnum - used by 'dbg_check_old_index()' 45 * @old_zroot_sqnum: old index root sqnum - used by 'dbg_check_old_index()'
46 *
46 * @failure_mode: failure mode for recovery testing 47 * @failure_mode: failure mode for recovery testing
47 * @fail_delay: 0=>don't delay, 1=>delay a time, 2=>delay a number of calls 48 * @fail_delay: 0=>don't delay, 1=>delay a time, 2=>delay a number of calls
48 * @fail_timeout: time in jiffies when delay of failure mode expires 49 * @fail_timeout: time in jiffies when delay of failure mode expires
49 * @fail_cnt: current number of calls to failure mode I/O functions 50 * @fail_cnt: current number of calls to failure mode I/O functions
50 * @fail_cnt_max: number of calls by which to delay failure mode 51 * @fail_cnt_max: number of calls by which to delay failure mode
52 *
51 * @chk_lpt_sz: used by LPT tree size checker 53 * @chk_lpt_sz: used by LPT tree size checker
52 * @chk_lpt_sz2: used by LPT tree size checker 54 * @chk_lpt_sz2: used by LPT tree size checker
53 * @chk_lpt_wastage: used by LPT tree size checker 55 * @chk_lpt_wastage: used by LPT tree size checker
@@ -61,21 +63,36 @@ typedef int (*dbg_znode_callback)(struct ubifs_info *c,
61 * @saved_free: saved amount of free space 63 * @saved_free: saved amount of free space
62 * @saved_idx_gc_cnt: saved value of @c->idx_gc_cnt 64 * @saved_idx_gc_cnt: saved value of @c->idx_gc_cnt
63 * 65 *
66 * @chk_gen: if general extra checks are enabled
67 * @chk_index: if index xtra checks are enabled
68 * @chk_orph: if orphans extra checks are enabled
69 * @chk_lprops: if lprops extra checks are enabled
70 * @chk_fs: if UBIFS contents extra checks are enabled
71 * @tst_rcvry: if UBIFS recovery testing mode enabled
72 *
64 * @dfs_dir_name: name of debugfs directory containing this file-system's files 73 * @dfs_dir_name: name of debugfs directory containing this file-system's files
65 * @dfs_dir: direntry object of the file-system debugfs directory 74 * @dfs_dir: direntry object of the file-system debugfs directory
66 * @dfs_dump_lprops: "dump lprops" debugfs knob 75 * @dfs_dump_lprops: "dump lprops" debugfs knob
67 * @dfs_dump_budg: "dump budgeting information" debugfs knob 76 * @dfs_dump_budg: "dump budgeting information" debugfs knob
68 * @dfs_dump_tnc: "dump TNC" debugfs knob 77 * @dfs_dump_tnc: "dump TNC" debugfs knob
78 * @dfs_chk_gen: debugfs knob to enable UBIFS general extra checks
79 * @dfs_chk_index: debugfs knob to enable UBIFS index extra checks
80 * @dfs_chk_orph: debugfs knob to enable UBIFS orphans extra checks
81 * @dfs_chk_lprops: debugfs knob to enable UBIFS LEP properties extra checks
82 * @dfs_chk_fs: debugfs knob to enable UBIFS contents extra checks
83 * @dfs_tst_rcvry: debugfs knob to enable UBIFS recovery testing
69 */ 84 */
70struct ubifs_debug_info { 85struct ubifs_debug_info {
71 struct ubifs_zbranch old_zroot; 86 struct ubifs_zbranch old_zroot;
72 int old_zroot_level; 87 int old_zroot_level;
73 unsigned long long old_zroot_sqnum; 88 unsigned long long old_zroot_sqnum;
89
74 int failure_mode; 90 int failure_mode;
75 int fail_delay; 91 int fail_delay;
76 unsigned long fail_timeout; 92 unsigned long fail_timeout;
77 unsigned int fail_cnt; 93 unsigned int fail_cnt;
78 unsigned int fail_cnt_max; 94 unsigned int fail_cnt_max;
95
79 long long chk_lpt_sz; 96 long long chk_lpt_sz;
80 long long chk_lpt_sz2; 97 long long chk_lpt_sz2;
81 long long chk_lpt_wastage; 98 long long chk_lpt_wastage;
@@ -89,11 +106,24 @@ struct ubifs_debug_info {
89 long long saved_free; 106 long long saved_free;
90 int saved_idx_gc_cnt; 107 int saved_idx_gc_cnt;
91 108
109 unsigned int chk_gen:1;
110 unsigned int chk_index:1;
111 unsigned int chk_orph:1;
112 unsigned int chk_lprops:1;
113 unsigned int chk_fs:1;
114 unsigned int tst_rcvry:1;
115
92 char dfs_dir_name[UBIFS_DFS_DIR_LEN + 1]; 116 char dfs_dir_name[UBIFS_DFS_DIR_LEN + 1];
93 struct dentry *dfs_dir; 117 struct dentry *dfs_dir;
94 struct dentry *dfs_dump_lprops; 118 struct dentry *dfs_dump_lprops;
95 struct dentry *dfs_dump_budg; 119 struct dentry *dfs_dump_budg;
96 struct dentry *dfs_dump_tnc; 120 struct dentry *dfs_dump_tnc;
121 struct dentry *dfs_chk_gen;
122 struct dentry *dfs_chk_index;
123 struct dentry *dfs_chk_orph;
124 struct dentry *dfs_chk_lprops;
125 struct dentry *dfs_chk_fs;
126 struct dentry *dfs_tst_rcvry;
97}; 127};
98 128
99#define ubifs_assert(expr) do { \ 129#define ubifs_assert(expr) do { \
@@ -169,59 +199,29 @@ const char *dbg_key_str1(const struct ubifs_info *c,
169 199
170extern spinlock_t dbg_lock; 200extern spinlock_t dbg_lock;
171 201
172/*
173 * Debugging check flags.
174 *
175 * UBIFS_CHK_GEN: general checks
176 * UBIFS_CHK_INDEX: check the index
177 * UBIFS_CHK_ORPH: check orphans
178 * UBIFS_CHK_LPROPS: check lprops
179 * UBIFS_CHK_FS: check the file-system
180 */
181enum {
182 UBIFS_CHK_GEN = 0x1,
183 UBIFS_CHK_INDEX = 0x2,
184 UBIFS_CHK_ORPH = 0x8,
185 UBIFS_CHK_LPROPS = 0x20,
186 UBIFS_CHK_FS = 0x40,
187};
188
189/*
190 * Special testing flags.
191 *
192 * UBIFS_TST_RCVRY: failure mode for recovery testing
193 */
194enum {
195 UBIFS_TST_RCVRY = 0x4,
196};
197
198extern unsigned int ubifs_msg_flags;
199extern unsigned int ubifs_chk_flags;
200extern unsigned int ubifs_tst_flags;
201
202static inline int dbg_is_chk_gen(const struct ubifs_info *c) 202static inline int dbg_is_chk_gen(const struct ubifs_info *c)
203{ 203{
204 return !!(ubifs_chk_flags & UBIFS_CHK_GEN); 204 return c->dbg->chk_gen;
205} 205}
206static inline int dbg_is_chk_index(const struct ubifs_info *c) 206static inline int dbg_is_chk_index(const struct ubifs_info *c)
207{ 207{
208 return !!(ubifs_chk_flags & UBIFS_CHK_INDEX); 208 return c->dbg->chk_index;
209} 209}
210static inline int dbg_is_chk_orph(const struct ubifs_info *c) 210static inline int dbg_is_chk_orph(const struct ubifs_info *c)
211{ 211{
212 return !!(ubifs_chk_flags & UBIFS_CHK_ORPH); 212 return c->dbg->chk_orph;
213} 213}
214static inline int dbg_is_chk_lprops(const struct ubifs_info *c) 214static inline int dbg_is_chk_lprops(const struct ubifs_info *c)
215{ 215{
216 return !!(ubifs_chk_flags & UBIFS_CHK_LPROPS); 216 return c->dbg->chk_lprops;
217} 217}
218static inline int dbg_is_chk_fs(const struct ubifs_info *c) 218static inline int dbg_is_chk_fs(const struct ubifs_info *c)
219{ 219{
220 return !!(ubifs_chk_flags & UBIFS_CHK_FS); 220 return c->dbg->chk_fs;
221} 221}
222static inline int dbg_is_tst_rcvry(const struct ubifs_info *c) 222static inline int dbg_is_tst_rcvry(const struct ubifs_info *c)
223{ 223{
224 return !!(ubifs_tst_flags & UBIFS_TST_RCVRY); 224 return c->dbg->tst_rcvry;
225} 225}
226 226
227int ubifs_debugging_init(struct ubifs_info *c); 227int ubifs_debugging_init(struct ubifs_info *c);