Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
mksquashfs: fix rare race in fragment waiting in filesystem finalisation
Fix a rare race condition in fragment waiting when finalising the
filesystem.  This is a race condition that was initially fixed in 2009,
but inadvertantly re-introduced in the latest release when the code
was rewritten.

Background:

When finalising the filesystem, the main control thread needs to ensure
all the in-flight fragments have been queued to the writer thread before
asking the writer thread to finish, and then writing the metadata.

It does this by waiting on the fragments_outstanding counter.  Once this
counter reaches 0, it synchronises with the writer thread, waiting until
the writer thread reports no outstanding data to be written.

However, the main thread can race with the fragment deflator thread(s)
because the fragment deflator thread(s) decrement the fragments_outstanding
counter and release the mutex before queueing the compressed fragment
to the writer thread, i.e. the offending code is:

                        fragments_outstanding --;
                        pthread_mutex_unlock(&fragment_mutex);
                        queue_put(to_writer, write_buffer);

In extremely rare circumstances, the main thread may see the
fragments_outstanding counter is zero before the fragment
deflator sends the fragment buffer to the writer thread, and synchronise
with the writer thread, and finalise before the fragment has been written.

The fix is to ensure the fragment is queued to the writer thread
before releasing the mutex.

Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
  • Loading branch information
plougher committed Sep 18, 2014
1 parent 27167b9 commit de03266
Showing 1 changed file with 1 addition and 1 deletion.
2 changes: 1 addition & 1 deletion squashfs-tools/mksquashfs.c
Expand Up @@ -2419,8 +2419,8 @@ void *frag_deflator(void *arg)
write_buffer->block = bytes;
bytes += compressed_size;
fragments_outstanding --;
pthread_mutex_unlock(&fragment_mutex);
queue_put(to_writer, write_buffer);
pthread_mutex_unlock(&fragment_mutex);
TRACE("Writing fragment %lld, uncompressed size %d, "
"compressed size %d\n", file_buffer->block,
file_buffer->size, compressed_size);
Expand Down

0 comments on commit de03266

Please sign in to comment.