|
@@ -1928,12 +1928,24 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
|
|
|
if (file->private_data)
|
|
|
btrfs_ioctl_trans_end(file);
|
|
|
|
|
|
+ /*
|
|
|
+ * We use start here because we will need to wait on the IO to complete
|
|
|
+ * in btrfs_sync_log, which could require joining a transaction (for
|
|
|
+ * example checking cross references in the nocow path). If we use join
|
|
|
+ * here we could get into a situation where we're waiting on IO to
|
|
|
+ * happen that is blocked on a transaction trying to commit. With start
|
|
|
+ * we inc the extwriter counter, so we wait for all extwriters to exit
|
|
|
+ * before we start blocking join'ers. This comment is to keep somebody
|
|
|
+ * from thinking they are super smart and changing this to
|
|
|
+ * btrfs_join_transaction *cough*Josef*cough*.
|
|
|
+ */
|
|
|
trans = btrfs_start_transaction(root, 0);
|
|
|
if (IS_ERR(trans)) {
|
|
|
ret = PTR_ERR(trans);
|
|
|
mutex_unlock(&inode->i_mutex);
|
|
|
goto out;
|
|
|
}
|
|
|
+ trans->sync = true;
|
|
|
|
|
|
ret = btrfs_log_dentry_safe(trans, root, dentry);
|
|
|
if (ret < 0) {
|