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 32 #include <libzutil.h> 33 34 static void 35 dump_ddt_stat(const ddt_stat_t *dds, int h) 36 { 37 char refcnt[6]; 38 char blocks[6], lsize[6], psize[6], dsize[6]; 39 char ref_blocks[6], ref_lsize[6], ref_psize[6], ref_dsize[6]; 40 41 if (dds == NULL || dds->dds_blocks == 0) 42 return; 43 44 if (h == -1) 45 (void) strcpy(refcnt, "Total"); 46 else 47 zfs_nicenum(1ULL << h, refcnt, sizeof (refcnt)); 48 49 zfs_nicenum(dds->dds_blocks, blocks, sizeof (blocks)); 50 zfs_nicebytes(dds->dds_lsize, lsize, sizeof (lsize)); 51 zfs_nicebytes(dds->dds_psize, psize, sizeof (psize)); 52 zfs_nicebytes(dds->dds_dsize, dsize, sizeof (dsize)); 53 zfs_nicenum(dds->dds_ref_blocks, ref_blocks, sizeof (ref_blocks)); 54 zfs_nicebytes(dds->dds_ref_lsize, ref_lsize, sizeof (ref_lsize)); 55 zfs_nicebytes(dds->dds_ref_psize, ref_psize, sizeof (ref_psize)); 56 zfs_nicebytes(dds->dds_ref_dsize, ref_dsize, sizeof (ref_dsize)); 57 58 (void) printf("%6s %6s %5s %5s %5s %6s %5s %5s %5s\n", 59 refcnt, 60 blocks, lsize, psize, dsize, 61 ref_blocks, ref_lsize, ref_psize, ref_dsize); 62 } 63 64 /* 65 * Print the DDT histogram and the column totals. 66 */ 67 void 68 zpool_dump_ddt(const ddt_stat_t *dds_total, const ddt_histogram_t *ddh) 69 { 70 int h; 71 72 (void) printf("\n"); 73 74 (void) printf("bucket " 75 " allocated " 76 " referenced \n"); 77 (void) printf("______ " 78 "______________________________ " 79 "______________________________\n"); 80 81 (void) printf("%6s %6s %5s %5s %5s %6s %5s %5s %5s\n", 82 "refcnt", 83 "blocks", "LSIZE", "PSIZE", "DSIZE", 84 "blocks", "LSIZE", "PSIZE", "DSIZE"); 85 86 (void) printf("%6s %6s %5s %5s %5s %6s %5s %5s %5s\n", 87 "------", 88 "------", "-----", "-----", "-----", 89 "------", "-----", "-----", "-----"); 90 91 for (h = 0; h < 64; h++) 92 dump_ddt_stat(&ddh->ddh_stat[h], h); 93 94 dump_ddt_stat(dds_total, -1); 95 96 (void) printf("\n"); 97 } 98 99 /* 100 * Process the buffer of nvlists, unpacking and storing each nvlist record 101 * into 'records'. 'leftover' is set to the number of bytes that weren't 102 * processed as there wasn't a complete record. 103 */ 104 int 105 zpool_history_unpack(char *buf, uint64_t bytes_read, uint64_t *leftover, 106 nvlist_t ***records, uint_t *numrecords) 107 { 108 uint64_t reclen; 109 nvlist_t *nv; 110 int i; 111 void *tmp; 112 113 while (bytes_read > sizeof (reclen)) { 114 115 /* get length of packed record (stored as little endian) */ 116 for (i = 0, reclen = 0; i < sizeof (reclen); i++) 117 reclen += (uint64_t)(((uchar_t *)buf)[i]) << (8*i); 118 119 if (bytes_read < sizeof (reclen) + reclen) 120 break; 121 122 /* unpack record */ 123 int err = nvlist_unpack(buf + sizeof (reclen), reclen, &nv, 0); 124 if (err != 0) 125 return (err); 126 bytes_read -= sizeof (reclen) + reclen; 127 buf += sizeof (reclen) + reclen; 128 129 /* add record to nvlist array */ 130 (*numrecords)++; 131 if (ISP2(*numrecords + 1)) { 132 tmp = realloc(*records, 133 *numrecords * 2 * sizeof (nvlist_t *)); 134 if (tmp == NULL) { 135 nvlist_free(nv); 136 (*numrecords)--; 137 return (ENOMEM); 138 } 139 *records = tmp; 140 } 141 (*records)[*numrecords - 1] = nv; 142 } 143 144 *leftover = bytes_read; 145 return (0); 146 } 147