Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 374906
b: refs/heads/master
c: 6d49ba1
h: refs/heads/master
v: v3
  • Loading branch information
Eric Sandeen authored and Josef Bacik committed May 6, 2013
1 parent 7712173 commit acf16a2
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 57 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: ace68bac61b338e52924d87ebdd0fa8c7439f896
refs/heads/master: 6d49ba1b47b9c6822d08f90af6f1a2d8ca1cf533
9 changes: 9 additions & 0 deletions trunk/fs/btrfs/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,12 @@ config BTRFS_FS_RUN_SANITY_TESTS

If unsure, say N.

config BTRFS_DEBUG
bool "Btrfs debugging support"
depends on BTRFS_FS
help
Enable run-time debugging support for the btrfs filesystem. This may
enable additional and expensive checks with negative impact on
performance, or export extra information via sysfs.

If unsure, say N.
113 changes: 58 additions & 55 deletions trunk/fs/btrfs/extent_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,62 @@
static struct kmem_cache *extent_state_cache;
static struct kmem_cache *extent_buffer_cache;

#ifdef CONFIG_BTRFS_DEBUG
static LIST_HEAD(buffers);
static LIST_HEAD(states);

#define LEAK_DEBUG 0
#if LEAK_DEBUG
static DEFINE_SPINLOCK(leak_lock);

static inline
void btrfs_leak_debug_add(struct list_head *new, struct list_head *head)
{
unsigned long flags;

spin_lock_irqsave(&leak_lock, flags);
list_add(new, head);
spin_unlock_irqrestore(&leak_lock, flags);
}

static inline
void btrfs_leak_debug_del(struct list_head *entry)
{
unsigned long flags;

spin_lock_irqsave(&leak_lock, flags);
list_del(entry);
spin_unlock_irqrestore(&leak_lock, flags);
}

static inline
void btrfs_leak_debug_check(void)
{
struct extent_state *state;
struct extent_buffer *eb;

while (!list_empty(&states)) {
state = list_entry(states.next, struct extent_state, leak_list);
printk(KERN_ERR "btrfs state leak: start %llu end %llu "
"state %lu in tree %p refs %d\n",
(unsigned long long)state->start,
(unsigned long long)state->end,
state->state, state->tree, atomic_read(&state->refs));
list_del(&state->leak_list);
kmem_cache_free(extent_state_cache, state);
}

while (!list_empty(&buffers)) {
eb = list_entry(buffers.next, struct extent_buffer, leak_list);
printk(KERN_ERR "btrfs buffer leak start %llu len %lu "
"refs %d\n", (unsigned long long)eb->start,
eb->len, atomic_read(&eb->refs));
list_del(&eb->leak_list);
kmem_cache_free(extent_buffer_cache, eb);
}
}
#else
#define btrfs_leak_debug_add(new, head) do {} while (0)
#define btrfs_leak_debug_del(entry) do {} while (0)
#define btrfs_leak_debug_check() do {} while (0)
#endif

#define BUFFER_LRU_MAX 64
Expand Down Expand Up @@ -84,29 +134,7 @@ int __init extent_io_init(void)

