Implemented a mount option "nocto" that disables cache coherency

checking at open time.  It may improve performance for read-only
NFS mounts.  Use deliberately.

MFC after:	1 week
Reviewed by:	rmacklem, jhb (earlier version)
This commit is contained in:
Ruslan Ermilov 2011-05-04 13:27:45 +00:00
parent 785b257239
commit e2f2b37089
7 changed files with 25 additions and 5 deletions

View File

@ -28,7 +28,7 @@
.\" @(#)mount_nfs.8 8.3 (Berkeley) 3/29/95 .\" @(#)mount_nfs.8 8.3 (Berkeley) 3/29/95
.\" $FreeBSD$ .\" $FreeBSD$
.\" .\"
.Dd April 27, 2011 .Dd May 3, 2011
.Dt MOUNT_NFS 8 .Dt MOUNT_NFS 8
.Os .Os
.Sh NAME .Sh NAME
@ -180,6 +180,17 @@ NFS port number 2049 or replies to requests using a different IP address
Setting the Setting the
.Va vfs.nfs.nfs_ip_paranoia .Va vfs.nfs.nfs_ip_paranoia
sysctl to 0 will make this option the default. sysctl to 0 will make this option the default.
.It Cm nocto
Normally, NFS clients maintain the close-to-open cache coherency.
This works by flushing at close time and checking at open time.
Checking at open time is implemented by getting attributes from
the server and purging the data cache if they do not match
attributes cached by the client.
.Pp
This option disables checking at open time.
It may improve performance for read-only mounts,
but should only be used if the data on the server changes rarely.
Be sure to understand the consequences before enabling this option.
.It Cm noinet4 , noinet6 .It Cm noinet4 , noinet6
Disables Disables
.Dv AF_INET .Dv AF_INET

View File

