Btrfs: fix dio write vs buffered read race
authorJosef Bacik <josef@redhat.com>
Tue, 19 Jun 2012 14:59:00 +0000 (10:59 -0400)
committerChris Mason <chris.mason@fusionio.com>
Mon, 2 Jul 2012 19:36:23 +0000 (15:36 -0400)
commitc3473e830074ef04f974f2829690942dd8580619
tree21e5e5117bffcf4cdb01e6985346747aeccd331e
parent597a60fadedf9a40fdff8735054bf772b3dafd57
Btrfs: fix dio write vs buffered read race

Miao pointed out there's a problem with mixing dio writes and buffered
reads.  If the read happens between us invalidating the page range and
actually locking the extent we can bring in pages into page cache.  Then
once the write finishes if somebody tries to read again it will just find
uptodate pages and we'll read stale data.  So we need to lock the extent and
check for uptodate bits in the range.  If there are uptodate bits we need to
unlock and invalidate again.  This will keep this race from happening since
we will hold the extent locked until we create the ordered extent, and then
teh read side always waits for ordered extents.  There was also a race in
how we updated i_size, previously we were relying on the generic DIO stuff
to adjust the i_size after the DIO had completed, but this happens outside
of the extent lock which means reads could come in and not see the updated
i_size.  So instead move this work into where we create the extents, and
then this way the update ordered i_size stuff works properly in the endio
handlers.  Thanks,

Signed-off-by: Josef Bacik <josef@redhat.com>
fs/btrfs/file.c
fs/btrfs/inode.c