void extent_io_exit(void)
{
struct extent_state *state;
struct extent_buffer *eb;

while (!list_empty(&states)) {
state = list_entry(states.next, struct extent_state, leak_list);
printk(KERN_ERR "btrfs state leak: start %llu end %llu "
"state %lu in tree %p refs %d\n",
(unsigned long long)state->start,
(unsigned long long)state->end,
state->state, state->tree, atomic_read(&state->refs));
list_del(&state->leak_list);
kmem_cache_free(extent_state_cache, state);

}

while (!list_empty(&buffers)) {
eb = list_entry(buffers.next, struct extent_buffer, leak_list);
printk(KERN_ERR "btrfs buffer leak start %llu len %lu "
"refs %d\n", (unsigned long long)eb->start,
eb->len, atomic_read(&eb->refs));
list_del(&eb->leak_list);
kmem_cache_free(extent_buffer_cache, eb);
}
btrfs_leak_debug_check();

/*
* Make sure all delayed rcu free are flushed before we
Expand Down Expand Up @@ -134,21 +162,14 @@ void extent_io_tree_init(struct extent_io_tree *tree,
static struct extent_state *alloc_extent_state(gfp_t mask)
{
struct extent_state *state;
#if LEAK_DEBUG
unsigned long flags;
#endif

state = kmem_cache_alloc(extent_state_cache, mask);
if (!state)
return state;
state->state = 0;
state->private = 0;
state->tree = NULL;
#if LEAK_DEBUG
spin_lock_irqsave(&leak_lock, flags);
list_add(&state->leak_list, &states);
spin_unlock_irqrestore(&leak_lock, flags);
#endif
btrfs_leak_debug_add(&state->leak_list, &states);
atomic_set(&state->refs, 1);
init_waitqueue_head(&state->wq);
trace_alloc_extent_state(state, mask, _RET_IP_);
Expand All @@ -160,15 +181,8 @@ void free_extent_state(struct extent_state *state)
if (!state)
return;
if (atomic_dec_and_test(&state->refs)) {
#if LEAK_DEBUG
unsigned long flags;
#endif
WARN_ON(state->tree);
#if LEAK_DEBUG
spin_lock_irqsave(&leak_lock, flags);
list_del(&state->leak_list);
spin_unlock_irqrestore(&leak_lock, flags);
#endif
btrfs_leak_debug_del(&state->leak_list);
trace_free_extent_state(state, _RET_IP_);
kmem_cache_free(extent_state_cache, state);
}
Expand Down Expand Up @@ -4065,12 +4079,7 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,

static void __free_extent_buffer(struct extent_buffer *eb)
{
#if LEAK_DEBUG
unsigned long flags;
spin_lock_irqsave(&leak_lock, flags);
list_del(&eb->leak_list);
spin_unlock_irqrestore(&leak_lock, flags);
#endif
btrfs_leak_debug_del(&eb->leak_list);
kmem_cache_free(extent_buffer_cache, eb);
}

Expand All @@ -4080,9 +4089,6 @@ static struct extent_buffer *__alloc_extent_buffer(struct extent_io_tree *tree,
gfp_t mask)
{
struct extent_buffer *eb = NULL;
#if LEAK_DEBUG
unsigned long flags;
#endif

eb = kmem_cache_zalloc(extent_buffer_cache, mask);
if (eb == NULL)
Expand All @@ -4102,11 +4108,8 @@ static struct extent_buffer *__alloc_extent_buffer(struct extent_io_tree *tree,
init_waitqueue_head(&eb->write_lock_wq);
init_waitqueue_head(&eb->read_lock_wq);

#if LEAK_DEBUG
spin_lock_irqsave(&leak_lock, flags);
list_add(&eb->leak_list, &buffers);
spin_unlock_irqrestore(&leak_lock, flags);
#endif
btrfs_leak_debug_add(&eb->leak_list, &buffers);

spin_lock_init(&eb->refs_lock);
atomic_set(&eb->refs, 1);
atomic_set(&eb->io_pages, 0);
Expand Down
6 changes: 5 additions & 1 deletion trunk/fs/btrfs/extent_io.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,9 @@ struct extent_state {
/* for use by the FS */
u64 private;

#ifdef CONFIG_BTRFS_DEBUG
struct list_head leak_list;
#endif
};

#define INLINE_EXTENT_BUFFER_PAGES 16
Expand All @@ -132,7 +134,6 @@ struct extent_buffer {
atomic_t refs;
atomic_t io_pages;
int read_mirror;
struct list_head leak_list;
struct rcu_head rcu_head;
pid_t lock_owner;

Expand All @@ -159,6 +160,9 @@ struct extent_buffer {
wait_queue_head_t read_lock_wq;
wait_queue_head_t lock_wq;
struct page *pages[INLINE_EXTENT_BUFFER_PAGES];
#ifdef CONFIG_BTRFS_DEBUG
struct list_head leak_list;
#endif
};

static inline void extent_set_compress_type(unsigned long *bio_flags,
Expand Down

0 comments on commit acf16a2

Please sign in to comment.