Module Name:    src
Committed By:   hannken
Date:           Mon Mar 18 09:22:15 UTC 2019

Modified Files:
        src/external/cddl/osnet/dist/uts/common/fs/zfs: zfs_ctldir.c
            zfs_vfsops.c
        src/external/cddl/osnet/dist/uts/common/fs/zfs/sys: zfs_ctldir.h

Log Message:
Make ZFS exportable by NFS, implement zfsctl_vptofh(),
zfs_netbsd_vptofh() and zfs_netbsd_fhtovp().

Undo changes to now completely unused zfs_fhtovp().


To generate a diff of this commit:
cvs rdiff -u -r1.8 -r1.9 \
    src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_ctldir.c
cvs rdiff -u -r1.20 -r1.21 \
    src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vfsops.c
cvs rdiff -u -r1.2 -r1.3 \
    src/external/cddl/osnet/dist/uts/common/fs/zfs/sys/zfs_ctldir.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_ctldir.c
diff -u src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_ctldir.c:1.8 src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_ctldir.c:1.9
--- src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_ctldir.c:1.8	Mon Mar 18 09:21:31 2019
+++ src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_ctldir.c	Mon Mar 18 09:22:14 2019
@@ -1885,6 +1885,33 @@ zfsctl_loadvnode(vfs_t *vfsp, vnode_t *v
 	return 0;
 }
 
+int
+zfsctl_vptofh(vnode_t *vp, fid_t *fidp, size_t *fh_size)
+{
+	struct sfs_node *node = VTOSFS(vp);
+	uint64_t object = node->sn_id;
+	zfid_short_t *zfid = (zfid_short_t *)fidp;
+	int i;
+
+	SFS_NODE_ASSERT(vp);
+
+	if (*fh_size < SHORT_FID_LEN) {
+		*fh_size = SHORT_FID_LEN;
+		return SET_ERROR(E2BIG);
+	}
+	*fh_size = SHORT_FID_LEN;
+
+	zfid->zf_len = SHORT_FID_LEN;
+	for (i = 0; i < sizeof(zfid->zf_object); i++)
+		zfid->zf_object[i] = (uint8_t)(object >> (8 * i));
+
+	/* .zfs nodes always have a generation number of 0 */
+	for (i = 0; i < sizeof(zfid->zf_gen); i++)
+		zfid->zf_gen[i] = 0;
+
+	return 0;
+}
+
 /*
  * Return the ".zfs" vnode.
  */

