aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/ioctl.c')
-rw-r--r--fs/btrfs/ioctl.c23
1 files changed, 23 insertions, 0 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index cfeff1b8dce0..818f7ec8bb0e 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -43,6 +43,8 @@
43#include "qgroup.h" 43#include "qgroup.h"
44#include "tree-log.h" 44#include "tree-log.h"
45#include "compression.h" 45#include "compression.h"
46#include "space-info.h"
47#include "delalloc-space.h"
46 48
47#ifdef CONFIG_64BIT 49#ifdef CONFIG_64BIT
48/* If we have a 32-bit userspace and 64-bit kernel, then the UAPI 50/* If we have a 32-bit userspace and 64-bit kernel, then the UAPI
@@ -3993,6 +3995,27 @@ static int btrfs_remap_file_range_prep(struct file *file_in, loff_t pos_in,
3993 if (!same_inode) 3995 if (!same_inode)
3994 inode_dio_wait(inode_out); 3996 inode_dio_wait(inode_out);
3995 3997
3998 /*
3999 * Workaround to make sure NOCOW buffered write reach disk as NOCOW.
4000 *
4001 * Btrfs' back references do not have a block level granularity, they
4002 * work at the whole extent level.
4003 * NOCOW buffered write without data space reserved may not be able
4004 * to fall back to CoW due to lack of data space, thus could cause
4005 * data loss.
4006 *
4007 * Here we take a shortcut by flushing the whole inode, so that all
4008 * nocow write should reach disk as nocow before we increase the
4009 * reference of the extent. We could do better by only flushing NOCOW
4010 * data, but that needs extra accounting.
4011 *
4012 * Also we don't need to check ASYNC_EXTENT, as async extent will be
4013 * CoWed anyway, not affecting nocow part.
4014 */
4015 ret = filemap_flush(inode_in->i_mapping);
4016 if (ret < 0)
4017 return ret;
4018
3996 ret = btrfs_wait_ordered_range(inode_in, ALIGN_DOWN(pos_in, bs), 4019 ret = btrfs_wait_ordered_range(inode_in, ALIGN_DOWN(pos_in, bs),
3997 wb_len); 4020 wb_len);
3998 if (ret < 0) 4021 if (ret < 0)