summaryrefslogtreecommitdiffstats
path: root/sys/nfsclient
diff options
context:
space:
mode:
authormohans <mohans@FreeBSD.org>2006-09-13 18:39:09 +0000
committermohans <mohans@FreeBSD.org>2006-09-13 18:39:09 +0000
commit21daa650a97ea27eb3fdf3915832cb2c1e49aa4f (patch)
treeecb7983045b3f7e892ee6bce4b4f36f4080332f4 /sys/nfsclient
parente751eb98323de041fcb2da0c3b6973368e75da67 (diff)
downloadFreeBSD-src-21daa650a97ea27eb3fdf3915832cb2c1e49aa4f.zip
FreeBSD-src-21daa650a97ea27eb3fdf3915832cb2c1e49aa4f.tar.gz
Fixes up the handling of shared vnode lock lookups in the NFS client,
adds a FS type specific flag indicating that the FS supports shared vnode lock lookups, adds some logic in vfs_lookup.c to test this flag and set lock flags appropriately. - amd on 6.x is a non-starter (without this change). Using amd under heavy load results in a deadlock (with cascading vnode locks all the way to the root) very quickly. - This change should also fix the more general problem of cascading vnode deadlocks when an NFS server goes down. Ideally, we wouldn't need these changes, as enabling shared vnode lock lookups globally would work. Unfortunately, UFS, for example isn't ready for shared vnode lock lookups, crashing pretty quickly. This change is the result of discussions with Stephan Uphoff (ups@). Reviewed by: ups@
Diffstat (limited to 'sys/nfsclient')
-rw-r--r--sys/nfsclient/nfs_node.c6
-rw-r--r--sys/nfsclient/nfs_subs.c2
-rw-r--r--sys/nfsclient/nfs_vfsops.c8
-rw-r--r--sys/nfsclient/nfs_vnops.c10
-rw-r--r--sys/nfsclient/nfsnode.h2
5 files changed, 14 insertions, 14 deletions
diff --git a/sys/nfsclient/nfs_node.c b/sys/nfsclient/nfs_node.c
index 7edf2dd..ebf453f 100644
--- a/sys/nfsclient/nfs_node.c
+++ b/sys/nfsclient/nfs_node.c
@@ -99,7 +99,7 @@ nfs_vncmpf(struct vnode *vp, void *arg)
* nfsnode structure is returned.
*/
int
-nfs_nget(struct mount *mntp, nfsfh_t *fhp, int fhsize, struct nfsnode **npp)
+nfs_nget(struct mount *mntp, nfsfh_t *fhp, int fhsize, struct nfsnode **npp, int flags)
{
struct thread *td = curthread; /* XXX */
struct nfsnode *np;
@@ -117,7 +117,7 @@ nfs_nget(struct mount *mntp, nfsfh_t *fhp, int fhsize, struct nfsnode **npp)
ncmp.fhsize = fhsize;
ncmp.fh = fhp;
- error = vfs_hash_get(mntp, hash, LK_EXCLUSIVE,
+ error = vfs_hash_get(mntp, hash, flags,
td, &nvp, nfs_vncmpf, &ncmp);
if (error)
return (error);
@@ -153,7 +153,7 @@ nfs_nget(struct mount *mntp, nfsfh_t *fhp, int fhsize, struct nfsnode **npp)
*/
vp->v_vnlock->lk_flags |= LK_CANRECURSE;
vp->v_vnlock->lk_flags &= ~LK_NOSHARE;
- error = vfs_hash_insert(vp, hash, LK_EXCLUSIVE,
+ error = vfs_hash_insert(vp, hash, flags,
td, &nvp, nfs_vncmpf, &ncmp);
if (error)
return (error);
diff --git a/sys/nfsclient/nfs_subs.c b/sys/nfsclient/nfs_subs.c
index 8556b3c..92dd32e 100644
--- a/sys/nfsclient/nfs_subs.c
+++ b/sys/nfsclient/nfs_subs.c
@@ -930,7 +930,7 @@ nfsm_mtofh_xx(struct vnode *d, struct vnode **v, int v3, int *f,
t1 = nfsm_getfh_xx(&ttfhp, &ttfhsize, (v3), md, dpos);
if (t1 != 0)
return t1;
- t1 = nfs_nget(d->v_mount, ttfhp, ttfhsize, &ttnp);
+ t1 = nfs_nget(d->v_mount, ttfhp, ttfhsize, &ttnp, LK_EXCLUSIVE);
if (t1 != 0)
return t1;
*v = NFSTOV(ttnp);
diff --git a/sys/nfsclient/nfs_vfsops.c b/sys/nfsclient/nfs_vfsops.c
index 6a29da8..480a5d6 100644
--- a/sys/nfsclient/nfs_vfsops.c
+++ b/sys/nfsclient/nfs_vfsops.c
@@ -254,7 +254,7 @@ nfs_statfs(struct mount *mp, struct statfs *sbp, struct thread *td)
error = vfs_busy(mp, LK_NOWAIT, NULL, td);
if (error)
return (error);
- error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np);
+ error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np, LK_EXCLUSIVE);
if (error) {
vfs_unbusy(mp, td);
return (error);
@@ -785,7 +785,7 @@ nfs_mount(struct mount *mp, struct thread *td)
error = mountnfs(&args, mp, nam, hst, &vp, td->td_ucred);
out:
if (!error)
- mp->mnt_kern_flag |= MNTK_MPSAFE;
+ mp->mnt_kern_flag |= (MNTK_MPSAFE|MNTK_LOOKUP_SHARED);
return (error);
}
@@ -913,7 +913,7 @@ mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
* this problem, because one can identify root inodes by their
* number == ROOTINO (2).
*/
- error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np);
+ error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np, LK_EXCLUSIVE);
if (error)
goto bad;
*vpp = NFSTOV(np);
@@ -995,7 +995,7 @@ nfs_root(struct mount *mp, int flags, struct vnode **vpp, struct thread *td)
int error;
nmp = VFSTONFS(mp);
- error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np);
+ error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np, flags);
if (error)
return error;
vp = NFSTOV(np);
diff --git a/sys/nfsclient/nfs_vnops.c b/sys/nfsclient/nfs_vnops.c
index b6ad271..e073de9 100644
--- a/sys/nfsclient/nfs_vnops.c
+++ b/sys/nfsclient/nfs_vnops.c
@@ -899,7 +899,7 @@ nfs_lookup(struct vop_lookup_args *ap)
m_freem(mrep);
return (EISDIR);
}
- error = nfs_nget(dvp->v_mount, fhp, fhsize, &np);
+ error = nfs_nget(dvp->v_mount, fhp, fhsize, &np, LK_EXCLUSIVE);
if (error) {
m_freem(mrep);
return (error);
@@ -918,7 +918,7 @@ nfs_lookup(struct vop_lookup_args *ap)
if (flags & ISDOTDOT) {
VOP_UNLOCK(dvp, 0, td);
- error = nfs_nget(dvp->v_mount, fhp, fhsize, &np);
+ error = nfs_nget(dvp->v_mount, fhp, fhsize, &np, cnp->cn_lkflags);
vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, td);
if (error)
return (error);
@@ -927,7 +927,7 @@ nfs_lookup(struct vop_lookup_args *ap)
VREF(dvp);
newvp = dvp;
} else {
- error = nfs_nget(dvp->v_mount, fhp, fhsize, &np);
+ error = nfs_nget(dvp->v_mount, fhp, fhsize, &np, cnp->cn_lkflags);
if (error) {
m_freem(mrep);
return (error);
@@ -2410,7 +2410,7 @@ nfs_readdirplusrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred)
np = dnp;
} else {
error = nfs_nget(vp->v_mount, fhp,
- fhsize, &np);
+ fhsize, &np, LK_EXCLUSIVE);
if (error)
doit = 0;
else
@@ -2604,7 +2604,7 @@ nfs_lookitup(struct vnode *dvp, const char *name, int len, struct ucred *cred,
VREF(dvp);
newvp = dvp;
} else {
- error = nfs_nget(dvp->v_mount, nfhp, fhlen, &np);
+ error = nfs_nget(dvp->v_mount, nfhp, fhlen, &np, LK_EXCLUSIVE);
if (error) {
m_freem(mrep);
return (error);
diff --git a/sys/nfsclient/nfsnode.h b/sys/nfsclient/nfsnode.h
index e03e97c..2287235 100644
--- a/sys/nfsclient/nfsnode.h
+++ b/sys/nfsclient/nfsnode.h
@@ -189,7 +189,7 @@ int nfs_reclaim(struct vop_reclaim_args *);
/* other stuff */
int nfs_removeit(struct sillyrename *);
int nfs4_removeit(struct sillyrename *);
-int nfs_nget(struct mount *, nfsfh_t *, int, struct nfsnode **);
+int nfs_nget(struct mount *, nfsfh_t *, int, struct nfsnode **, int flags);
nfsuint64 *nfs_getcookie(struct nfsnode *, off_t, int);
uint64_t *nfs4_getcookie(struct nfsnode *, off_t, int);
void nfs_invaldir(struct vnode *);
OpenPOWER on IntegriCloud