summaryrefslogtreecommitdiffstats
path: root/sys/fs/nfsserver/nfs_nfsdport.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/fs/nfsserver/nfs_nfsdport.c')
-rw-r--r--sys/fs/nfsserver/nfs_nfsdport.c32
1 files changed, 19 insertions, 13 deletions
diff --git a/sys/fs/nfsserver/nfs_nfsdport.c b/sys/fs/nfsserver/nfs_nfsdport.c
index 09f410c..4b18cbb 100644
--- a/sys/fs/nfsserver/nfs_nfsdport.c
+++ b/sys/fs/nfsserver/nfs_nfsdport.c
@@ -100,18 +100,24 @@ static struct nfsheur {
*/
int
nfsvno_getattr(struct vnode *vp, struct nfsvattr *nvap, struct ucred *cred,
- struct thread *p)
+ struct thread *p, int vpislocked)
{
int error, lockedit = 0;
- /* Since FreeBSD insists the vnode be locked... */
- if (VOP_ISLOCKED(vp) != LK_EXCLUSIVE) {
- lockedit = 1;
- NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY, p);
+ if (vpislocked == 0) {
+ /*
+ * When vpislocked == 0, the vnode is either exclusively
+ * locked by this thread or not locked by this thread.
+ * As such, shared lock it, if not exclusively locked.
+ */
+ if (VOP_ISLOCKED(vp) != LK_EXCLUSIVE) {
+ lockedit = 1;
+ vn_lock(vp, LK_SHARED | LK_RETRY);
+ }
}
error = VOP_GETATTR(vp, &nvap->na_vattr, cred);
- if (lockedit)
- NFSVOPUNLOCK(vp, 0, p);
+ if (lockedit != 0)
+ VOP_UNLOCK(vp, 0);
return (error);
}
@@ -1375,7 +1381,7 @@ nfsvno_updfilerev(struct vnode *vp, struct nfsvattr *nvap,
VATTR_NULL(&va);
getnanotime(&va.va_mtime);
(void) VOP_SETATTR(vp, &va, cred);
- (void) nfsvno_getattr(vp, nvap, cred, p);
+ (void) nfsvno_getattr(vp, nvap, cred, p, 1);
}
/*
@@ -1456,7 +1462,7 @@ nfsrvd_readdir(struct nfsrv_descript *nd, int isdgram,
fullsiz = siz;
if (nd->nd_flag & ND_NFSV3) {
nd->nd_repstat = getret = nfsvno_getattr(vp, &at, nd->nd_cred,
- p);
+ p, 1);
#if 0
/*
* va_filerev is not sufficient as a cookie verifier,
@@ -1512,7 +1518,7 @@ again:
if (!cookies && !nd->nd_repstat)
nd->nd_repstat = NFSERR_PERM;
if (nd->nd_flag & ND_NFSV3) {
- getret = nfsvno_getattr(vp, &at, nd->nd_cred, p);
+ getret = nfsvno_getattr(vp, &at, nd->nd_cred, p, 1);
if (!nd->nd_repstat)
nd->nd_repstat = getret;
}
@@ -1723,7 +1729,7 @@ nfsrvd_readdirplus(struct nfsrv_descript *nd, int isdgram,
NFSZERO_ATTRBIT(&attrbits);
}
fullsiz = siz;
- nd->nd_repstat = getret = nfsvno_getattr(vp, &at, nd->nd_cred, p);
+ nd->nd_repstat = getret = nfsvno_getattr(vp, &at, nd->nd_cred, p, 1);
if (!nd->nd_repstat) {
if (off && verf != at.na_filerev) {
/*
@@ -1782,7 +1788,7 @@ again:
if (io.uio_resid)
siz -= io.uio_resid;
- getret = nfsvno_getattr(vp, &at, nd->nd_cred, p);
+ getret = nfsvno_getattr(vp, &at, nd->nd_cred, p, 1);
if (!cookies && !nd->nd_repstat)
nd->nd_repstat = NFSERR_PERM;
@@ -1958,7 +1964,7 @@ again:
r = nfsvno_getfh(nvp, &nfh, p);
if (!r)
r = nfsvno_getattr(nvp, nvap,
- nd->nd_cred, p);
+ nd->nd_cred, p, 1);
}
} else {
nvp = NULL;
OpenPOWER on IntegriCloud