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 https://opensource.org/licenses/CDDL-1.0. 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 */ 25 26 #include <stdio.h> 27 #include <stdlib.h> 28 #include <string.h> 29 #include <sys/nvpair.h> 30 #include <sys/fs/zfs.h> 31 #include <math.h> 32 33 #include <libzutil.h> 34 35 static void 36 dump_ddt_stat(const ddt_stat_t *dds, int h) 37 { 38 char refcnt[6]; 39 char blocks[6], lsize[6], psize[6], dsize[6]; 40 char ref_blocks[6], ref_lsize[6], ref_psize[6], ref_dsize[6]; 41 42 if (dds == NULL || dds->dds_blocks == 0) 43 return; 44 45 if (h == -1) 46 (void) strcpy(refcnt, "Total"); 47 else 48 zfs_nicenum(1ULL << h, refcnt, sizeof (refcnt)); 49 50 zfs_nicenum(dds->dds_blocks, blocks, sizeof (blocks)); 51 zfs_nicebytes(dds->dds_lsize, lsize, sizeof (lsize)); 52 zfs_nicebytes(dds->dds_psize, psize, sizeof (psize)); 53 zfs_nicebytes(dds->dds_dsize, dsize, sizeof (dsize)); 54 zfs_nicenum(dds->dds_ref_blocks, ref_blocks, sizeof (ref_blocks)); 55 zfs_nicebytes(dds->dds_ref_lsize, ref_lsize, sizeof (ref_lsize)); 56 zfs_nicebytes(dds->dds_ref_psize, ref_psize, sizeof (ref_psize)); 57 zfs_nicebytes(dds->dds_ref_dsize, ref_dsize, sizeof (ref_dsize)); 58 59 (void) printf("%6s %6s %5s %5s %5s %6s %5s %5s %5s\n", 60 refcnt, 61 blocks, lsize, psize, dsize, 62 ref_blocks, ref_lsize, ref_psize, ref_dsize); 63 } 64 65 /* 66 * Print the DDT histogram and the column totals. 67 */ 68 void 69 zpool_dump_ddt(const ddt_stat_t *dds_total, const ddt_histogram_t *ddh) 70 { 71 int h; 72 73 (void) printf("\n"); 74 75 (void) printf("bucket " 76 " allocated " 77 " referenced \n"); 78 (void) printf("______ " 79 "______________________________ " 80 "______________________________\n"); 81 82 (void) printf("%6s %6s %5s %5s %5s %6s %5s %5s %5s\n", 83 "refcnt", 84 "blocks", "LSIZE", "PSIZE", "DSIZE", 85 "blocks", "LSIZE", "PSIZE", "DSIZE"); 86 87 (void) printf("%6s %6s %5s %5s %5s %6s %5s %5s %5s\n", 88 "------", 89 "------", "-----", "-----", "-----", 90 "------", "-----", "-----", "-----"); 91 92 for (h = 0; h < 64; h++) 93 dump_ddt_stat(&ddh->ddh_stat[h], h); 94 95 dump_ddt_stat(dds_total, -1); 96 97 (void) printf("\n"); 98 } 99 100 /* 101 * Process the buffer of nvlists, unpacking and storing each nvlist record 102 * into 'records'. 'leftover' is set to the number of bytes that weren't 103 * processed as there wasn't a complete record. 104 */ 105 int 106 zpool_history_unpack(char *buf, uint64_t bytes_read, uint64_t *leftover, 107 nvlist_t ***records, uint_t *numrecords) 108 { 109 uint64_t reclen; 110 nvlist_t *nv; 111 int i; 112 void *tmp; 113 114 while (bytes_read > sizeof (reclen)) { 115 116 /* get length of packed record (stored as little endian) */ 117 for (i = 0, reclen = 0; i < sizeof (reclen); i++) 118 reclen += (uint64_t)(((uchar_t *)buf)[i]) << (8*i); 119 120 if (bytes_read < sizeof (reclen) + reclen) 121 break; 122 123 /* unpack record */ 124 int err = nvlist_unpack(buf + sizeof (reclen), reclen, &nv, 0); 125 if (err != 0) 126 return (err); 127 bytes_read -= sizeof (reclen) + reclen; 128 buf += sizeof (reclen) + reclen; 129 130 /* add record to nvlist array */ 131 (*numrecords)++; 132 if (ISP2(*numrecords + 1)) { 133 tmp = realloc(*records, 134 *numrecords * 2 * sizeof (nvlist_t *)); 135 if (tmp == NULL) { 136 nvlist_free(nv); 137 (*numrecords)--; 138 return (ENOMEM); 139 } 140 *records = tmp; 141 } 142 (*records)[*numrecords - 1] = nv; 143 } 144 145 *leftover = bytes_read; 146 return (0); 147 } 148 149 /* 150 * Floating point sleep(). Allows you to pass in a floating point value for 151 * seconds. 152 */ 153 void 154 fsleep(float sec) 155 { 156 struct timespec req; 157 req.tv_sec = floor(sec); 158 req.tv_nsec = (sec - (float)req.tv_sec) * NANOSEC; 159 nanosleep(&req, NULL); 160 } 161 162 /* 163 * Get environment variable 'env' and return it as an integer. 164 * If 'env' is not set, then return 'default_val' instead. 165 */ 166 int 167 zpool_getenv_int(const char *env, int default_val) 168 { 169 char *str; 170 int val; 171 str = getenv(env); 172 if ((str == NULL) || sscanf(str, "%d", &val) != 1 || 173 val < 0) { 174 val = default_val; 175 } 176 return (val); 177 } 178