diff options
Diffstat (limited to 'fs/btrfs/file.c')
| -rw-r--r-- | fs/btrfs/file.c | 16 |
1 files changed, 13 insertions, 3 deletions
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 7e85dca0e6f2..89f5be2bfb43 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
| @@ -2068,6 +2068,18 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) | |||
| 2068 | u64 len; | 2068 | u64 len; |
| 2069 | 2069 | ||
| 2070 | /* | 2070 | /* |
| 2071 | * If the inode needs a full sync, make sure we use a full range to | ||
| 2072 | * avoid log tree corruption, due to hole detection racing with ordered | ||
| 2073 | * extent completion for adjacent ranges, and assertion failures during | ||
| 2074 | * hole detection. | ||
| 2075 | */ | ||
| 2076 | if (test_bit(BTRFS_INODE_NEEDS_FULL_SYNC, | ||
| 2077 | &BTRFS_I(inode)->runtime_flags)) { | ||
| 2078 | start = 0; | ||
| 2079 | end = LLONG_MAX; | ||
| 2080 | } | ||
| 2081 | |||
| 2082 | /* | ||
| 2071 | * The range length can be represented by u64, we have to do the typecasts | 2083 | * The range length can be represented by u64, we have to do the typecasts |
| 2072 | * to avoid signed overflow if it's [0, LLONG_MAX] eg. from fsync() | 2084 | * to avoid signed overflow if it's [0, LLONG_MAX] eg. from fsync() |
| 2073 | */ | 2085 | */ |
| @@ -2554,10 +2566,8 @@ static int btrfs_punch_hole(struct inode *inode, loff_t offset, loff_t len) | |||
| 2554 | 2566 | ||
| 2555 | ret = btrfs_punch_hole_lock_range(inode, lockstart, lockend, | 2567 | ret = btrfs_punch_hole_lock_range(inode, lockstart, lockend, |
| 2556 | &cached_state); | 2568 | &cached_state); |
| 2557 | if (ret) { | 2569 | if (ret) |
| 2558 | inode_unlock(inode); | ||
| 2559 | goto out_only_mutex; | 2570 | goto out_only_mutex; |
| 2560 | } | ||
| 2561 | 2571 | ||
| 2562 | path = btrfs_alloc_path(); | 2572 | path = btrfs_alloc_path(); |
| 2563 | if (!path) { | 2573 | if (!path) { |
