diff options
author | Artem Bityutskiy <Artem.Bityutskiy@nokia.com> | 2011-06-01 10:43:43 -0400 |
---|---|---|
committer | Artem Bityutskiy <dedekind1@gmail.com> | 2011-07-04 03:54:32 -0400 |
commit | e7717060ddd509e6c305ad7bf5a090a95e91c8cf (patch) | |
tree | 03869be56858dfc5226a94129d528714838e4dc0 /fs/ubifs | |
parent | 28488fc28aa39815b78c2cbeaaf25f33fef92ce8 (diff) |
UBIFS: add global debugfs knobs
Now we have per-FS (superblock) debugfs knobs, but they have one drawback - you
have to first mount the FS and only after this you can switch self-checks
on/off. But often we want to have the checks enabled during the mount.
Introduce global debugging knobs for this purpose.
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Diffstat (limited to 'fs/ubifs')
-rw-r--r-- | fs/ubifs/debug.c | 138 | ||||
-rw-r--r-- | fs/ubifs/debug.h | 35 |
2 files changed, 157 insertions, 16 deletions
diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c index b98638eb0fcb..15bec635bf3e 100644 --- a/fs/ubifs/debug.c +++ b/fs/ubifs/debug.c | |||
@@ -3064,7 +3064,7 @@ out_remove: | |||
3064 | debugfs_remove_recursive(d->dfs_dir); | 3064 | debugfs_remove_recursive(d->dfs_dir); |
3065 | out: | 3065 | out: |
3066 | err = dent ? PTR_ERR(dent) : -ENODEV; | 3066 | err = dent ? PTR_ERR(dent) : -ENODEV; |
3067 | ubifs_err("cannot create \"%s\" debugfs filr or directory, error %d\n", | 3067 | ubifs_err("cannot create \"%s\" debugfs file or directory, error %d\n", |
3068 | fname, err); | 3068 | fname, err); |
3069 | return err; | 3069 | return err; |
3070 | } | 3070 | } |
@@ -3078,6 +3078,74 @@ void dbg_debugfs_exit_fs(struct ubifs_info *c) | |||
3078 | debugfs_remove_recursive(c->dbg->dfs_dir); | 3078 | debugfs_remove_recursive(c->dbg->dfs_dir); |
3079 | } | 3079 | } |
3080 | 3080 | ||
3081 | struct ubifs_global_debug_info ubifs_dbg; | ||
3082 | |||
3083 | static struct dentry *dfs_chk_gen; | ||
3084 | static struct dentry *dfs_chk_index; | ||
3085 | static struct dentry *dfs_chk_orph; | ||
3086 | static struct dentry *dfs_chk_lprops; | ||
3087 | static struct dentry *dfs_chk_fs; | ||
3088 | static struct dentry *dfs_tst_rcvry; | ||
3089 | |||
3090 | static ssize_t dfs_global_file_read(struct file *file, char __user *u, | ||
3091 | size_t count, loff_t *ppos) | ||
3092 | { | ||
3093 | struct dentry *dent = file->f_path.dentry; | ||
3094 | int val; | ||
3095 | |||
3096 | if (dent == dfs_chk_gen) | ||
3097 | val = ubifs_dbg.chk_gen; | ||
3098 | else if (dent == dfs_chk_index) | ||
3099 | val = ubifs_dbg.chk_index; | ||
3100 | else if (dent == dfs_chk_orph) | ||
3101 | val = ubifs_dbg.chk_orph; | ||
3102 | else if (dent == dfs_chk_lprops) | ||
3103 | val = ubifs_dbg.chk_lprops; | ||
3104 | else if (dent == dfs_chk_fs) | ||
3105 | val = ubifs_dbg.chk_fs; | ||
3106 | else if (dent == dfs_tst_rcvry) | ||
3107 | val = ubifs_dbg.tst_rcvry; | ||
3108 | else | ||
3109 | return -EINVAL; | ||
3110 | |||
3111 | return provide_user_output(val, u, count, ppos); | ||
3112 | } | ||
3113 | |||
3114 | static ssize_t dfs_global_file_write(struct file *file, const char __user *u, | ||
3115 | size_t count, loff_t *ppos) | ||
3116 | { | ||
3117 | struct dentry *dent = file->f_path.dentry; | ||
3118 | int val; | ||
3119 | |||
3120 | val = interpret_user_input(u, count); | ||
3121 | if (val < 0) | ||
3122 | return val; | ||
3123 | |||
3124 | if (dent == dfs_chk_gen) | ||
3125 | ubifs_dbg.chk_gen = val; | ||
3126 | else if (dent == dfs_chk_index) | ||
3127 | ubifs_dbg.chk_index = val; | ||
3128 | else if (dent == dfs_chk_orph) | ||
3129 | ubifs_dbg.chk_orph = val; | ||
3130 | else if (dent == dfs_chk_lprops) | ||
3131 | ubifs_dbg.chk_lprops = val; | ||
3132 | else if (dent == dfs_chk_fs) | ||
3133 | ubifs_dbg.chk_fs = val; | ||
3134 | else if (dent == dfs_tst_rcvry) | ||
3135 | ubifs_dbg.tst_rcvry = val; | ||
3136 | else | ||
3137 | return -EINVAL; | ||
3138 | |||
3139 | return count; | ||
3140 | } | ||
3141 | |||
3142 | static const struct file_operations dfs_global_fops = { | ||
3143 | .read = dfs_global_file_read, | ||
3144 | .write = dfs_global_file_write, | ||
3145 | .owner = THIS_MODULE, | ||
3146 | .llseek = no_llseek, | ||
3147 | }; | ||
3148 | |||
3081 | /** | 3149 | /** |
3082 | * dbg_debugfs_init - initialize debugfs file-system. | 3150 | * dbg_debugfs_init - initialize debugfs file-system. |
3083 | * | 3151 | * |
@@ -3088,15 +3156,67 @@ void dbg_debugfs_exit_fs(struct ubifs_info *c) | |||
3088 | */ | 3156 | */ |
3089 | int dbg_debugfs_init(void) | 3157 | int dbg_debugfs_init(void) |
3090 | { | 3158 | { |
3091 | dfs_rootdir = debugfs_create_dir("ubifs", NULL); | 3159 | int err; |
3092 | if (IS_ERR_OR_NULL(dfs_rootdir)) { | 3160 | const char *fname; |
3093 | int err = dfs_rootdir ? PTR_ERR(dfs_rootdir) : -ENODEV; | 3161 | struct dentry *dent; |
3094 | ubifs_err("cannot create \"ubifs\" debugfs directory, " | 3162 | |
3095 | "error %d\n", err); | 3163 | fname = "ubifs"; |
3096 | return err; | 3164 | dent = debugfs_create_dir(fname, NULL); |
3097 | } | 3165 | if (IS_ERR_OR_NULL(dent)) |
3166 | goto out; | ||
3167 | dfs_rootdir = dent; | ||
3168 | |||
3169 | fname = "chk_general"; | ||
3170 | dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, dfs_rootdir, NULL, | ||
3171 | &dfs_global_fops); | ||
3172 | if (IS_ERR_OR_NULL(dent)) | ||
3173 | goto out_remove; | ||
3174 | dfs_chk_gen = dent; | ||
3175 | |||
3176 | fname = "chk_index"; | ||
3177 | dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, dfs_rootdir, NULL, | ||
3178 | &dfs_global_fops); | ||
3179 | if (IS_ERR_OR_NULL(dent)) | ||
3180 | goto out_remove; | ||
3181 | dfs_chk_index = dent; | ||
3182 | |||
3183 | fname = "chk_orphans"; | ||
3184 | dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, dfs_rootdir, NULL, | ||
3185 | &dfs_global_fops); | ||
3186 | if (IS_ERR_OR_NULL(dent)) | ||
3187 | goto out_remove; | ||
3188 | dfs_chk_orph = dent; | ||
3189 | |||
3190 | fname = "chk_lprops"; | ||
3191 | dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, dfs_rootdir, NULL, | ||
3192 | &dfs_global_fops); | ||
3193 | if (IS_ERR_OR_NULL(dent)) | ||
3194 | goto out_remove; | ||
3195 | dfs_chk_lprops = dent; | ||
3196 | |||
3197 | fname = "chk_fs"; | ||
3198 | dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, dfs_rootdir, NULL, | ||
3199 | &dfs_global_fops); | ||
3200 | if (IS_ERR_OR_NULL(dent)) | ||
3201 | goto out_remove; | ||
3202 | dfs_chk_fs = dent; | ||
3203 | |||
3204 | fname = "tst_recovery"; | ||
3205 | dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, dfs_rootdir, NULL, | ||
3206 | &dfs_global_fops); | ||
3207 | if (IS_ERR_OR_NULL(dent)) | ||
3208 | goto out_remove; | ||
3209 | dfs_tst_rcvry = dent; | ||
3098 | 3210 | ||
3099 | return 0; | 3211 | return 0; |
3212 | |||
3213 | out_remove: | ||
3214 | debugfs_remove_recursive(dfs_rootdir); | ||
3215 | out: | ||
3216 | err = dent ? PTR_ERR(dent) : -ENODEV; | ||
3217 | ubifs_err("cannot create \"%s\" debugfs file or directory, error %d\n", | ||
3218 | fname, err); | ||
3219 | return err; | ||
3100 | } | 3220 | } |
3101 | 3221 | ||
3102 | /** | 3222 | /** |
@@ -3104,7 +3224,7 @@ int dbg_debugfs_init(void) | |||
3104 | */ | 3224 | */ |
3105 | void dbg_debugfs_exit(void) | 3225 | void dbg_debugfs_exit(void) |
3106 | { | 3226 | { |
3107 | debugfs_remove(dfs_rootdir); | 3227 | debugfs_remove_recursive(dfs_rootdir); |
3108 | } | 3228 | } |
3109 | 3229 | ||
3110 | /** | 3230 | /** |
diff --git a/fs/ubifs/debug.h b/fs/ubifs/debug.h index 8c3bdd378037..43ec5d120d7c 100644 --- a/fs/ubifs/debug.h +++ b/fs/ubifs/debug.h | |||
@@ -126,6 +126,25 @@ struct ubifs_debug_info { | |||
126 | struct dentry *dfs_tst_rcvry; | 126 | struct dentry *dfs_tst_rcvry; |
127 | }; | 127 | }; |
128 | 128 | ||
129 | /** | ||
130 | * ubifs_global_debug_info - global (not per-FS) UBIFS debugging information. | ||
131 | * | ||
132 | * @chk_gen: if general extra checks are enabled | ||
133 | * @chk_index: if index xtra checks are enabled | ||
134 | * @chk_orph: if orphans extra checks are enabled | ||
135 | * @chk_lprops: if lprops extra checks are enabled | ||
136 | * @chk_fs: if UBIFS contents extra checks are enabled | ||
137 | * @tst_rcvry: if UBIFS recovery testing mode enabled | ||
138 | */ | ||
139 | struct ubifs_global_debug_info { | ||
140 | unsigned int chk_gen:1; | ||
141 | unsigned int chk_index:1; | ||
142 | unsigned int chk_orph:1; | ||
143 | unsigned int chk_lprops:1; | ||
144 | unsigned int chk_fs:1; | ||
145 | unsigned int tst_rcvry:1; | ||
146 | }; | ||
147 | |||
129 | #define ubifs_assert(expr) do { \ | 148 | #define ubifs_assert(expr) do { \ |
130 | if (unlikely(!(expr))) { \ | 149 | if (unlikely(!(expr))) { \ |
131 | printk(KERN_CRIT "UBIFS assert failed in %s at %u (pid %d)\n", \ | 150 | printk(KERN_CRIT "UBIFS assert failed in %s at %u (pid %d)\n", \ |
@@ -162,6 +181,8 @@ const char *dbg_key_str1(const struct ubifs_info *c, | |||
162 | #define DBGKEY(key) dbg_key_str0(c, (key)) | 181 | #define DBGKEY(key) dbg_key_str0(c, (key)) |
163 | #define DBGKEY1(key) dbg_key_str1(c, (key)) | 182 | #define DBGKEY1(key) dbg_key_str1(c, (key)) |
164 | 183 | ||
184 | extern spinlock_t dbg_lock; | ||
185 | |||
165 | #define ubifs_dbg_msg(type, fmt, ...) do { \ | 186 | #define ubifs_dbg_msg(type, fmt, ...) do { \ |
166 | spin_lock(&dbg_lock); \ | 187 | spin_lock(&dbg_lock); \ |
167 | pr_debug("UBIFS DBG " type ": " fmt "\n", ##__VA_ARGS__); \ | 188 | pr_debug("UBIFS DBG " type ": " fmt "\n", ##__VA_ARGS__); \ |
@@ -197,31 +218,31 @@ const char *dbg_key_str1(const struct ubifs_info *c, | |||
197 | /* Additional recovery messages */ | 218 | /* Additional recovery messages */ |
198 | #define dbg_rcvry(fmt, ...) ubifs_dbg_msg("rcvry", fmt, ##__VA_ARGS__) | 219 | #define dbg_rcvry(fmt, ...) ubifs_dbg_msg("rcvry", fmt, ##__VA_ARGS__) |
199 | 220 | ||
200 | extern spinlock_t dbg_lock; | 221 | extern struct ubifs_global_debug_info ubifs_dbg; |
201 | 222 | ||
202 | static inline int dbg_is_chk_gen(const struct ubifs_info *c) | 223 | static inline int dbg_is_chk_gen(const struct ubifs_info *c) |
203 | { | 224 | { |
204 | return c->dbg->chk_gen; | 225 | return !!(ubifs_dbg.chk_gen || c->dbg->chk_gen); |
205 | } | 226 | } |
206 | static inline int dbg_is_chk_index(const struct ubifs_info *c) | 227 | static inline int dbg_is_chk_index(const struct ubifs_info *c) |
207 | { | 228 | { |
208 | return c->dbg->chk_index; | 229 | return !!(ubifs_dbg.chk_index || c->dbg->chk_index); |
209 | } | 230 | } |
210 | static inline int dbg_is_chk_orph(const struct ubifs_info *c) | 231 | static inline int dbg_is_chk_orph(const struct ubifs_info *c) |
211 | { | 232 | { |
212 | return c->dbg->chk_orph; | 233 | return !!(ubifs_dbg.chk_orph || c->dbg->chk_orph); |
213 | } | 234 | } |
214 | static inline int dbg_is_chk_lprops(const struct ubifs_info *c) | 235 | static inline int dbg_is_chk_lprops(const struct ubifs_info *c) |
215 | { | 236 | { |
216 | return c->dbg->chk_lprops; | 237 | return !!(ubifs_dbg.chk_lprops || c->dbg->chk_lprops); |
217 | } | 238 | } |
218 | static inline int dbg_is_chk_fs(const struct ubifs_info *c) | 239 | static inline int dbg_is_chk_fs(const struct ubifs_info *c) |
219 | { | 240 | { |
220 | return c->dbg->chk_fs; | 241 | return !!(ubifs_dbg.chk_fs || c->dbg->chk_fs); |
221 | } | 242 | } |
222 | static inline int dbg_is_tst_rcvry(const struct ubifs_info *c) | 243 | static inline int dbg_is_tst_rcvry(const struct ubifs_info *c) |
223 | { | 244 | { |
224 | return c->dbg->tst_rcvry; | 245 | return !!(ubifs_dbg.tst_rcvry || c->dbg->tst_rcvry); |
225 | } | 246 | } |
226 | 247 | ||
227 | int ubifs_debugging_init(struct ubifs_info *c); | 248 | int ubifs_debugging_init(struct ubifs_info *c); |