diff options
-rw-r--r-- | sys/fs/nfs/nfs_var.h | 2 | ||||
-rw-r--r-- | sys/fs/nfs/nfsdport.h | 1 | ||||
-rw-r--r-- | sys/fs/nfsserver/nfs_nfsdport.c | 78 | ||||
-rw-r--r-- | sys/fs/nfsserver/nfs_nfsdserv.c | 45 | ||||
-rw-r--r-- | sys/fs/nfsserver/nfs_nfsdsocket.c | 99 |
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) |