diff options
author | Eric Sandeen <sandeen@redhat.com> | 2013-04-22 12:12:31 -0400 |
---|---|---|
committer | Josef Bacik <jbacik@fusionio.com> | 2013-05-06 15:55:16 -0400 |
commit | 6d49ba1b47b9c6822d08f90af6f1a2d8ca1cf533 (patch) | |
tree | 316890f9d5ce407a6767b279620ee3131b6c8e75 /fs/btrfs/extent_io.c | |
parent | ace68bac61b338e52924d87ebdd0fa8c7439f896 (diff) |
btrfs: move leak debug code to functions
Clean up the leak debugging in extent_io.c by moving
the debug code into functions. This also removes the
list_heads used for debugging from the extent_buffer
and extent_state structures when debug is not enabled.
Since we need a global debug config to do that last
part, implement CONFIG_BTRFS_DEBUG to accommodate.
Thanks to Dave Sterba for the Kconfig bit.
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
Reviewed-by: David Sterba <dsterba@suse.cz>
Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Diffstat (limited to 'fs/btrfs/extent_io.c')
-rw-r--r-- | fs/btrfs/extent_io.c | 113 |
1 files changed, 58 insertions, 55 deletions
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index d9a82f261e04..f110d12de2d5 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
@@ -24,12 +24,62 @@ | |||
24 | static struct kmem_cache *extent_state_cache; | 24 | static struct kmem_cache *extent_state_cache; |
25 | static struct kmem_cache *extent_buffer_cache; | 25 | static struct kmem_cache *extent_buffer_cache; |
26 | 26 | ||
27 | #ifdef CONFIG_BTRFS_DEBUG | ||
27 | static LIST_HEAD(buffers); | 28 | static LIST_HEAD(buffers); |
28 | static LIST_HEAD(states); | 29 | static LIST_HEAD(states); |
29 | 30 | ||
30 | #define LEAK_DEBUG 0 | ||
31 | #if LEAK_DEBUG | ||
32 | static DEFINE_SPINLOCK(leak_lock); | 31 | static DEFINE_SPINLOCK(leak_lock); |
32 | |||
33 | static inline | ||
34 | void btrfs_leak_debug_add(struct list_head *new, struct list_head *head) | ||
35 | { | ||
36 | unsigned long flags; | ||
37 | |||
38 | spin_lock_irqsave(&leak_lock, flags); | ||
39 | list_add(new, head); | ||
40 | spin_unlock_irqrestore(&leak_lock, flags); | ||
41 | } | ||
42 | |||
43 | static inline | ||
44 | void btrfs_leak_debug_del(struct list_head *entry) | ||
45 | { | ||
46 | unsigned long flags; | ||
47 | |||
48 | spin_lock_irqsave(&leak_lock, flags); | ||
49 | list_del(entry); | ||
50 | spin_unlock_irqrestore(&leak_lock, flags); | ||
51 | } | ||
52 | |||
53 | static inline | ||
54 | void btrfs_leak_debug_check(void) | ||
55 | { | ||
56 | struct extent_state *state; | ||
57 | struct extent_buffer *eb; | ||
58 | |||
59 | while (!list_empty(&states)) { | ||
60 | state = list_entry(states.next, struct extent_state, leak_list); | ||
61 | printk(KERN_ERR "btrfs state leak: start %llu end %llu " | ||
62 | "state %lu in tree %p refs %d\n", | ||
63 | (unsigned long long)state->start, | ||
64 | (unsigned long long)state->end, | ||
65 | state->state, state->tree, atomic_read(&state->refs)); | ||
66 | list_del(&state->leak_list); | ||
67 | kmem_cache_free(extent_state_cache, state); | ||
68 | } | ||
69 | |||
70 | while (!list_empty(&buffers)) { | ||
71 | eb = list_entry(buffers.next, struct extent_buffer, leak_list); | ||
72 | printk(KERN_ERR "btrfs buffer leak start %llu len %lu " | ||
73 | "refs %d\n", (unsigned long long)eb->start, | ||
74 | eb->len, atomic_read(&eb->refs)); | ||
75 | list_del(&eb->leak_list); | ||
76 | kmem_cache_free(extent_buffer_cache, eb); | ||
77 | } | ||
78 | } | ||
79 | #else | ||
80 | #define btrfs_leak_debug_add(new, head) do {} while (0) | ||
81 | #define btrfs_leak_debug_del(entry) do {} while (0) | ||
82 | #define btrfs_leak_debug_check() do {} while (0) | ||
33 | #endif | 83 | #endif |
34 | 84 | ||
35 | #define BUFFER_LRU_MAX 64 | 85 | #define BUFFER_LRU_MAX 64 |
@@ -84,29 +134,7 @@ free_state_cache: | |||
84 | 134 | ||
85 | void extent_io_exit(void) | 135 | void extent_io_exit(void) |
86 | { | 136 | { |
87 | struct extent_state *state; | 137 | btrfs_leak_debug_check(); |
88 | struct extent_buffer *eb; | ||
89 | |||
90 | while (!list_empty(&states)) { | ||
91 | state = list_entry(states.next, struct extent_state, leak_list); | ||
92 | printk(KERN_ERR "btrfs state leak: start %llu end %llu " | ||
93 | "state %lu in tree %p refs %d\n", | ||
94 | (unsigned long long)state->start, | ||
95 | (unsigned long long)state->end, | ||
96 | state->state, state->tree, atomic_read(&state->refs)); | ||
97 | list_del(&state->leak_list); | ||
98 | kmem_cache_free(extent_state_cache, state); | ||
99 | |||
100 | } | ||
101 | |||
102 | while (!list_empty(&buffers)) { | ||
103 | eb = list_entry(buffers.next, struct extent_buffer, leak_list); | ||
104 | printk(KERN_ERR "btrfs buffer leak start %llu len %lu " | ||
105 | "refs %d\n", (unsigned long long)eb->start, | ||
106 | eb->len, atomic_read(&eb->refs)); | ||
107 | list_del(&eb->leak_list); | ||
108 | kmem_cache_free(extent_buffer_cache, eb); | ||
109 | } | ||
110 | 138 | ||
111 | /* | 139 | /* |
112 | * Make sure all delayed rcu free are flushed before we | 140 | * Make sure all delayed rcu free are flushed before we |
@@ -134,9 +162,6 @@ void extent_io_tree_init(struct extent_io_tree *tree, | |||
134 | static struct extent_state *alloc_extent_state(gfp_t mask) | 162 | static struct extent_state *alloc_extent_state(gfp_t mask) |
135 | { | 163 | { |
136 | struct extent_state *state; | 164 | struct extent_state *state; |
137 | #if LEAK_DEBUG | ||
138 | unsigned long flags; | ||
139 | #endif | ||
140 | 165 | ||
141 | state = kmem_cache_alloc(extent_state_cache, mask); | 166 | state = kmem_cache_alloc(extent_state_cache, mask); |
142 | if (!state) | 167 | if (!state) |
@@ -144,11 +169,7 @@ static struct extent_state *alloc_extent_state(gfp_t mask) | |||
144 | state->state = 0; | 169 | state->state = 0; |
145 | state->private = 0; | 170 | state->private = 0; |
146 | state->tree = NULL; | 171 | state->tree = NULL; |
147 | #if LEAK_DEBUG | 172 | btrfs_leak_debug_add(&state->leak_list, &states); |
148 | spin_lock_irqsave(&leak_lock, flags); | ||
149 | list_add(&state->leak_list, &states); | ||
150 | spin_unlock_irqrestore(&leak_lock, flags); | ||
151 | #endif | ||
152 | atomic_set(&state->refs, 1); | 173 | atomic_set(&state->refs, 1); |
153 | init_waitqueue_head(&state->wq); | 174 | init_waitqueue_head(&state->wq); |
154 | trace_alloc_extent_state(state, mask, _RET_IP_); | 175 | trace_alloc_extent_state(state, mask, _RET_IP_); |
@@ -160,15 +181,8 @@ void free_extent_state(struct extent_state *state) | |||
160 | if (!state) | 181 | if (!state) |
161 | return; | 182 | return; |
162 | if (atomic_dec_and_test(&state->refs)) { | 183 | if (atomic_dec_and_test(&state->refs)) { |
163 | #if LEAK_DEBUG | ||
164 | unsigned long flags; | ||
165 | #endif | ||
166 | WARN_ON(state->tree); | 184 | WARN_ON(state->tree); |
167 | #if LEAK_DEBUG | 185 | btrfs_leak_debug_del(&state->leak_list); |
168 | spin_lock_irqsave(&leak_lock, flags); | ||
169 | list_del(&state->leak_list); | ||
170 | spin_unlock_irqrestore(&leak_lock, flags); | ||
171 | #endif | ||
172 | trace_free_extent_state(state, _RET_IP_); | 186 | trace_free_extent_state(state, _RET_IP_); |
173 | kmem_cache_free(extent_state_cache, state); | 187 | kmem_cache_free(extent_state_cache, state); |
174 | } | 188 | } |
@@ -4065,12 +4079,7 @@ out: | |||
4065 | 4079 | ||
4066 | static void __free_extent_buffer(struct extent_buffer *eb) | 4080 | static void __free_extent_buffer(struct extent_buffer *eb) |
4067 | { | 4081 | { |
4068 | #if LEAK_DEBUG | 4082 | btrfs_leak_debug_del(&eb->leak_list); |
4069 | unsigned long flags; | ||
4070 | spin_lock_irqsave(&leak_lock, flags); | ||
4071 | list_del(&eb->leak_list); | ||
4072 | spin_unlock_irqrestore(&leak_lock, flags); | ||
4073 | #endif | ||
4074 | kmem_cache_free(extent_buffer_cache, eb); | 4083 | kmem_cache_free(extent_buffer_cache, eb); |
4075 | } | 4084 | } |
4076 | 4085 | ||
@@ -4080,9 +4089,6 @@ static struct extent_buffer *__alloc_extent_buffer(struct extent_io_tree *tree, | |||
4080 | gfp_t mask) | 4089 | gfp_t mask) |
4081 | { | 4090 | { |
4082 | struct extent_buffer *eb = NULL; | 4091 | struct extent_buffer *eb = NULL; |
4083 | #if LEAK_DEBUG | ||
4084 | unsigned long flags; | ||
4085 | #endif | ||
4086 | 4092 | ||
4087 | eb = kmem_cache_zalloc(extent_buffer_cache, mask); | 4093 | eb = kmem_cache_zalloc(extent_buffer_cache, mask); |
4088 | if (eb == NULL) | 4094 | if (eb == NULL) |
@@ -4102,11 +4108,8 @@ static struct extent_buffer *__alloc_extent_buffer(struct extent_io_tree *tree, | |||
4102 | init_waitqueue_head(&eb->write_lock_wq); | 4108 | init_waitqueue_head(&eb->write_lock_wq); |
4103 | init_waitqueue_head(&eb->read_lock_wq); | 4109 | init_waitqueue_head(&eb->read_lock_wq); |
4104 | 4110 | ||
4105 | #if LEAK_DEBUG | 4111 | btrfs_leak_debug_add(&eb->leak_list, &buffers); |
4106 | spin_lock_irqsave(&leak_lock, flags); | 4112 | |
4107 | list_add(&eb->leak_list, &buffers); | ||
4108 | spin_unlock_irqrestore(&leak_lock, flags); | ||
4109 | #endif | ||
4110 | spin_lock_init(&eb->refs_lock); | 4113 | spin_lock_init(&eb->refs_lock); |
4111 | atomic_set(&eb->refs, 1); | 4114 | atomic_set(&eb->refs, 1); |
4112 | atomic_set(&eb->io_pages, 0); | 4115 | atomic_set(&eb->io_pages, 0); |