zfs.c revision 331722
1273929Sjmmv/*- 2240116Smarcel * Copyright (c) 2007 Ulf Lilleengen 3240116Smarcel * All rights reserved. 4240116Smarcel * 5240116Smarcel * Redistribution and use in source and binary forms, with or without 6240116Smarcel * modification, are permitted provided that the following conditions 7240116Smarcel * are met: 8240116Smarcel * 1. Redistributions of source code must retain the above copyright 9240116Smarcel * notice, this list of conditions and the following disclaimer. 10240116Smarcel * 2. Redistributions in binary form must reproduce the above copyright 11240116Smarcel * notice, this list of conditions and the following disclaimer in the 12240116Smarcel * documentation and/or other materials provided with the distribution. 13240116Smarcel * 14240116Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15240116Smarcel * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16240116Smarcel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17240116Smarcel * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18240116Smarcel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19240116Smarcel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20240116Smarcel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21240116Smarcel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22240116Smarcel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23240116Smarcel * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24273929Sjmmv * SUCH DAMAGE. 25240116Smarcel * 26273929Sjmmv * $FreeBSD: stable/11/lib/libprocstat/zfs.c 331722 2018-03-29 02:50:57Z eadler $ 27273929Sjmmv */ 28240116Smarcel 29240116Smarcel#include <sys/param.h> 30240116Smarcel#define _KERNEL 31273929Sjmmv#include <sys/mount.h> 32240116Smarcel#include <sys/taskqueue.h> 33240116Smarcel#undef _KERNEL 34240116Smarcel#include <sys/sysctl.h> 35240116Smarcel 36240116Smarcel#undef lbolt 37240116Smarcel#undef lbolt64 38240116Smarcel#undef gethrestime_sec 39240116Smarcel#include <sys/zfs_context.h> 40240116Smarcel#include <sys/spa.h> 41240116Smarcel#include <sys/spa_impl.h> 42240116Smarcel#include <sys/dmu.h> 43240116Smarcel#include <sys/zap.h> 44240116Smarcel#include <sys/fs/zfs.h> 45240116Smarcel#include <sys/zfs_znode.h> 46240116Smarcel#include <sys/zfs_sa.h> 47240116Smarcel 48240116Smarcel#include <netinet/in.h> 49240116Smarcel 50240116Smarcel#include <err.h> 51240116Smarcel#include <kvm.h> 52240116Smarcel#include <stdio.h> 53240116Smarcel#include <stdlib.h> 54240116Smarcel 55240116Smarcel#define ZFS 56240116Smarcel#include "libprocstat.h" 57240116Smarcel#include "common_kvm.h" 58240116Smarcel 59240116Smarcel/* 60240116Smarcel * Offset calculations that are used to get data from znode without having the 61240116Smarcel * definition. 62240116Smarcel */ 63240116Smarcel#define LOCATION_ZID (2 * sizeof(void *)) 64240116Smarcel#define LOCATION_ZPHYS(zsize) ((zsize) - (2 * sizeof(void *) + sizeof(struct task))) 65240116Smarcel 66240116Smarcelint 67240116Smarcelzfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn) 68240116Smarcel{ 69240116Smarcel 70240116Smarcel znode_phys_t zphys; 71240116Smarcel struct mount mount, *mountptr; 72240116Smarcel uint64_t *zid; 73240116Smarcel void *znodeptr, *vnodeptr; 74240116Smarcel char *dataptr; 75240116Smarcel void *zphys_addr; 76240116Smarcel size_t len; 77240116Smarcel int size; 78240116Smarcel 79240116Smarcel len = sizeof(size); 80240116Smarcel if (sysctlbyname("debug.sizeof.znode", &size, &len, NULL, 0) == -1) { 81240116Smarcel warnx("error getting sysctl"); 82240116Smarcel return (1); 83240116Smarcel } 84240116Smarcel znodeptr = malloc(size); 85240116Smarcel if (znodeptr == NULL) { 86240116Smarcel warnx("error allocating memory for znode storage"); 87240116Smarcel return (1); 88240116Smarcel } 89240116Smarcel /* Since we have problems including vnode.h, we'll use the wrappers. */ 90240116Smarcel vnodeptr = getvnodedata(vp); 91240116Smarcel if (!kvm_read_all(kd, (unsigned long)vnodeptr, znodeptr, 92240116Smarcel (size_t)size)) { 93240116Smarcel warnx("can't read znode at %p", (void *)vnodeptr); 94240116Smarcel goto bad; 95240116Smarcel } 96240116Smarcel 97240116Smarcel /* 98240116Smarcel * z_id field is stored in the third pointer. We therefore skip the two 99240116Smarcel * first bytes. 100240116Smarcel * 101240116Smarcel * Pointer to the z_phys structure is the next last pointer. Therefore 102240116Smarcel * go back two bytes from the end. 103240116Smarcel */ 104240116Smarcel dataptr = znodeptr; 105240116Smarcel zid = (uint64_t *)(dataptr + LOCATION_ZID); 106240116Smarcel zphys_addr = *(void **)(dataptr + LOCATION_ZPHYS(size)); 107240116Smarcel 108240116Smarcel if (!kvm_read_all(kd, (unsigned long)zphys_addr, &zphys, 109240116Smarcel sizeof(zphys))) { 110240116Smarcel warnx("can't read znode_phys at %p", zphys_addr); 111240116Smarcel goto bad; 112240116Smarcel } 113240116Smarcel 114240116Smarcel /* Get the mount pointer, and read from the address. */ 115240116Smarcel mountptr = getvnodemount(vp); 116240116Smarcel if (!kvm_read_all(kd, (unsigned long)mountptr, &mount, sizeof(mount))) { 117240116Smarcel warnx("can't read mount at %p", (void *)mountptr); 118240116Smarcel goto bad; 119240116Smarcel } 120240116Smarcel vn->vn_fsid = mount.mnt_stat.f_fsid.val[0]; 121240116Smarcel vn->vn_fileid = *zid; 122240116Smarcel /* 123240116Smarcel * XXX: Shows up wrong in output, but UFS has this error too. Could 124240116Smarcel * be that we're casting mode-variables from 64-bit to 8-bit or simply 125240116Smarcel * error in the mode-to-string function. 126240116Smarcel */ 127240116Smarcel vn->vn_mode = (mode_t)zphys.zp_mode; 128240116Smarcel vn->vn_size = (u_long)zphys.zp_size; 129240116Smarcel free(znodeptr); 130240116Smarcel return (0); 131240116Smarcelbad: 132240116Smarcel free(znodeptr); 133240116Smarcel return (1); 134240116Smarcel} 135240116Smarcel