Index: src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vfsops.c
diff -u src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vfsops.c:1.20 src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vfsops.c:1.21
--- src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vfsops.c:1.20	Mon Mar 18 09:20:58 2019
+++ src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vfsops.c	Mon Mar 18 09:22:14 2019
@@ -136,7 +136,8 @@ static int zfs_umount(vfs_t *vfsp, int f
 static int zfs_root(vfs_t *vfsp, int flags, vnode_t **vpp);
 static int zfs_netbsd_root(vfs_t *vfsp, vnode_t **vpp);
 static int zfs_statvfs(vfs_t *vfsp, struct statvfs *statp);
-static int zfs_fhtovp(vfs_t *vfsp, fid_t *fidp, vnode_t **vpp);
+static int zfs_netbsd_vptofh(vnode_t *vp, fid_t *fidp, size_t *fh_size);
+static int zfs_netbsd_fhtovp(vfs_t *vfsp, fid_t *fidp, vnode_t **vpp);
 static int zfs_vget(vfs_t *vfsp, ino_t ino, vnode_t **vpp);
 static int zfs_sync(vfs_t *vfsp, int waitfor);
 static int zfs_netbsd_sync(vfs_t *vfsp, int waitfor, cred_t *cr);
@@ -172,8 +173,8 @@ struct vfsops zfs_vfsops = {
 	.vfs_renamelock_enter = genfs_renamelock_enter,
 	.vfs_renamelock_exit = genfs_renamelock_exit,
 	.vfs_reinit = (void *)nullop,
-	.vfs_vptofh = (void *)eopnotsupp,
-	.vfs_fhtovp = (void *)eopnotsupp,
+	.vfs_vptofh = zfs_netbsd_vptofh,
+	.vfs_fhtovp = zfs_netbsd_fhtovp,
 	.vfs_quotactl = (void *)eopnotsupp,
 	.vfs_extattrctl = (void *)eopnotsupp,
 	.vfs_suspendctl = genfs_suspendctl,
@@ -254,6 +255,171 @@ zfs_netbsd_root(vfs_t *vfsp, vnode_t **v
 	return zfs_root(vfsp, LK_EXCLUSIVE | LK_RETRY, vpp);
 }
 
+static int
+zfs_netbsd_vptofh(vnode_t *vp, fid_t *fidp, size_t *fh_size)
+{
+	znode_t		*zp;
+	zfsvfs_t	*zfsvfs;
+	uint32_t	gen;
+	uint64_t	gen64;
+	uint64_t	object;
+	zfid_short_t	*zfid;
+	int		size, i, error;
+
+	if (zfsctl_is_node(vp))
+		return zfsctl_vptofh(vp, fidp, fh_size);
+
+	zp = VTOZ(vp);
+	zfsvfs = zp->z_zfsvfs;
+	object = zp->z_id;
+
+	ZFS_ENTER(zfsvfs);
+	ZFS_VERIFY_ZP(zp);
+
+	if ((error = sa_lookup(zp->z_sa_hdl, SA_ZPL_GEN(zfsvfs),
+	    &gen64, sizeof (uint64_t))) != 0) {
+		ZFS_EXIT(zfsvfs);
+		return (error);
+	}
+
+	gen = (uint32_t)gen64;
+
+	size = (zfsvfs->z_parent != zfsvfs) ? LONG_FID_LEN : SHORT_FID_LEN;
+
+	if (*fh_size < size) {
+		ZFS_EXIT(zfsvfs);
+		*fh_size = size;
+		return SET_ERROR(E2BIG);
+	}
+	*fh_size = size;
+
+	zfid = (zfid_short_t *)fidp;
+
+	zfid->zf_len = size;
+
+	for (i = 0; i < sizeof (zfid->zf_object); i++)
+		zfid->zf_object[i] = (uint8_t)(object >> (8 * i));
+
+	/* Must have a non-zero generation number to distinguish from .zfs */
+	if (gen == 0)
+		gen = 1;
+	for (i = 0; i < sizeof (zfid->zf_gen); i++)
+		zfid->zf_gen[i] = (uint8_t)(gen >> (8 * i));
+
+	if (size == LONG_FID_LEN) {
+		uint64_t	objsetid = dmu_objset_id(zfsvfs->z_os);
+		zfid_long_t	*zlfid;
+
+		zlfid = (zfid_long_t *)fidp;
+
+		for (i = 0; i < sizeof (zlfid->zf_setid); i++)
+			zlfid->zf_setid[i] = (uint8_t)(objsetid >> (8 * i));
+
+		/* XXX - this should be the generation number for the objset */
+		for (i = 0; i < sizeof (zlfid->zf_setgen); i++)
+			zlfid->zf_setgen[i] = 0;
+	}
+
+	ZFS_EXIT(zfsvfs);
+	return 0;
+}
+
+static int
+zfs_netbsd_fhtovp(vfs_t *vfsp, fid_t *fidp, vnode_t **vpp)
+{
+	zfsvfs_t	*zfsvfs = vfsp->vfs_data;
+	znode_t		*zp;
+	vnode_t		*dvp;
+	uint64_t	object = 0;
+	uint64_t	fid_gen = 0;
+	uint64_t	gen_mask;
+	uint64_t	zp_gen;
+	int 		i, err;
+
+	*vpp = NULL;
+
+	ZFS_ENTER(zfsvfs);
+
+	if (zfsvfs->z_parent == zfsvfs && fidp->fid_len == LONG_FID_LEN) {
+		zfid_long_t	*zlfid = (zfid_long_t *)fidp;
+		uint64_t	objsetid = 0;
+		uint64_t	setgen = 0;
+
+		for (i = 0; i < sizeof (zlfid->zf_setid); i++)
+			objsetid |= ((uint64_t)zlfid->zf_setid[i]) << (8 * i);
+
+		for (i = 0; i < sizeof (zlfid->zf_setgen); i++)
+			setgen |= ((uint64_t)zlfid->zf_setgen[i]) << (8 * i);
+
+		ZFS_EXIT(zfsvfs);
+
+		err = zfsctl_lookup_objset(vfsp, objsetid, &zfsvfs);
+		if (err)
+			return (SET_ERROR(EINVAL));
+		ZFS_ENTER(zfsvfs);
+	}
+
+	if (fidp->fid_len == SHORT_FID_LEN || fidp->fid_len == LONG_FID_LEN) {
+		zfid_short_t	*zfid = (zfid_short_t *)fidp;
+
+		for (i = 0; i < sizeof (zfid->zf_object); i++)
+			object |= ((uint64_t)zfid->zf_object[i]) << (8 * i);
+
+		for (i = 0; i < sizeof (zfid->zf_gen); i++)
+			fid_gen |= ((uint64_t)zfid->zf_gen[i]) << (8 * i);
+	} else {
+		ZFS_EXIT(zfsvfs);
+		return (SET_ERROR(EINVAL));
+	}
+
+	/* A zero fid_gen means we are in the .zfs control directories */
+	if (fid_gen == 0 &&
+	     (object == ZFSCTL_INO_ROOT || object == ZFSCTL_INO_SNAPDIR)) {
+		ZFS_EXIT(zfsvfs);
+		if (object == ZFSCTL_INO_ROOT)
+			err = zfsctl_root(zfsvfs, vpp);
+		else
+			err = zfsctl_snapshot(zfsvfs, vpp);
+		if (err)
+			return err;
+		err = vn_lock(*vpp, LK_EXCLUSIVE);
+		if (err) {
+			vrele(*vpp);
+			*vpp = NULL;
+			return err;
+		}
+		return 0;
+	}
+
+	gen_mask = -1ULL >> (64 - 8 * i);
+
+	dprintf("getting %llu [%u mask %llx]\n", object, fid_gen, gen_mask);
+	if (err = zfs_zget(zfsvfs, object, &zp)) {
+		ZFS_EXIT(zfsvfs);
+		return SET_ERROR(ESTALE);
+	}
+	(void) sa_lookup(zp->z_sa_hdl, SA_ZPL_GEN(zfsvfs), &zp_gen,
+	    sizeof (uint64_t));
+	zp_gen = zp_gen & gen_mask;
+	if (zp_gen == 0)
+		zp_gen = 1;
+	if (zp->z_unlinked || zp_gen != fid_gen) {
+		dprintf("znode gen (%u) != fid gen (%u)\n", zp_gen, fid_gen);
+		VN_RELE(ZTOV(zp));
+		ZFS_EXIT(zfsvfs);
+		return SET_ERROR(ESTALE);
+	}
+
+	*vpp = ZTOV(zp);
+	ZFS_EXIT(zfsvfs);
+	err = vn_lock(*vpp, LK_EXCLUSIVE);
+	if (err) {
+		vrele(*vpp);
+		*vpp = NULL;
+		return err;
+	}
+	return 0;
+}
 #endif /* __NetBSD__ */
 
 /*
@@ -2368,11 +2534,6 @@ CTASSERT(LONG_FID_LEN <= sizeof(struct f
 #ifdef __FreeBSD_kernel__
 static int
 zfs_fhtovp(vfs_t *vfsp, fid_t *fidp, int flags, vnode_t **vpp)
-#endif
-#ifdef __NetBSD__
-static int
-zfs_fhtovp(vfs_t *vfsp, fid_t *fidp, vnode_t **vpp)
-#endif
 {
 	struct componentname cn;
 	zfsvfs_t	*zfsvfs = vfsp->vfs_data;
@@ -2386,13 +2547,8 @@ zfs_fhtovp(vfs_t *vfsp, fid_t *fidp, vno
 
 	*vpp = NULL;
 
-#ifdef __NetBSD__
-	return (SET_ERROR(ENOTSUP));
-#endif
-
 	ZFS_ENTER(zfsvfs);
 
-#ifdef __FreeBSD_kernel__
 	/*
 	 * On FreeBSD we can get snapshot's mount point or its parent file
 	 * system mount point depending if snapshot is already mounted or not.
@@ -2465,7 +2621,7 @@ zfs_fhtovp(vfs_t *vfsp, fid_t *fidp, vno
 		}
 		return (err);
 	}
-#endif
+
 	gen_mask = -1ULL >> (64 - 8 * i);
 
 	dprintf("getting %llu [%u mask %llx]\n", object, fid_gen, gen_mask);
@@ -2487,15 +2643,14 @@ zfs_fhtovp(vfs_t *vfsp, fid_t *fidp, vno
 
 	*vpp = ZTOV(zp);
 	ZFS_EXIT(zfsvfs);
-#ifdef __FreeBSD_kernel__
 	err = vn_lock(*vpp, flags);
 	if (err == 0)
 		vnode_create_vobject(*vpp, zp->z_size, curthread);
 	else
 		*vpp = NULL;
-#endif
 	return (err);
 }
+#endif /* __FreeBSD_kernel__ */
 
 /*
  * Block out VOPs and close zfsvfs_t::z_os

Index: src/external/cddl/osnet/dist/uts/common/fs/zfs/sys/zfs_ctldir.h
diff -u src/external/cddl/osnet/dist/uts/common/fs/zfs/sys/zfs_ctldir.h:1.2 src/external/cddl/osnet/dist/uts/common/fs/zfs/sys/zfs_ctldir.h:1.3
--- src/external/cddl/osnet/dist/uts/common/fs/zfs/sys/zfs_ctldir.h:1.2	Tue Feb  5 09:54:36 2019
+++ src/external/cddl/osnet/dist/uts/common/fs/zfs/sys/zfs_ctldir.h	Mon Mar 18 09:22:14 2019
@@ -46,6 +46,7 @@ void zfsctl_create(zfsvfs_t *);
 void zfsctl_destroy(zfsvfs_t *);
 #ifdef __NetBSD__
 int zfsctl_loadvnode(vfs_t *, vnode_t *, const void *, size_t, const void **);
+int zfsctl_vptofh(vnode_t *, fid_t *, size_t *);
 int zfsctl_root(zfsvfs_t *, vnode_t **);
 int zfsctl_snapshot(zfsvfs_t *, vnode_t **);
 #else

Reply via email to