From owner-svn-src-head@freebsd.org  Mon May 16 06:40:53 2016
Return-Path: <owner-svn-src-head@freebsd.org>
Delivered-To: svn-src-head@mailman.ysv.freebsd.org
Received: from mx1.freebsd.org (mx1.freebsd.org
 [IPv6:2001:1900:2254:206a::19:1])
 by mailman.ysv.freebsd.org (Postfix) with ESMTP id 42ED4B3D77E;
 Mon, 16 May 2016 06:40:53 +0000 (UTC) (envelope-from avg@FreeBSD.org)
Received: from repo.freebsd.org (repo.freebsd.org
 [IPv6:2610:1c1:1:6068::e6a:0])
 (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
 (Client did not present a certificate)
 by mx1.freebsd.org (Postfix) with ESMTPS id EC117110A;
 Mon, 16 May 2016 06:40:52 +0000 (UTC) (envelope-from avg@FreeBSD.org)
Received: from repo.freebsd.org ([127.0.1.37])
 by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id u4G6eqH6063932;
 Mon, 16 May 2016 06:40:52 GMT (envelope-from avg@FreeBSD.org)
Received: (from avg@localhost)
 by repo.freebsd.org (8.15.2/8.15.2/Submit) id u4G6eqtT063931;
 Mon, 16 May 2016 06:40:52 GMT (envelope-from avg@FreeBSD.org)
Message-Id: <201605160640.u4G6eqtT063931@repo.freebsd.org>
X-Authentication-Warning: repo.freebsd.org: avg set sender to avg@FreeBSD.org
 using -f
From: Andriy Gapon <avg@FreeBSD.org>
Date: Mon, 16 May 2016 06:40:52 +0000 (UTC)
To: src-committers@freebsd.org, svn-src-all@freebsd.org,
 svn-src-head@freebsd.org
Subject: svn commit: r299906 -
 head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs
X-SVN-Group: head
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
X-BeenThere: svn-src-head@freebsd.org
X-Mailman-Version: 2.1.22
Precedence: list
List-Id: SVN commit messages for the src tree for head/-current
 <svn-src-head.freebsd.org>
List-Unsubscribe: <https://lists.freebsd.org/mailman/options/svn-src-head>,
 <mailto:svn-src-head-request@freebsd.org?subject=unsubscribe>
List-Archive: <http://lists.freebsd.org/pipermail/svn-src-head/>
List-Post: <mailto:svn-src-head@freebsd.org>
List-Help: <mailto:svn-src-head-request@freebsd.org?subject=help>
List-Subscribe: <https://lists.freebsd.org/mailman/listinfo/svn-src-head>,
 <mailto:svn-src-head-request@freebsd.org?subject=subscribe>
X-List-Received-Date: Mon, 16 May 2016 06:40:53 -0000

Author: avg
Date: Mon May 16 06:40:51 2016
New Revision: 299906
URL: https://svnweb.freebsd.org/changeset/base/299906

Log:
  add zfs_vptocnp with special handling for snapshots under .zfs
  
  The logic is similar to that already present in zfs_dirlook() to handle
  a dot-dot lookup on a root vnode of a snapshot mounted under
  .zfs/snapshot/.
  illumos does not have an equivalent of vop_vptocnp, so there only the
  lookup had to be patched up.
  
  MFC after:	4 weeks

Modified:
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c	Mon May 16 06:40:17 2016	(r299905)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c	Mon May 16 06:40:51 2016	(r299906)
@@ -7160,6 +7160,44 @@ zfs_freebsd_aclcheck(ap)
 	return (EOPNOTSUPP);
 }
 
+static int
+zfs_vptocnp(struct vop_vptocnp_args *ap)
+{
+	vnode_t *covered_vp;
+	vnode_t *vp = ap->a_vp;;
+	zfsvfs_t *zfsvfs = vp->v_vfsp->vfs_data;
+	znode_t *zp = VTOZ(vp);
+	uint64_t parent;
+	int ltype;
+	int error;
+
+	/*
+	 * If we are a snapshot mounted under .zfs, run the operation
+	 * on the covered vnode.
+	 */
+	if ((error = sa_lookup(zp->z_sa_hdl,
+	    SA_ZPL_PARENT(zfsvfs), &parent, sizeof (parent))) != 0)
+		return (error);
+
+	if (zp->z_id != parent || zfsvfs->z_parent == zfsvfs)
+		return (vop_stdvptocnp(ap));
+
+	covered_vp = vp->v_mount->mnt_vnodecovered;
+	vhold(covered_vp);
+	ltype = VOP_ISLOCKED(vp);
+	VOP_UNLOCK(vp, 0);
+	error = vget(covered_vp, LK_EXCLUSIVE | LK_VNHELD, curthread);
+	if (error == 0) {
+		error = VOP_VPTOCNP(covered_vp, ap->a_vpp, ap->a_cred,
+		    ap->a_buf, ap->a_buflen);
+		vput(covered_vp);
+	}
+	vn_lock(vp, ltype | LK_RETRY);
+	if ((vp->v_iflag & VI_DOOMED) != 0)
+		error = SET_ERROR(ENOENT);
+	return (error);
+}
+
 struct vop_vector zfs_vnodeops;
 struct vop_vector zfs_fifoops;
 struct vop_vector zfs_shareops;
@@ -7205,6 +7243,7 @@ struct vop_vector zfs_vnodeops = {
 	.vop_aclcheck =		zfs_freebsd_aclcheck,
 	.vop_getpages =		zfs_freebsd_getpages,
 	.vop_putpages =		zfs_freebsd_putpages,
+	.vop_vptocnp =		zfs_vptocnp,
 };
 
 struct vop_vector zfs_fifoops = {