@ -716,7 +716,7 @@ static const char *nfs_opts[] = { "from", "nfs_args",
"retrans", "acregmin", "acregmax", "acdirmin", "acdirmax", "resvport", "retrans", "acregmin", "acregmax", "acdirmin", "acdirmax", "resvport",
"readahead", "hostname", "timeout", "addr", "fh", "nfsv3", "sec", "readahead", "hostname", "timeout", "addr", "fh", "nfsv3", "sec",
"principal", "nfsv4", "gssname", "allgssname", "dirpath", "principal", "nfsv4", "gssname", "allgssname", "dirpath",
"negnametimeo", "negnametimeo", "nocto",
NULL }; NULL };
/* /*
@ -833,6 +833,8 @@ nfs_mount(struct mount *mp)
} }
if (vfs_getopt(mp->mnt_optnew, "allgssname", NULL, NULL) == 0) if (vfs_getopt(mp->mnt_optnew, "allgssname", NULL, NULL) == 0)
args.flags |= NFSMNT_ALLGSSNAME; args.flags |= NFSMNT_ALLGSSNAME;
if (vfs_getopt(mp->mnt_optnew, "nocto", NULL, NULL) == 0)
args.flags |= NFSMNT_NOCTO;
if (vfs_getopt(mp->mnt_optnew, "readdirsize", (void **)&opt, NULL) == 0) { if (vfs_getopt(mp->mnt_optnew, "readdirsize", (void **)&opt, NULL) == 0) {
if (opt == NULL) { if (opt == NULL) {
vfs_mount_error(mp, "illegal readdirsize"); vfs_mount_error(mp, "illegal readdirsize");

View File

@ -1026,7 +1026,8 @@ nfs_lookup(struct vop_lookup_args *ap)
*/ */
newvp = *vpp; newvp = *vpp;
newnp = VTONFS(newvp); newnp = VTONFS(newvp);
if ((flags & (ISLASTCN | ISOPEN)) == (ISLASTCN | ISOPEN) && if (!(nmp->nm_flag & NFSMNT_NOCTO) &&
(flags & (ISLASTCN | ISOPEN)) == (ISLASTCN | ISOPEN) &&
!(newnp->n_flag & NMODIFIED)) { !(newnp->n_flag & NMODIFIED)) {
mtx_lock(&newnp->n_mtx); mtx_lock(&newnp->n_mtx);
newnp->n_attrstamp = 0; newnp->n_attrstamp = 0;

View File

@ -112,6 +112,8 @@ nfs_parse_options(const char *envopts, struct nfs_args *nd)
nd->flags |= NFSMNT_NOCONN; nd->flags |= NFSMNT_NOCONN;
else if (strcmp(o, "nolockd") == 0) else if (strcmp(o, "nolockd") == 0)
nd->flags |= NFSMNT_NOLOCKD; nd->flags |= NFSMNT_NOLOCKD;
else if (strcmp(o, "nocto") == 0)
nd->flags |= NFSMNT_NOCTO;
else if (strcmp(o, "nfsv2") == 0) else if (strcmp(o, "nfsv2") == 0)
nd->flags &= ~(NFSMNT_NFSV3 | NFSMNT_NFSV4); nd->flags &= ~(NFSMNT_NFSV3 | NFSMNT_NFSV4);
else if (strcmp(o, "nfsv3") == 0) { else if (strcmp(o, "nfsv3") == 0) {

View File

@ -786,7 +786,7 @@ static const char *nfs_opts[] = { "from", "nfs_args",
"readahead", "readdirsize", "soft", "hard", "mntudp", "tcp", "udp", "readahead", "readdirsize", "soft", "hard", "mntudp", "tcp", "udp",
"wsize", "rsize", "retrans", "acregmin", "acregmax", "acdirmin", "wsize", "rsize", "retrans", "acregmin", "acregmax", "acdirmin",
"acdirmax", "deadthresh", "hostname", "timeout", "addr", "fh", "nfsv3", "acdirmax", "deadthresh", "hostname", "timeout", "addr", "fh", "nfsv3",
"sec", "maxgroups", "principal", "negnametimeo", "sec", "maxgroups", "principal", "negnametimeo", "nocto",
NULL }; NULL };
/* /*
@ -901,6 +901,8 @@ nfs_mount(struct mount *mp)
args.sotype = SOCK_STREAM; args.sotype = SOCK_STREAM;
if (vfs_getopt(mp->mnt_optnew, "nfsv3", NULL, NULL) == 0) if (vfs_getopt(mp->mnt_optnew, "nfsv3", NULL, NULL) == 0)
args.flags |= NFSMNT_NFSV3; args.flags |= NFSMNT_NFSV3;
if (vfs_getopt(mp->mnt_optnew, "nocto", NULL, NULL) == 0)
args.flags |= NFSMNT_NOCTO;
if (vfs_getopt(mp->mnt_optnew, "readdirsize", (void **)&opt, NULL) == 0) { if (vfs_getopt(mp->mnt_optnew, "readdirsize", (void **)&opt, NULL) == 0) {
if (opt == NULL) { if (opt == NULL) {
vfs_mount_error(mp, "illegal readdirsize"); vfs_mount_error(mp, "illegal readdirsize");

View File

@ -960,7 +960,8 @@ nfs_lookup(struct vop_lookup_args *ap)
*/ */
newvp = *vpp; newvp = *vpp;
newnp = VTONFS(newvp); newnp = VTONFS(newvp);
if ((flags & (ISLASTCN | ISOPEN)) == (ISLASTCN | ISOPEN) && if (!(nmp->nm_flag & NFSMNT_NOCTO) &&
(flags & (ISLASTCN | ISOPEN)) == (ISLASTCN | ISOPEN) &&
!(newnp->n_flag & NMODIFIED)) { !(newnp->n_flag & NMODIFIED)) {
mtx_lock(&newnp->n_mtx); mtx_lock(&newnp->n_mtx);
newnp->n_attrstamp = 0; newnp->n_attrstamp = 0;

View File

@ -97,5 +97,6 @@ struct nfs_args {
#define NFSMNT_PRIVACY 0x04000000 /* Use privacy with RPCSEC_GSS */ #define NFSMNT_PRIVACY 0x04000000 /* Use privacy with RPCSEC_GSS */
#define NFSMNT_ALLGSSNAME 0x08000000 /* Use principal for all accesses */ #define NFSMNT_ALLGSSNAME 0x08000000 /* Use principal for all accesses */
#define NFSMNT_STRICT3530 0x10000000 /* Adhere strictly to RFC3530 */ #define NFSMNT_STRICT3530 0x10000000 /* Adhere strictly to RFC3530 */
#define NFSMNT_NOCTO 0x20000000 /* Don't flush attrcache on open */
#endif #endif