diff options
author | Theodore Ts'o <tytso@mit.edu> | 2009-09-18 13:38:55 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2009-09-18 13:38:55 -0400 |
commit | 6ba495e9259cd9a0b40ebd6c315143535c92542f (patch) | |
tree | 7d43ea10a8971087e6e8b00c9934b0cf83e53d1e /fs | |
parent | 91cc219ad963731191247c5f2db4118be2bc341a (diff) |
ext4: Add configurable run-time mballoc debugging
Allow mballoc debugging to be enabled at run-time instead of just at
compile time.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ext4/Kconfig | 9 | ||||
-rw-r--r-- | fs/ext4/mballoc.c | 81 | ||||
-rw-r--r-- | fs/ext4/mballoc.h | 16 |
3 files changed, 80 insertions, 26 deletions
diff --git a/fs/ext4/Kconfig b/fs/ext4/Kconfig index 152304624644..d5c0ea2e8f2d 100644 --- a/fs/ext4/Kconfig +++ b/fs/ext4/Kconfig | |||
@@ -77,3 +77,12 @@ config EXT4_FS_SECURITY | |||
77 | 77 | ||
78 | If you are not using a security module that requires using | 78 | If you are not using a security module that requires using |
79 | extended attributes for file security labels, say N. | 79 | extended attributes for file security labels, say N. |
80 | |||
81 | config EXT4_DEBUG | ||
82 | bool "EXT4 debugging support" | ||
83 | depends on EXT4_FS | ||
84 | help | ||
85 | Enables run-time debugging support for the ext4 filesystem. | ||
86 | |||
87 | If you select Y here, then you will be able to turn on debugging | ||
88 | with a command such as "echo 1 > /sys/kernel/debug/ext4/mballoc-debug" | ||
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 68cde598b3bf..d80b300c1779 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c | |||
@@ -22,6 +22,7 @@ | |||
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include "mballoc.h" | 24 | #include "mballoc.h" |
25 | #include <linux/debugfs.h> | ||
25 | #include <trace/events/ext4.h> | 26 | #include <trace/events/ext4.h> |
26 | 27 | ||
27 | /* | 28 | /* |
@@ -743,7 +744,7 @@ static int ext4_mb_init_cache(struct page *page, char *incore) | |||
743 | char *data; | 744 | char *data; |
744 | char *bitmap; | 745 | char *bitmap; |
745 | 746 | ||
746 | mb_debug("init page %lu\n", page->index); | 747 | mb_debug(1, "init page %lu\n", page->index); |
747 | 748 | ||
748 | inode = page->mapping->host; | 749 | inode = page->mapping->host; |
749 | sb = inode->i_sb; | 750 | sb = inode->i_sb; |
@@ -822,7 +823,7 @@ static int ext4_mb_init_cache(struct page *page, char *incore) | |||
822 | set_bitmap_uptodate(bh[i]); | 823 | set_bitmap_uptodate(bh[i]); |
823 | bh[i]->b_end_io = end_buffer_read_sync; | 824 | bh[i]->b_end_io = end_buffer_read_sync; |
824 | submit_bh(READ, bh[i]); | 825 | submit_bh(READ, bh[i]); |
825 | mb_debug("read bitmap for group %u\n", first_group + i); | 826 | mb_debug(1, "read bitmap for group %u\n", first_group + i); |
826 | } | 827 | } |
827 | 828 | ||
828 | /* wait for I/O completion */ | 829 | /* wait for I/O completion */ |
@@ -862,7 +863,7 @@ static int ext4_mb_init_cache(struct page *page, char *incore) | |||
862 | if ((first_block + i) & 1) { | 863 | if ((first_block + i) & 1) { |
863 | /* this is block of buddy */ | 864 | /* this is block of buddy */ |
864 | BUG_ON(incore == NULL); | 865 | BUG_ON(incore == NULL); |
865 | mb_debug("put buddy for group %u in page %lu/%x\n", | 866 | mb_debug(1, "put buddy for group %u in page %lu/%x\n", |
866 | group, page->index, i * blocksize); | 867 | group, page->index, i * blocksize); |
867 | grinfo = ext4_get_group_info(sb, group); | 868 | grinfo = ext4_get_group_info(sb, group); |
868 | grinfo->bb_fragments = 0; | 869 | grinfo->bb_fragments = 0; |
@@ -878,7 +879,7 @@ static int ext4_mb_init_cache(struct page *page, char *incore) | |||
878 | } else { | 879 | } else { |
879 | /* this is block of bitmap */ | 880 | /* this is block of bitmap */ |
880 | BUG_ON(incore != NULL); | 881 | BUG_ON(incore != NULL); |
881 | mb_debug("put bitmap for group %u in page %lu/%x\n", | 882 | mb_debug(1, "put bitmap for group %u in page %lu/%x\n", |
882 | group, page->index, i * blocksize); | 883 | group, page->index, i * blocksize); |
883 | 884 | ||
884 | /* see comments in ext4_mb_put_pa() */ | 885 | /* see comments in ext4_mb_put_pa() */ |
@@ -922,7 +923,7 @@ ext4_mb_load_buddy(struct super_block *sb, ext4_group_t group, | |||
922 | struct ext4_sb_info *sbi = EXT4_SB(sb); | 923 | struct ext4_sb_info *sbi = EXT4_SB(sb); |
923 | struct inode *inode = sbi->s_buddy_cache; | 924 | struct inode *inode = sbi->s_buddy_cache; |
924 | 925 | ||
925 | mb_debug("load group %u\n", group); | 926 | mb_debug(1, "load group %u\n", group); |
926 | 927 | ||
927 | blocks_per_page = PAGE_CACHE_SIZE / sb->s_blocksize; | 928 | blocks_per_page = PAGE_CACHE_SIZE / sb->s_blocksize; |
928 | grp = ext4_get_group_info(sb, group); | 929 | grp = ext4_get_group_info(sb, group); |
@@ -1851,7 +1852,7 @@ int ext4_mb_init_group(struct super_block *sb, ext4_group_t group) | |||
1851 | struct inode *inode = sbi->s_buddy_cache; | 1852 | struct inode *inode = sbi->s_buddy_cache; |
1852 | struct page *page = NULL, *bitmap_page = NULL; | 1853 | struct page *page = NULL, *bitmap_page = NULL; |
1853 | 1854 | ||
1854 | mb_debug("init group %u\n", group); | 1855 | mb_debug(1, "init group %u\n", group); |
1855 | blocks_per_page = PAGE_CACHE_SIZE / sb->s_blocksize; | 1856 | blocks_per_page = PAGE_CACHE_SIZE / sb->s_blocksize; |
1856 | this_grp = ext4_get_group_info(sb, group); | 1857 | this_grp = ext4_get_group_info(sb, group); |
1857 | /* | 1858 | /* |
@@ -2739,7 +2740,7 @@ static void ext4_mb_cleanup_pa(struct ext4_group_info *grp) | |||
2739 | kmem_cache_free(ext4_pspace_cachep, pa); | 2740 | kmem_cache_free(ext4_pspace_cachep, pa); |
2740 | } | 2741 | } |
2741 | if (count) | 2742 | if (count) |
2742 | mb_debug("mballoc: %u PAs left\n", count); | 2743 | mb_debug(1, "mballoc: %u PAs left\n", count); |
2743 | 2744 | ||
2744 | } | 2745 | } |
2745 | 2746 | ||
@@ -2820,7 +2821,7 @@ static void release_blocks_on_commit(journal_t *journal, transaction_t *txn) | |||
2820 | list_for_each_safe(l, ltmp, &txn->t_private_list) { | 2821 | list_for_each_safe(l, ltmp, &txn->t_private_list) { |
2821 | entry = list_entry(l, struct ext4_free_data, list); | 2822 | entry = list_entry(l, struct ext4_free_data, list); |
2822 | 2823 | ||
2823 | mb_debug("gonna free %u blocks in group %u (0x%p):", | 2824 | mb_debug(1, "gonna free %u blocks in group %u (0x%p):", |
2824 | entry->count, entry->group, entry); | 2825 | entry->count, entry->group, entry); |
2825 | 2826 | ||
2826 | err = ext4_mb_load_buddy(sb, entry->group, &e4b); | 2827 | err = ext4_mb_load_buddy(sb, entry->group, &e4b); |
@@ -2855,9 +2856,43 @@ static void release_blocks_on_commit(journal_t *journal, transaction_t *txn) | |||
2855 | ext4_mb_release_desc(&e4b); | 2856 | ext4_mb_release_desc(&e4b); |
2856 | } | 2857 | } |
2857 | 2858 | ||
2858 | mb_debug("freed %u blocks in %u structures\n", count, count2); | 2859 | mb_debug(1, "freed %u blocks in %u structures\n", count, count2); |
2859 | } | 2860 | } |
2860 | 2861 | ||
2862 | #ifdef CONFIG_EXT4_DEBUG | ||
2863 | u8 mb_enable_debug __read_mostly; | ||
2864 | |||
2865 | static struct dentry *debugfs_dir; | ||
2866 | static struct dentry *debugfs_debug; | ||
2867 | |||
2868 | static void __init ext4_create_debugfs_entry(void) | ||
2869 | { | ||
2870 | debugfs_dir = debugfs_create_dir("ext4", NULL); | ||
2871 | if (debugfs_dir) | ||
2872 | debugfs_debug = debugfs_create_u8("mballoc-debug", | ||
2873 | S_IRUGO | S_IWUSR, | ||
2874 | debugfs_dir, | ||
2875 | &mb_enable_debug); | ||
2876 | } | ||
2877 | |||
2878 | static void ext4_remove_debugfs_entry(void) | ||
2879 | { | ||
2880 | debugfs_remove(debugfs_debug); | ||
2881 | debugfs_remove(debugfs_dir); | ||
2882 | } | ||
2883 | |||
2884 | #else | ||
2885 | |||
2886 | static void __init ext4_create_debugfs_entry(void) | ||
2887 | { | ||
2888 | } | ||
2889 | |||
2890 | static void ext4_remove_debugfs_entry(void) | ||
2891 | { | ||
2892 | } | ||
2893 | |||
2894 | #endif | ||
2895 | |||
2861 | int __init init_ext4_mballoc(void) | 2896 | int __init init_ext4_mballoc(void) |
2862 | { | 2897 | { |
2863 | ext4_pspace_cachep = | 2898 | ext4_pspace_cachep = |
@@ -2885,6 +2920,7 @@ int __init init_ext4_mballoc(void) | |||
2885 | kmem_cache_destroy(ext4_ac_cachep); | 2920 | kmem_cache_destroy(ext4_ac_cachep); |
2886 | return -ENOMEM; | 2921 | return -ENOMEM; |
2887 | } | 2922 | } |
2923 | ext4_create_debugfs_entry(); | ||
2888 | return 0; | 2924 | return 0; |
2889 | } | 2925 | } |
2890 | 2926 | ||
@@ -2898,6 +2934,7 @@ void exit_ext4_mballoc(void) | |||
2898 | kmem_cache_destroy(ext4_pspace_cachep); | 2934 | kmem_cache_destroy(ext4_pspace_cachep); |
2899 | kmem_cache_destroy(ext4_ac_cachep); | 2935 | kmem_cache_destroy(ext4_ac_cachep); |
2900 | kmem_cache_destroy(ext4_free_ext_cachep); | 2936 | kmem_cache_destroy(ext4_free_ext_cachep); |
2937 | ext4_remove_debugfs_entry(); | ||
2901 | } | 2938 | } |
2902 | 2939 | ||
2903 | 2940 | ||
@@ -3042,7 +3079,7 @@ static void ext4_mb_normalize_group_request(struct ext4_allocation_context *ac) | |||
3042 | ac->ac_g_ex.fe_len = EXT4_SB(sb)->s_stripe; | 3079 | ac->ac_g_ex.fe_len = EXT4_SB(sb)->s_stripe; |
3043 | else | 3080 | else |
3044 | ac->ac_g_ex.fe_len = EXT4_SB(sb)->s_mb_group_prealloc; | 3081 | ac->ac_g_ex.fe_len = EXT4_SB(sb)->s_mb_group_prealloc; |
3045 | mb_debug("#%u: goal %u blocks for locality group\n", | 3082 | mb_debug(1, "#%u: goal %u blocks for locality group\n", |
3046 | current->pid, ac->ac_g_ex.fe_len); | 3083 | current->pid, ac->ac_g_ex.fe_len); |
3047 | } | 3084 | } |
3048 | 3085 | ||
@@ -3232,7 +3269,7 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac, | |||
3232 | ac->ac_flags |= EXT4_MB_HINT_TRY_GOAL; | 3269 | ac->ac_flags |= EXT4_MB_HINT_TRY_GOAL; |
3233 | } | 3270 | } |
3234 | 3271 | ||
3235 | mb_debug("goal: %u(was %u) blocks at %u\n", (unsigned) size, | 3272 | mb_debug(1, "goal: %u(was %u) blocks at %u\n", (unsigned) size, |
3236 | (unsigned) orig_size, (unsigned) start); | 3273 | (unsigned) orig_size, (unsigned) start); |
3237 | } | 3274 | } |
3238 | 3275 | ||
@@ -3281,7 +3318,7 @@ static void ext4_mb_use_inode_pa(struct ext4_allocation_context *ac, | |||
3281 | BUG_ON(pa->pa_free < len); | 3318 | BUG_ON(pa->pa_free < len); |
3282 | pa->pa_free -= len; | 3319 | pa->pa_free -= len; |
3283 | 3320 | ||
3284 | mb_debug("use %llu/%u from inode pa %p\n", start, len, pa); | 3321 | mb_debug(1, "use %llu/%u from inode pa %p\n", start, len, pa); |
3285 | } | 3322 | } |
3286 | 3323 | ||
3287 | /* | 3324 | /* |
@@ -3305,7 +3342,7 @@ static void ext4_mb_use_group_pa(struct ext4_allocation_context *ac, | |||
3305 | * in on-disk bitmap -- see ext4_mb_release_context() | 3342 | * in on-disk bitmap -- see ext4_mb_release_context() |
3306 | * Other CPUs are prevented from allocating from this pa by lg_mutex | 3343 | * Other CPUs are prevented from allocating from this pa by lg_mutex |
3307 | */ | 3344 | */ |
3308 | mb_debug("use %u/%u from group pa %p\n", pa->pa_lstart-len, len, pa); | 3345 | mb_debug(1, "use %u/%u from group pa %p\n", pa->pa_lstart-len, len, pa); |
3309 | } | 3346 | } |
3310 | 3347 | ||
3311 | /* | 3348 | /* |
@@ -3484,7 +3521,7 @@ void ext4_mb_generate_from_pa(struct super_block *sb, void *bitmap, | |||
3484 | preallocated += len; | 3521 | preallocated += len; |
3485 | count++; | 3522 | count++; |
3486 | } | 3523 | } |
3487 | mb_debug("prellocated %u for group %u\n", preallocated, group); | 3524 | mb_debug(1, "prellocated %u for group %u\n", preallocated, group); |
3488 | } | 3525 | } |
3489 | 3526 | ||
3490 | static void ext4_mb_pa_callback(struct rcu_head *head) | 3527 | static void ext4_mb_pa_callback(struct rcu_head *head) |
@@ -3619,7 +3656,7 @@ ext4_mb_new_inode_pa(struct ext4_allocation_context *ac) | |||
3619 | pa->pa_deleted = 0; | 3656 | pa->pa_deleted = 0; |
3620 | pa->pa_type = MB_INODE_PA; | 3657 | pa->pa_type = MB_INODE_PA; |
3621 | 3658 | ||
3622 | mb_debug("new inode pa %p: %llu/%u for %u\n", pa, | 3659 | mb_debug(1, "new inode pa %p: %llu/%u for %u\n", pa, |
3623 | pa->pa_pstart, pa->pa_len, pa->pa_lstart); | 3660 | pa->pa_pstart, pa->pa_len, pa->pa_lstart); |
3624 | trace_ext4_mb_new_inode_pa(ac, pa); | 3661 | trace_ext4_mb_new_inode_pa(ac, pa); |
3625 | 3662 | ||
@@ -3679,7 +3716,7 @@ ext4_mb_new_group_pa(struct ext4_allocation_context *ac) | |||
3679 | pa->pa_deleted = 0; | 3716 | pa->pa_deleted = 0; |
3680 | pa->pa_type = MB_GROUP_PA; | 3717 | pa->pa_type = MB_GROUP_PA; |
3681 | 3718 | ||
3682 | mb_debug("new group pa %p: %llu/%u for %u\n", pa, | 3719 | mb_debug(1, "new group pa %p: %llu/%u for %u\n", pa, |
3683 | pa->pa_pstart, pa->pa_len, pa->pa_lstart); | 3720 | pa->pa_pstart, pa->pa_len, pa->pa_lstart); |
3684 | trace_ext4_mb_new_group_pa(ac, pa); | 3721 | trace_ext4_mb_new_group_pa(ac, pa); |
3685 | 3722 | ||
@@ -3758,7 +3795,7 @@ ext4_mb_release_inode_pa(struct ext4_buddy *e4b, struct buffer_head *bitmap_bh, | |||
3758 | next = mb_find_next_bit(bitmap_bh->b_data, end, bit); | 3795 | next = mb_find_next_bit(bitmap_bh->b_data, end, bit); |
3759 | start = group * EXT4_BLOCKS_PER_GROUP(sb) + bit + | 3796 | start = group * EXT4_BLOCKS_PER_GROUP(sb) + bit + |
3760 | le32_to_cpu(sbi->s_es->s_first_data_block); | 3797 | le32_to_cpu(sbi->s_es->s_first_data_block); |
3761 | mb_debug(" free preallocated %u/%u in group %u\n", | 3798 | mb_debug(1, " free preallocated %u/%u in group %u\n", |
3762 | (unsigned) start, (unsigned) next - bit, | 3799 | (unsigned) start, (unsigned) next - bit, |
3763 | (unsigned) group); | 3800 | (unsigned) group); |
3764 | free += next - bit; | 3801 | free += next - bit; |
@@ -3849,7 +3886,7 @@ ext4_mb_discard_group_preallocations(struct super_block *sb, | |||
3849 | int busy = 0; | 3886 | int busy = 0; |
3850 | int free = 0; | 3887 | int free = 0; |
3851 | 3888 | ||
3852 | mb_debug("discard preallocation for group %u\n", group); | 3889 | mb_debug(1, "discard preallocation for group %u\n", group); |
3853 | 3890 | ||
3854 | if (list_empty(&grp->bb_prealloc_list)) | 3891 | if (list_empty(&grp->bb_prealloc_list)) |
3855 | return 0; | 3892 | return 0; |
@@ -3973,7 +4010,7 @@ void ext4_discard_preallocations(struct inode *inode) | |||
3973 | return; | 4010 | return; |
3974 | } | 4011 | } |
3975 | 4012 | ||
3976 | mb_debug("discard preallocation for inode %lu\n", inode->i_ino); | 4013 | mb_debug(1, "discard preallocation for inode %lu\n", inode->i_ino); |
3977 | trace_ext4_discard_preallocations(inode); | 4014 | trace_ext4_discard_preallocations(inode); |
3978 | 4015 | ||
3979 | INIT_LIST_HEAD(&list); | 4016 | INIT_LIST_HEAD(&list); |
@@ -4078,7 +4115,7 @@ static void ext4_mb_return_to_preallocation(struct inode *inode, | |||
4078 | { | 4115 | { |
4079 | BUG_ON(!list_empty(&EXT4_I(inode)->i_prealloc_list)); | 4116 | BUG_ON(!list_empty(&EXT4_I(inode)->i_prealloc_list)); |
4080 | } | 4117 | } |
4081 | #ifdef MB_DEBUG | 4118 | #ifdef CONFIG_EXT4_DEBUG |
4082 | static void ext4_mb_show_ac(struct ext4_allocation_context *ac) | 4119 | static void ext4_mb_show_ac(struct ext4_allocation_context *ac) |
4083 | { | 4120 | { |
4084 | struct super_block *sb = ac->ac_sb; | 4121 | struct super_block *sb = ac->ac_sb; |
@@ -4227,7 +4264,7 @@ ext4_mb_initialize_context(struct ext4_allocation_context *ac, | |||
4227 | * locality group. this is a policy, actually */ | 4264 | * locality group. this is a policy, actually */ |
4228 | ext4_mb_group_or_file(ac); | 4265 | ext4_mb_group_or_file(ac); |
4229 | 4266 | ||
4230 | mb_debug("init ac: %u blocks @ %u, goal %u, flags %x, 2^%d, " | 4267 | mb_debug(1, "init ac: %u blocks @ %u, goal %u, flags %x, 2^%d, " |
4231 | "left: %u/%u, right %u/%u to %swritable\n", | 4268 | "left: %u/%u, right %u/%u to %swritable\n", |
4232 | (unsigned) ar->len, (unsigned) ar->logical, | 4269 | (unsigned) ar->len, (unsigned) ar->logical, |
4233 | (unsigned) ar->goal, ac->ac_flags, ac->ac_2order, | 4270 | (unsigned) ar->goal, ac->ac_flags, ac->ac_2order, |
@@ -4249,7 +4286,7 @@ ext4_mb_discard_lg_preallocations(struct super_block *sb, | |||
4249 | struct ext4_prealloc_space *pa, *tmp; | 4286 | struct ext4_prealloc_space *pa, *tmp; |
4250 | struct ext4_allocation_context *ac; | 4287 | struct ext4_allocation_context *ac; |
4251 | 4288 | ||
4252 | mb_debug("discard locality group preallocation\n"); | 4289 | mb_debug(1, "discard locality group preallocation\n"); |
4253 | 4290 | ||
4254 | INIT_LIST_HEAD(&discard_list); | 4291 | INIT_LIST_HEAD(&discard_list); |
4255 | ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS); | 4292 | ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS); |
diff --git a/fs/ext4/mballoc.h b/fs/ext4/mballoc.h index c96bb19f58f9..9db890d4d275 100644 --- a/fs/ext4/mballoc.h +++ b/fs/ext4/mballoc.h | |||
@@ -37,11 +37,19 @@ | |||
37 | 37 | ||
38 | /* | 38 | /* |
39 | */ | 39 | */ |
40 | #define MB_DEBUG__ | 40 | #ifdef CONFIG_EXT4_DEBUG |
41 | #ifdef MB_DEBUG | 41 | extern u8 mb_enable_debug; |
42 | #define mb_debug(fmt, a...) printk(fmt, ##a) | 42 | |
43 | #define mb_debug(n, fmt, a...) \ | ||
44 | do { \ | ||
45 | if ((n) <= mb_enable_debug) { \ | ||
46 | printk(KERN_DEBUG "(%s, %d): %s: ", \ | ||
47 | __FILE__, __LINE__, __func__); \ | ||
48 | printk(fmt, ## a); \ | ||
49 | } \ | ||
50 | } while (0) | ||
43 | #else | 51 | #else |
44 | #define mb_debug(fmt, a...) | 52 | #define mb_debug(n, fmt, a...) |
45 | #endif | 53 | #endif |
46 | 54 | ||
47 | /* | 55 | /* |