summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/fs/nfsclient/nfs_clbio.c7
-rw-r--r--sys/fs/nfsclient/nfs_clnode.c2
-rw-r--r--sys/fs/nfsclient/nfs_clvnops.c16
-rw-r--r--sys/fs/nfsclient/nfsnode.h1
-rw-r--r--sys/nfsclient/nfs_bio.c7
-rw-r--r--sys/nfsclient/nfs_node.c2
-rw-r--r--sys/nfsclient/nfs_vnops.c16
-rw-r--r--sys/nfsclient/nfsnode.h1
8 files changed, 50 insertions, 2 deletions
diff --git a/sys/fs/nfsclient/nfs_clbio.c b/sys/fs/nfsclient/nfs_clbio.c
index a160d37..fa9636b 100644
--- a/sys/fs/nfsclient/nfs_clbio.c
+++ b/sys/fs/nfsclient/nfs_clbio.c
@@ -281,7 +281,11 @@ ncl_putpages(struct vop_putpages_args *ap)
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 *ap)
iomode = NFSWRITE_FILESYNC;
error = ncl_writerpc(vp, &uio, cred, &iomode, &must_commit, 0);
+ crfree(cred);
pmap_qremove(kva, npages);
relpbuf(bp, &ncl_pbuf_freecnt);
diff --git a/sys/fs/nfsclient/nfs_clnode.c b/sys/fs/nfsclient/nfs_clnode.c
index 21de25e..db3a350 100644
--- a/sys/fs/nfsclient/nfs_clnode.c
+++ b/sys/fs/nfsclient/nfs_clnode.c
@@ -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);
diff --git a/sys/fs/nfsclient/nfs_clvnops.c b/sys/fs/nfsclient/nfs_clvnops.c
index 0687d6c..12e018c 100644
--- a/sys/fs/nfsclient/nfs_clvnops.c
+++ b/sys/fs/nfsclient/nfs_clvnops.c
@@ -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);
}
diff --git a/sys/fs/nfsclient/nfsnode.h b/sys/fs/nfsclient/nfsnode.h
index f2992c9..209945a 100644
--- a/sys/fs/nfsclient/nfsnode.h
+++ b/sys/fs/nfsclient/nfsnode.h
@@ -123,6 +123,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
diff --git a/sys/nfsclient/nfs_bio.c b/sys/nfsclient/nfs_bio.c
index 90fe96e..2ffd822 100644
--- a/sys/nfsclient/nfs_bio.c
+++ b/sys/nfsclient/nfs_bio.c
@@ -275,7 +275,11 @@ nfs_putpages(struct vop_putpages_args *ap)
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 *ap)
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);
diff --git a/sys/nfsclient/nfs_node.c b/sys/nfsclient/nfs_node.c
index afe3341..3805f6c 100644
--- a/sys/nfsclient/nfs_node.c
+++ b/sys/nfsclient/nfs_node.c
@@ -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);
}
diff --git a/sys/nfsclient/nfs_vnops.c b/sys/nfsclient/nfs_vnops.c
index 872317b..ca9edad 100644
--- a/sys/nfsclient/nfs_vnops.c
+++ b/sys/nfsclient/nfs_vnops.c
@@ -507,6 +507,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);
@@ -563,7 +564,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);
}
diff --git a/sys/nfsclient/nfsnode.h b/sys/nfsclient/nfsnode.h
index 60e5613..c6fa73e 100644
--- a/sys/nfsclient/nfsnode.h
+++ b/sys/nfsclient/nfsnode.h
@@ -128,6 +128,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
OpenPOWER on IntegriCloud