|
@@ -2088,6 +2088,30 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
|
|
|
|
|
|
atomic_inc(&root->log_batch);
|
|
|
|
|
|
+ /*
|
|
|
+ * Before we acquired the inode's lock, someone may have dirtied more
|
|
|
+ * pages in the target range. We need to make sure that writeback for
|
|
|
+ * any such pages does not start while we are logging the inode, because
|
|
|
+ * if it does, any of the following might happen when we are not doing a
|
|
|
+ * full inode sync:
|
|
|
+ *
|
|
|
+ * 1) We log an extent after its writeback finishes but before its
|
|
|
+ * checksums are added to the csum tree, leading to -EIO errors
|
|
|
+ * when attempting to read the extent after a log replay.
|
|
|
+ *
|
|
|
+ * 2) We can end up logging an extent before its writeback finishes.
|
|
|
+ * Therefore after the log replay we will have a file extent item
|
|
|
+ * pointing to an unwritten extent (and no data checksums as well).
|
|
|
+ *
|
|
|
+ * So trigger writeback for any eventual new dirty pages and then we
|
|
|
+ * wait for all ordered extents to complete below.
|
|
|
+ */
|
|
|
+ ret = start_ordered_ops(inode, start, end);
|
|
|
+ if (ret) {
|
|
|
+ inode_unlock(inode);
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+
|
|
|
/*
|
|
|
* We have to do this here to avoid the priority inversion of waiting on
|
|
|
* IO of a lower priority task while holding a transaciton open.
|