1221807Sstas/*- 2221807Sstas * Copyright (c) 2007 Ulf Lilleengen 3221807Sstas * All rights reserved. 4221807Sstas * 5221807Sstas * Redistribution and use in source and binary forms, with or without 6221807Sstas * modification, are permitted provided that the following conditions 7221807Sstas * are met: 8221807Sstas * 1. Redistributions of source code must retain the above copyright 9221807Sstas * notice, this list of conditions and the following disclaimer. 10221807Sstas * 2. Redistributions in binary form must reproduce the above copyright 11221807Sstas * notice, this list of conditions and the following disclaimer in the 12221807Sstas * documentation and/or other materials provided with the distribution. 13221807Sstas * 14221807Sstas * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15221807Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16221807Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17221807Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18221807Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19221807Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20221807Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21221807Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22221807Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23221807Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24221807Sstas * SUCH DAMAGE. 25221807Sstas * 26221807Sstas * $FreeBSD$ 27221807Sstas */ 28221807Sstas 29221807Sstas#include <sys/param.h> 30221807Sstas#define _KERNEL 31221807Sstas#include <sys/mount.h> 32221807Sstas#include <sys/taskqueue.h> 33221807Sstas#undef _KERNEL 34221807Sstas#include <sys/sysctl.h> 35221807Sstas 36221807Sstas#undef lbolt 37221807Sstas#undef lbolt64 38221807Sstas#undef gethrestime_sec 39221807Sstas#include <sys/zfs_context.h> 40221807Sstas#include <sys/spa.h> 41221807Sstas#include <sys/spa_impl.h> 42221807Sstas#include <sys/dmu.h> 43221807Sstas#include <sys/zap.h> 44221807Sstas#include <sys/fs/zfs.h> 45221807Sstas#include <sys/zfs_znode.h> 46221807Sstas#include <sys/zfs_sa.h> 47221807Sstas 48221807Sstas#include <netinet/in.h> 49221807Sstas 50221807Sstas#include <err.h> 51221807Sstas#include <kvm.h> 52221807Sstas#include <stdio.h> 53221807Sstas#include <stdlib.h> 54221807Sstas 55221807Sstas#define ZFS 56221807Sstas#include "libprocstat.h" 57221807Sstas#include "common_kvm.h" 58221807Sstas 59221807Sstas/* 60221807Sstas * Offset calculations that are used to get data from znode without having the 61221807Sstas * definition. 62221807Sstas */ 63221807Sstas#define LOCATION_ZID (2 * sizeof(void *)) 64221807Sstas#define LOCATION_ZPHYS(zsize) ((zsize) - (2 * sizeof(void *) + sizeof(struct task))) 65221807Sstas 66221807Sstasint 67221807Sstaszfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn) 68221807Sstas{ 69221807Sstas 70221807Sstas znode_phys_t zphys; 71221807Sstas struct mount mount, *mountptr; 72221807Sstas uint64_t *zid; 73221807Sstas void *znodeptr, *vnodeptr; 74221807Sstas char *dataptr; 75221807Sstas void *zphys_addr; 76221807Sstas size_t len; 77221807Sstas int size; 78221807Sstas 79221807Sstas len = sizeof(size); 80221807Sstas if (sysctlbyname("debug.sizeof.znode", &size, &len, NULL, 0) == -1) { 81221807Sstas warnx("error getting sysctl"); 82221807Sstas return (1); 83221807Sstas } 84221807Sstas znodeptr = malloc(size); 85221807Sstas if (znodeptr == NULL) { 86221807Sstas warnx("error allocating memory for znode storage"); 87221807Sstas return (1); 88221807Sstas } 89221807Sstas /* Since we have problems including vnode.h, we'll use the wrappers. */ 90221807Sstas vnodeptr = getvnodedata(vp); 91221807Sstas if (!kvm_read_all(kd, (unsigned long)vnodeptr, znodeptr, 92221807Sstas (size_t)size)) { 93221807Sstas warnx("can't read znode at %p", (void *)vnodeptr); 94221807Sstas goto bad; 95221807Sstas } 96221807Sstas 97221807Sstas /* 98221807Sstas * z_id field is stored in the third pointer. We therefore skip the two 99221807Sstas * first bytes. 100221807Sstas * 101221807Sstas * Pointer to the z_phys structure is the next last pointer. Therefore 102221807Sstas * go back two bytes from the end. 103221807Sstas */ 104221807Sstas dataptr = znodeptr; 105221807Sstas zid = (uint64_t *)(dataptr + LOCATION_ZID); 106221807Sstas zphys_addr = *(void **)(dataptr + LOCATION_ZPHYS(size)); 107221807Sstas 108221807Sstas if (!kvm_read_all(kd, (unsigned long)zphys_addr, &zphys, 109221807Sstas sizeof(zphys))) { 110221807Sstas warnx("can't read znode_phys at %p", zphys_addr); 111221807Sstas goto bad; 112221807Sstas } 113221807Sstas 114221807Sstas /* Get the mount pointer, and read from the address. */ 115221807Sstas mountptr = getvnodemount(vp); 116221807Sstas if (!kvm_read_all(kd, (unsigned long)mountptr, &mount, sizeof(mount))) { 117221807Sstas warnx("can't read mount at %p", (void *)mountptr); 118221807Sstas goto bad; 119221807Sstas } 120221807Sstas vn->vn_fsid = mount.mnt_stat.f_fsid.val[0]; 121221807Sstas vn->vn_fileid = *zid; 122221807Sstas /* 123221807Sstas * XXX: Shows up wrong in output, but UFS has this error too. Could 124221807Sstas * be that we're casting mode-variables from 64-bit to 8-bit or simply 125221807Sstas * error in the mode-to-string function. 126221807Sstas */ 127221807Sstas vn->vn_mode = (mode_t)zphys.zp_mode; 128221807Sstas vn->vn_size = (u_long)zphys.zp_size; 129221807Sstas free(znodeptr); 130221807Sstas return (0); 131221807Sstasbad: 132221807Sstas free(znodeptr); 133221807Sstas return (1); 134221807Sstas} 135