aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2008-10-23 04:49:28 -0400
committerArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2008-12-03 06:14:33 -0500
commit552ff3179d1e93a3e982357544c059f3e9a5516e (patch)
treefb53c9ab1b19e1c98fc0a316859413723e34d186 /fs
parent17c2f9f85c896b48a5d74a9155d99ec5b241a0e6 (diff)
UBIFS: add debugfs support
We need to have a possibility to see various UBIFS variables and ask UBIFS to dump various information. Debugfs is what we need. Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/ubifs/debug.c173
-rw-r--r--fs/ubifs/debug.h27
-rw-r--r--fs/ubifs/super.c12
-rw-r--r--fs/ubifs/ubifs.h1
4 files changed, 193 insertions, 20 deletions
diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c
index 0332a856a082..56842772c804 100644
--- a/fs/ubifs/debug.c
+++ b/fs/ubifs/debug.c
@@ -32,6 +32,7 @@
32#include "ubifs.h" 32#include "ubifs.h"
33#include <linux/module.h> 33#include <linux/module.h>
34#include <linux/moduleparam.h> 34#include <linux/moduleparam.h>
35#include <linux/debugfs.h>
35 36
36#ifdef CONFIG_UBIFS_FS_DEBUG 37#ifdef CONFIG_UBIFS_FS_DEBUG
37 38
@@ -988,22 +989,20 @@ static int dbg_check_key_order(struct ubifs_info *c, struct ubifs_zbranch *zbr1,
988 err = 1; 989 err = 1;
989 key_read(c, &dent1->key, &key); 990 key_read(c, &dent1->key, &key);
990 if (keys_cmp(c, &zbr1->key, &key)) { 991 if (keys_cmp(c, &zbr1->key, &key)) {
991 dbg_err("1st entry at %d:%d has key %s", zbr1->lnum, 992 ubifs_err("1st entry at %d:%d has key %s", zbr1->lnum,
992 zbr1->offs, DBGKEY(&key)); 993 zbr1->offs, DBGKEY(&key));
993 dbg_err("but it should have key %s according to tnc", 994 ubifs_err("but it should have key %s according to tnc",
994 DBGKEY(&zbr1->key)); 995 DBGKEY(&zbr1->key)); dbg_dump_node(c, dent1);
995 dbg_dump_node(c, dent1); 996 goto out_free;
996 goto out_free;
997 } 997 }
998 998
999 key_read(c, &dent2->key, &key); 999 key_read(c, &dent2->key, &key);
1000 if (keys_cmp(c, &zbr2->key, &key)) { 1000 if (keys_cmp(c, &zbr2->key, &key)) {
1001 dbg_err("2nd entry at %d:%d has key %s", zbr1->lnum, 1001 ubifs_err("2nd entry at %d:%d has key %s", zbr1->lnum,
1002 zbr1->offs, DBGKEY(&key)); 1002 zbr1->offs, DBGKEY(&key));
1003 dbg_err("but it should have key %s according to tnc", 1003 ubifs_err("but it should have key %s according to tnc",
1004 DBGKEY(&zbr2->key)); 1004 DBGKEY(&zbr2->key)); dbg_dump_node(c, dent2);
1005 dbg_dump_node(c, dent2); 1005 goto out_free;
1006 goto out_free;
1007 } 1006 }
1008 1007
1009 nlen1 = le16_to_cpu(dent1->nlen); 1008 nlen1 = le16_to_cpu(dent1->nlen);
@@ -1015,14 +1014,14 @@ static int dbg_check_key_order(struct ubifs_info *c, struct ubifs_zbranch *zbr1,
1015 goto out_free; 1014 goto out_free;
1016 } 1015 }
1017 if (cmp == 0 && nlen1 == nlen2) 1016 if (cmp == 0 && nlen1 == nlen2)
1018 dbg_err("2 xent/dent nodes with the same name"); 1017 ubifs_err("2 xent/dent nodes with the same name");
1019 else 1018 else
1020 dbg_err("bad order of colliding key %s", 1019 ubifs_err("bad order of colliding key %s",
1021 DBGKEY(&key)); 1020 DBGKEY(&key));
1022 1021
1023 dbg_msg("first node at %d:%d\n", zbr1->lnum, zbr1->offs); 1022 ubifs_msg("first node at %d:%d\n", zbr1->lnum, zbr1->offs);
1024 dbg_dump_node(c, dent1); 1023 dbg_dump_node(c, dent1);
1025 dbg_msg("second node at %d:%d\n", zbr2->lnum, zbr2->offs); 1024 ubifs_msg("second node at %d:%d\n", zbr2->lnum, zbr2->offs);
1026 dbg_dump_node(c, dent2); 1025 dbg_dump_node(c, dent2);
1027 1026
1028out_free: 1027out_free:
@@ -2103,7 +2102,7 @@ static void failure_mode_init(struct ubifs_info *c)
2103 2102
2104 fmi = kmalloc(sizeof(struct failure_mode_info), GFP_NOFS); 2103 fmi = kmalloc(sizeof(struct failure_mode_info), GFP_NOFS);
2105 if (!fmi) { 2104 if (!fmi) {
2106 dbg_err("Failed to register failure mode - no memory"); 2105 ubifs_err("Failed to register failure mode - no memory");
2107 return; 2106 return;
2108 } 2107 }
2109 fmi->c = c; 2108 fmi->c = c;
@@ -2383,4 +2382,144 @@ void ubifs_debugging_exit(struct ubifs_info *c)
2383 kfree(c->dbg); 2382 kfree(c->dbg);
2384} 2383}
2385 2384
2385/*
2386 * Root directory for UBIFS stuff in debugfs. Contains sub-directories which
2387 * contain the stuff specific to particular file-system mounts.
2388 */
2389static struct dentry *debugfs_rootdir;
2390
2391/**
2392 * dbg_debugfs_init - initialize debugfs file-system.
2393 *
2394 * UBIFS uses debugfs file-system to expose various debugging knobs to
2395 * user-space. This function creates "ubifs" directory in the debugfs
2396 * file-system. Returns zero in case of success and a negative error code in
2397 * case of failure.
2398 */
2399int dbg_debugfs_init(void)
2400{
2401 debugfs_rootdir = debugfs_create_dir("ubifs", NULL);
2402 if (IS_ERR(debugfs_rootdir)) {
2403 int err = PTR_ERR(debugfs_rootdir);
2404 ubifs_err("cannot create \"ubifs\" debugfs directory, "
2405 "error %d\n", err);
2406 return err;
2407 }
2408
2409 return 0;
2410}
2411
2412/**
2413 * dbg_debugfs_exit - remove the "ubifs" directory from debugfs file-system.
2414 */
2415void dbg_debugfs_exit(void)
2416{
2417 debugfs_remove(debugfs_rootdir);
2418}
2419
2420static int open_debugfs_file(struct inode *inode, struct file *file)
2421{
2422 file->private_data = inode->i_private;
2423 return 0;
2424}
2425
2426static ssize_t write_debugfs_file(struct file *file, const char __user *buf,
2427 size_t count, loff_t *ppos)
2428{
2429 struct ubifs_info *c = file->private_data;
2430 struct ubifs_debug_info *d = c->dbg;
2431
2432 if (file->f_path.dentry == d->dump_lprops)
2433 dbg_dump_lprops(c);
2434 else if (file->f_path.dentry == d->dump_budg) {
2435 spin_lock(&c->space_lock);
2436 dbg_dump_budg(c);
2437 spin_unlock(&c->space_lock);
2438 } else if (file->f_path.dentry == d->dump_budg) {
2439 mutex_lock(&c->tnc_mutex);
2440 dbg_dump_tnc(c);
2441 mutex_unlock(&c->tnc_mutex);
2442 } else
2443 return -EINVAL;
2444
2445 *ppos += count;
2446 return count;
2447}
2448
2449static const struct file_operations debugfs_fops = {
2450 .open = open_debugfs_file,
2451 .write = write_debugfs_file,
2452 .owner = THIS_MODULE,
2453};
2454
2455/**
2456 * dbg_debugfs_init_fs - initialize debugfs for UBIFS instance.
2457 * @c: UBIFS file-system description object
2458 *
2459 * This function creates all debugfs files for this instance of UBIFS. Returns
2460 * zero in case of success and a negative error code in case of failure.
2461 *
2462 * Note, the only reason we have not merged this function with the
2463 * 'ubifs_debugging_init()' function is because it is better to initialize
2464 * debugfs interfaces at the very end of the mount process, and remove them at
2465 * the very beginning of the mount process.
2466 */
2467int dbg_debugfs_init_fs(struct ubifs_info *c)
2468{
2469 int err;
2470 const char *fname;
2471 struct dentry *dent;
2472 struct ubifs_debug_info *d = c->dbg;
2473
2474 sprintf(d->debugfs_dir_name, "ubi%d_%d", c->vi.ubi_num, c->vi.vol_id);
2475 d->debugfs_dir = debugfs_create_dir(d->debugfs_dir_name,
2476 debugfs_rootdir);
2477 if (IS_ERR(d->debugfs_dir)) {
2478 err = PTR_ERR(d->debugfs_dir);
2479 ubifs_err("cannot create \"%s\" debugfs directory, error %d\n",
2480 d->debugfs_dir_name, err);
2481 goto out;
2482 }
2483
2484 fname = "dump_lprops";
2485 dent = debugfs_create_file(fname, S_IWUGO, d->debugfs_dir, c,
2486 &debugfs_fops);
2487 if (IS_ERR(dent))
2488 goto out_remove;
2489 d->dump_lprops = dent;
2490
2491 fname = "dump_budg";
2492 dent = debugfs_create_file(fname, S_IWUGO, d->debugfs_dir, c,
2493 &debugfs_fops);
2494 if (IS_ERR(dent))
2495 goto out_remove;
2496 d->dump_budg = dent;
2497
2498 fname = "dump_tnc";
2499 dent = debugfs_create_file(fname, S_IWUGO, d->debugfs_dir, c,
2500 &debugfs_fops);
2501 if (IS_ERR(dent))
2502 goto out_remove;
2503 d->dump_tnc = dent;
2504
2505 return 0;
2506
2507out_remove:
2508 err = PTR_ERR(dent);
2509 ubifs_err("cannot create \"%s\" debugfs directory, error %d\n",
2510 fname, err);
2511 debugfs_remove_recursive(d->debugfs_dir);
2512out:
2513 return err;
2514}
2515
2516/**
2517 * dbg_debugfs_exit_fs - remove all debugfs files.
2518 * @c: UBIFS file-system description object
2519 */
2520void dbg_debugfs_exit_fs(struct ubifs_info *c)
2521{
2522 debugfs_remove_recursive(c->dbg->debugfs_dir);
2523}
2524
2386#endif /* CONFIG_UBIFS_FS_DEBUG */ 2525#endif /* CONFIG_UBIFS_FS_DEBUG */
diff --git a/fs/ubifs/debug.h b/fs/ubifs/debug.h
index d6ea1362d56a..a6b70f8aac9c 100644
--- a/fs/ubifs/debug.h
+++ b/fs/ubifs/debug.h
@@ -43,6 +43,13 @@
43 * @new_nhead_offs: used by LPT tree size checker 43 * @new_nhead_offs: used by LPT tree size checker
44 * @new_ihead_lnum: used by debugging to check ihead_lnum 44 * @new_ihead_lnum: used by debugging to check ihead_lnum
45 * @new_ihead_offs: used by debugging to check ihead_offs 45 * @new_ihead_offs: used by debugging to check ihead_offs
46 *
47 * debugfs_dir_name: name of debugfs directory containing this file-system's
48 * files
49 * debugfs_dir: direntry object of the file-system debugfs directory
50 * dump_lprops: "dump lprops" debugfs knob
51 * dump_budg: "dump budgeting information" debugfs knob
52 * dump_tnc: "dump TNC" debugfs knob
46 */ 53 */
47struct ubifs_debug_info { 54struct ubifs_debug_info {
48 void *buf; 55 void *buf;
@@ -61,6 +68,12 @@ struct ubifs_debug_info {
61 int new_nhead_offs; 68 int new_nhead_offs;
62 int new_ihead_lnum; 69 int new_ihead_lnum;
63 int new_ihead_offs; 70 int new_ihead_offs;
71
72 char debugfs_dir_name[100];
73 struct dentry *debugfs_dir;
74 struct dentry *dump_lprops;
75 struct dentry *dump_budg;
76 struct dentry *dump_tnc;
64}; 77};
65 78
66#define ubifs_assert(expr) do { \ 79#define ubifs_assert(expr) do { \
@@ -251,7 +264,6 @@ int ubifs_debugging_init(struct ubifs_info *c);
251void ubifs_debugging_exit(struct ubifs_info *c); 264void ubifs_debugging_exit(struct ubifs_info *c);
252 265
253/* Dump functions */ 266/* Dump functions */
254
255const char *dbg_ntype(int type); 267const char *dbg_ntype(int type);
256const char *dbg_cstate(int cmt_state); 268const char *dbg_cstate(int cmt_state);
257const char *dbg_get_key_dump(const struct ubifs_info *c, 269const char *dbg_get_key_dump(const struct ubifs_info *c,
@@ -274,7 +286,6 @@ void dbg_dump_tnc(struct ubifs_info *c);
274void dbg_dump_index(struct ubifs_info *c); 286void dbg_dump_index(struct ubifs_info *c);
275 287
276/* Checking helper functions */ 288/* Checking helper functions */
277
278typedef int (*dbg_leaf_callback)(struct ubifs_info *c, 289typedef int (*dbg_leaf_callback)(struct ubifs_info *c,
279 struct ubifs_zbranch *zbr, void *priv); 290 struct ubifs_zbranch *zbr, void *priv);
280typedef int (*dbg_znode_callback)(struct ubifs_info *c, 291typedef int (*dbg_znode_callback)(struct ubifs_info *c,
@@ -354,6 +365,12 @@ static inline int dbg_change(struct ubi_volume_desc *desc, int lnum,
354 return dbg_leb_change(desc, lnum, buf, len, UBI_UNKNOWN); 365 return dbg_leb_change(desc, lnum, buf, len, UBI_UNKNOWN);
355} 366}
356 367
368/* Debugfs-related stuff */
369int dbg_debugfs_init(void);
370void dbg_debugfs_exit(void);
371int dbg_debugfs_init_fs(struct ubifs_info *c);
372void dbg_debugfs_exit_fs(struct ubifs_info *c);
373
357#else /* !CONFIG_UBIFS_FS_DEBUG */ 374#else /* !CONFIG_UBIFS_FS_DEBUG */
358 375
359/* Use "if (0)" to make compiler check arguments even if debugging is off */ 376/* Use "if (0)" to make compiler check arguments even if debugging is off */
@@ -434,6 +451,10 @@ static inline int dbg_change(struct ubi_volume_desc *desc, int lnum,
434#define dbg_force_in_the_gaps() 0 451#define dbg_force_in_the_gaps() 0
435#define dbg_failure_mode 0 452#define dbg_failure_mode 0
436 453
437#endif /* !CONFIG_UBIFS_FS_DEBUG */ 454#define dbg_debugfs_init() 0
455#define dbg_debugfs_exit()
456#define dbg_debugfs_init_fs(c) 0
457#define dbg_debugfs_exit_fs(c) 0
438 458
459#endif /* !CONFIG_UBIFS_FS_DEBUG */
439#endif /* !__UBIFS_DEBUG_H__ */ 460#endif /* !__UBIFS_DEBUG_H__ */
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index ad44822059c7..2dbaa4fc2cbb 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -1258,6 +1258,10 @@ static int mount_ubifs(struct ubifs_info *c)
1258 } 1258 }
1259 } 1259 }
1260 1260
1261 err = dbg_debugfs_init_fs(c);
1262 if (err)
1263 goto out_infos;
1264
1261 err = dbg_check_filesystem(c); 1265 err = dbg_check_filesystem(c);
1262 if (err) 1266 if (err)
1263 goto out_infos; 1267 goto out_infos;
@@ -1369,6 +1373,7 @@ static void ubifs_umount(struct ubifs_info *c)
1369 dbg_gen("un-mounting UBI device %d, volume %d", c->vi.ubi_num, 1373 dbg_gen("un-mounting UBI device %d, volume %d", c->vi.ubi_num,
1370 c->vi.vol_id); 1374 c->vi.vol_id);
1371 1375
1376 dbg_debugfs_exit_fs(c);
1372 spin_lock(&ubifs_infos_lock); 1377 spin_lock(&ubifs_infos_lock);
1373 list_del(&c->infos_list); 1378 list_del(&c->infos_list);
1374 spin_unlock(&ubifs_infos_lock); 1379 spin_unlock(&ubifs_infos_lock);
@@ -2079,11 +2084,17 @@ static int __init ubifs_init(void)
2079 2084
2080 err = ubifs_compressors_init(); 2085 err = ubifs_compressors_init();
2081 if (err) 2086 if (err)
2087 goto out_shrinker;
2088
2089 err = dbg_debugfs_init();
2090 if (err)
2082 goto out_compr; 2091 goto out_compr;
2083 2092
2084 return 0; 2093 return 0;
2085 2094
2086out_compr: 2095out_compr:
2096 ubifs_compressors_exit();
2097out_shrinker:
2087 unregister_shrinker(&ubifs_shrinker_info); 2098 unregister_shrinker(&ubifs_shrinker_info);
2088 kmem_cache_destroy(ubifs_inode_slab); 2099 kmem_cache_destroy(ubifs_inode_slab);
2089out_reg: 2100out_reg:
@@ -2098,6 +2109,7 @@ static void __exit ubifs_exit(void)
2098 ubifs_assert(list_empty(&ubifs_infos)); 2109 ubifs_assert(list_empty(&ubifs_infos));
2099 ubifs_assert(atomic_long_read(&ubifs_clean_zn_cnt) == 0); 2110 ubifs_assert(atomic_long_read(&ubifs_clean_zn_cnt) == 0);
2100 2111
2112 dbg_debugfs_exit();
2101 ubifs_compressors_exit(); 2113 ubifs_compressors_exit();
2102 unregister_shrinker(&ubifs_shrinker_info); 2114 unregister_shrinker(&ubifs_shrinker_info);
2103 kmem_cache_destroy(ubifs_inode_slab); 2115 kmem_cache_destroy(ubifs_inode_slab);
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
index 7e090a5e2bf6..4cf28e85de78 100644
--- a/fs/ubifs/ubifs.h
+++ b/fs/ubifs/ubifs.h
@@ -1158,6 +1158,7 @@ struct ubifs_debug_info;
1158 * @mount_opts: UBIFS-specific mount options 1158 * @mount_opts: UBIFS-specific mount options
1159 * 1159 *
1160 * @dbg: debugging-related information 1160 * @dbg: debugging-related information
1161 * @dfs: debugfs support-related information
1161 */ 1162 */
1162struct ubifs_info { 1163struct ubifs_info {
1163 struct super_block *vfs_sb; 1164 struct super_block *vfs_sb;