Btrfs: fix race when checking if we can skip fsync'ing an inode
authorFilipe Manana <fdmanana@suse.com>
Wed, 24 Feb 2016 07:35:05 +0000 (07:35 +0000)
committerChris Mason <clm@fb.com>
Tue, 1 Mar 2016 16:23:44 +0000 (08:23 -0800)
commitaffc0ff902d539ebe9bba405d330410314f46e9f
tree9ce9bf779414693af3a199b2fffb26a3425f93fd
parentdaac7ba61a0d338c66b70c47d205ba7465718155
Btrfs: fix race when checking if we can skip fsync'ing an inode

If we're about to do a fast fsync for an inode and btrfs_inode_in_log()
returns false, it's possible that we had an ordered extent in progress
(btrfs_finish_ordered_io() not run yet) when we noticed that the inode's
last_trans field was not greater than the id of the last committed
transaction, but shortly after, before we checked if there were any
ongoing ordered extents, the ordered extent had just completed and
removed itself from the inode's ordered tree, in which case we end up not
logging the inode, losing some data if a power failure or crash happens
after the fsync handler returns and before the transaction is committed.

Fix this by checking first if there are any ongoing ordered extents
before comparing the inode's last_trans with the id of the last committed
transaction - when it completes, an ordered extent always updates the
inode's last_trans before it removes itself from the inode's ordered
tree (at btrfs_finish_ordered_io()).

Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: Chris Mason <clm@fb.com>
fs/btrfs/file.c