Date: Fri, 5 Jun 2020 06:34:04 +0000 (UTC) From: Andriy Gapon <avg@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org Subject: svn commit: r361823 - in stable/12/lib/libprocstat: . zfs Message-ID: <202006050634.0556Y4ch048671@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: avg Date: Fri Jun 5 06:34:04 2020 New Revision: 361823 URL: https://svnweb.freebsd.org/changeset/base/361823 Log: MFC r361363,r361434: 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 Sponsored by: Panzura Added: stable/12/lib/libprocstat/zfs_defs.c - copied, changed from r361363, head/lib/libprocstat/zfs_defs.c stable/12/lib/libprocstat/zfs_defs.h - copied unchanged from r361363, head/lib/libprocstat/zfs_defs.h Modified: stable/12/lib/libprocstat/Makefile stable/12/lib/libprocstat/zfs.c stable/12/lib/libprocstat/zfs/Makefile Directory Properties: stable/12/ (props changed) Modified: stable/12/lib/libprocstat/Makefile ============================================================================== --- stable/12/lib/libprocstat/Makefile Fri Jun 5 06:21:23 2020 (r361822) +++ stable/12/lib/libprocstat/Makefile Fri Jun 5 06:34:04 2020 (r361823) @@ -61,16 +61,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: stable/12/lib/libprocstat/zfs.c ============================================================================== --- stable/12/lib/libprocstat/zfs.c Fri Jun 5 06:21:23 2020 (r361822) +++ stable/12/lib/libprocstat/zfs.c Fri Jun 5 06:34:04 2020 (r361823) @@ -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: stable/12/lib/libprocstat/zfs/Makefile ============================================================================== --- stable/12/lib/libprocstat/zfs/Makefile Fri Jun 5 06:21:23 2020 (r361822) +++ stable/12/lib/libprocstat/zfs/Makefile Fri Jun 5 06:34:04 2020 (r361823) @@ -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} Copied and modified: stable/12/lib/libprocstat/zfs_defs.c (from r361363, head/lib/libprocstat/zfs_defs.c) ============================================================================== --- head/lib/libprocstat/zfs_defs.c Fri May 22 11:20:23 2020 (r361363, copy source) +++ stable/12/lib/libprocstat/zfs_defs.c Fri Jun 5 06:34:04 2020 (r361823) @@ -57,3 +57,7 @@ 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); + +/* Keep pcpu.h satisfied. */ +uintptr_t *__start_set_pcpu; +uintptr_t *__stop_set_pcpu; Copied: stable/12/lib/libprocstat/zfs_defs.h (from r361363, head/lib/libprocstat/zfs_defs.h) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ stable/12/lib/libprocstat/zfs_defs.h Fri Jun 5 06:34:04 2020 (r361823, copy of r361363, head/lib/libprocstat/zfs_defs.h) @@ -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?202006050634.0556Y4ch048671>