Btrfs: don't return true in releasepage unless we actually freed the eb
I noticed while looking at an extent_buffer race that we will unconditionally return 1 if we get down to release_extent_buffer after clearing the tree ref. However we can easily race in here and get a ref on the eb and not actually free the eb. So make release_extent_buffer return 1 if it free'd the eb and 0 if not so we can be a little kinder to the vm. Thanks, Signed-off-by: Josef Bacik <jbacik@fusionio.com>
This commit is contained in:
Родитель
a98cdb85b9
Коммит
e64860aa05
|
@ -4300,7 +4300,7 @@ static inline void btrfs_release_extent_buffer_rcu(struct rcu_head *head)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Expects to have eb->eb_lock already held */
|
/* Expects to have eb->eb_lock already held */
|
||||||
static void release_extent_buffer(struct extent_buffer *eb, gfp_t mask)
|
static int release_extent_buffer(struct extent_buffer *eb, gfp_t mask)
|
||||||
{
|
{
|
||||||
WARN_ON(atomic_read(&eb->refs) == 0);
|
WARN_ON(atomic_read(&eb->refs) == 0);
|
||||||
if (atomic_dec_and_test(&eb->refs)) {
|
if (atomic_dec_and_test(&eb->refs)) {
|
||||||
|
@ -4321,9 +4321,11 @@ static void release_extent_buffer(struct extent_buffer *eb, gfp_t mask)
|
||||||
btrfs_release_extent_buffer_page(eb, 0);
|
btrfs_release_extent_buffer_page(eb, 0);
|
||||||
|
|
||||||
call_rcu(&eb->rcu_head, btrfs_release_extent_buffer_rcu);
|
call_rcu(&eb->rcu_head, btrfs_release_extent_buffer_rcu);
|
||||||
return;
|
return 1;
|
||||||
}
|
}
|
||||||
spin_unlock(&eb->refs_lock);
|
spin_unlock(&eb->refs_lock);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void free_extent_buffer(struct extent_buffer *eb)
|
void free_extent_buffer(struct extent_buffer *eb)
|
||||||
|
@ -4962,7 +4964,6 @@ int try_release_extent_buffer(struct page *page, gfp_t mask)
|
||||||
spin_unlock(&eb->refs_lock);
|
spin_unlock(&eb->refs_lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
release_extent_buffer(eb, mask);
|
|
||||||
|
|
||||||
return 1;
|
return release_extent_buffer(eb, mask);
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче