Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 22 May 2020 11:20:24 +0000 (UTC)
From:      Andriy Gapon <avg@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r361363 - in head/lib/libprocstat: . zfs
Message-ID:  <202005221120.04MBKOiH003190@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: avg
Date: Fri May 22 11:20:23 2020
New Revision: 361363
URL: https://svnweb.freebsd.org/changeset/base/361363

Log:
  libprocstat: fix ZFS support
  
  First of all, znode_phys_t hasn't been used for storing file attributes
  for a long time now.  Modern ZFS versions use a System Attribute table
  with a flexible layout.  But more importantly all the required
  information is available in znode_t itself.
  
  It's not easy to include zfs_znode.h in userland without breaking code
  because the most interesting parts of the header are kernel-only. And
  hardcoding field offsets is too fragile.  So, I created a new
  compilation unit that includes zfs_znode.h using some mild kludges to
  get it and its dependencies to compile in userland.  The compilation
  unit exports interesting field offsets and does not have any other code.
  
  PR:		194117
  Reviewed by:	markj
  MFC after:	2 weeks
  Sponsored by:	Panzura
  Differential Revision: https://reviews.freebsd.org/D24941

Added:
  head/lib/libprocstat/zfs_defs.c   (contents, props changed)
  head/lib/libprocstat/zfs_defs.h   (contents, props changed)
Modified:
  head/lib/libprocstat/Makefile
  head/lib/libprocstat/zfs.c
  head/lib/libprocstat/zfs/Makefile

Modified: head/lib/libprocstat/Makefile
==============================================================================
--- head/lib/libprocstat/Makefile	Fri May 22 10:50:29 2020	(r361362)
+++ head/lib/libprocstat/Makefile	Fri May 22 11:20:23 2020	(r361363)
@@ -57,16 +57,17 @@ MLINKS+=libprocstat.3 procstat_close.3 \
 # XXX This is a hack.
 .if ${MK_CDDL} != "no"
 CFLAGS+=	-DLIBPROCSTAT_ZFS
-OBJS+=	zfs/zfs.o
-SOBJS+=	zfs/zfs.pico
-POBJS+=	zfs/zfs.po
+SRCS+=	zfs.c
+OBJS+=	zfs/zfs_defs.o
+SOBJS+=	zfs/zfs_defs.pico
+POBJS+=	zfs/zfs_defs.po
 SUBDIR=	zfs
-zfs/zfs.o: .PHONY
-	@cd ${.CURDIR}/zfs && ${MAKE} zfs.o
-zfs/zfs.pico: .PHONY
-	@cd ${.CURDIR}/zfs && ${MAKE} zfs.pico
-zfs/zfs.po: .PHONY
-	@cd ${.CURDIR}/zfs && ${MAKE} zfs.po
+zfs/zfs_defs.o: .PHONY
+	@cd ${.CURDIR}/zfs && ${MAKE} zfs_defs.o
+zfs/zfs_defs.pico: .PHONY
+	@cd ${.CURDIR}/zfs && ${MAKE} zfs_defs.pico
+zfs/zfs_defs.po: .PHONY
+	@cd ${.CURDIR}/zfs && ${MAKE} zfs_defs.po
 .endif
 
 .include <bsd.lib.mk>

Modified: head/lib/libprocstat/zfs.c
==============================================================================
--- head/lib/libprocstat/zfs.c	Fri May 22 10:50:29 2020	(r361362)
+++ head/lib/libprocstat/zfs.c	Fri May 22 11:20:23 2020	(r361363)
@@ -31,22 +31,13 @@
 #include <sys/param.h>
 #define _KERNEL
 #include <sys/mount.h>
-#include <sys/taskqueue.h>
 #undef _KERNEL
+#include <sys/queue.h>
+#include <sys/stat.h>
 #include <sys/sysctl.h>
+#include <sys/time.h>
+#include <sys/vnode.h>
 
-#undef lbolt
-#undef lbolt64
-#undef gethrestime_sec
-#include <sys/zfs_context.h>
-#include <sys/spa.h>
-#include <sys/spa_impl.h>
-#include <sys/dmu.h>
-#include <sys/zap.h>
-#include <sys/fs/zfs.h>
-#include <sys/zfs_znode.h>
-#include <sys/zfs_sa.h>
-
 #include <netinet/in.h>
 
 #include <err.h>
