1*eda14cbcSMatt Macy /* 2*eda14cbcSMatt Macy * CDDL HEADER START 3*eda14cbcSMatt Macy * 4*eda14cbcSMatt Macy * The contents of this file are subject to the terms of the 5*eda14cbcSMatt Macy * Common Development and Distribution License (the "License"). 6*eda14cbcSMatt Macy * You may not use this file except in compliance with the License. 7*eda14cbcSMatt Macy * 8*eda14cbcSMatt Macy * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*eda14cbcSMatt Macy * or http://www.opensolaris.org/os/licensing. 10*eda14cbcSMatt Macy * See the License for the specific language governing permissions 11*eda14cbcSMatt Macy * and limitations under the License. 12*eda14cbcSMatt Macy * 13*eda14cbcSMatt Macy * When distributing Covered Code, include this CDDL HEADER in each 14*eda14cbcSMatt Macy * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*eda14cbcSMatt Macy * If applicable, add the following below this CDDL HEADER, with the 16*eda14cbcSMatt Macy * fields enclosed by brackets "[]" replaced with your own identifying 17*eda14cbcSMatt Macy * information: Portions Copyright [yyyy] [name of copyright owner] 18*eda14cbcSMatt Macy * 19*eda14cbcSMatt Macy * CDDL HEADER END 20*eda14cbcSMatt Macy */ 21*eda14cbcSMatt Macy /* 22*eda14cbcSMatt Macy * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 23*eda14cbcSMatt Macy * Copyright (c) 2016 by Delphix. All rights reserved. 24*eda14cbcSMatt Macy * Copyright 2017 Jason King 25*eda14cbcSMatt Macy * Copyright (c) 2017, Intel Corporation. 26*eda14cbcSMatt Macy */ 27*eda14cbcSMatt Macy 28*eda14cbcSMatt Macy #include <assert.h> 29*eda14cbcSMatt Macy #include <sys/zfs_context.h> 30*eda14cbcSMatt Macy #include <sys/avl.h> 31*eda14cbcSMatt Macy #include <string.h> 32*eda14cbcSMatt Macy #include <stdio.h> 33*eda14cbcSMatt Macy #include <stdlib.h> 34*eda14cbcSMatt Macy #include <sys/spa.h> 35*eda14cbcSMatt Macy #include <sys/fs/zfs.h> 36*eda14cbcSMatt Macy #include <sys/zfs_refcount.h> 37*eda14cbcSMatt Macy #include <sys/zfs_ioctl.h> 38*eda14cbcSMatt Macy #include <dlfcn.h> 39*eda14cbcSMatt Macy #include <libzutil.h> 40*eda14cbcSMatt Macy 41*eda14cbcSMatt Macy /* 42*eda14cbcSMatt Macy * Routines needed by more than one client of libzpool. 43*eda14cbcSMatt Macy */ 44*eda14cbcSMatt Macy 45*eda14cbcSMatt Macy static void 46*eda14cbcSMatt Macy show_vdev_stats(const char *desc, const char *ctype, nvlist_t *nv, int indent) 47*eda14cbcSMatt Macy { 48*eda14cbcSMatt Macy vdev_stat_t *vs; 49*eda14cbcSMatt Macy vdev_stat_t *v0 = { 0 }; 50*eda14cbcSMatt Macy uint64_t sec; 51*eda14cbcSMatt Macy uint64_t is_log = 0; 52*eda14cbcSMatt Macy nvlist_t **child; 53*eda14cbcSMatt Macy uint_t c, children; 54*eda14cbcSMatt Macy char used[6], avail[6]; 55*eda14cbcSMatt Macy char rops[6], wops[6], rbytes[6], wbytes[6], rerr[6], werr[6], cerr[6]; 56*eda14cbcSMatt Macy 57*eda14cbcSMatt Macy v0 = umem_zalloc(sizeof (*v0), UMEM_NOFAIL); 58*eda14cbcSMatt Macy 59*eda14cbcSMatt Macy if (indent == 0 && desc != NULL) { 60*eda14cbcSMatt Macy (void) printf(" " 61*eda14cbcSMatt Macy " capacity operations bandwidth ---- errors ----\n"); 62*eda14cbcSMatt Macy (void) printf("description " 63*eda14cbcSMatt Macy "used avail read write read write read write cksum\n"); 64*eda14cbcSMatt Macy } 65*eda14cbcSMatt Macy 66*eda14cbcSMatt Macy if (desc != NULL) { 67*eda14cbcSMatt Macy char *suffix = "", *bias = NULL; 68*eda14cbcSMatt Macy char bias_suffix[32]; 69*eda14cbcSMatt Macy 70*eda14cbcSMatt Macy (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_IS_LOG, &is_log); 71*eda14cbcSMatt Macy (void) nvlist_lookup_string(nv, ZPOOL_CONFIG_ALLOCATION_BIAS, 72*eda14cbcSMatt Macy &bias); 73*eda14cbcSMatt Macy if (nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS, 74*eda14cbcSMatt Macy (uint64_t **)&vs, &c) != 0) 75*eda14cbcSMatt Macy vs = v0; 76*eda14cbcSMatt Macy 77*eda14cbcSMatt Macy if (bias != NULL) { 78*eda14cbcSMatt Macy (void) snprintf(bias_suffix, sizeof (bias_suffix), 79*eda14cbcSMatt Macy " (%s)", bias); 80*eda14cbcSMatt Macy suffix = bias_suffix; 81*eda14cbcSMatt Macy } else if (is_log) { 82*eda14cbcSMatt Macy suffix = " (log)"; 83*eda14cbcSMatt Macy } 84*eda14cbcSMatt Macy 85*eda14cbcSMatt Macy sec = MAX(1, vs->vs_timestamp / NANOSEC); 86*eda14cbcSMatt Macy 87*eda14cbcSMatt Macy nicenum(vs->vs_alloc, used, sizeof (used)); 88*eda14cbcSMatt Macy nicenum(vs->vs_space - vs->vs_alloc, avail, sizeof (avail)); 89*eda14cbcSMatt Macy nicenum(vs->vs_ops[ZIO_TYPE_READ] / sec, rops, sizeof (rops)); 90*eda14cbcSMatt Macy nicenum(vs->vs_ops[ZIO_TYPE_WRITE] / sec, wops, sizeof (wops)); 91*eda14cbcSMatt Macy nicenum(vs->vs_bytes[ZIO_TYPE_READ] / sec, rbytes, 92*eda14cbcSMatt Macy sizeof (rbytes)); 93*eda14cbcSMatt Macy nicenum(vs->vs_bytes[ZIO_TYPE_WRITE] / sec, wbytes, 94*eda14cbcSMatt Macy sizeof (wbytes)); 95*eda14cbcSMatt Macy nicenum(vs->vs_read_errors, rerr, sizeof (rerr)); 96*eda14cbcSMatt Macy nicenum(vs->vs_write_errors, werr, sizeof (werr)); 97*eda14cbcSMatt Macy nicenum(vs->vs_checksum_errors, cerr, sizeof (cerr)); 98*eda14cbcSMatt Macy 99*eda14cbcSMatt Macy (void) printf("%*s%s%*s%*s%*s %5s %5s %5s %5s %5s %5s %5s\n", 100*eda14cbcSMatt Macy indent, "", 101*eda14cbcSMatt Macy desc, 102*eda14cbcSMatt Macy (int)(indent+strlen(desc)-25-(vs->vs_space ? 0 : 12)), 103*eda14cbcSMatt Macy suffix, 104*eda14cbcSMatt Macy vs->vs_space ? 6 : 0, vs->vs_space ? used : "", 105*eda14cbcSMatt Macy vs->vs_space ? 6 : 0, vs->vs_space ? avail : "", 106*eda14cbcSMatt Macy rops, wops, rbytes, wbytes, rerr, werr, cerr); 107*eda14cbcSMatt Macy } 108*eda14cbcSMatt Macy umem_free(v0, sizeof (*v0)); 109*eda14cbcSMatt Macy 110*eda14cbcSMatt Macy if (nvlist_lookup_nvlist_array(nv, ctype, &child, &children) != 0) 111*eda14cbcSMatt Macy return; 112*eda14cbcSMatt Macy 113*eda14cbcSMatt Macy for (c = 0; c < children; c++) { 114*eda14cbcSMatt Macy nvlist_t *cnv = child[c]; 115*eda14cbcSMatt Macy char *cname = NULL, *tname; 116*eda14cbcSMatt Macy uint64_t np; 117*eda14cbcSMatt Macy int len; 118*eda14cbcSMatt Macy if (nvlist_lookup_string(cnv, ZPOOL_CONFIG_PATH, &cname) && 119*eda14cbcSMatt Macy nvlist_lookup_string(cnv, ZPOOL_CONFIG_TYPE, &cname)) 120*eda14cbcSMatt Macy cname = "<unknown>"; 121*eda14cbcSMatt Macy len = strlen(cname) + 2; 122*eda14cbcSMatt Macy tname = umem_zalloc(len, UMEM_NOFAIL); 123*eda14cbcSMatt Macy (void) strlcpy(tname, cname, len); 124*eda14cbcSMatt Macy if (nvlist_lookup_uint64(cnv, ZPOOL_CONFIG_NPARITY, &np) == 0) 125*eda14cbcSMatt Macy tname[strlen(tname)] = '0' + np; 126*eda14cbcSMatt Macy show_vdev_stats(tname, ctype, cnv, indent + 2); 127*eda14cbcSMatt Macy umem_free(tname, len); 128*eda14cbcSMatt Macy } 129*eda14cbcSMatt Macy } 130*eda14cbcSMatt Macy 131*eda14cbcSMatt Macy void 132*eda14cbcSMatt Macy show_pool_stats(spa_t *spa) 133*eda14cbcSMatt Macy { 134*eda14cbcSMatt Macy nvlist_t *config, *nvroot; 135*eda14cbcSMatt Macy char *name; 136*eda14cbcSMatt Macy 137*eda14cbcSMatt Macy VERIFY(spa_get_stats(spa_name(spa), &config, NULL, 0) == 0); 138*eda14cbcSMatt Macy 139*eda14cbcSMatt Macy VERIFY(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 140*eda14cbcSMatt Macy &nvroot) == 0); 141*eda14cbcSMatt Macy VERIFY(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, 142*eda14cbcSMatt Macy &name) == 0); 143*eda14cbcSMatt Macy 144*eda14cbcSMatt Macy show_vdev_stats(name, ZPOOL_CONFIG_CHILDREN, nvroot, 0); 145*eda14cbcSMatt Macy show_vdev_stats(NULL, ZPOOL_CONFIG_L2CACHE, nvroot, 0); 146*eda14cbcSMatt Macy show_vdev_stats(NULL, ZPOOL_CONFIG_SPARES, nvroot, 0); 147*eda14cbcSMatt Macy 148*eda14cbcSMatt Macy nvlist_free(config); 149*eda14cbcSMatt Macy } 150*eda14cbcSMatt Macy 151*eda14cbcSMatt Macy /* 152*eda14cbcSMatt Macy * Sets given global variable in libzpool to given unsigned 32-bit value. 153*eda14cbcSMatt Macy * arg: "<variable>=<value>" 154*eda14cbcSMatt Macy */ 155*eda14cbcSMatt Macy int 156*eda14cbcSMatt Macy set_global_var(char *arg) 157*eda14cbcSMatt Macy { 158*eda14cbcSMatt Macy void *zpoolhdl; 159*eda14cbcSMatt Macy char *varname = arg, *varval; 160*eda14cbcSMatt Macy u_longlong_t val; 161*eda14cbcSMatt Macy 162*eda14cbcSMatt Macy #ifndef _LITTLE_ENDIAN 163*eda14cbcSMatt Macy /* 164*eda14cbcSMatt Macy * On big endian systems changing a 64-bit variable would set the high 165*eda14cbcSMatt Macy * 32 bits instead of the low 32 bits, which could cause unexpected 166*eda14cbcSMatt Macy * results. 167*eda14cbcSMatt Macy */ 168*eda14cbcSMatt Macy fprintf(stderr, "Setting global variables is only supported on " 169*eda14cbcSMatt Macy "little-endian systems\n"); 170*eda14cbcSMatt Macy return (ENOTSUP); 171*eda14cbcSMatt Macy #endif 172*eda14cbcSMatt Macy if (arg != NULL && (varval = strchr(arg, '=')) != NULL) { 173*eda14cbcSMatt Macy *varval = '\0'; 174*eda14cbcSMatt Macy varval++; 175*eda14cbcSMatt Macy val = strtoull(varval, NULL, 0); 176*eda14cbcSMatt Macy if (val > UINT32_MAX) { 177*eda14cbcSMatt Macy fprintf(stderr, "Value for global variable '%s' must " 178*eda14cbcSMatt Macy "be a 32-bit unsigned integer\n", varname); 179*eda14cbcSMatt Macy return (EOVERFLOW); 180*eda14cbcSMatt Macy } 181*eda14cbcSMatt Macy } else { 182*eda14cbcSMatt Macy return (EINVAL); 183*eda14cbcSMatt Macy } 184*eda14cbcSMatt Macy 185*eda14cbcSMatt Macy zpoolhdl = dlopen("libzpool.so", RTLD_LAZY); 186*eda14cbcSMatt Macy if (zpoolhdl != NULL) { 187*eda14cbcSMatt Macy uint32_t *var; 188*eda14cbcSMatt Macy var = dlsym(zpoolhdl, varname); 189*eda14cbcSMatt Macy if (var == NULL) { 190*eda14cbcSMatt Macy fprintf(stderr, "Global variable '%s' does not exist " 191*eda14cbcSMatt Macy "in libzpool.so\n", varname); 192*eda14cbcSMatt Macy return (EINVAL); 193*eda14cbcSMatt Macy } 194*eda14cbcSMatt Macy *var = (uint32_t)val; 195*eda14cbcSMatt Macy 196*eda14cbcSMatt Macy dlclose(zpoolhdl); 197*eda14cbcSMatt Macy } else { 198*eda14cbcSMatt Macy fprintf(stderr, "Failed to open libzpool.so to set global " 199*eda14cbcSMatt Macy "variable\n"); 200*eda14cbcSMatt Macy return (EIO); 201*eda14cbcSMatt Macy } 202*eda14cbcSMatt Macy 203*eda14cbcSMatt Macy return (0); 204*eda14cbcSMatt Macy } 205*eda14cbcSMatt Macy 206*eda14cbcSMatt Macy static nvlist_t * 207*eda14cbcSMatt Macy refresh_config(void *unused, nvlist_t *tryconfig) 208*eda14cbcSMatt Macy { 209*eda14cbcSMatt Macy return (spa_tryimport(tryconfig)); 210*eda14cbcSMatt Macy } 211*eda14cbcSMatt Macy 212*eda14cbcSMatt Macy static int 213*eda14cbcSMatt Macy pool_active(void *unused, const char *name, uint64_t guid, 214*eda14cbcSMatt Macy boolean_t *isactive) 215*eda14cbcSMatt Macy { 216*eda14cbcSMatt Macy zfs_cmd_t *zcp; 217*eda14cbcSMatt Macy nvlist_t *innvl; 218*eda14cbcSMatt Macy char *packed = NULL; 219*eda14cbcSMatt Macy size_t size = 0; 220*eda14cbcSMatt Macy int fd, ret; 221*eda14cbcSMatt Macy 222*eda14cbcSMatt Macy /* 223*eda14cbcSMatt Macy * Use ZFS_IOC_POOL_SYNC to confirm if a pool is active 224*eda14cbcSMatt Macy */ 225*eda14cbcSMatt Macy 226*eda14cbcSMatt Macy fd = open(ZFS_DEV, O_RDWR); 227*eda14cbcSMatt Macy if (fd < 0) 228*eda14cbcSMatt Macy return (-1); 229*eda14cbcSMatt Macy 230*eda14cbcSMatt Macy zcp = umem_zalloc(sizeof (zfs_cmd_t), UMEM_NOFAIL); 231*eda14cbcSMatt Macy 232*eda14cbcSMatt Macy innvl = fnvlist_alloc(); 233*eda14cbcSMatt Macy fnvlist_add_boolean_value(innvl, "force", B_FALSE); 234*eda14cbcSMatt Macy 235*eda14cbcSMatt Macy (void) strlcpy(zcp->zc_name, name, sizeof (zcp->zc_name)); 236*eda14cbcSMatt Macy packed = fnvlist_pack(innvl, &size); 237*eda14cbcSMatt Macy zcp->zc_nvlist_src = (uint64_t)(uintptr_t)packed; 238*eda14cbcSMatt Macy zcp->zc_nvlist_src_size = size; 239*eda14cbcSMatt Macy 240*eda14cbcSMatt Macy ret = zfs_ioctl_fd(fd, ZFS_IOC_POOL_SYNC, zcp); 241*eda14cbcSMatt Macy 242*eda14cbcSMatt Macy fnvlist_pack_free(packed, size); 243*eda14cbcSMatt Macy free((void *)(uintptr_t)zcp->zc_nvlist_dst); 244*eda14cbcSMatt Macy nvlist_free(innvl); 245*eda14cbcSMatt Macy umem_free(zcp, sizeof (zfs_cmd_t)); 246*eda14cbcSMatt Macy 247*eda14cbcSMatt Macy (void) close(fd); 248*eda14cbcSMatt Macy 249*eda14cbcSMatt Macy *isactive = (ret == 0); 250*eda14cbcSMatt Macy 251*eda14cbcSMatt Macy return (0); 252*eda14cbcSMatt Macy } 253*eda14cbcSMatt Macy 254*eda14cbcSMatt Macy const pool_config_ops_t libzpool_config_ops = { 255*eda14cbcSMatt Macy .pco_refresh_config = refresh_config, 256*eda14cbcSMatt Macy .pco_pool_active = pool_active, 257*eda14cbcSMatt Macy }; 258