1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 24 * Copyright 2020 Joyent, Inc. 25 */ 26 27 #include <stdio.h> 28 #include <stdlib.h> 29 #include <string.h> 30 #include <sys/nvpair.h> 31 #include <sys/fs/zfs.h> 32 #include <sys/sysmacros.h> 33 #include <unistd.h> 34 35 #include <libzutil.h> 36 37 static void 38 dump_ddt_stat(const ddt_stat_t *dds, int h) 39 { 40 char refcnt[6]; 41 char blocks[6], lsize[6], psize[6], dsize[6]; 42 char ref_blocks[6], ref_lsize[6], ref_psize[6], ref_dsize[6]; 43 44 if (dds == NULL || dds->dds_blocks == 0) 45 return; 46 47 if (h == -1) 48 (void) strcpy(refcnt, "Total"); 49 else 50 zfs_nicenum(1ULL << h, refcnt, sizeof (refcnt)); 51 52 zfs_nicenum(dds->dds_blocks, blocks, sizeof (blocks)); 53 zfs_nicebytes(dds->dds_lsize, lsize, sizeof (lsize)); 54 zfs_nicebytes(dds->dds_psize, psize, sizeof (psize)); 55 zfs_nicebytes(dds->dds_dsize, dsize, sizeof (dsize)); 56 zfs_nicenum(dds->dds_ref_blocks, ref_blocks, sizeof (ref_blocks)); 57 zfs_nicebytes(dds->dds_ref_lsize, ref_lsize, sizeof (ref_lsize)); 58 zfs_nicebytes(dds->dds_ref_psize, ref_psize, sizeof (ref_psize)); 59 zfs_nicebytes(dds->dds_ref_dsize, ref_dsize, sizeof (ref_dsize)); 60 61 (void) printf("%6s %6s %5s %5s %5s %6s %5s %5s %5s\n", 62 refcnt, 63 blocks, lsize, psize, dsize, 64 ref_blocks, ref_lsize, ref_psize, ref_dsize); 65 } 66 67 /* 68 * Print the DDT histogram and the column totals. 69 */ 70 void 71 zpool_dump_ddt(const ddt_stat_t *dds_total, const ddt_histogram_t *ddh) 72 { 73 int h; 74 75 (void) printf("\n"); 76 77 (void) printf("bucket " 78 " allocated " 79 " referenced \n"); 80 (void) printf("______ " 81 "______________________________ " 82 "______________________________\n"); 83 84 (void) printf("%6s %6s %5s %5s %5s %6s %5s %5s %5s\n", 85 "refcnt", 86 "blocks", "LSIZE", "PSIZE", "DSIZE", 87 "blocks", "LSIZE", "PSIZE", "DSIZE"); 88 89 (void) printf("%6s %6s %5s %5s %5s %6s %5s %5s %5s\n", 90 "------", 91 "------", "-----", "-----", "-----", 92 "------", "-----", "-----", "-----"); 93 94 for (h = 0; h < 64; h++) 95 dump_ddt_stat(&ddh->ddh_stat[h], h); 96 97 dump_ddt_stat(dds_total, -1); 98 99 (void) printf("\n"); 100 } 101 102 /* 103 * Process the buffer of nvlists, unpacking and storing each nvlist record 104 * into 'records'. 'leftover' is set to the number of bytes that weren't 105 * processed as there wasn't a complete record. 106 */ 107 int 108 zpool_history_unpack(char *buf, uint64_t bytes_read, uint64_t *leftover, 109 nvlist_t ***records, uint_t *numrecords) 110 { 111 uint64_t reclen; 112 nvlist_t *nv; 113 int i; 114 void *tmp; 115 116 while (bytes_read > sizeof (reclen)) { 117 118 /* get length of packed record (stored as little endian) */ 119 for (i = 0, reclen = 0; i < sizeof (reclen); i++) 120 reclen += (uint64_t)(((uchar_t *)buf)[i]) << (8*i); 121 122 if (bytes_read < sizeof (reclen) + reclen) 123 break; 124 125 /* unpack record */ 126 if (nvlist_unpack(buf + sizeof (reclen), reclen, &nv, 0) != 0) 127 return (ENOMEM); 128 bytes_read -= sizeof (reclen) + reclen; 129 buf += sizeof (reclen) + reclen; 130 131 /* add record to nvlist array */ 132 (*numrecords)++; 133 if (ISP2(*numrecords + 1)) { 134 tmp = realloc(*records, 135 *numrecords * 2 * sizeof (nvlist_t *)); 136 if (tmp == NULL) { 137 nvlist_free(nv); 138 (*numrecords)--; 139 return (ENOMEM); 140 } 141 *records = tmp; 142 } 143 (*records)[*numrecords - 1] = nv; 144 } 145 146 *leftover = bytes_read; 147 return (0); 148 } 149 150 ulong_t 151 get_system_hostid(void) 152 { 153 char *env; 154 155 /* 156 * Allow the hostid to be subverted for testing. 157 */ 158 env = getenv("ZFS_HOSTID"); 159 if (env) { 160 ulong_t hostid = strtoull(env, NULL, 16); 161 return (hostid & 0xFFFFFFFF); 162 } 163 164 return (gethostid()); 165 } 166