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 <a...@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 */
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to