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