aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorJosef Bacik <jbacik@fusionio.com>2012-07-20 16:25:24 -0400
committerChris Mason <chris.mason@fusionio.com>2012-07-23 16:28:09 -0400
commit51561ffec9614618f3da362f9d1b03a95b717484 (patch)
tree0698cb8f1e7de2217b3060866b91a5bd7faa8411 /fs/btrfs
parent594831c4b232b094d645503ecedec2e35dcebdf3 (diff)
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>
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/extent_io.c9
1 files changed, 9 insertions, 0 deletions
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index e1939a6c7478..97efc2f22597 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -3077,8 +3077,15 @@ static int lock_extent_buffer_for_io(struct extent_buffer *eb,
3077 } 3077 }
3078 } 3078 }
3079 3079
3080 /*
3081 * We need to do this to prevent races in people who check if the eb is
3082 * under IO since we can end up having no IO bits set for a short period
3083 * of time.
3084 */
3085 spin_lock(&eb->refs_lock);
3080 if (test_and_clear_bit(EXTENT_BUFFER_DIRTY, &eb->bflags)) { 3086 if (test_and_clear_bit(EXTENT_BUFFER_DIRTY, &eb->bflags)) {
3081 set_bit(EXTENT_BUFFER_WRITEBACK, &eb->bflags); 3087 set_bit(EXTENT_BUFFER_WRITEBACK, &eb->bflags);
3088 spin_unlock(&eb->refs_lock);
3082 btrfs_set_header_flag(eb, BTRFS_HEADER_FLAG_WRITTEN); 3089 btrfs_set_header_flag(eb, BTRFS_HEADER_FLAG_WRITTEN);
3083 spin_lock(&fs_info->delalloc_lock); 3090 spin_lock(&fs_info->delalloc_lock);
3084 if (fs_info->dirty_metadata_bytes >= eb->len) 3091 if (fs_info->dirty_metadata_bytes >= eb->len)
@@ -3087,6 +3094,8 @@ static int lock_extent_buffer_for_io(struct extent_buffer *eb,
3087 WARN_ON(1); 3094 WARN_ON(1);
3088 spin_unlock(&fs_info->delalloc_lock); 3095 spin_unlock(&fs_info->delalloc_lock);
3089 ret = 1; 3096 ret = 1;
3097 } else {
3098 spin_unlock(&eb->refs_lock);
3090 } 3099 }
3091 3100
3092 btrfs_tree_unlock(eb); 3101 btrfs_tree_unlock(eb);