aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/file.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/file.c')
-rw-r--r--fs/btrfs/file.c24
1 files changed, 24 insertions, 0 deletions
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index a3c22e16509b..58e93bce3036 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -2089,6 +2089,30 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
2089 atomic_inc(&root->log_batch); 2089 atomic_inc(&root->log_batch);
2090 2090
2091 /* 2091 /*
2092 * Before we acquired the inode's lock, someone may have dirtied more
2093 * pages in the target range. We need to make sure that writeback for
2094 * any such pages does not start while we are logging the inode, because
2095 * if it does, any of the following might happen when we are not doing a
2096 * full inode sync:
2097 *
2098 * 1) We log an extent after its writeback finishes but before its
2099 * checksums are added to the csum tree, leading to -EIO errors
2100 * when attempting to read the extent after a log replay.
2101 *
2102 * 2) We can end up logging an extent before its writeback finishes.
2103 * Therefore after the log replay we will have a file extent item
2104 * pointing to an unwritten extent (and no data checksums as well).
2105 *
2106 * So trigger writeback for any eventual new dirty pages and then we
2107 * wait for all ordered extents to complete below.
2108 */
2109 ret = start_ordered_ops(inode, start, end);
2110 if (ret) {
2111 inode_unlock(inode);
2112 goto out;
2113 }
2114
2115 /*
2092 * We have to do this here to avoid the priority inversion of waiting on 2116 * We have to do this here to avoid the priority inversion of waiting on
2093 * IO of a lower priority task while holding a transaciton open. 2117 * IO of a lower priority task while holding a transaciton open.
2094 */ 2118 */