aboutsummaryrefslogtreecommitdiffstats
path: root/module/zfs
diff options
context:
space:
mode:
authorGeorge Wilson <[email protected]>2019-03-11 12:13:37 -0400
committerBrian Behlendorf <[email protected]>2019-03-11 09:13:37 -0700
commitb1b94e9644ee6af27ce71d127618b7d5323561c6 (patch)
tree5972c857d1005562e42d5b8f77aee119f5ffe45c /module/zfs
parent1118f9944924678095aa43636dce742a03c5fde3 (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.c32
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);