From owner-svn-src-stable@FreeBSD.ORG Fri Apr 29 18:17:01 2011 Return-Path: Delivered-To: svn-src-stable@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id BFF4E106564A; Fri, 29 Apr 2011 18:17:01 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id ADE8C8FC17; Fri, 29 Apr 2011 18:17:01 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id p3TIH1Cq009761; Fri, 29 Apr 2011 18:17:01 GMT (envelope-from rmacklem@svn.freebsd.org) Received: (from rmacklem@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id p3TIH1ix009753; Fri, 29 Apr 2011 18:17:01 GMT (envelope-from rmacklem@svn.freebsd.org) Message-Id: <201104291817.p3TIH1ix009753@svn.freebsd.org> From: Rick Macklem Date: Fri, 29 Apr 2011 18:17:01 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org X-SVN-Group: stable-8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r221213 - in stable/8/sys/fs: nfs nfsclient nfsserver X-BeenThere: svn-src-stable@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for all the -stable branches of the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 29 Apr 2011 18:17:01 -0000 Author: rmacklem Date: Fri Apr 29 18:17:01 2011 New Revision: 221213 URL: http://svn.freebsd.org/changeset/base/221213 Log: MFC: r220645 Modify the experimental NFSv4 server so that it handles crossing of server mount points properly. The functions nfsvno_fillattr() and nfsv4_fillattr() were modified to take the extra arguments that are the mount point, a flag to indicate that it is a file system root and the mounted on fileno. The mount point argument needs to be busy when nfsvno_fillattr() is called, since the vp argument is not locked. Modified: stable/8/sys/fs/nfs/nfs_commonsubs.c stable/8/sys/fs/nfs/nfs_var.h stable/8/sys/fs/nfsclient/nfs_clport.c stable/8/sys/fs/nfsclient/nfs_clrpcops.c stable/8/sys/fs/nfsclient/nfs_clstate.c stable/8/sys/fs/nfsserver/nfs_nfsdport.c stable/8/sys/fs/nfsserver/nfs_nfsdserv.c Directory Properties: stable/8/sys/ (props changed) stable/8/sys/amd64/include/xen/ (props changed) stable/8/sys/cddl/contrib/opensolaris/ (props changed) stable/8/sys/contrib/dev/acpica/ (props changed) stable/8/sys/contrib/pf/ (props changed) Modified: stable/8/sys/fs/nfs/nfs_commonsubs.c ============================================================================== --- stable/8/sys/fs/nfs/nfs_commonsubs.c Fri Apr 29 17:57:35 2011 (r221212) +++ stable/8/sys/fs/nfs/nfs_commonsubs.c Fri Apr 29 18:17:01 2011 (r221213) @@ -1916,9 +1916,10 @@ nfsrv_mtostr(struct nfsrv_descript *nd, * Fill in the attributes as marked by the bitmap (V4). */ APPLESTATIC int -nfsv4_fillattr(struct nfsrv_descript *nd, vnode_t vp, NFSACL_T *saclp, - struct vattr *vap, fhandle_t *fhp, int rderror, nfsattrbit_t *attrbitp, - struct ucred *cred, NFSPROC_T *p, int isdgram, int reterr) +nfsv4_fillattr(struct nfsrv_descript *nd, struct mount *mp, vnode_t vp, + NFSACL_T *saclp, struct vattr *vap, fhandle_t *fhp, int rderror, + nfsattrbit_t *attrbitp, struct ucred *cred, NFSPROC_T *p, int isdgram, + int reterr, int at_root, uint64_t mounted_on_fileno) { int bitpos, retnum = 0; u_int32_t *tl; @@ -1928,7 +1929,6 @@ nfsv4_fillattr(struct nfsrv_descript *nd nfsattrbit_t *retbitp = &retbits; u_int32_t freenum, *retnump; u_int64_t uquad; - long fid; struct statfs fs; struct nfsfsinfo fsinf; struct timespec temptime; @@ -1958,7 +1958,7 @@ nfsv4_fillattr(struct nfsrv_descript *nd * Get the VFS_STATFS(), since some attributes need them. */ if (NFSISSETSTATFS_ATTRBIT(retbitp)) { - error = VFS_STATFS(vnode_mount(vp), &fs); + error = VFS_STATFS(mp, &fs); if (error != 0) { if (reterr) { nd->nd_repstat = NFSERR_ACCES; @@ -1974,12 +1974,12 @@ nfsv4_fillattr(struct nfsrv_descript *nd */ if (NFSISSET_ATTRBIT(retbitp, NFSATTRBIT_ACLSUPPORT) && (nfsrv_useacl == 0 || ((cred != NULL || p != NULL) && - !NFSHASNFS4ACL(vnode_mount(vp))))) { + !NFSHASNFS4ACL(mp)))) { NFSCLRBIT_ATTRBIT(retbitp, NFSATTRBIT_ACLSUPPORT); } if (NFSISSET_ATTRBIT(retbitp, NFSATTRBIT_ACL)) { if (nfsrv_useacl == 0 || ((cred != NULL || p != NULL) && - !NFSHASNFS4ACL(vnode_mount(vp)))) { + !NFSHASNFS4ACL(mp))) { NFSCLRBIT_ATTRBIT(retbitp, NFSATTRBIT_ACL); } else if (naclp != NULL) { if (vn_lock(vp, LK_SHARED) == 0) { @@ -2016,7 +2016,7 @@ nfsv4_fillattr(struct nfsrv_descript *nd case NFSATTRBIT_SUPPORTEDATTRS: NFSSETSUPP_ATTRBIT(&attrbits); if (nfsrv_useacl == 0 || ((cred != NULL || p != NULL) - && !NFSHASNFS4ACL(vnode_mount(vp)))) { + && !NFSHASNFS4ACL(mp))) { NFSCLRBIT_ATTRBIT(&attrbits,NFSATTRBIT_ACLSUPPORT); NFSCLRBIT_ATTRBIT(&attrbits,NFSATTRBIT_ACL); } @@ -2066,9 +2066,9 @@ nfsv4_fillattr(struct nfsrv_descript *nd case NFSATTRBIT_FSID: NFSM_BUILD(tl, u_int32_t *, NFSX_V4FSID); *tl++ = 0; - *tl++=txdr_unsigned(vfs_statfs(vnode_mount(vp))->f_fsid.val[0]); + *tl++ = txdr_unsigned(mp->mnt_stat.f_fsid.val[0]); *tl++ = 0; - *tl=txdr_unsigned(vfs_statfs(vnode_mount(vp))->f_fsid.val[1]); + *tl = txdr_unsigned(mp->mnt_stat.f_fsid.val[1]); retnum += NFSX_V4FSID; break; case NFSATTRBIT_UNIQUEHANDLES: @@ -2142,7 +2142,7 @@ nfsv4_fillattr(struct nfsrv_descript *nd */ savuid = p->p_cred->p_ruid; p->p_cred->p_ruid = cred->cr_uid; - if (!VFS_QUOTACTL(vnode_mount(vp),QCMD(Q_GETQUOTA,USRQUOTA), + if (!VFS_QUOTACTL(mp, QCMD(Q_GETQUOTA,USRQUOTA), cred->cr_uid, (caddr_t)&dqb)) freenum = min(dqb.dqb_isoftlimit-dqb.dqb_curinodes, freenum); @@ -2249,7 +2249,7 @@ nfsv4_fillattr(struct nfsrv_descript *nd */ savuid = p->p_cred->p_ruid; p->p_cred->p_ruid = cred->cr_uid; - if (!VFS_QUOTACTL(vnode_mount(vp),QCMD(Q_GETQUOTA,USRQUOTA), + if (!VFS_QUOTACTL(mp, QCMD(Q_GETQUOTA,USRQUOTA), cred->cr_uid, (caddr_t)&dqb)) freenum = min(dqb.dqb_bhardlimit, freenum); p->p_cred->p_ruid = savuid; @@ -2273,7 +2273,7 @@ nfsv4_fillattr(struct nfsrv_descript *nd */ savuid = p->p_cred->p_ruid; p->p_cred->p_ruid = cred->cr_uid; - if (!VFS_QUOTACTL(vnode_mount(vp),QCMD(Q_GETQUOTA,USRQUOTA), + if (!VFS_QUOTACTL(mp, QCMD(Q_GETQUOTA,USRQUOTA), cred->cr_uid, (caddr_t)&dqb)) freenum = min(dqb.dqb_bsoftlimit, freenum); p->p_cred->p_ruid = savuid; @@ -2294,7 +2294,7 @@ nfsv4_fillattr(struct nfsrv_descript *nd */ savuid = p->p_cred->p_ruid; p->p_cred->p_ruid = cred->cr_uid; - if (!VFS_QUOTACTL(vnode_mount(vp),QCMD(Q_GETQUOTA,USRQUOTA), + if (!VFS_QUOTACTL(mp, QCMD(Q_GETQUOTA,USRQUOTA), cred->cr_uid, (caddr_t)&dqb)) freenum = dqb.dqb_curblocks; p->p_cred->p_ruid = savuid; @@ -2390,11 +2390,11 @@ nfsv4_fillattr(struct nfsrv_descript *nd break; case NFSATTRBIT_MOUNTEDONFILEID: NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER); - *tl++ = 0; - if (nfsrv_atroot(vp, &fid)) - *tl = txdr_unsigned(fid); + if (at_root != 0) + uquad = mounted_on_fileno; else - *tl = txdr_unsigned(vap->va_fileid); + uquad = (u_int64_t)vap->va_fileid; + txdr_hyper(uquad, tl); retnum += NFSX_HYPER; break; default: Modified: stable/8/sys/fs/nfs/nfs_var.h ============================================================================== --- stable/8/sys/fs/nfs/nfs_var.h Fri Apr 29 17:57:35 2011 (r221212) +++ stable/8/sys/fs/nfs/nfs_var.h Fri Apr 29 18:17:01 2011 (r221213) @@ -288,9 +288,9 @@ int nfsrv_mtofh(struct nfsrv_descript *, int nfsrv_putattrbit(struct nfsrv_descript *, nfsattrbit_t *); void nfsrv_wcc(struct nfsrv_descript *, int, struct nfsvattr *, int, struct nfsvattr *); -int nfsv4_fillattr(struct nfsrv_descript *, vnode_t, NFSACL_T *, +int nfsv4_fillattr(struct nfsrv_descript *, struct mount *, vnode_t, NFSACL_T *, struct vattr *, fhandle_t *, int, nfsattrbit_t *, - struct ucred *, NFSPROC_T *, int, int); + struct ucred *, NFSPROC_T *, int, int, int, uint64_t); void nfsrv_fillattr(struct nfsrv_descript *, struct nfsvattr *); void nfsrv_adj(mbuf_t, int, int); void nfsrv_postopattr(struct nfsrv_descript *, int, struct nfsvattr *); @@ -556,9 +556,9 @@ void nfsvno_open(struct nfsrv_descript * struct nfsexstuff *, vnode_t *); void nfsvno_updfilerev(vnode_t, struct nfsvattr *, struct ucred *, NFSPROC_T *); -int nfsvno_fillattr(struct nfsrv_descript *, vnode_t, +int nfsvno_fillattr(struct nfsrv_descript *, struct mount *, vnode_t, struct nfsvattr *, fhandle_t *, int, nfsattrbit_t *, - struct ucred *, NFSPROC_T *, int, int); + struct ucred *, NFSPROC_T *, int, int, int, uint64_t); int nfsrv_sattr(struct nfsrv_descript *, struct nfsvattr *, nfsattrbit_t *, NFSACL_T *, NFSPROC_T *); int nfsv4_sattr(struct nfsrv_descript *, struct nfsvattr *, nfsattrbit_t *, Modified: stable/8/sys/fs/nfsclient/nfs_clport.c ============================================================================== --- stable/8/sys/fs/nfsclient/nfs_clport.c Fri Apr 29 17:57:35 2011 (r221212) +++ stable/8/sys/fs/nfsclient/nfs_clport.c Fri Apr 29 18:17:01 2011 (r221213) @@ -803,8 +803,8 @@ nfscl_fillsattr(struct nfsrv_descript *n NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_TIMEACCESSSET); if (vap->va_mtime.tv_sec != VNOVAL) NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_TIMEMODIFYSET); - (void) nfsv4_fillattr(nd, vp, NULL, vap, NULL, 0, &attrbits, - NULL, NULL, 0, 0); + (void) nfsv4_fillattr(nd, vp->v_mount, vp, NULL, vap, NULL, 0, + &attrbits, NULL, NULL, 0, 0, 0, (uint64_t)0); break; }; } Modified: stable/8/sys/fs/nfsclient/nfs_clrpcops.c ============================================================================== --- stable/8/sys/fs/nfsclient/nfs_clrpcops.c Fri Apr 29 17:57:35 2011 (r221212) +++ stable/8/sys/fs/nfsclient/nfs_clrpcops.c Fri Apr 29 18:17:01 2011 (r221213) @@ -4176,8 +4176,8 @@ nfsrpc_setaclrpc(vnode_t vp, struct ucre nfsm_stateidtom(nd, stateidp, NFSSTATEID_PUTSTATEID); NFSZERO_ATTRBIT(&attrbits); NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_ACL); - (void) nfsv4_fillattr(nd, vp, aclp, NULL, NULL, 0, &attrbits, - NULL, NULL, 0, 0); + (void) nfsv4_fillattr(nd, vnode_mount(vp), vp, aclp, NULL, NULL, 0, + &attrbits, NULL, NULL, 0, 0, 0, (uint64_t)0); error = nfscl_request(nd, vp, p, cred, stuff); if (error) return (error); Modified: stable/8/sys/fs/nfsclient/nfs_clstate.c ============================================================================== --- stable/8/sys/fs/nfsclient/nfs_clstate.c Fri Apr 29 17:57:35 2011 (r221212) +++ stable/8/sys/fs/nfsclient/nfs_clstate.c Fri Apr 29 18:17:01 2011 (r221213) @@ -3061,8 +3061,9 @@ nfscl_docb(struct nfsrv_descript *nd, NF NFSSETBIT_ATTRBIT(&rattrbits, NFSATTRBIT_CHANGE); } - (void) nfsv4_fillattr(nd, NULL, NULL, &va, - NULL, 0, &rattrbits, NULL, NULL, 0, 0); + (void) nfsv4_fillattr(nd, NULL, NULL, NULL, &va, + NULL, 0, &rattrbits, NULL, NULL, 0, 0, 0, + (uint64_t)0); if (!ret) vrele(vp); } Modified: stable/8/sys/fs/nfsserver/nfs_nfsdport.c ============================================================================== --- stable/8/sys/fs/nfsserver/nfs_nfsdport.c Fri Apr 29 17:57:35 2011 (r221212) +++ stable/8/sys/fs/nfsserver/nfs_nfsdport.c Fri Apr 29 18:17:01 2011 (r221213) @@ -68,15 +68,15 @@ static uint32_t nfsv4_sysid = 0; static int nfssvc_srvcall(struct thread *, struct nfssvc_args *, struct ucred *); -static int enable_crossmntpt = 1; +int nfsrv_enable_crossmntpt = 1; static int nfs_commit_blks; static int nfs_commit_miss; extern int nfsrv_issuedelegs; extern int nfsrv_dolocallocks; SYSCTL_DECL(_vfs_newnfs); -SYSCTL_INT(_vfs_newnfs, OID_AUTO, mirrormnt, CTLFLAG_RW, &enable_crossmntpt, - 0, "Enable nfsd to cross mount points"); +SYSCTL_INT(_vfs_newnfs, OID_AUTO, mirrormnt, CTLFLAG_RW, + &nfsrv_enable_crossmntpt, 0, "Enable nfsd to cross mount points"); SYSCTL_INT(_vfs_newnfs, OID_AUTO, commit_blks, CTLFLAG_RW, &nfs_commit_blks, 0, ""); SYSCTL_INT(_vfs_newnfs, OID_AUTO, commit_miss, CTLFLAG_RW, &nfs_commit_miss, @@ -306,12 +306,12 @@ nfsvno_namei(struct nfsrv_descript *nd, dp = rootvnode; VREF(dp); } - } else if ((enable_crossmntpt == 0 && NFSVNO_EXPORTED(exp)) || + } else if ((nfsrv_enable_crossmntpt == 0 && NFSVNO_EXPORTED(exp)) || (nd->nd_flag & ND_NFSV4) == 0) { /* * Only cross mount points for NFSv4 when doing a * mount while traversing the file system above - * the mount point, unless enable_crossmntpt is set. + * the mount point, unless nfsrv_enable_crossmntpt is set. */ cnp->cn_flags |= NOCROSSMOUNT; crossmnt = 0; @@ -1391,14 +1391,15 @@ nfsvno_updfilerev(struct vnode *vp, stru * Glue routine to nfsv4_fillattr(). */ int -nfsvno_fillattr(struct nfsrv_descript *nd, struct vnode *vp, +nfsvno_fillattr(struct nfsrv_descript *nd, struct mount *mp, struct vnode *vp, struct nfsvattr *nvap, fhandle_t *fhp, int rderror, nfsattrbit_t *attrbitp, - struct ucred *cred, struct thread *p, int isdgram, int reterr) + struct ucred *cred, struct thread *p, int isdgram, int reterr, int at_root, + uint64_t mounted_on_fileno) { int error; - error = nfsv4_fillattr(nd, vp, NULL, &nvap->na_vattr, fhp, rderror, - attrbitp, cred, p, isdgram, reterr); + error = nfsv4_fillattr(nd, mp, vp, NULL, &nvap->na_vattr, fhp, rderror, + attrbitp, cred, p, isdgram, reterr, at_root, mounted_on_fileno); return (error); } @@ -1688,8 +1689,9 @@ nfsrvd_readdirplus(struct nfsrv_descript struct uio io; struct iovec iv; struct componentname cn; - int not_zfs; - struct mount *mp; + int at_root, needs_unbusy, not_zfs; + struct mount *mp, *new_mp; + uint64_t mounted_on_fileno; if (nd->nd_repstat) { nfsrv_postopattr(nd, getret, &at); @@ -1929,6 +1931,10 @@ again: nvp = NULL; refp = NULL; r = 0; + at_root = 0; + needs_unbusy = 0; + new_mp = mp; + mounted_on_fileno = (uint64_t)dp->d_fileno; if ((nd->nd_flag & ND_NFSV3) || NFSNONZERO_ATTRBIT(&savbits)) { if (nd->nd_flag & ND_NFSV4) @@ -1980,6 +1986,29 @@ again: 0); } } + + /* + * For NFSv4, check to see if nvp is + * a mount point and get the mount + * point vnode, as required. + */ + if (r == 0 && + nfsrv_enable_crossmntpt != 0 && + (nd->nd_flag & ND_NFSV4) != 0 && + nvp->v_type == VDIR && + nvp->v_mountedhere != NULL) { + new_mp = nvp->v_mountedhere; + r = vfs_busy(new_mp, 0); + vput(nvp); + nvp = NULL; + if (r == 0) { + r = VFS_ROOT(new_mp, + LK_SHARED, &nvp); + needs_unbusy = 1; + if (r == 0) + at_root = 1; + } + } } if (!r) { if (refp == NULL && @@ -1998,6 +2027,8 @@ again: NFSATTRBIT_RDATTRERROR)) { if (nvp != NULL) vput(nvp); + if (needs_unbusy != 0) + vfs_unbusy(new_mp); nd->nd_repstat = r; break; } @@ -2036,21 +2067,27 @@ again: if (nd->nd_repstat) { if (nvp != NULL) vrele(nvp); + if (needs_unbusy != 0) + vfs_unbusy(new_mp); break; } } else if (r) { - dirlen += nfsvno_fillattr(nd, nvp, nvap, - &nfh, r, &rderrbits, nd->nd_cred, - p, isdgram, 0); + dirlen += nfsvno_fillattr(nd, new_mp, + nvp, nvap, &nfh, r, &rderrbits, + nd->nd_cred, p, isdgram, 0, at_root, + mounted_on_fileno); } else { - dirlen += nfsvno_fillattr(nd, nvp, nvap, - &nfh, r, &attrbits, nd->nd_cred, - p, isdgram, 0); + dirlen += nfsvno_fillattr(nd, new_mp, + nvp, nvap, &nfh, r, &attrbits, + nd->nd_cred, p, isdgram, 0, at_root, + mounted_on_fileno); } if (nvp != NULL) vrele(nvp); dirlen += (3 * NFSX_UNSIGNED); } + if (needs_unbusy != 0) + vfs_unbusy(new_mp); if (dirlen <= cnt) entrycnt++; } Modified: stable/8/sys/fs/nfsserver/nfs_nfsdserv.c ============================================================================== --- stable/8/sys/fs/nfsserver/nfs_nfsdserv.c Fri Apr 29 17:57:35 2011 (r221212) +++ stable/8/sys/fs/nfsserver/nfs_nfsdserv.c Fri Apr 29 18:17:01 2011 (r221213) @@ -52,6 +52,7 @@ extern u_int32_t newnfs_false, newnfs_tr extern enum vtype nv34tov_type[8]; extern struct timeval nfsboottime; extern int nfs_rootfhset; +extern int nfsrv_enable_crossmntpt; #endif /* !APPLEKEXT */ /* @@ -169,9 +170,13 @@ nfsrvd_getattr(struct nfsrv_descript *nd { struct nfsvattr nva; fhandle_t fh; - int error = 0; + int at_root = 0, error = 0; struct nfsreferral *refp; nfsattrbit_t attrbits; + struct mount *mp; + struct vnode *tvp = NULL; + struct vattr va; + uint64_t mounted_on_fileno = 0; if (nd->nd_repstat) return (0); @@ -207,11 +212,46 @@ nfsrvd_getattr(struct nfsrv_descript *nd if (!nd->nd_repstat) nd->nd_repstat = nfsrv_checkgetattr(nd, vp, &nva, &attrbits, nd->nd_cred, p); - NFSVOPUNLOCK(vp, 0, p); - if (!nd->nd_repstat) - (void) nfsvno_fillattr(nd, vp, &nva, &fh, - 0, &attrbits, nd->nd_cred, p, isdgram, 1); - vrele(vp); + if (nd->nd_repstat == 0) { + mp = vp->v_mount; + if (nfsrv_enable_crossmntpt != 0 && + vp->v_type == VDIR && + (vp->v_vflag & VV_ROOT) != 0 && + vp != rootvnode) { + tvp = mp->mnt_vnodecovered; + VREF(tvp); + at_root = 1; + } else + at_root = 0; + vfs_ref(mp); + VOP_UNLOCK(vp, 0); + if (at_root != 0) { + if ((nd->nd_repstat = + vn_lock(tvp, LK_SHARED)) == 0) { + nd->nd_repstat = VOP_GETATTR( + tvp, &va, nd->nd_cred); + vput(tvp); + } else + vrele(tvp); + if (nd->nd_repstat == 0) + mounted_on_fileno = (uint64_t) + va.va_fileid; + else + at_root = 0; + } + if (nd->nd_repstat == 0) + nd->nd_repstat = vfs_busy(mp, 0); + vfs_rel(mp); + if (nd->nd_repstat == 0) { + (void)nfsvno_fillattr(nd, mp, vp, &nva, + &fh, 0, &attrbits, nd->nd_cred, p, + isdgram, 1, at_root, + mounted_on_fileno); + vfs_unbusy(mp); + } + vrele(vp); + } else + vput(vp); } else { nfsrv_fillattr(nd, &nva); vput(vp);