Btrfs: lock the transition from dirty to writeback for an eb
There is a small window where an eb can have no IO bits set on it, which could potentially result in extent_buffer_under_io() returning false when we want it to return true, which could result in not fun things happening. So in order to protect this case we need to hold the refs_lock when we make this transition to make sure we get reliable results out of extent_buffer_udner_io(). Thanks, Signed-off-by: Josef Bacik <jbacik@fusionio.com>
This commit is contained in:
Родитель
594831c4b2
Коммит
51561ffec9
|
@ -3077,8 +3077,15 @@ static int lock_extent_buffer_for_io(struct extent_buffer *eb,
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We need to do this to prevent races in people who check if the eb is
|
||||
* under IO since we can end up having no IO bits set for a short period
|
||||
* of time.
|
||||
*/
|
||||
spin_lock(&eb->refs_lock);
|
||||
if (test_and_clear_bit(EXTENT_BUFFER_DIRTY, &eb->bflags)) {
|
||||
set_bit(EXTENT_BUFFER_WRITEBACK, &eb->bflags);
|
||||
spin_unlock(&eb->refs_lock);
|
||||
btrfs_set_header_flag(eb, BTRFS_HEADER_FLAG_WRITTEN);
|
||||
spin_lock(&fs_info->delalloc_lock);
|
||||
if (fs_info->dirty_metadata_bytes >= eb->len)
|
||||
|
@ -3087,6 +3094,8 @@ static int lock_extent_buffer_for_io(struct extent_buffer *eb,
|
|||
WARN_ON(1);
|
||||
spin_unlock(&fs_info->delalloc_lock);
|
||||
ret = 1;
|
||||
} else {
|
||||
spin_unlock(&eb->refs_lock);
|
||||
}
|
||||
|
||||
btrfs_tree_unlock(eb);
|
||||
|
|
Загрузка…
Ссылка в новой задаче