diff options
author | Josef Bacik <jbacik@fusionio.com> | 2013-01-24 12:02:07 -0500 |
---|---|---|
committer | Josef Bacik <jbacik@fusionio.com> | 2013-01-24 12:49:48 -0500 |
commit | 201a90389424d6771d24fc5d72f7e34cb4a8f967 (patch) | |
tree | 2e184b0b5a702855163d7da2fa5bee2a6fb8ef98 /fs/btrfs/extent_map.c | |
parent | a105bb88f46b60de2adf1ee98745bd59362b09ab (diff) | |
download | op-kernel-dev-201a90389424d6771d24fc5d72f7e34cb4a8f967.zip op-kernel-dev-201a90389424d6771d24fc5d72f7e34cb4a8f967.tar.gz |
Btrfs: do not allow logged extents to be merged or removed
We drop the extent map tree lock while we're logging extents, so somebody
could come in and merge another extent into this one and screw up our
logging, or they could even remove us from the list which would keep us from
logging the extent or freeing our ref on it, so we need to make sure to not
clear LOGGING until after the extent is logged, and then we can merge it to
adjacent extents. Thanks,
Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Diffstat (limited to 'fs/btrfs/extent_map.c')
-rw-r--r-- | fs/btrfs/extent_map.c | 13 |
1 files changed, 12 insertions, 1 deletions
diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c index fff2c28..ed88f5e 100644 --- a/fs/btrfs/extent_map.c +++ b/fs/btrfs/extent_map.c @@ -171,6 +171,10 @@ static int mergable_maps(struct extent_map *prev, struct extent_map *next) if (test_bit(EXTENT_FLAG_COMPRESSED, &prev->flags)) return 0; + if (test_bit(EXTENT_FLAG_LOGGING, &prev->flags) || + test_bit(EXTENT_FLAG_LOGGING, &next->flags)) + return 0; + if (extent_map_end(prev) == next->start && prev->flags == next->flags && prev->bdev == next->bdev && @@ -256,7 +260,8 @@ int unpin_extent_cache(struct extent_map_tree *tree, u64 start, u64 len, if (!em) goto out; - list_move(&em->list, &tree->modified_extents); + if (!test_bit(EXTENT_FLAG_LOGGING, &em->flags)) + list_move(&em->list, &tree->modified_extents); em->generation = gen; clear_bit(EXTENT_FLAG_PINNED, &em->flags); em->mod_start = em->start; @@ -281,6 +286,12 @@ out: } +void clear_em_logging(struct extent_map_tree *tree, struct extent_map *em) +{ + clear_bit(EXTENT_FLAG_LOGGING, &em->flags); + try_merge_map(tree, em); +} + /** * add_extent_mapping - add new extent map to the extent tree * @tree: tree to insert new map in |