/* * Print the configuration of an exported pool. Iterate over all vdevs in the * pool, printing out the name and status for each one. */ static void lzwu_print_import_config(libzfs_handle_t *p_zhd, const char *name, nvlist_t *nv, int namewidth, int depth) { nvlist_t **child; uint_t c, children; vdev_stat_t *vs; char *type, *vname; verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0); if (strcmp(type, VDEV_TYPE_MISSING) == 0 || strcmp(type, VDEV_TYPE_HOLE) == 0) return; verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_STATS, (uint64_t **)&vs, &c) == 0); (void) printf("\t%*s%-*s", depth, "", namewidth - depth, name); (void) printf(" %s", zpool_state_to_name(vs->vs_state, vs->vs_aux)); if (vs->vs_aux != 0) { (void) printf(" "); switch (vs->vs_aux) { case VDEV_AUX_OPEN_FAILED: printf("cannot open"); break; case VDEV_AUX_BAD_GUID_SUM: printf("missing device"); break; case VDEV_AUX_NO_REPLICAS: printf("insufficient replicas"); break; case VDEV_AUX_VERSION_NEWER: printf("newer version"); break; case VDEV_AUX_ERR_EXCEEDED: printf("too many errors"); break; default: printf("corrupted data"); break; } } (void) printf("\n"); if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, &child, &children) != 0) return; for (c = 0; c < children; c++) { uint64_t is_log = B_FALSE; (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, &is_log); if (is_log) continue; vname = zpool_vdev_name(p_zhd, NULL, child[c], B_TRUE); lzwu_print_import_config(p_zhd, vname, child[c], namewidth, depth + 2); free(vname); } if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE, &child, &children) == 0) { printf("\tcache\n"); for (c = 0; c < children; c++) { vname = zpool_vdev_name(p_zhd, NULL, child[c], B_FALSE); (void) printf("\t %s\n", vname); free(vname); } } if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, &child, &children) == 0) { printf("\tspares\n"); for (c = 0; c < children; c++) { vname = zpool_vdev_name(p_zhd, NULL, child[c], B_FALSE); (void) printf("\t %s\n", vname); free(vname); } } }
/* * Convert the nvpair [nvp] to a string which is added to the environment * of the child process. * Return 0 on success, -1 on error. * * FIXME: Refactor with cmd/zpool/zpool_main.c:zpool_do_events_nvprint()? */ static void _zed_event_add_nvpair(uint64_t eid, zed_strings_t *zsp, nvpair_t *nvp) { const char *name; data_type_t type; const char *prefix = ZEVENT_VAR_PREFIX; boolean_t b; double d; uint8_t i8; uint16_t i16; uint32_t i32; uint64_t i64; char *str; assert(zsp != NULL); assert(nvp != NULL); name = nvpair_name(nvp); type = nvpair_type(nvp); switch (type) { case DATA_TYPE_BOOLEAN: _zed_event_add_var(eid, zsp, prefix, name, "%s", "1"); break; case DATA_TYPE_BOOLEAN_VALUE: (void) nvpair_value_boolean_value(nvp, &b); _zed_event_add_var(eid, zsp, prefix, name, "%s", b ? "1" : "0"); break; case DATA_TYPE_BYTE: (void) nvpair_value_byte(nvp, &i8); _zed_event_add_var(eid, zsp, prefix, name, "%d", i8); break; case DATA_TYPE_INT8: (void) nvpair_value_int8(nvp, (int8_t *) &i8); _zed_event_add_var(eid, zsp, prefix, name, "%d", i8); break; case DATA_TYPE_UINT8: (void) nvpair_value_uint8(nvp, &i8); _zed_event_add_var(eid, zsp, prefix, name, "%u", i8); break; case DATA_TYPE_INT16: (void) nvpair_value_int16(nvp, (int16_t *) &i16); _zed_event_add_var(eid, zsp, prefix, name, "%d", i16); break; case DATA_TYPE_UINT16: (void) nvpair_value_uint16(nvp, &i16); _zed_event_add_var(eid, zsp, prefix, name, "%u", i16); break; case DATA_TYPE_INT32: (void) nvpair_value_int32(nvp, (int32_t *) &i32); _zed_event_add_var(eid, zsp, prefix, name, "%d", i32); break; case DATA_TYPE_UINT32: (void) nvpair_value_uint32(nvp, &i32); _zed_event_add_var(eid, zsp, prefix, name, "%u", i32); break; case DATA_TYPE_INT64: (void) nvpair_value_int64(nvp, (int64_t *) &i64); _zed_event_add_var(eid, zsp, prefix, name, "%lld", (longlong_t) i64); break; case DATA_TYPE_UINT64: (void) nvpair_value_uint64(nvp, &i64); _zed_event_add_var(eid, zsp, prefix, name, (_zed_event_value_is_hex(name) ? "0x%.16llX" : "%llu"), (u_longlong_t) i64); /* * shadow readable strings for vdev state pairs */ if (strcmp(name, FM_EREPORT_PAYLOAD_ZFS_VDEV_STATE) == 0 || strcmp(name, FM_EREPORT_PAYLOAD_ZFS_VDEV_LASTSTATE) == 0) { char alt[32]; (void) snprintf(alt, sizeof (alt), "%s_str", name); _zed_event_add_var(eid, zsp, prefix, alt, "%s", zpool_state_to_name(i64, VDEV_AUX_NONE)); } break; case DATA_TYPE_DOUBLE: (void) nvpair_value_double(nvp, &d); _zed_event_add_var(eid, zsp, prefix, name, "%g", d); break; case DATA_TYPE_HRTIME: (void) nvpair_value_hrtime(nvp, (hrtime_t *) &i64); _zed_event_add_var(eid, zsp, prefix, name, "%llu", (u_longlong_t) i64); break; case DATA_TYPE_NVLIST: _zed_event_add_var(eid, zsp, prefix, name, "%s", "_NOT_IMPLEMENTED_"); /* FIXME */ break; case DATA_TYPE_STRING: (void) nvpair_value_string(nvp, &str); _zed_event_add_var(eid, zsp, prefix, name, "%s", (str ? str : "<NULL>")); break; case DATA_TYPE_BOOLEAN_ARRAY: _zed_event_add_var(eid, zsp, prefix, name, "%s", "_NOT_IMPLEMENTED_"); /* FIXME */ break; case DATA_TYPE_BYTE_ARRAY: _zed_event_add_var(eid, zsp, prefix, name, "%s", "_NOT_IMPLEMENTED_"); /* FIXME */ break; case DATA_TYPE_INT8_ARRAY: _zed_event_add_int8_array(eid, zsp, prefix, nvp); break; case DATA_TYPE_UINT8_ARRAY: _zed_event_add_uint8_array(eid, zsp, prefix, nvp); break; case DATA_TYPE_INT16_ARRAY: _zed_event_add_int16_array(eid, zsp, prefix, nvp); break; case DATA_TYPE_UINT16_ARRAY: _zed_event_add_uint16_array(eid, zsp, prefix, nvp); break; case DATA_TYPE_INT32_ARRAY: _zed_event_add_int32_array(eid, zsp, prefix, nvp); break; case DATA_TYPE_UINT32_ARRAY: _zed_event_add_uint32_array(eid, zsp, prefix, nvp); break; case DATA_TYPE_INT64_ARRAY: _zed_event_add_int64_array(eid, zsp, prefix, nvp); break; case DATA_TYPE_UINT64_ARRAY: _zed_event_add_uint64_array(eid, zsp, prefix, nvp); break; case DATA_TYPE_STRING_ARRAY: _zed_event_add_string_array(eid, zsp, prefix, nvp); break; case DATA_TYPE_NVLIST_ARRAY: _zed_event_add_var(eid, zsp, prefix, name, "%s", "_NOT_IMPLEMENTED_"); /* FIXME */ break; default: errno = EINVAL; zed_log_msg(LOG_WARNING, "Failed to convert nvpair \"%s\" for eid=%llu: " "Unrecognized type=%u", name, eid, (unsigned int) type); break; } }
/* * Print out configuration state as requested by status_callback. */ void lzwu_zpool_print_status_config(libzfs_handle_t *p_zhd, zpool_handle_t *zhp, const char *name, nvlist_t *nv, int namewidth, int depth, boolean_t isspare) { nvlist_t **child; uint_t children; unsigned c; vdev_stat_t *vs; char rbuf[6], wbuf[6], cbuf[6], repaired[7]; char *vname; uint64_t notpresent; spare_cbdata_t cb; char *state; verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_STATS, (uint64_t **)&vs, &c) == 0); if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, &child, &children) != 0) children = 0; state = zpool_state_to_name(vs->vs_state, vs->vs_aux); if(isspare) { /* * For hot spares, we use the terms 'INUSE' and 'AVAILABLE' for * online drives. */ if(vs->vs_aux == VDEV_AUX_SPARED) state = "INUSE"; else if(vs->vs_state == VDEV_STATE_HEALTHY) state = "AVAIL"; } printf("\t%*s%-*s %-8s", depth, "", namewidth - depth, name, state); if(!isspare) { zfs_nicenum(vs->vs_read_errors, rbuf, sizeof (rbuf)); zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf)); zfs_nicenum(vs->vs_checksum_errors, cbuf, sizeof (cbuf)); printf(" %5s %5s %5s", rbuf, wbuf, cbuf); } if(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, ¬present) == 0) { char *path; verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0); printf(" was %s", path); } else if(vs->vs_aux != 0) { printf(" "); switch (vs->vs_aux) { case VDEV_AUX_OPEN_FAILED: printf("cannot open"); break; case VDEV_AUX_BAD_GUID_SUM: printf("missing device"); break; case VDEV_AUX_NO_REPLICAS: printf("insufficient replicas"); break; case VDEV_AUX_VERSION_NEWER: printf("newer version"); break; case VDEV_AUX_SPARED: verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &cb.cb_guid) == 0); if(zpool_iter(p_zhd, lzwu_find_spare, &cb) == 1) { if(strcmp(zpool_get_name(cb.cb_zhp), zpool_get_name(zhp)) == 0) printf("currently in use"); else printf("in use by pool '%s'", zpool_get_name(cb.cb_zhp)); zpool_close(cb.cb_zhp); } else printf("currently in use"); break; case VDEV_AUX_ERR_EXCEEDED: printf("too many errors"); break; case VDEV_AUX_IO_FAILURE: printf("experienced I/O failures"); break; case VDEV_AUX_BAD_LOG: printf("bad intent log"); break; case VDEV_AUX_EXTERNAL: printf("external device fault"); break; case VDEV_AUX_SPLIT_POOL: printf("split into new pool"); break; default: printf("corrupted data"); break; } } else if(vs->vs_scrub_repaired != 0 && children == 0) { /* * Report bytes resilvered/repaired on leaf devices. */ zfs_nicenum(vs->vs_scrub_repaired, repaired, sizeof (repaired)); printf(" %s %s", repaired, (vs->vs_scrub_type == POOL_SCRUB_RESILVER) ? "resilvered" : "repaired"); } printf("\n"); for(unsigned c = 0; c < children; c++) { uint64_t islog = B_FALSE, ishole = B_FALSE; /* Don't print logs or holes here */ nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, &islog); nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_HOLE, &ishole); if(islog || ishole) continue; vname = zpool_vdev_name(p_zhd, zhp, child[c], B_TRUE); lzwu_zpool_print_status_config(p_zhd, zhp, vname, child[c], namewidth, depth + 2, isspare); free(vname); } }