diff options
author | George Wilson <[email protected]> | 2019-03-11 12:13:37 -0400 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2019-03-11 09:13:37 -0700 |
commit | b1b94e9644ee6af27ce71d127618b7d5323561c6 (patch) | |
tree | 5972c857d1005562e42d5b8f77aee119f5ffe45c /module/zfs | |
parent | 1118f9944924678095aa43636dce742a03c5fde3 (diff) |
zfs does not honor NFS sync write semantics
The linux kernel's nfsd implementation use RWF_SYNC to determine if the
write is synchronous or not. This flag is used to set the kernel's I/O
control block flags. Unfortunately, ZFS was not updated to inspect these
flags so NFS sync writes were not being honored.
This change maps the IOCB_* flags to the ZFS equivalent.
Reviewed-by: Don Brady <[email protected]>
Reviewed-by: Brian Behlendorf <[email protected]>
Signed-off-by: George Wilson <[email protected]>
Closes #8474
Closes #8452
Closes #8486
Diffstat (limited to 'module/zfs')
-rw-r--r-- | module/zfs/zpl_file.c | 32 |
1 files changed, 30 insertions, 2 deletions
diff --git a/module/zfs/zpl_file.c b/module/zfs/zpl_file.c index 8d9c44b37..45e82c80d 100644 --- a/module/zfs/zpl_file.c +++ b/module/zfs/zpl_file.c @@ -216,6 +216,30 @@ zpl_aio_fsync(struct kiocb *kiocb, int datasync) #error "Unsupported fops->fsync() implementation" #endif +static inline int +zfs_io_flags(struct kiocb *kiocb) +{ + int flags = 0; + +#if defined(IOCB_DSYNC) + if (kiocb->ki_flags & IOCB_DSYNC) + flags |= FDSYNC; +#endif +#if defined(IOCB_SYNC) + if (kiocb->ki_flags & IOCB_SYNC) + flags |= FSYNC; +#endif +#if defined(IOCB_APPEND) + if (kiocb->ki_flags & IOCB_APPEND) + flags |= FAPPEND; +#endif +#if defined(IOCB_DIRECT) + if (kiocb->ki_flags & IOCB_DIRECT) + flags |= FDIRECT; +#endif + return (flags); +} + static ssize_t zpl_read_common_iovec(struct inode *ip, const struct iovec *iovp, size_t count, unsigned long nr_segs, loff_t *ppos, uio_seg_t segment, int flags, @@ -266,10 +290,12 @@ zpl_iter_read_common(struct kiocb *kiocb, const struct iovec *iovp, cred_t *cr = CRED(); struct file *filp = kiocb->ki_filp; ssize_t read; + unsigned int f_flags = filp->f_flags; + f_flags |= zfs_io_flags(kiocb); crhold(cr); read = zpl_read_common_iovec(filp->f_mapping->host, iovp, count, - nr_segs, &kiocb->ki_pos, seg, filp->f_flags, cr, skip); + nr_segs, &kiocb->ki_pos, seg, f_flags, cr, skip); crfree(cr); file_accessed(filp); @@ -362,10 +388,12 @@ zpl_iter_write_common(struct kiocb *kiocb, const struct iovec *iovp, cred_t *cr = CRED(); struct file *filp = kiocb->ki_filp; ssize_t wrote; + unsigned int f_flags = filp->f_flags; + f_flags |= zfs_io_flags(kiocb); crhold(cr); wrote = zpl_write_common_iovec(filp->f_mapping->host, iovp, count, - nr_segs, &kiocb->ki_pos, seg, filp->f_flags, cr, skip); + nr_segs, &kiocb->ki_pos, seg, f_flags, cr, skip); crfree(cr); return (wrote); |