diff options
author | Mauro Carvalho Chehab <mchehab+huawei@kernel.org> | 2024-08-05 08:25:09 +0200 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab+huawei@kernel.org> | 2024-08-05 08:25:09 +0200 |
commit | 2c25dcc2361949bc7da730d22de36c019c6bf1e3 (patch) | |
tree | 3422f89adb17748bde8419918cb7959d79c773f3 /fs/btrfs/direct-io.c | |
parent | ba5c778cab1dd3e4918f940989e771e2818afee8 (diff) | |
parent | de9c2c66ad8e787abec7c9d7eff4f8c3cdd28aed (diff) |
Merge tag 'v6.11-rc2' into media_stage
Linux 6.11-rc2
* tag 'v6.11-rc2': (283 commits)
Linux 6.11-rc2
profiling: remove profile=sleep support
arm: dts: arm: versatile-ab: Fix duplicate clock node name
runtime constants: deal with old decrepit linkers
clocksource: Fix brown-bag boolean thinko in cs_watchdog_read()
cifs: update internal version number
smb: client: fix FSCTL_GET_REPARSE_POINT against NetApp
smb3: add dynamic tracepoints for shutdown ioctl
cifs: Remove cifs_aio_ctx
smb: client: handle lack of FSCTL_GET_REPARSE_POINT support
arm64: jump_label: Ensure patched jump_labels are visible to all CPUs
syscalls: fix syscall macros for newfstat/newfstatat
uretprobe: change syscall number, again
thermal: core: Update thermal zone registration documentation
Revert "nouveau: rip out busy fence waits"
protect the fetch of ->fd[fd] in do_dup2() from mispredictions
x86/uaccess: Zero the 8-byte get_range case on failure on 32-bit
riscv: Fix linear mapping checks for non-contiguous memory regions
KVM: x86/mmu: fix determination of max NPT mapping level for private pages
PCI: pciehp: Retain Power Indicator bits for userspace indicators
...
Diffstat (limited to 'fs/btrfs/direct-io.c')
-rw-r--r-- | fs/btrfs/direct-io.c | 38 |
1 files changed, 28 insertions, 10 deletions
diff --git a/fs/btrfs/direct-io.c b/fs/btrfs/direct-io.c index f9fb2db6a1e4..67adbe9d294a 100644 --- a/fs/btrfs/direct-io.c +++ b/fs/btrfs/direct-io.c @@ -856,21 +856,37 @@ relock: * So here we disable page faults in the iov_iter and then retry if we * got -EFAULT, faulting in the pages before the retry. */ +again: from->nofault = true; dio = btrfs_dio_write(iocb, from, written); from->nofault = false; - /* - * iomap_dio_complete() will call btrfs_sync_file() if we have a dsync - * iocb, and that needs to lock the inode. So unlock it before calling - * iomap_dio_complete() to avoid a deadlock. - */ - btrfs_inode_unlock(BTRFS_I(inode), ilock_flags); - - if (IS_ERR_OR_NULL(dio)) + if (IS_ERR_OR_NULL(dio)) { ret = PTR_ERR_OR_ZERO(dio); - else + } else { + struct btrfs_file_private stack_private = { 0 }; + struct btrfs_file_private *private; + const bool have_private = (file->private_data != NULL); + + if (!have_private) + file->private_data = &stack_private; + + /* + * If we have a synchronous write, we must make sure the fsync + * triggered by the iomap_dio_complete() call below doesn't + * deadlock on the inode lock - we are already holding it and we + * can't call it after unlocking because we may need to complete + * partial writes due to the input buffer (or parts of it) not + * being already faulted in. + */ + private = file->private_data; + private->fsync_skip_inode_lock = true; ret = iomap_dio_complete(dio); + private->fsync_skip_inode_lock = false; + + if (!have_private) + file->private_data = NULL; + } /* No increment (+=) because iomap returns a cumulative value. */ if (ret > 0) @@ -897,10 +913,12 @@ relock: } else { fault_in_iov_iter_readable(from, left); prev_left = left; - goto relock; + goto again; } } + btrfs_inode_unlock(BTRFS_I(inode), ilock_flags); + /* * If 'ret' is -ENOTBLK or we have not written all data, then it means * we must fallback to buffered IO. |