aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/tree-log.c
diff options
context:
space:
mode:
authorFilipe Manana <fdmanana@suse.com>2016-02-25 18:19:38 -0500
committerChris Mason <clm@fb.com>2016-03-01 11:23:47 -0500
commit5e33a2bd7ca7fa687fb0965869196eea6815d1f3 (patch)
tree5f90810654e14860bb062f991bc07aee29db3366 /fs/btrfs/tree-log.c
parentaffc0ff902d539ebe9bba405d330410314f46e9f (diff)
Btrfs: do not collect ordered extents when logging that inode exists
When logging that an inode exists, for example as part of a directory fsync operation, we were collecting any ordered extents for the inode but we ended up doing nothing with them except tagging them as processed, by setting the flag BTRFS_ORDERED_LOGGED on them, which prevented a subsequent fsync of that inode (using the LOG_INODE_ALL mode) from collecting and processing them. This created a time window where a second fsync against the inode, using the fast path, ended up not logging the checksums for the new extents but it logged the extents since they were part of the list of modified extents. This happened because the ordered extents were not collected and checksums were not yet added to the csum tree - the ordered extents have not gone through btrfs_finish_ordered_io() yet (which is where we add them to the csum tree by calling inode.c:add_pending_csums()). So fix this by not collecting an inode's ordered extents if we are logging it with the LOG_INODE_EXISTS mode. Signed-off-by: Filipe Manana <fdmanana@suse.com> Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'fs/btrfs/tree-log.c')
-rw-r--r--fs/btrfs/tree-log.c17
1 files changed, 16 insertions, 1 deletions
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index 9f6372dd0eab..9d2e8ecc5382 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -4500,7 +4500,22 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans,
4500 4500
4501 mutex_lock(&BTRFS_I(inode)->log_mutex); 4501 mutex_lock(&BTRFS_I(inode)->log_mutex);
4502 4502
4503 btrfs_get_logged_extents(inode, &logged_list, start, end); 4503 /*
4504 * Collect ordered extents only if we are logging data. This is to
4505 * ensure a subsequent request to log this inode in LOG_INODE_ALL mode
4506 * will process the ordered extents if they still exists at the time,
4507 * because when we collect them we test and set for the flag
4508 * BTRFS_ORDERED_LOGGED to prevent multiple log requests to process the
4509 * same ordered extents. The consequence for the LOG_INODE_ALL log mode
4510 * not processing the ordered extents is that we end up logging the
4511 * corresponding file extent items, based on the extent maps in the
4512 * inode's extent_map_tree's modified_list, without logging the
4513 * respective checksums (since the may still be only attached to the
4514 * ordered extents and have not been inserted in the csum tree by
4515 * btrfs_finish_ordered_io() yet).
4516 */
4517 if (inode_only == LOG_INODE_ALL)
4518 btrfs_get_logged_extents(inode, &logged_list, start, end);
4504 4519
4505 /* 4520 /*
4506 * a brute force approach to making sure we get the most uptodate 4521 * a brute force approach to making sure we get the most uptodate