btrfs-image: Fix a data race in build_chunk_tree.
authorAdam Buchbinder <abuchbinder@google.com>
Mon, 19 May 2014 05:40:42 +0000 (22:40 -0700)
committerDavid Sterba <dsterba@suse.cz>
Fri, 22 Aug 2014 12:39:32 +0000 (14:39 +0200)
A mdrestore_struct was being written to without its mutex being held.
This race was found with ThreadSanitizer; the relevant part of the report
looks like this:

WARNING: ThreadSanitizer: data race (pid=18828)
  Write of size 8 at 0x7fffffc3d088 by main thread:
    #0 build_chunk_tree .../btrfs-progs/btrfs-image.c:2233
    #1 __restore_metadump .../btrfs-progs/btrfs-image.c:2294
    #2 restore_metadump .../btrfs-progs/btrfs-image.c:2345
    #3 main .../btrfs-progs/btrfs-image.c:2545

  Previous read of size 8 at 0x7fffffc3d088 by thread T1 (mutexes: write M0):
    #0 restore_worker .../btrfs-progs/btrfs-image.c:1636

  Location is stack of main thread.

  Mutex M0 created at:
    #0 pthread_mutex_init ??:0
    #1 mdrestore_init .../btrfs-progs/btrfs-image.c:1766
    #2 __restore_metadump .../btrfs-progs/btrfs-image.c:2286
    #3 restore_metadump .../btrfs-progs/btrfs-image.c:2345
    #4 main .../btrfs-progs/btrfs-image.c:2545

  Thread T1 (tid=18830, running) created by main thread at:
    #0 pthread_create ??:0
    #1 mdrestore_init .../btrfs-progs/btrfs-image.c:1784
    #2 __restore_metadump .../btrfs-progs/btrfs-image.c:2286
    #3 restore_metadump .../btrfs-progs/btrfs-image.c:2345
    #4 main .../btrfs-progs/btrfs-image.c:2545

Signed-off-by: Adam Buchbinder <abuchbinder@google.com>
Signed-off-by: David Sterba <dsterba@suse.cz>
btrfs-image.c

index 4c31e28..cf1fe2d 100644 (file)
@@ -2216,6 +2216,7 @@ static int build_chunk_tree(struct mdrestore_struct *mdres,
                buffer = tmp;
        }
 
+       pthread_mutex_lock(&mdres->mutex);
        super = (struct btrfs_super_block *)buffer;
        chunk_root_bytenr = btrfs_super_chunk_root(super);
        mdres->leafsize = btrfs_super_leafsize(super);
@@ -2224,6 +2225,7 @@ static int build_chunk_tree(struct mdrestore_struct *mdres,
                       BTRFS_UUID_SIZE);
        mdres->devid = le64_to_cpu(super->dev_item.devid);
        free(buffer);
+       pthread_mutex_unlock(&mdres->mutex);
 
        return search_for_chunk_blocks(mdres, chunk_root_bytenr, 0);
 }