summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/fs/nfs/nfs_var.h2
-rw-r--r--sys/fs/nfs/nfsdport.h1
-rw-r--r--sys/fs/nfsserver/nfs_nfsdport.c78
-rw-r--r--sys/fs/nfsserver/nfs_nfsdserv.c45
-rw-r--r--sys/fs/nfsserver/nfs_nfsdsocket.c99
5 files changed, 54 insertions, 171 deletions
diff --git a/sys/fs/nfs/nfs_var.h b/sys/fs/nfs/nfs_var.h
index 782630b..2dbbdda 100644
--- a/sys/fs/nfs/nfs_var.h
+++ b/sys/fs/nfs/nfs_var.h
@@ -570,8 +570,6 @@ int nfsvno_pathconf(vnode_t, int, register_t *, struct ucred *,
NFSPROC_T *);
vnode_t nfsvno_getvp(fhandle_t *);
int nfsvno_advlock(vnode_t, int, u_int64_t, u_int64_t, NFSPROC_T *);
-void nfsvno_unlockvfs(mount_t);
-int nfsvno_lockvfs(mount_t);
int nfsrv_v4rootexport(void *, struct ucred *, NFSPROC_T *);
int nfsvno_testexp(struct nfsrv_descript *, struct nfsexstuff *);
uint32_t nfsrv_hashfh(fhandle_t *);
diff --git a/sys/fs/nfs/nfsdport.h b/sys/fs/nfs/nfsdport.h
index 4888866..a3f05db 100644
--- a/sys/fs/nfs/nfsdport.h
+++ b/sys/fs/nfs/nfsdport.h
@@ -52,7 +52,6 @@
* needs to be returned by nfsd_fhtovp().
*/
struct nfsexstuff {
- int nes_vfslocked; /* required for all ports */
int nes_exflag; /* export flags */
int nes_numsecflavor; /* # of security flavors */
int nes_secflavors[MAXSECFLAVORS]; /* and the flavors */
diff --git a/sys/fs/nfsserver/nfs_nfsdport.c b/sys/fs/nfsserver/nfs_nfsdport.c
index 8201efc..4a03f4b 100644
--- a/sys/fs/nfsserver/nfs_nfsdport.c
+++ b/sys/fs/nfsserver/nfs_nfsdport.c
@@ -332,18 +332,7 @@ nfsvno_namei(struct nfsrv_descript *nd, struct nameidata *ndp,
* In either case ni_startdir will be dereferenced and NULLed
* out.
*/
- if (exp->nes_vfslocked)
- ndp->ni_cnd.cn_flags |= GIANTHELD;
error = lookup(ndp);
- /*
- * The Giant lock should only change when
- * crossing mount points.
- */
- if (crossmnt) {
- exp->nes_vfslocked =
- (ndp->ni_cnd.cn_flags & GIANTHELD) != 0;
- ndp->ni_cnd.cn_flags &= ~GIANTHELD;
- }
if (error)
break;
@@ -2471,7 +2460,10 @@ nfsvno_fhtovp(struct mount *mp, fhandle_t *fhp, struct sockaddr *nam,
*credp = NULL;
exp->nes_numsecflavor = 0;
- error = VFS_FHTOVP(mp, &fhp->fh_fid, vpp);
+ if (VFS_NEEDSGIANT(mp))
+ error = ESTALE;
+ else
+ error = VFS_FHTOVP(mp, &fhp->fh_fid, vpp);
if (error != 0)
/* Make sure the server replies ESTALE to the client. */
error = ESTALE;
@@ -2521,19 +2513,8 @@ nfsvno_pathconf(struct vnode *vp, int flag, register_t *retf,
* - get vp and export rights by calling nfsvno_fhtovp()
* - if cred->cr_uid == 0 or MNT_EXPORTANON set it to credanon
* for AUTH_SYS
- * Also handle getting the Giant lock for the file system,
- * as required:
- * - if same mount point as *mpp
- * do nothing
- * else if *mpp == NULL
- * if already locked
- * leave it locked
- * else
- * call VFS_LOCK_GIANT()
- * else
- * if already locked
- * unlock Giant
- * call VFS_LOCK_GIANT()
+ * - if mpp != NULL, return the mount point so that it can
+ * be used for vn_finished_write() by the caller
*/
void
nfsd_fhtovp(struct nfsrv_descript *nd, struct nfsrvfh *nfp, int lktype,
@@ -2549,27 +2530,14 @@ nfsd_fhtovp(struct nfsrv_descript *nd, struct nfsrvfh *nfp, int lktype,
* Check for the special case of the nfsv4root_fh.
*/
mp = vfs_busyfs(&fhp->fh_fsid);
+ if (mpp != NULL)
+ *mpp = mp;
if (mp == NULL) {
*vpp = NULL;
nd->nd_repstat = ESTALE;
- if (*mpp && exp->nes_vfslocked)
- VFS_UNLOCK_GIANT(*mpp);
- *mpp = NULL;
- exp->nes_vfslocked = 0;
return;
}
- /*
- * Now, handle Giant for the file system.
- */
- if (*mpp != NULL && *mpp != mp && exp->nes_vfslocked) {
- VFS_UNLOCK_GIANT(*mpp);
- exp->nes_vfslocked = 0;
- }
- if (!exp->nes_vfslocked && *mpp != mp)
- exp->nes_vfslocked = VFS_LOCK_GIANT(mp);
-
- *mpp = mp;
if (startwrite)
vn_start_write(NULL, mpp, V_WAIT);
@@ -2633,12 +2601,9 @@ nfsd_fhtovp(struct nfsrv_descript *nd, struct nfsrvfh *nfp, int lktype,
if (nd->nd_repstat) {
if (startwrite)
vn_finished_write(mp);
- if (exp->nes_vfslocked) {
- VFS_UNLOCK_GIANT(mp);
- exp->nes_vfslocked = 0;
- }
*vpp = NULL;
- *mpp = NULL;
+ if (mpp != NULL)
+ *mpp = NULL;
}
}
@@ -2840,29 +2805,6 @@ nfsvno_advlock(struct vnode *vp, int ftype, u_int64_t first,
}
/*
- * Unlock an underlying local file system.
- */
-void
-nfsvno_unlockvfs(struct mount *mp)
-{
-
- VFS_UNLOCK_GIANT(mp);
-}
-
-/*
- * Lock an underlying file system, as required, and return
- * whether or not it is locked.
- */
-int
-nfsvno_lockvfs(struct mount *mp)
-{
- int ret;
-
- ret = VFS_LOCK_GIANT(mp);
- return (ret);
-}
-
-/*
* Check the nfsv4 root exports.
*/
int
diff --git a/sys/fs/nfsserver/nfs_nfsdserv.c b/sys/fs/nfsserver/nfs_nfsdserv.c
index f3eb52d..09a82b7 100644
--- a/sys/fs/nfsserver/nfs_nfsdserv.c
+++ b/sys/fs/nfsserver/nfs_nfsdserv.c
@@ -1351,7 +1351,6 @@ nfsrvd_rename(struct nfsrv_descript *nd, int isdgram,
struct nfsvattr fdirfor, fdiraft, tdirfor, tdiraft;
struct nfsexstuff tnes;
struct nfsrvfh tfh;
- mount_t mp = NULL;
char *bufp, *tbufp = NULL;
u_long *hashp;
@@ -1387,9 +1386,7 @@ nfsrvd_rename(struct nfsrv_descript *nd, int isdgram,
return (error);
}
nd->nd_cred->cr_uid = nd->nd_saveduid;
- /* Won't lock vfs if already locked, mp == NULL */
- tnes.nes_vfslocked = exp->nes_vfslocked;
- nfsd_fhtovp(nd, &tfh, LK_EXCLUSIVE, &tdp, &tnes, &mp, 0, p);
+ nfsd_fhtovp(nd, &tfh, LK_EXCLUSIVE, &tdp, &tnes, NULL, 0, p);
if (tdp) {
tdirfor_ret = nfsvno_getattr(tdp, &tdirfor, nd->nd_cred,
p, 1);
@@ -1401,12 +1398,8 @@ nfsrvd_rename(struct nfsrv_descript *nd, int isdgram,
if (!nd->nd_repstat) {
error = nfsrv_parsename(nd, tbufp, hashp, &tond.ni_pathlen);
if (error) {
- if (tdp) {
- if (tnes.nes_vfslocked && !exp->nes_vfslocked &&
- !(nd->nd_flag & ND_NFSV4))
- nfsvno_unlockvfs(mp);
+ if (tdp)
vrele(tdp);
- }
vput(dp);
nfsvno_relpathbuf(&fromnd);
nfsvno_relpathbuf(&tond);
@@ -1420,12 +1413,8 @@ nfsrvd_rename(struct nfsrv_descript *nd, int isdgram,
nfsrv_wcc(nd, tdirfor_ret, &tdirfor, tdiraft_ret,
&tdiraft);
}
- if (tdp) {
- if (tnes.nes_vfslocked && !exp->nes_vfslocked &&
- !(nd->nd_flag & ND_NFSV4))
- nfsvno_unlockvfs(mp);
+ if (tdp)
vrele(tdp);
- }
vput(dp);
nfsvno_relpathbuf(&fromnd);
nfsvno_relpathbuf(&tond);
@@ -1445,12 +1434,8 @@ nfsrvd_rename(struct nfsrv_descript *nd, int isdgram,
}
if (fdirp)
vrele(fdirp);
- if (tdp) {
- if (tnes.nes_vfslocked && !exp->nes_vfslocked &&
- !(nd->nd_flag & ND_NFSV4))
- nfsvno_unlockvfs(mp);
+ if (tdp)
vrele(tdp);
- }
nfsvno_relpathbuf(&tond);
return (0);
}
@@ -1465,9 +1450,6 @@ nfsrvd_rename(struct nfsrv_descript *nd, int isdgram,
if (tdirp)
tdiraft_ret = nfsvno_getattr(tdirp, &tdiraft, nd->nd_cred, p,
0);
- if (tnes.nes_vfslocked && !exp->nes_vfslocked &&
- !(nd->nd_flag & ND_NFSV4))
- nfsvno_unlockvfs(mp);
if (fdirp)
vrele(fdirp);
if (tdirp)
@@ -1505,7 +1487,6 @@ nfsrvd_link(struct nfsrv_descript *nd, int isdgram,
struct nfsvattr dirfor, diraft, at;
struct nfsexstuff tnes;
struct nfsrvfh dfh;
- mount_t mp = NULL;
char *bufp;
u_long *hashp;
@@ -1541,9 +1522,7 @@ nfsrvd_link(struct nfsrv_descript *nd, int isdgram,
/* tovp is always NULL unless NFSv4 */
return (error);
}
- /* Won't lock vfs if already locked, mp == NULL */
- tnes.nes_vfslocked = exp->nes_vfslocked;
- nfsd_fhtovp(nd, &dfh, LK_EXCLUSIVE, &dp, &tnes, &mp, 0,
+ nfsd_fhtovp(nd, &dfh, LK_EXCLUSIVE, &dp, &tnes, NULL, 0,
p);
if (dp)
NFSVOPUNLOCK(dp, 0, p);
@@ -1556,12 +1535,8 @@ nfsrvd_link(struct nfsrv_descript *nd, int isdgram,
error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen);
if (error) {
vrele(vp);
- if (dp) {
- if (tnes.nes_vfslocked && !exp->nes_vfslocked &&
- !(nd->nd_flag & ND_NFSV4))
- nfsvno_unlockvfs(mp);
+ if (dp)
vrele(dp);
- }
nfsvno_relpathbuf(&named);
return (error);
}
@@ -1591,9 +1566,6 @@ nfsrvd_link(struct nfsrv_descript *nd, int isdgram,
diraft_ret = nfsvno_getattr(dirp, &diraft, nd->nd_cred, p, 0);
vrele(dirp);
}
- if (tnes.nes_vfslocked && !exp->nes_vfslocked &&
- !(nd->nd_flag & ND_NFSV4))
- nfsvno_unlockvfs(mp);
vrele(vp);
if (nd->nd_flag & ND_NFSV3) {
nfsrv_postopattr(nd, getret, &at);
@@ -3101,7 +3073,6 @@ nfsrvd_secinfo(struct nfsrv_descript *nd, int isdgram,
vnode_t dirp = NULL, vp;
struct nfsrvfh fh;
struct nfsexstuff retnes;
- mount_t mp;
u_int32_t *sizp;
int error, savflag, i;
char *bufp;
@@ -3134,12 +3105,10 @@ nfsrvd_secinfo(struct nfsrv_descript *nd, int isdgram,
fh.nfsrvfh_len = NFSX_MYFH;
vp = named.ni_vp;
nd->nd_repstat = nfsvno_getfh(vp, (fhandle_t *)fh.nfsrvfh_data, p);
- mp = vnode_mount(vp); /* so it won't try to re-lock filesys */
- retnes.nes_vfslocked = exp->nes_vfslocked;
vput(vp);
savflag = nd->nd_flag;
if (!nd->nd_repstat) {
- nfsd_fhtovp(nd, &fh, LK_SHARED, &vp, &retnes, &mp, 0, p);
+ nfsd_fhtovp(nd, &fh, LK_SHARED, &vp, &retnes, NULL, 0, p);
if (vp)
vput(vp);
}
diff --git a/sys/fs/nfsserver/nfs_nfsdsocket.c b/sys/fs/nfsserver/nfs_nfsdsocket.c
index ebee570..eeecded 100644
--- a/sys/fs/nfsserver/nfs_nfsdsocket.c
+++ b/sys/fs/nfsserver/nfs_nfsdsocket.c
@@ -386,7 +386,6 @@ nfsrvd_dorpc(struct nfsrv_descript *nd, int isdgram,
lktype = LK_SHARED;
else
lktype = LK_EXCLUSIVE;
- nes.nes_vfslocked = 0;
if (nd->nd_flag & ND_PUBLOOKUP)
nfsd_fhtovp(nd, &nfs_pubfh, lktype, &vp, &nes,
&mp, nfs_writerpc[nd->nd_procnum], p);
@@ -415,12 +414,8 @@ nfsrvd_dorpc(struct nfsrv_descript *nd, int isdgram,
if (nd->nd_repstat && (nd->nd_flag & ND_NFSV2)) {
*nd->nd_errp = nfsd_errmap(nd);
NFSINCRGLOBAL(newnfsstats.srvrpccnt[nfsv3to4op[nd->nd_procnum]]);
- if (mp != NULL) {
- if (nfs_writerpc[nd->nd_procnum])
- NFS_ENDWRITE(mp);
- if (nes.nes_vfslocked)
- nfsvno_unlockvfs(mp);
- }
+ if (mp != NULL && nfs_writerpc[nd->nd_procnum] != 0)
+ vn_finished_write(mp);
return;
}
@@ -445,12 +440,8 @@ nfsrvd_dorpc(struct nfsrv_descript *nd, int isdgram,
error = (*(nfsrv3_procs0[nd->nd_procnum]))(nd, isdgram,
vp, p, &nes);
}
- if (mp) {
- if (nfs_writerpc[nd->nd_procnum])
- NFS_ENDWRITE(mp);
- if (nes.nes_vfslocked)
- nfsvno_unlockvfs(mp);
- }
+ if (mp != NULL && nfs_writerpc[nd->nd_procnum] != 0)
+ vn_finished_write(mp);
NFSINCRGLOBAL(newnfsstats.srvrpccnt[nfsv3to4op[nd->nd_procnum]]);
}
if (error) {
@@ -498,9 +489,10 @@ nfsrvd_compound(struct nfsrv_descript *nd, int isdgram,
u_char tag[NFSV4_SMALLSTR + 1], *tagstr;
vnode_t vp, nvp, savevp;
struct nfsrvfh fh;
- mount_t mp, savemp, temp_mp = NULL;
+ mount_t new_mp, temp_mp = NULL;
struct ucred *credanon;
struct nfsexstuff nes, vpnes, savevpnes;
+ fsid_t cur_fsid, save_fsid;
static u_int64_t compref = 0;
NFSVNO_EXINIT(&vpnes);
@@ -597,8 +589,8 @@ nfsrvd_compound(struct nfsrv_descript *nd, int isdgram,
}
savevp = vp = NULL;
- savevpnes.nes_vfslocked = vpnes.nes_vfslocked = 0;
- savemp = mp = NULL;
+ save_fsid.val[0] = save_fsid.val[1] = 0;
+ cur_fsid.val[0] = cur_fsid.val[1] = 0;
NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
taglen = fxdr_unsigned(int, *tl);
if (taglen < 0) {
@@ -704,46 +696,44 @@ nfsrvd_compound(struct nfsrv_descript *nd, int isdgram,
error = nfsrv_mtofh(nd, &fh);
if (error)
goto nfsmout;
- if (!nd->nd_repstat) {
- nes.nes_vfslocked = vpnes.nes_vfslocked;
- nfsd_fhtovp(nd, &fh, LK_SHARED, &nvp, &nes, &mp,
- 0, p);
- }
+ if (!nd->nd_repstat)
+ nfsd_fhtovp(nd, &fh, LK_SHARED, &nvp, &nes,
+ NULL, 0, p);
/* For now, allow this for non-export FHs */
if (!nd->nd_repstat) {
if (vp)
vrele(vp);
vp = nvp;
- NFSVOPUNLOCK(vp, 0, p);
+ cur_fsid = vp->v_mount->mnt_stat.f_fsid;
+ VOP_UNLOCK(vp, 0);
vpnes = nes;
}
break;
case NFSV4OP_PUTPUBFH:
- if (nfs_pubfhset) {
- nes.nes_vfslocked = vpnes.nes_vfslocked;
+ if (nfs_pubfhset)
nfsd_fhtovp(nd, &nfs_pubfh, LK_SHARED, &nvp,
- &nes, &mp, 0, p);
- } else {
+ &nes, NULL, 0, p);
+ else
nd->nd_repstat = NFSERR_NOFILEHANDLE;
- }
if (!nd->nd_repstat) {
if (vp)
vrele(vp);
vp = nvp;
- NFSVOPUNLOCK(vp, 0, p);
+ cur_fsid = vp->v_mount->mnt_stat.f_fsid;
+ VOP_UNLOCK(vp, 0);
vpnes = nes;
}
break;
case NFSV4OP_PUTROOTFH:
if (nfs_rootfhset) {
- nes.nes_vfslocked = vpnes.nes_vfslocked;
nfsd_fhtovp(nd, &nfs_rootfh, LK_SHARED, &nvp,
- &nes, &mp, 0, p);
+ &nes, NULL, 0, p);
if (!nd->nd_repstat) {
if (vp)
vrele(vp);
vp = nvp;
- NFSVOPUNLOCK(vp, 0, p);
+ cur_fsid = vp->v_mount->mnt_stat.f_fsid;
+ VOP_UNLOCK(vp, 0);
vpnes = nes;
}
} else
@@ -759,7 +749,7 @@ nfsrvd_compound(struct nfsrv_descript *nd, int isdgram,
VREF(vp);
savevp = vp;
savevpnes = vpnes;
- savemp = mp;
+ save_fsid = cur_fsid;
}
} else {
nd->nd_repstat = NFSERR_NOFILEHANDLE;
@@ -771,23 +761,10 @@ nfsrvd_compound(struct nfsrv_descript *nd, int isdgram,
/* If vp == savevp, a no-op */
if (vp != savevp) {
VREF(savevp);
- if (mp == NULL || savemp == NULL)
- panic("nfscmpmp");
- if (!savevpnes.nes_vfslocked &&
- vpnes.nes_vfslocked) {
- if (mp == savemp)
- panic("nfscmp2");
- nfsvno_unlockvfs(mp);
- } else if (savevpnes.nes_vfslocked &&
- !vpnes.nes_vfslocked) {
- if (mp == savemp)
- panic("nfscmp3");
- savevpnes.nes_vfslocked = nfsvno_lockvfs(savemp);
- }
vrele(vp);
vp = savevp;
vpnes = savevpnes;
- mp = savemp;
+ cur_fsid = save_fsid;
}
} else {
nd->nd_repstat = NFSERR_RESTOREFH;
@@ -841,11 +818,14 @@ nfsrvd_compound(struct nfsrv_descript *nd, int isdgram,
error = (*(nfsrv4_ops1[op]))(nd, isdgram, vp,
&nvp, (fhandle_t *)fh.nfsrvfh_data, p, &vpnes);
if (!error && !nd->nd_repstat) {
- if (vfs_statfs(mp)->f_fsid.val[0] !=
- vfs_statfs(vnode_mount(nvp))->f_fsid.val[0] ||
- vfs_statfs(mp)->f_fsid.val[1] !=
- vfs_statfs(vnode_mount(nvp))->f_fsid.val[1]) {
- nd->nd_repstat = nfsvno_checkexp(vnode_mount(nvp),
+ if (op == NFSV4OP_LOOKUP || op == NFSV4OP_LOOKUPP) {
+ new_mp = nvp->v_mount;
+ if (cur_fsid.val[0] !=
+ new_mp->mnt_stat.f_fsid.val[0] ||
+ cur_fsid.val[1] !=
+ new_mp->mnt_stat.f_fsid.val[1]) {
+ /* crossed a server mount point */
+ nd->nd_repstat = nfsvno_checkexp(new_mp,
nd->nd_nam, &nes, &credanon);
if (!nd->nd_repstat)
nd->nd_repstat = nfsd_excred(nd,
@@ -853,17 +833,13 @@ nfsrvd_compound(struct nfsrv_descript *nd, int isdgram,
if (credanon != NULL)
crfree(credanon);
if (!nd->nd_repstat) {
- if (vpnes.nes_vfslocked)
- nfsvno_unlockvfs(mp);
- mp = vnode_mount(nvp);
vpnes = nes;
- vpnes.nes_vfslocked =
- nfsvno_lockvfs(mp);
+ cur_fsid = new_mp->mnt_stat.f_fsid;
}
+ }
+ /* Lookup ops return a locked vnode */
+ VOP_UNLOCK(nvp, 0);
}
- if (op == NFSV4OP_LOOKUP || op == NFSV4OP_LOOKUPP)
- /* Lookup ops return a locked vnode */
- VOP_UNLOCK(nvp, 0);
if (!nd->nd_repstat) {
vrele(vp);
vp = nvp;
@@ -876,7 +852,8 @@ nfsrvd_compound(struct nfsrv_descript *nd, int isdgram,
if (vp == NULL || savevp == NULL) {
nd->nd_repstat = NFSERR_NOFILEHANDLE;
break;
- } else if (mp != savemp) {
+ } else if (cur_fsid.val[0] != save_fsid.val[0] ||
+ cur_fsid.val[1] != save_fsid.val[1]) {
nd->nd_repstat = NFSERR_XDEV;
break;
}
@@ -960,8 +937,6 @@ nfsmout:
} else {
*retopsp = txdr_unsigned(retops);
}
- if (mp && vpnes.nes_vfslocked)
- nfsvno_unlockvfs(mp);
if (vp)
vrele(vp);
if (savevp)
OpenPOWER on IntegriCloud