@@ -57,24 +48,15 @@
 #define ZFS
 #include "libprocstat.h"
 #include "common_kvm.h"
+#include "zfs_defs.h"
 
-/* 
- * Offset calculations that are used to get data from znode without having the
- * definition.
- */
-#define LOCATION_ZID (2 * sizeof(void *))
-#define LOCATION_ZPHYS(zsize) ((zsize) - (2 * sizeof(void *) + sizeof(struct task)))
-
 int
 zfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn)
 {
 
-	znode_phys_t zphys;
 	struct mount mount, *mountptr;
-	uint64_t *zid;
-	void *znodeptr, *vnodeptr;
+	void *znodeptr;
 	char *dataptr;
-	void *zphys_addr;
 	size_t len;
 	int size;
 
@@ -83,33 +65,27 @@ zfs_filestat(kvm_t *kd, struct vnode *vp, struct vnsta
 		warnx("error getting sysctl");
 		return (1);
 	}
-	znodeptr = malloc(size);
-	if (znodeptr == NULL) {
+	dataptr = malloc(size);
+	if (dataptr == NULL) {
 		warnx("error allocating memory for znode storage");
 		return (1);
 	}
-	/* Since we have problems including vnode.h, we'll use the wrappers. */
-	vnodeptr = getvnodedata(vp);
-	if (!kvm_read_all(kd, (unsigned long)vnodeptr, znodeptr,
-	    (size_t)size)) {
-		warnx("can't read znode at %p", (void *)vnodeptr);
+
+	if ((size_t)size < offsetof_z_id + sizeof(uint64_t) ||
+	    (size_t)size < offsetof_z_mode + sizeof(mode_t) ||
+	    (size_t)size < offsetof_z_size + sizeof(uint64_t)) {
+		warnx("znode_t size is too small");
 		goto bad;
 	}
 
-	/* 
-	 * z_id field is stored in the third pointer. We therefore skip the two
-	 * first bytes. 
-	 *
-	 * Pointer to the z_phys structure is the next last pointer. Therefore
-	 * go back two bytes from the end.
-	 */
-	dataptr = znodeptr;
-	zid = (uint64_t *)(dataptr + LOCATION_ZID);
-	zphys_addr = *(void **)(dataptr + LOCATION_ZPHYS(size));
+	if ((size_t)size != sizeof_znode_t)
+		warnx("znode_t size mismatch, data could be wrong");
 
-	if (!kvm_read_all(kd, (unsigned long)zphys_addr, &zphys,
-	    sizeof(zphys))) {
-		warnx("can't read znode_phys at %p", zphys_addr);
+	/* Since we have problems including vnode.h, we'll use the wrappers. */
+	znodeptr = getvnodedata(vp);
+	if (!kvm_read_all(kd, (unsigned long)znodeptr, dataptr,
+	    (size_t)size)) {
+		warnx("can't read znode at %p", (void *)znodeptr);
 		goto bad;
 	}
 
@@ -119,18 +95,18 @@ zfs_filestat(kvm_t *kd, struct vnode *vp, struct vnsta
 		warnx("can't read mount at %p", (void *)mountptr);
 		goto bad;
 	}
-	vn->vn_fsid = mount.mnt_stat.f_fsid.val[0];
-	vn->vn_fileid = *zid;
+
 	/*
-	 * XXX: Shows up wrong in output, but UFS has this error too. Could
-	 * be that we're casting mode-variables from 64-bit to 8-bit or simply
-	 * error in the mode-to-string function.
+	 * XXX Assume that this is a znode, but it can be a special node
+	 * under .zfs/.
 	 */
-	vn->vn_mode = (mode_t)zphys.zp_mode;
-	vn->vn_size = (u_long)zphys.zp_size;
-	free(znodeptr);
+	vn->vn_fsid = mount.mnt_stat.f_fsid.val[0];
+	vn->vn_fileid = *(uint64_t *)(void *)(dataptr + offsetof_z_id);
+	vn->vn_mode = *(mode_t *)(void *)(dataptr + offsetof_z_mode);
+	vn->vn_size = *(uint64_t *)(void *)(dataptr + offsetof_z_size);
+	free(dataptr);
 	return (0);
 bad:
-	free(znodeptr);
+	free(dataptr);
 	return (1);
 }

Modified: head/lib/libprocstat/zfs/Makefile
==============================================================================
--- head/lib/libprocstat/zfs/Makefile	Fri May 22 10:50:29 2020	(r361362)
+++ head/lib/libprocstat/zfs/Makefile	Fri May 22 11:20:23 2020	(r361363)
@@ -2,20 +2,20 @@
 
 .PATH: ${.CURDIR:H}
 
-SRCS=	zfs.c
-OBJS=	zfs.o
+SRCS=	zfs_defs.c
+OBJS=	zfs_defs.o
 WARNS?=	1
 
 CFLAGS+= -I${SRCTOP}/sys/cddl/compat/opensolaris
 CFLAGS+= -I${SRCTOP}/cddl/compat/opensolaris/include
 CFLAGS+= -I${SRCTOP}/cddl/compat/opensolaris/lib/libumem
-CFLAGS+= -I${SRCTOP}/cddl/contrib/opensolaris/lib/libzpool/common
 CFLAGS+= -I${SRCTOP}/sys/cddl/contrib/opensolaris/common/zfs
 CFLAGS+= -I${SRCTOP}/sys/cddl/contrib/opensolaris/uts/common/fs/zfs
 CFLAGS+= -I${SRCTOP}/sys/cddl/contrib/opensolaris/uts/common
 CFLAGS+= -I${SRCTOP}/cddl/contrib/opensolaris/head
 CFLAGS+= -I${.CURDIR:H}
 CFLAGS+= -DNEED_SOLARIS_BOOLEAN
+CFLAGS+= -fno-builtin -nostdlib
 
 all: ${OBJS}
 CLEANFILES= ${OBJS}

Added: head/lib/libprocstat/zfs_defs.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/lib/libprocstat/zfs_defs.c	Fri May 22 11:20:23 2020	(r361363)
@@ -0,0 +1,59 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2020 Andriy Gapon <avg@FreeBSD.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/* Pretend we are kernel to get the same binary layout. */
+#define _KERNEL
+
+/* A hack to deal with kpilite.h. */
+#define KLD_MODULE
+
+/*
+ * Prevent some headers from getting included and fake some types
+ * in order to allow this file to compile without bringing in
+ * too many kernel build dependencies.
+ */
+#define _OPENSOLARIS_SYS_PATHNAME_H_
+#define _OPENSOLARIS_SYS_POLICY_H_
+#define _OPENSOLARIS_SYS_VNODE_H_
+#define _VNODE_PAGER_
+
+typedef struct vnode vnode_t;
+typedef struct vattr vattr_t;
+typedef struct xvattr xvattr_t;
+typedef struct vsecattr vsecattr_t;
+typedef enum vtype vtype_t;
+
+#include <sys/zfs_context.h>
+#include <sys/zfs_znode.h>
+
+size_t sizeof_znode_t = sizeof(znode_t);
+size_t offsetof_z_id = offsetof(znode_t, z_id);
+size_t offsetof_z_size = offsetof(znode_t, z_size);
+size_t offsetof_z_mode = offsetof(znode_t, z_mode);

Added: head/lib/libprocstat/zfs_defs.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/lib/libprocstat/zfs_defs.h	Fri May 22 11:20:23 2020	(r361363)
@@ -0,0 +1,38 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2020 Andriy Gapon <avg@FreeBSD.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _LIBPROCSTAT_ZFS_DEFS_H
+#define _LIBPROCSTAT_ZFS_DEFS_H
+
+extern size_t sizeof_znode_t;
+extern size_t offsetof_z_id;
+extern size_t offsetof_z_size;
+extern size_t offsetof_z_mode;
+
+#endif 	/* _LIBPROCSTAT_ZFS_DEFS_H */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202005221120.04MBKOiH003190>