summaryrefslogtreecommitdiffstats
path: root/sys/nfsclient/nfs_vnops.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/nfsclient/nfs_vnops.c')
-rw-r--r--sys/nfsclient/nfs_vnops.c39
1 files changed, 39 insertions, 0 deletions
diff --git a/sys/nfsclient/nfs_vnops.c b/sys/nfsclient/nfs_vnops.c
index 294f9c3..dd88e42 100644
--- a/sys/nfsclient/nfs_vnops.c
+++ b/sys/nfsclient/nfs_vnops.c
@@ -211,6 +211,24 @@ static int nfs_clean_pages_on_close = 1;
SYSCTL_INT(_vfs_nfs, OID_AUTO, clean_pages_on_close, CTLFLAG_RW,
&nfs_clean_pages_on_close, 0, "NFS clean dirty pages on close");
+int nfs_directio_enable = 1;
+SYSCTL_INT(_vfs_nfs, OID_AUTO, nfs_directio_enable, CTLFLAG_RW,
+ &nfs_directio_enable, 0, "Enable NFS directio");
+
+/*
+ * This sysctl allows other processes to mmap a file that has been opened O_DIRECT
+ * by a process. In general, having processes mmap the file while Direct IO is in
+ * progress can lead to Data Inconsistencies. But, we allow this by default to
+ * prevent DoS attacks - to prevent a malicious user from opening up files O_DIRECT
+ * preventing other users from mmap'ing these files. "Protected" environments where
+ * stricter consistency guarantees are required can disable this knob.
+ * The process that opened the file O_DIRECT cannot mmap() the file, because
+ * mmap'ed IO on an O_DIRECT open() is not meaningful.
+ */
+int nfs_directio_allow_mmap = 1;
+SYSCTL_INT(_vfs_nfs, OID_AUTO, nfs_directio_allow_mmap, CTLFLAG_RW,
+ &nfs_directio_allow_mmap, 0, "Enable mmaped IO on file with O_DIRECT opens");
+
#if 0
SYSCTL_INT(_vfs_nfs, OID_AUTO, access_cache_hits, CTLFLAG_RD,
&nfsstats.accesscache_hits, 0, "NFS ACCESS cache hit count");
@@ -401,6 +419,7 @@ nfs_open(struct vop_open_args *ap)
struct nfsnode *np = VTONFS(vp);
struct vattr vattr;
int error;
+ int fmode = ap->a_mode;
if (vp->v_type != VREG && vp->v_type != VDIR && vp->v_type != VLNK)
return (EOPNOTSUPP);
@@ -434,6 +453,18 @@ nfs_open(struct vop_open_args *ap)
np->n_mtime = vattr.va_mtime;
}
}
+ /*
+ * If the object has >= 1 O_DIRECT active opens, we disable caching.
+ */
+ if (nfs_directio_enable && (fmode & O_DIRECT) && (vp->v_type == VREG)) {
+ if (np->n_directio_opens == 0) {
+ error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_td, 1);
+ if (error)
+ return (error);
+ np->n_flag |= NNONCACHE;
+ }
+ np->n_directio_opens++;
+ }
np->ra_expect_lbn = 0;
return (0);
}
@@ -472,6 +503,7 @@ nfs_close(struct vop_close_args *ap)
struct vnode *vp = ap->a_vp;
struct nfsnode *np = VTONFS(vp);
int error = 0;
+ int fmode = ap->a_fflag;
if (vp->v_type == VREG) {
/*
@@ -520,6 +552,13 @@ nfs_close(struct vop_close_args *ap)
error = np->n_error;
}
}
+ if (nfs_directio_enable && (fmode & O_DIRECT) && (vp->v_type == VREG)) {
+ KASSERT((np->n_directio_opens > 0),
+ ("nfs_close: unexpectedly value (0) of n_directio_opens\n"));
+ np->n_directio_opens--;
+ if (np->n_directio_opens == 0)
+ np->n_flag &= ~NNONCACHE;
+ }
return (error);
}
OpenPOWER on IntegriCloud