Date: Thu, 26 Aug 2010 23:41:40 +0000 (UTC) From: Pawel Jakub Dawidek <pjd@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r211854 - head/sys/nfsserver Message-ID: <201008262341.o7QNfeR2057181@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: pjd Date: Thu Aug 26 23:41:40 2010 New Revision: 211854 URL: http://svn.freebsd.org/changeset/base/211854 Log: - When VFS_VGET() is not supported, switch to VOP_LOOKUP(). - We are fine by only share-locking the vnode. - Remove assertion that doesn't hold for ZFS where we cross mount points boundaries by going into .zfs/snapshot/<name>/. Reviewed by: rmacklem MFC after: 1 month Modified: head/sys/nfsserver/nfs_serv.c Modified: head/sys/nfsserver/nfs_serv.c ============================================================================== --- head/sys/nfsserver/nfs_serv.c Thu Aug 26 23:33:04 2010 (r211853) +++ head/sys/nfsserver/nfs_serv.c Thu Aug 26 23:41:40 2010 (r211854) @@ -3041,7 +3041,8 @@ nfsrv_readdirplus(struct nfsrv_descript u_quad_t off, toff, verf; u_long *cookies = NULL, *cookiep; /* needs to be int64_t or off_t */ int v3 = (nfsd->nd_flag & ND_NFSV3); - int vfslocked; + int usevget = 1, vfslocked; + struct componentname cn; nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); vfslocked = 0; @@ -3186,28 +3187,6 @@ again: goto again; } - /* - * Probe one of the directory entries to see if the filesystem - * supports VGET. - */ - error = VFS_VGET(vp->v_mount, dp->d_fileno, LK_EXCLUSIVE, &nvp); - if (error) { - if (error == EOPNOTSUPP) - error = NFSERR_NOTSUPP; - else - error = NFSERR_SERVERFAULT; - vrele(vp); - vp = NULL; - free((caddr_t)cookies, M_TEMP); - free((caddr_t)rbuf, M_TEMP); - nfsm_reply(NFSX_V3POSTOPATTR); - nfsm_srvpostop_attr(getret, &at); - error = 0; - goto nfsmout; - } - vput(nvp); - nvp = NULL; - dirlen = len = NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF + 2 * NFSX_UNSIGNED; nfsm_reply(cnt); @@ -3224,23 +3203,49 @@ again: nlen = dp->d_namlen; rem = nfsm_rndup(nlen)-nlen; - /* - * For readdir_and_lookup get the vnode using - * the file number. - */ - if (VFS_VGET(vp->v_mount, dp->d_fileno, LK_EXCLUSIVE, - &nvp)) - goto invalid; + if (usevget) { + /* + * For readdir_and_lookup get the vnode using + * the file number. + */ + error = VFS_VGET(vp->v_mount, dp->d_fileno, + LK_SHARED, &nvp); + if (error != 0 && error != EOPNOTSUPP) { + error = 0; + goto invalid; + } else if (error == EOPNOTSUPP) { + /* + * VFS_VGET() not supported? + * Let's switch to VOP_LOOKUP(). + */ + error = 0; + usevget = 0; + cn.cn_nameiop = LOOKUP; + cn.cn_flags = ISLASTCN | NOFOLLOW | \ + LOCKSHARED | LOCKLEAF | MPSAFE; + cn.cn_lkflags = LK_SHARED | LK_RETRY; + cn.cn_cred = cred; + cn.cn_thread = curthread; + } + } + if (!usevget) { + cn.cn_nameptr = dp->d_name; + cn.cn_namelen = dp->d_namlen; + if (dp->d_namlen == 2 && + dp->d_name[0] == '.' && + dp->d_name[1] == '.') { + cn.cn_flags |= ISDOTDOT; + } else { + cn.cn_flags &= ~ISDOTDOT; + } + if (!VOP_ISLOCKED(vp)) + vn_lock(vp, LK_SHARED | LK_RETRY); + if (VOP_LOOKUP(vp, &nvp, &cn) != 0) + goto invalid; + } + bzero((caddr_t)nfhp, NFSX_V3FH); - nfhp->fh_fsid = - nvp->v_mount->mnt_stat.f_fsid; - /* - * XXXRW: Assert the mountpoints are the same so that - * we know that acquiring Giant based on the - * directory is the right thing for the child. - */ - KASSERT(nvp->v_mount == vp->v_mount, - ("nfsrv_readdirplus: nvp mount != vp mount")); + nfhp->fh_fsid = nvp->v_mount->mnt_stat.f_fsid; if (VOP_VPTOFH(nvp, &nfhp->fh_fid)) { vput(nvp); nvp = NULL; @@ -3336,7 +3341,10 @@ invalid: cookiep++; ncookies--; } - vrele(vp); + if (!usevget && VOP_ISLOCKED(vp)) + vput(vp); + else + vrele(vp); vp = NULL; nfsm_clget; *tl = nfsrv_nfs_false;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201008262341.o7QNfeR2057181>