diff options
author | Artem Bityutskiy <Artem.Bityutskiy@nokia.com> | 2008-10-23 04:49:28 -0400 |
---|---|---|
committer | Artem Bityutskiy <Artem.Bityutskiy@nokia.com> | 2008-12-03 06:14:33 -0500 |
commit | 552ff3179d1e93a3e982357544c059f3e9a5516e (patch) | |
tree | fb53c9ab1b19e1c98fc0a316859413723e34d186 /fs/ubifs/debug.c | |
parent | 17c2f9f85c896b48a5d74a9155d99ec5b241a0e6 (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/ubifs/debug.c')
-rw-r--r-- | fs/ubifs/debug.c | 173 |
1 files changed, 156 insertions, 17 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 | ||
1028 | out_free: | 1027 | out_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 | */ | ||
2389 | static 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 | */ | ||
2399 | int 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 | */ | ||
2415 | void dbg_debugfs_exit(void) | ||
2416 | { | ||
2417 | debugfs_remove(debugfs_rootdir); | ||
2418 | } | ||
2419 | |||
2420 | static int open_debugfs_file(struct inode *inode, struct file *file) | ||
2421 | { | ||
2422 | file->private_data = inode->i_private; | ||
2423 | return 0; | ||
2424 | } | ||
2425 | |||
2426 | static 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 | |||
2449 | static 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 | */ | ||
2467 | int 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 | |||
2507 | out_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); | ||
2512 | out: | ||
2513 | return err; | ||
2514 | } | ||
2515 | |||
2516 | /** | ||
2517 | * dbg_debugfs_exit_fs - remove all debugfs files. | ||
2518 | * @c: UBIFS file-system description object | ||
2519 | */ | ||
2520 | void 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 */ |