1 // SPDX-License-Identifier: CDDL-1.0 2 /* 3 * CDDL HEADER START 4 * 5 * This file and its contents are supplied under the terms of the 6 * Common Development and Distribution License ("CDDL"), version 1.0. 7 * You may only use this file in accordance with the terms of version 8 * 1.0 of the CDDL. 9 * 10 * A full copy of the text of the CDDL should have accompanied this 11 * source. A copy of the CDDL is also available via the Internet at 12 * http://www.illumos.org/license/CDDL. 13 * 14 * CDDL HEADER END 15 */ 16 17 /* 18 * Copyright (c) 2020 by Delphix. All rights reserved. 19 */ 20 21 #include <assert.h> 22 #include <fcntl.h> 23 #include <stdio.h> 24 #include <libzfs.h> 25 #include <sys/zfs_ioctl.h> 26 #include <sys/nvpair.h> 27 #include <sys/fm/protocol.h> 28 #include <sys/fm/fs/zfs.h> 29 30 /* 31 * Command to output io and checksum ereport values, one per line. 32 * Used by zpool_events_duplicates.ksh to check for duplicate events. 33 * 34 * example output line: 35 * 36 * checksum "error_pool" 0x856dd01ce52e336 0x000034 0x000400 0x000a402c00 37 * 0x000004 0x000000 0x000000 0x000000 0x000001 38 */ 39 40 /* 41 * Our ereport duplicate criteria 42 * 43 * When the class and all of these values match, then an ereport is 44 * considered to be a duplicate. 45 */ 46 static const char *const criteria_name[] = { 47 FM_EREPORT_PAYLOAD_ZFS_POOL, 48 FM_EREPORT_PAYLOAD_ZFS_VDEV_GUID, 49 FM_EREPORT_PAYLOAD_ZFS_ZIO_ERR, 50 FM_EREPORT_PAYLOAD_ZFS_ZIO_SIZE, 51 FM_EREPORT_PAYLOAD_ZFS_ZIO_OFFSET, 52 FM_EREPORT_PAYLOAD_ZFS_ZIO_TYPE, 53 FM_EREPORT_PAYLOAD_ZFS_ZIO_PRIORITY, 54 55 /* logical zio criteriai (optional) */ 56 FM_EREPORT_PAYLOAD_ZFS_ZIO_OBJSET, 57 FM_EREPORT_PAYLOAD_ZFS_ZIO_OBJECT, 58 FM_EREPORT_PAYLOAD_ZFS_ZIO_BLKID, 59 FM_EREPORT_PAYLOAD_ZFS_ZIO_LEVEL, 60 }; 61 62 #define CRITERIA_NAMES_COUNT ARRAY_SIZE(criteria_name) 63 64 static void 65 print_ereport_line(nvlist_t *nvl) 66 { 67 const char *class; 68 int last = CRITERIA_NAMES_COUNT - 1; 69 70 /* 71 * For the test case context, we only want to see 'io' and 72 * 'checksum' subclass. We skip 'data' to minimize the output. 73 */ 74 if (nvlist_lookup_string(nvl, FM_CLASS, &class) != 0 || 75 strstr(class, "ereport.fs.zfs.") == NULL || 76 strcmp(class, "ereport.fs.zfs.data") == 0) { 77 return; 78 } 79 80 (void) printf("%s\t", class + strlen("ereport.fs.zfs.")); 81 82 for (int i = 0; i < CRITERIA_NAMES_COUNT; i++) { 83 nvpair_t *nvp; 84 uint32_t i32 = 0; 85 uint64_t i64 = 0; 86 const char *str = NULL; 87 88 if (nvlist_lookup_nvpair(nvl, criteria_name[i], &nvp) != 0) { 89 /* print a proxy for optional criteria */ 90 (void) printf("--------"); 91 (void) printf("%c", i == last ? '\n' : '\t'); 92 continue; 93 } 94 95 switch (nvpair_type(nvp)) { 96 case DATA_TYPE_STRING: 97 (void) nvpair_value_string(nvp, &str); 98 (void) printf("\"%s\"", str ? str : "<NULL>"); 99 break; 100 101 case DATA_TYPE_INT32: 102 (void) nvpair_value_int32(nvp, (void *)&i32); 103 (void) printf("0x%06x", i32); 104 break; 105 106 case DATA_TYPE_UINT32: 107 (void) nvpair_value_uint32(nvp, &i32); 108 (void) printf("0x%06x", i32); 109 break; 110 111 case DATA_TYPE_INT64: 112 (void) nvpair_value_int64(nvp, (void *)&i64); 113 (void) printf("0x%06llx", (u_longlong_t)i64); 114 break; 115 116 case DATA_TYPE_UINT64: 117 (void) nvpair_value_uint64(nvp, &i64); 118 if (strcmp(FM_EREPORT_PAYLOAD_ZFS_ZIO_OFFSET, 119 criteria_name[i]) == 0) 120 (void) printf("0x%010llx", (u_longlong_t)i64); 121 else 122 (void) printf("0x%06llx", (u_longlong_t)i64); 123 break; 124 default: 125 (void) printf("<unknown>"); 126 break; 127 } 128 (void) printf("%c", i == last ? '\n' : '\t'); 129 } 130 } 131 132 static void 133 ereports_dump(libzfs_handle_t *zhdl, int zevent_fd) 134 { 135 nvlist_t *nvl; 136 int ret, dropped; 137 138 while (1) { 139 ret = zpool_events_next(zhdl, &nvl, &dropped, ZEVENT_NONBLOCK, 140 zevent_fd); 141 if (ret || nvl == NULL) 142 break; 143 if (dropped > 0) 144 (void) fprintf(stdout, "dropped %d events\n", dropped); 145 print_ereport_line(nvl); 146 (void) fflush(stdout); 147 nvlist_free(nvl); 148 } 149 } 150 151 int 152 main(void) 153 { 154 libzfs_handle_t *hdl; 155 int fd; 156 157 hdl = libzfs_init(); 158 if (hdl == NULL) { 159 (void) fprintf(stderr, "libzfs_init: %s\n", strerror(errno)); 160 exit(2); 161 } 162 fd = open(ZFS_DEV, O_RDWR); 163 if (fd < 0) { 164 (void) fprintf(stderr, "open: %s\n", strerror(errno)); 165 libzfs_fini(hdl); 166 exit(2); 167 } 168 169 ereports_dump(hdl, fd); 170 171 (void) close(fd); 172 libzfs_fini(hdl); 173 174 return (0); 175 } 176