diff options
Diffstat (limited to 'sys/fs/nfsserver')
-rw-r--r-- | sys/fs/nfsserver/nfs_nfsdport.c | 24 | ||||
-rw-r--r-- | sys/fs/nfsserver/nfs_nfsdserv.c | 7 | ||||
-rw-r--r-- | sys/fs/nfsserver/nfs_nfsdsocket.c | 50 |
3 files changed, 51 insertions, 30 deletions
diff --git a/sys/fs/nfsserver/nfs_nfsdport.c b/sys/fs/nfsserver/nfs_nfsdport.c index 4b18cbb..beedfef 100644 --- a/sys/fs/nfsserver/nfs_nfsdport.c +++ b/sys/fs/nfsserver/nfs_nfsdport.c @@ -180,7 +180,7 @@ nfsvno_accchk(struct vnode *vp, accmode_t accmode, struct ucred *cred, return (ETXTBSY); } if (vpislocked == 0) - NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY, p); + vn_lock(vp, LK_SHARED | LK_RETRY); /* * Should the override still be applied when ACLs are enabled? @@ -218,7 +218,7 @@ nfsvno_accchk(struct vnode *vp, accmode_t accmode, struct ucred *cred, } } if (vpislocked == 0) - NFSVOPUNLOCK(vp, 0, p); + VOP_UNLOCK(vp, 0); return (error); } @@ -1916,7 +1916,7 @@ again: if (refp == NULL) { if (usevget) r = VFS_VGET(vp->v_mount, - dp->d_fileno, LK_EXCLUSIVE, + dp->d_fileno, LK_SHARED, &nvp); else r = EOPNOTSUPP; @@ -1925,7 +1925,7 @@ again: usevget = 0; cn.cn_nameiop = LOOKUP; cn.cn_lkflags = - LK_EXCLUSIVE | + LK_SHARED | LK_RETRY; cn.cn_cred = nd->nd_cred; @@ -1941,7 +1941,7 @@ again: dp->d_name[1] == '.') cn.cn_flags |= ISDOTDOT; - if (vn_lock(vp, LK_EXCLUSIVE) + if (vn_lock(vp, LK_SHARED) != 0) { nd->nd_repstat = EPERM; break; @@ -2454,7 +2454,8 @@ nfsvno_checkexp(struct mount *mp, struct sockaddr *nam, struct nfsexstuff *exp, */ int nfsvno_fhtovp(struct mount *mp, fhandle_t *fhp, struct sockaddr *nam, - struct vnode **vpp, struct nfsexstuff *exp, struct ucred **credp) + int lktype, struct vnode **vpp, struct nfsexstuff *exp, + struct ucred **credp) { int i, error, *secflavors; @@ -2481,6 +2482,13 @@ nfsvno_fhtovp(struct mount *mp, fhandle_t *fhp, struct sockaddr *nam, exp->nes_secflavors[i] = secflavors[i]; } } + if (error == 0 && lktype == LK_SHARED) + /* + * It would be much better to pass lktype to VFS_FHTOVP(), + * but this will have to do until VFS_FHTOVP() has a lock + * type argument like VFS_VGET(). + */ + vn_lock(*vpp, LK_DOWNGRADE | LK_RETRY); return (error); } @@ -2518,7 +2526,7 @@ nfsvno_pathconf(struct vnode *vp, int flag, register_t *retf, * call VFS_LOCK_GIANT() */ void -nfsd_fhtovp(struct nfsrv_descript *nd, struct nfsrvfh *nfp, +nfsd_fhtovp(struct nfsrv_descript *nd, struct nfsrvfh *nfp, int lktype, struct vnode **vpp, struct nfsexstuff *exp, struct mount **mpp, int startwrite, struct thread *p) { @@ -2555,7 +2563,7 @@ nfsd_fhtovp(struct nfsrv_descript *nd, struct nfsrvfh *nfp, if (startwrite) vn_start_write(NULL, mpp, V_WAIT); - nd->nd_repstat = nfsvno_fhtovp(mp, fhp, nd->nd_nam, vpp, exp, + nd->nd_repstat = nfsvno_fhtovp(mp, fhp, nd->nd_nam, lktype, vpp, exp, &credanon); /* diff --git a/sys/fs/nfsserver/nfs_nfsdserv.c b/sys/fs/nfsserver/nfs_nfsdserv.c index e4976f5..b4a4126 100644 --- a/sys/fs/nfsserver/nfs_nfsdserv.c +++ b/sys/fs/nfsserver/nfs_nfsdserv.c @@ -1392,7 +1392,7 @@ nfsrvd_rename(struct nfsrv_descript *nd, int isdgram, 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, &tdp, &tnes, &mp, 0, p); + nfsd_fhtovp(nd, &tfh, LK_EXCLUSIVE, &tdp, &tnes, &mp, 0, p); if (tdp) { tdirfor_ret = nfsvno_getattr(tdp, &tdirfor, nd->nd_cred, p, 1); @@ -1546,7 +1546,8 @@ nfsrvd_link(struct nfsrv_descript *nd, int isdgram, } /* Won't lock vfs if already locked, mp == NULL */ tnes.nes_vfslocked = exp->nes_vfslocked; - nfsd_fhtovp(nd, &dfh, &dp, &tnes, &mp, 0, p); + nfsd_fhtovp(nd, &dfh, LK_EXCLUSIVE, &dp, &tnes, &mp, 0, + p); if (dp) NFSVOPUNLOCK(dp, 0, p); } @@ -3141,7 +3142,7 @@ nfsrvd_secinfo(struct nfsrv_descript *nd, int isdgram, vput(vp); savflag = nd->nd_flag; if (!nd->nd_repstat) { - nfsd_fhtovp(nd, &fh, &vp, &retnes, &mp, 0, p); + nfsd_fhtovp(nd, &fh, LK_SHARED, &vp, &retnes, &mp, 0, p); if (vp) vput(vp); } diff --git a/sys/fs/nfsserver/nfs_nfsdsocket.c b/sys/fs/nfsserver/nfs_nfsdsocket.c index af1a3fa..8917e92 100644 --- a/sys/fs/nfsserver/nfs_nfsdsocket.c +++ b/sys/fs/nfsserver/nfs_nfsdsocket.c @@ -354,7 +354,7 @@ APPLESTATIC void nfsrvd_dorpc(struct nfsrv_descript *nd, int isdgram, NFSPROC_T *p) { - int error = 0; + int error = 0, lktype; vnode_t vp; mount_t mp = NULL; struct nfsrvfh fh; @@ -380,12 +380,20 @@ nfsrvd_dorpc(struct nfsrv_descript *nd, int isdgram, nd->nd_repstat = NFSERR_GARBAGE; return; } + if (nd->nd_procnum == NFSPROC_READ || + nd->nd_procnum == NFSPROC_READDIR || + nd->nd_procnum == NFSPROC_READLINK || + nd->nd_procnum == NFSPROC_GETATTR || + nd->nd_procnum == NFSPROC_ACCESS) + lktype = LK_SHARED; + else + lktype = LK_EXCLUSIVE; nes.nes_vfslocked = 0; if (nd->nd_flag & ND_PUBLOOKUP) - nfsd_fhtovp(nd, &nfs_pubfh, &vp, &nes, + nfsd_fhtovp(nd, &nfs_pubfh, lktype, &vp, &nes, &mp, nfs_writerpc[nd->nd_procnum], p); else - nfsd_fhtovp(nd, &fh, &vp, &nes, + nfsd_fhtovp(nd, &fh, lktype, &vp, &nes, &mp, nfs_writerpc[nd->nd_procnum], p); if (nd->nd_repstat == NFSERR_PROGNOTV4) return; @@ -700,7 +708,7 @@ nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, goto nfsmout; if (!nd->nd_repstat) { nes.nes_vfslocked = vpnes.nes_vfslocked; - nfsd_fhtovp(nd, &fh, &nvp, &nes, &mp, + nfsd_fhtovp(nd, &fh, LK_SHARED, &nvp, &nes, &mp, 0, p); } /* For now, allow this for non-export FHs */ @@ -715,7 +723,7 @@ nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, case NFSV4OP_PUTPUBFH: if (nfs_pubfhset) { nes.nes_vfslocked = vpnes.nes_vfslocked; - nfsd_fhtovp(nd, &nfs_pubfh, &nvp, + nfsd_fhtovp(nd, &nfs_pubfh, LK_SHARED, &nvp, &nes, &mp, 0, p); } else { nd->nd_repstat = NFSERR_NOFILEHANDLE; @@ -731,7 +739,7 @@ nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, case NFSV4OP_PUTROOTFH: if (nfs_rootfhset) { nes.nes_vfslocked = vpnes.nes_vfslocked; - nfsd_fhtovp(nd, &nfs_rootfh, &nvp, + nfsd_fhtovp(nd, &nfs_rootfh, LK_SHARED, &nvp, &nes, &mp, 0, p); if (!nd->nd_repstat) { if (vp) @@ -907,24 +915,28 @@ nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, if (nfsv4_opflag[op].retfh != 0) panic("nfsrvd_compound"); if (nfsv4_opflag[op].needscfh) { - if (vp) { - VREF(vp); - if (nfsv4_opflag[op].modifyfs) - NFS_STARTWRITE(NULL, &mp); - NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY, p); - } else { + if (vp != NULL) { + if (vn_lock(vp, nfsv4_opflag[op].lktype) + != 0) + nd->nd_repstat = NFSERR_PERM; + } else nd->nd_repstat = NFSERR_NOFILEHANDLE; + if (nd->nd_repstat != 0) { if (op == NFSV4OP_SETATTR) { - /* - * Setattr reply requires a bitmap - * even for errors like these. - */ - NFSM_BUILD(tl, u_int32_t *, - NFSX_UNSIGNED); - *tl = 0; + /* + * Setattr reply requires a + * bitmap even for errors like + * these. + */ + NFSM_BUILD(tl, u_int32_t *, + NFSX_UNSIGNED); + *tl = 0; } break; } + VREF(vp); + if (nfsv4_opflag[op].modifyfs) + NFS_STARTWRITE(NULL, &mp); error = (*(nfsrv4_ops0[op]))(nd, isdgram, vp, p, &vpnes); if (nfsv4_opflag[op].modifyfs) |