]> git.ipfire.org Git - thirdparty/kernel/stable.git/commit
Btrfs: check for the full sync flag while holding the inode lock during fsync
authorFilipe Manana <fdmanana@suse.com>
Wed, 16 Oct 2019 15:28:52 +0000 (16:28 +0100)
committerBen Hutchings <ben@decadent.org.uk>
Thu, 19 Dec 2019 15:58:36 +0000 (15:58 +0000)
commit6a80b5382babec0a0aced7169b27c2fe5212b019
tree421d190a300805caa3455a13e0e3c3157f8a14bb
parent848cf94ec9943ecb4fc8437466753cd0cd62f515
Btrfs: check for the full sync flag while holding the inode lock during fsync

commit ba0b084ac309283db6e329785c1dc4f45fdbd379 upstream.

We were checking for the full fsync flag in the inode before locking the
inode, which is racy, since at that that time it might not be set but
after we acquire the inode lock some other task set it. One case where
this can happen is on a system low on memory and some concurrent task
failed to allocate an extent map and therefore set the full sync flag on
the inode, to force the next fsync to work in full mode.

A consequence of missing the full fsync flag set is hitting the problems
fixed by commit 0c713cbab620 ("Btrfs: fix race between ranged fsync and
writeback of adjacent ranges"), BUG_ON() when dropping extents from a log
tree, hitting assertion failures at tree-log.c:copy_items() or all sorts
of weird inconsistencies after replaying a log due to file extents items
representing ranges that overlap.

So just move the check such that it's done after locking the inode and
before starting writeback again.

Fixes: 0c713cbab620 ("Btrfs: fix race between ranged fsync and writeback of adjacent ranges")
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
[bwh: Backported to 3.16:
 - Keep the "len" variable since we pass it to btrfs_wait_ordered_range()
   in two different places here
 - Adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
fs/btrfs/file.c