diff options
author | Adam Buchbinder <abuchbinder@google.com> | 2017-07-12 13:05:10 -0700 |
---|---|---|
committer | David Sterba <dsterba@suse.com> | 2017-07-20 17:43:43 +0200 |
commit | 76daaec5ccbda11f6cd343f85f6f47a56626fe00 (patch) | |
tree | d3d71fde3ac2ca0eb90f307161d8fdec0235f373 /image/main.c | |
parent | 1639cc2a511cb6f2a40b706b3c41e5cb4e01b809 (diff) |
btrfs-progs: image: Fix data races when reporting progress
Making the code data-race safe requires that reads *and* writes
happen under a mutex lock, if any of the access are writes. See
Dmitri Vyukov, "Benign data races: what could possibly go wrong?"
for more details.
The fix here was to put most of the main loop of restore_worker
under a mutex lock.
This race was detected using fsck-tests/012-leaf-corruption.
==================
WARNING: ThreadSanitizer: data race
Write of size 4 by main thread:
#0 add_cluster btrfs-progs/image/main.c:1931
#1 restore_metadump btrfs-progs/image/main.c:2566
#2 main btrfs-progs/image/main.c:2859
Previous read of size 4 by thread T6:
#0 restore_worker btrfs-progs/image/main.c:1720
Location is stack of main thread.
Thread T6 (running) created by main thread at:
#0 pthread_create <null>
#1 mdrestore_init btrfs-progs/image/main.c:1868
#2 restore_metadump btrfs-progs/image/main.c:2534
#3 main btrfs-progs/image/main.c:2859
SUMMARY: ThreadSanitizer: data race btrfs-progs/image/main.c:1931 in
add_cluster
Signed-off-by: Adam Buchbinder <abuchbinder@google.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'image/main.c')
-rw-r--r-- | image/main.c | 6 |
1 files changed, 4 insertions, 2 deletions
diff --git a/image/main.c b/image/main.c index fac9b760..2100f204 100644 --- a/image/main.c +++ b/image/main.c @@ -1720,12 +1720,13 @@ static void *restore_worker(void *data) } async = list_entry(mdres->list.next, struct async_work, list); list_del_init(&async->list); - pthread_mutex_unlock(&mdres->mutex); if (mdres->compress_method == COMPRESS_ZLIB) { size = compress_size; + pthread_mutex_unlock(&mdres->mutex); ret = uncompress(buffer, (unsigned long *)&size, async->buffer, async->bufsize); + pthread_mutex_lock(&mdres->mutex); if (ret != Z_OK) { error("decompressiion failed with %d", ret); err = -EIO; @@ -1803,7 +1804,6 @@ error: if (!mdres->multi_devices && async->start == BTRFS_SUPER_INFO_OFFSET) write_backup_supers(outfd, outbuf); - pthread_mutex_lock(&mdres->mutex); if (err && !mdres->error) mdres->error = err; mdres->num_items--; @@ -1933,7 +1933,9 @@ static int add_cluster(struct meta_cluster *cluster, u32 i, nritems; int ret; + pthread_mutex_lock(&mdres->mutex); mdres->compress_method = header->compress; + pthread_mutex_unlock(&mdres->mutex); bytenr = le64_to_cpu(header->bytenr) + BLOCK_SIZE; nritems = le32_to_cpu(header->nritems); |