Skip to content

Commit

Permalink
Btrfs: do not allow logged extents to be merged or removed
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Josef Bacik committed Jan 24, 2013
1 parent a105bb8 commit 201a903
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 3 deletions.
13 changes: 12 additions & 1 deletion fs/btrfs/extent_map.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 &&
Expand Down Expand Up @@ -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;
Expand All @@ -281,6 +286,12 @@ int unpin_extent_cache(struct extent_map_tree *tree, u64 start, u64 len,

}

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
Expand Down
1 change: 1 addition & 0 deletions fs/btrfs/extent_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ void free_extent_map(struct extent_map *em);
int __init extent_map_init(void);
void extent_map_exit(void);
int unpin_extent_cache(struct extent_map_tree *tree, u64 start, u64 len, u64 gen);
void clear_em_logging(struct extent_map_tree *tree, struct extent_map *em);
struct extent_map *search_extent_mapping(struct extent_map_tree *tree,
u64 start, u64 len);
#endif
5 changes: 3 additions & 2 deletions fs/btrfs/tree-log.c
Original file line number Diff line number Diff line change
Expand Up @@ -3410,22 +3410,23 @@ static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans,
em = list_entry(extents.next, struct extent_map, list);

list_del_init(&em->list);
clear_bit(EXTENT_FLAG_LOGGING, &em->flags);

/*
* If we had an error we just need to delete everybody from our
* private list.
*/
if (ret) {
clear_em_logging(tree, em);
free_extent_map(em);
continue;
}

write_unlock(&tree->lock);

ret = log_one_extent(trans, inode, root, em, path);
free_extent_map(em);
write_lock(&tree->lock);
clear_em_logging(tree, em);
free_extent_map(em);
}
WARN_ON(!list_empty(&extents));
write_unlock(&tree->lock);
Expand Down

0 comments on commit 201a903

Please sign in to comment.