svn commit: r236096 - in stable/9/sys: fs/nfsclient nfsclient
Rick Macklem
rmacklem at FreeBSD.org
Sat May 26 13:12:14 UTC 2012
Author: rmacklem
Date: Sat May 26 13:12:14 2012
New Revision: 236096
URL: http://svn.freebsd.org/changeset/base/236096
Log:
MFC: r235332
PR# 165923 reported intermittent write failures for dirty
memory mapped pages being written back on an NFS mount.
Since any thread can call VOP_PUTPAGES() to write back a
dirty page, the credentials of that thread may not have
write access to the file on an NFS server. (Often the uid
is 0, which may be mapped to "nobody" in the NFS server.)
Although there is no completely correct fix for this
(NFS servers check access on every write RPC instead of at
open/mmap time), this patch avoids the common cases by
holding onto a credential that recently opened the file
for writing and uses that credential for the write RPCs
being done by VOP_PUTPAGES() for both NFS clients.
Modified:
stable/9/sys/fs/nfsclient/nfs_clbio.c
stable/9/sys/fs/nfsclient/nfs_clnode.c
stable/9/sys/fs/nfsclient/nfs_clvnops.c
stable/9/sys/fs/nfsclient/nfsnode.h
stable/9/sys/nfsclient/nfs_bio.c
stable/9/sys/nfsclient/nfs_node.c
stable/9/sys/nfsclient/nfs_vnops.c
stable/9/sys/nfsclient/nfsnode.h
Directory Properties:
stable/9/sys/ (props changed)
stable/9/sys/amd64/include/xen/ (props changed)
stable/9/sys/boot/ (props changed)
stable/9/sys/boot/i386/efi/ (props changed)
stable/9/sys/boot/ia64/efi/ (props changed)
stable/9/sys/boot/ia64/ski/ (props changed)
stable/9/sys/boot/powerpc/boot1.chrp/ (props changed)
stable/9/sys/boot/powerpc/ofw/ (props changed)
stable/9/sys/cddl/contrib/opensolaris/ (props changed)
stable/9/sys/conf/ (props changed)
stable/9/sys/contrib/dev/acpica/ (props changed)
stable/9/sys/contrib/octeon-sdk/ (props changed)
stable/9/sys/contrib/pf/ (props changed)
stable/9/sys/contrib/x86emu/ (props changed)
stable/9/sys/dev/ (props changed)
stable/9/sys/dev/e1000/ (props changed)
stable/9/sys/dev/ixgbe/ (props changed)
stable/9/sys/fs/ (props changed)
stable/9/sys/fs/ntfs/ (props changed)
stable/9/sys/modules/ (props changed)
Modified: stable/9/sys/fs/nfsclient/nfs_clbio.c
==============================================================================
--- stable/9/sys/fs/nfsclient/nfs_clbio.c Sat May 26 12:39:23 2012 (r236095)
+++ stable/9/sys/fs/nfsclient/nfs_clbio.c Sat May 26 13:12:14 2012 (r236096)
@@ -281,7 +281,11 @@ ncl_putpages(struct vop_putpages_args *a
vp = ap->a_vp;
np = VTONFS(vp);
td = curthread; /* XXX */
- cred = curthread->td_ucred; /* XXX */
+ /* Set the cred to n_writecred for the write rpcs. */
+ if (np->n_writecred != NULL)
+ cred = crhold(np->n_writecred);
+ else
+ cred = crhold(curthread->td_ucred); /* XXX */
nmp = VFSTONFS(vp->v_mount);
pages = ap->a_m;
count = ap->a_count;
@@ -345,6 +349,7 @@ ncl_putpages(struct vop_putpages_args *a
iomode = NFSWRITE_FILESYNC;
error = ncl_writerpc(vp, &uio, cred, &iomode, &must_commit, 0);
+ crfree(cred);
pmap_qremove(kva, npages);
relpbuf(bp, &ncl_pbuf_freecnt);
Modified: stable/9/sys/fs/nfsclient/nfs_clnode.c
==============================================================================
--- stable/9/sys/fs/nfsclient/nfs_clnode.c Sat May 26 12:39:23 2012 (r236095)
+++ stable/9/sys/fs/nfsclient/nfs_clnode.c Sat May 26 13:12:14 2012 (r236096)
@@ -300,6 +300,8 @@ ncl_reclaim(struct vop_reclaim_args *ap)
FREE((caddr_t)dp2, M_NFSDIROFF);
}
}
+ if (np->n_writecred != NULL)
+ crfree(np->n_writecred);
FREE((caddr_t)np->n_fhp, M_NFSFH);
if (np->n_v4 != NULL)
FREE((caddr_t)np->n_v4, M_NFSV4NODE);
Modified: stable/9/sys/fs/nfsclient/nfs_clvnops.c
==============================================================================
--- stable/9/sys/fs/nfsclient/nfs_clvnops.c Sat May 26 12:39:23 2012 (r236095)
+++ stable/9/sys/fs/nfsclient/nfs_clvnops.c Sat May 26 13:12:14 2012 (r236096)
@@ -513,6 +513,7 @@ nfs_open(struct vop_open_args *ap)
struct vattr vattr;
int error;
int fmode = ap->a_mode;
+ struct ucred *cred;
if (vp->v_type != VREG && vp->v_type != VDIR && vp->v_type != VLNK)
return (EOPNOTSUPP);
@@ -604,7 +605,22 @@ nfs_open(struct vop_open_args *ap)
}
np->n_directio_opens++;
}
+
+ /*
+ * If this is an open for writing, capture a reference to the
+ * credentials, so they can be used by ncl_putpages(). Using
+ * these write credentials is preferable to the credentials of
+ * whatever thread happens to be doing the VOP_PUTPAGES() since
+ * the write RPCs are less likely to fail with EACCES.
+ */
+ if ((fmode & FWRITE) != 0) {
+ cred = np->n_writecred;
+ np->n_writecred = crhold(ap->a_cred);
+ } else
+ cred = NULL;
mtx_unlock(&np->n_mtx);
+ if (cred != NULL)
+ crfree(cred);
vnode_create_vobject(vp, vattr.va_size, ap->a_td);
return (0);
}
Modified: stable/9/sys/fs/nfsclient/nfsnode.h
==============================================================================
--- stable/9/sys/fs/nfsclient/nfsnode.h Sat May 26 12:39:23 2012 (r236095)
+++ stable/9/sys/fs/nfsclient/nfsnode.h Sat May 26 13:12:14 2012 (r236096)
@@ -126,6 +126,7 @@ struct nfsnode {
int n_directio_asyncwr;
u_int64_t n_change; /* old Change attribute */
struct nfsv4node *n_v4; /* extra V4 stuff */
+ struct ucred *n_writecred; /* Cred. for putpages */
};
#define n_atim n_un1.nf_atim
Modified: stable/9/sys/nfsclient/nfs_bio.c
==============================================================================
--- stable/9/sys/nfsclient/nfs_bio.c Sat May 26 12:39:23 2012 (r236095)
+++ stable/9/sys/nfsclient/nfs_bio.c Sat May 26 13:12:14 2012 (r236096)
@@ -275,7 +275,11 @@ nfs_putpages(struct vop_putpages_args *a
vp = ap->a_vp;
np = VTONFS(vp);
td = curthread; /* XXX */
- cred = curthread->td_ucred; /* XXX */
+ /* Set the cred to n_writecred for the write rpcs. */
+ if (np->n_writecred != NULL)
+ cred = crhold(np->n_writecred);
+ else
+ cred = crhold(curthread->td_ucred); /* XXX */
nmp = VFSTONFS(vp->v_mount);
pages = ap->a_m;
count = ap->a_count;
@@ -339,6 +343,7 @@ nfs_putpages(struct vop_putpages_args *a
iomode = NFSV3WRITE_FILESYNC;
error = (nmp->nm_rpcops->nr_writerpc)(vp, &uio, cred, &iomode, &must_commit);
+ crfree(cred);
pmap_qremove(kva, npages);
relpbuf(bp, &nfs_pbuf_freecnt);
Modified: stable/9/sys/nfsclient/nfs_node.c
==============================================================================
--- stable/9/sys/nfsclient/nfs_node.c Sat May 26 12:39:23 2012 (r236095)
+++ stable/9/sys/nfsclient/nfs_node.c Sat May 26 13:12:14 2012 (r236096)
@@ -270,6 +270,8 @@ nfs_reclaim(struct vop_reclaim_args *ap)
free((caddr_t)dp2, M_NFSDIROFF);
}
}
+ if (np->n_writecred != NULL)
+ crfree(np->n_writecred);
if (np->n_fhsize > NFS_SMALLFH) {
free((caddr_t)np->n_fhp, M_NFSBIGFH);
}
Modified: stable/9/sys/nfsclient/nfs_vnops.c
==============================================================================
--- stable/9/sys/nfsclient/nfs_vnops.c Sat May 26 12:39:23 2012 (r236095)
+++ stable/9/sys/nfsclient/nfs_vnops.c Sat May 26 13:12:14 2012 (r236096)
@@ -509,6 +509,7 @@ nfs_open(struct vop_open_args *ap)
struct vattr vattr;
int error;
int fmode = ap->a_mode;
+ struct ucred *cred;
if (vp->v_type != VREG && vp->v_type != VDIR && vp->v_type != VLNK)
return (EOPNOTSUPP);
@@ -565,7 +566,22 @@ nfs_open(struct vop_open_args *ap)
}
np->n_directio_opens++;
}
+
+ /*
+ * If this is an open for writing, capture a reference to the
+ * credentials, so they can be used by nfs_putpages(). Using
+ * these write credentials is preferable to the credentials of
+ * whatever thread happens to be doing the VOP_PUTPAGES() since
+ * the write RPCs are less likely to fail with EACCES.
+ */
+ if ((fmode & FWRITE) != 0) {
+ cred = np->n_writecred;
+ np->n_writecred = crhold(ap->a_cred);
+ } else
+ cred = NULL;
mtx_unlock(&np->n_mtx);
+ if (cred != NULL)
+ crfree(cred);
vnode_create_vobject(vp, vattr.va_size, ap->a_td);
return (0);
}
Modified: stable/9/sys/nfsclient/nfsnode.h
==============================================================================
--- stable/9/sys/nfsclient/nfsnode.h Sat May 26 12:39:23 2012 (r236095)
+++ stable/9/sys/nfsclient/nfsnode.h Sat May 26 13:12:14 2012 (r236096)
@@ -131,6 +131,7 @@ struct nfsnode {
uint32_t n_namelen;
int n_directio_opens;
int n_directio_asyncwr;
+ struct ucred *n_writecred; /* Cred. for putpages */
};
#define n_atim n_un1.nf_atim
More information about the svn-src-stable-9
mailing list