OSDN Git Service

Btrfs: ensure deletion from pinned_chunks list is protected
authorFilipe Manana <fdmanana@suse.com>
Thu, 4 Dec 2014 15:31:01 +0000 (15:31 +0000)
committerChris Mason <clm@fb.com>
Wed, 10 Dec 2014 20:22:28 +0000 (12:22 -0800)
The call to remove_extent_mapping() actually deletes the extent map
from the list it's included in - fs_info->pinned_chunks - and that
list is protected by the chunk mutex. Therefore make that call
while holding the chunk mutex and remove the redundant list delete
call because it's a noop.

This fixes an overlook of the patch titled
"Btrfs: fix race between fs trimming and block group remove/allocation"
following the same obvervation from the patch titled
"Btrfs: fix unprotected deletion from pending_chunks list".

Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: Chris Mason <clm@fb.com>
fs/btrfs/free-space-cache.c

index 030847b..edf32c5 100644 (file)
@@ -3185,16 +3185,18 @@ out:
 
                spin_unlock(&block_group->lock);
 
+               lock_chunks(block_group->fs_info->chunk_root);
                em_tree = &block_group->fs_info->mapping_tree.map_tree;
                write_lock(&em_tree->lock);
                em = lookup_extent_mapping(em_tree, block_group->key.objectid,
                                           1);
                BUG_ON(!em); /* logic error, can't happen */
+               /*
+                * remove_extent_mapping() will delete us from the pinned_chunks
+                * list, which is protected by the chunk mutex.
+                */
                remove_extent_mapping(em_tree, em);
                write_unlock(&em_tree->lock);
-
-               lock_chunks(block_group->fs_info->chunk_root);
-               list_del_init(&em->list);
                unlock_chunks(block_group->fs_info->chunk_root);
 
                /* once for us and once for the tree */