/*ARGSUSED*/ static int simple_report_collection_cb(lcollection_t *lcol, void *arg) { #define DELTA(field) \ (unsigned long long)( \ (lcol->lcol_stat.field - lcol->lcol_stat_old.field)) debug("%s %s status: succeeded/attempted (k): %llu/%llu, " "ineffective/scans/unenforced/samplings: %llu/%llu/%llu/%llu, RSS " "min/max (k): %llu/%llu, cap %llu kB, processes/thpt: %llu/%llu, " "%llu scans over %llu ms\n", (lcol->lcol_id.rcid_type == RCIDT_PROJECT ? "project" : "zone"), lcol->lcol_name, DELTA(lcols_pg_eff), DELTA(lcols_pg_att), DELTA(lcols_scan_ineffective), DELTA(lcols_scan), DELTA(lcols_unenforced_cap), DELTA(lcols_rss_sample), (unsigned long long)lcol->lcol_stat.lcols_min_rss, (unsigned long long)lcol->lcol_stat.lcols_max_rss, (unsigned long long)lcol->lcol_rss_cap, (unsigned long long)(lcol->lcol_stat.lcols_proc_in - lcol->lcol_stat.lcols_proc_out), DELTA(lcols_proc_out), DELTA(lcols_scan_count), NSEC2MSEC(DELTA(lcols_scan_time_complete))); #undef DELTA return (0); }
static int print_delay_handler(int id, const char *pool, zinject_record_t *record, void *data) { int *count = data; if (record->zi_guid == 0 || record->zi_func[0] != '\0') return (0); if (record->zi_cmd != ZINJECT_DELAY_IO) return (0); if (*count == 0) { (void) printf("%3s %-15s %-15s %-15s %s\n", "ID", "POOL", "DELAY (ms)", "LANES", "GUID"); (void) printf("--- --------------- --------------- " "--------------- ----------------\n"); } *count += 1; (void) printf("%3d %-15s %-15llu %-15llu %llx\n", id, pool, (u_longlong_t)NSEC2MSEC(record->zi_timer), (u_longlong_t)record->zi_nlanes, (u_longlong_t)record->zi_guid); return (0); }
static boolean_t dsl_scan_check_pause(dsl_scan_t *scn, const zbookmark_t *zb) { uint64_t elapsed_nanosecs; int mintime; /* we never skip user/group accounting objects */ if (zb && (int64_t)zb->zb_object < 0) return (B_FALSE); if (scn->scn_pausing) return (B_TRUE); /* we're already pausing */ if (!ZB_IS_ZERO(&scn->scn_phys.scn_bookmark)) return (B_FALSE); /* we're resuming */ /* We only know how to resume from level-0 blocks. */ if (zb && zb->zb_level != 0) return (B_FALSE); mintime = (scn->scn_phys.scn_func == POOL_SCAN_RESILVER) ? zfs_resilver_min_time_ms : zfs_scan_min_time_ms; elapsed_nanosecs = gethrtime() - scn->scn_sync_start_time; if (elapsed_nanosecs / NANOSEC > zfs_txg_timeout || (NSEC2MSEC(elapsed_nanosecs) > mintime && txg_sync_waiting(scn->scn_dp)) || spa_shutting_down(scn->scn_dp->dp_spa)) { if (zb) { dprintf("pausing at bookmark %llx/%llx/%llx/%llx\n", (longlong_t)zb->zb_objset, (longlong_t)zb->zb_object, (longlong_t)zb->zb_level, (longlong_t)zb->zb_blkid); scn->scn_phys.scn_bookmark = *zb; } dprintf("pausing at DDT bookmark %llx/%llx/%llx/%llx\n", (longlong_t)scn->scn_phys.scn_ddt_bookmark.ddb_class, (longlong_t)scn->scn_phys.scn_ddt_bookmark.ddb_type, (longlong_t)scn->scn_phys.scn_ddt_bookmark.ddb_checksum, (longlong_t)scn->scn_phys.scn_ddt_bookmark.ddb_cursor); scn->scn_pausing = B_TRUE; return (B_TRUE); } return (B_FALSE); }
/*ARGSUSED*/ static void print_unformatted_stats(void) { col_t *col; #define DELTA(field) \ (col->col_src_stat.field - col->col_old_stat.field) col = col_head; while (col != NULL) { if (bcmp(&col->col_src_stat, &col->col_old_stat, sizeof (col->col_src_stat)) == 0) { col = col->col_next; continue; } (void) printf("%s %s status: succeeded/attempted (k): " "%llu/%llu, ineffective/scans/unenforced/samplings: " "%llu/%llu/%llu/%llu, RSS min/max (k): %llu/%llu, cap %llu " "kB, processes/thpt: %llu/%llu, %llu scans over %lld ms\n", mode, col->col_name, DELTA(lcols_pg_eff), DELTA(lcols_pg_att), DELTA(lcols_scan_ineffective), DELTA(lcols_scan), DELTA(lcols_unenforced_cap), DELTA(lcols_rss_sample), col->col_src_stat.lcols_min_rss, col->col_src_stat.lcols_max_rss, col->col_rsslimit, (col->col_src_stat.lcols_proc_in - col->col_old_stat.lcols_proc_out), DELTA(lcols_proc_out), DELTA(lcols_scan_count), NSEC2MSEC(DELTA(lcols_scan_time_complete))); col->col_old_stat = col->col_src_stat; col = col->col_next; } if (global) (void) printf(gettext("physical memory utilization: %3u%% " "cap enforcement threshold: %3u%%\n"), hdr.rs_pressure_cur, hdr.rs_pressure_cap); #undef DELTA }
static int request_log(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { request_log_entry_t cur; hrtime_t dur; hrtime_t dursec; hrtime_t durnsec; char durstr[20]; char stampstr[20]; char requstr[30]; char respstr[30]; char typestr[30]; uintptr_t node = 0; uintptr_t client = 0; uint64_t clientid = 0; int idx; int opt_v = FALSE; /* verbose */ if (!(flags & DCMD_ADDRSPEC)) { if (mdb_walk_dcmd("configd_log", "configd_log", argc, argv) == -1) { mdb_warn("can't walk 'configd_log'"); return (DCMD_ERR); } return (DCMD_OK); } if (mdb_getopts(argc, argv, 'c', MDB_OPT_UINTPTR, &client, 'i', MDB_OPT_UINT64, &clientid, 'n', MDB_OPT_UINTPTR, &node, 'v', MDB_OPT_SETBITS, TRUE, &opt_v, NULL) != argc) return (DCMD_USAGE); if (DCMD_HDRSPEC(flags)) { mdb_printf("%<u>%-?s %-4s %-14s %9s %-22s %-17s\n%</u>", "ADDR", "THRD", "START", "DURATION", "REQUEST", "RESPONSE"); } if (mdb_vread(&cur, sizeof (cur), addr) == -1) { mdb_warn("couldn't read log entry at %p", addr); return (DCMD_ERR); } /* * apply filters, if any. */ if (clientid != 0 && clientid != cur.rl_clientid) return (DCMD_OK); if (client != 0 && client != (uintptr_t)cur.rl_client) return (DCMD_OK); if (node != 0) { for (idx = 0; idx < MIN(MAX_PTRS, cur.rl_num_ptrs); idx++) { if ((uintptr_t)cur.rl_ptrs[idx].rlp_data == node) { node = 0; /* found it */ break; } } if (node != 0) return (DCMD_OK); } enum_lookup(requstr, sizeof (requstr), request_enum, cur.rl_request, "REP_PROTOCOL_", ""); if (cur.rl_end != 0) { enum_lookup(respstr, sizeof (respstr), response_enum, cur.rl_response, "REP_PROTOCOL_", "FAIL_"); dur = cur.rl_end - cur.rl_start; dursec = dur / NANOSEC; durnsec = dur % NANOSEC; if (dursec <= 9) mdb_snprintf(durstr, sizeof (durstr), "%lld.%06lld", dursec, durnsec / (NANOSEC / MICROSEC)); else if (dursec <= 9999) mdb_snprintf(durstr, sizeof (durstr), "%lld.%03lld", dursec, NSEC2MSEC(durnsec)); else mdb_snprintf(durstr, sizeof (durstr), "%lld", dursec); } else { (void) strcpy(durstr, "-"); (void) strcpy(respstr, "-"); } if (max_time_seen != 0 && max_time_seen >= cur.rl_start) { dur = max_time_seen - cur.rl_start; dursec = dur / NANOSEC; durnsec = dur % NANOSEC; if (dursec <= 99ULL) mdb_snprintf(stampstr, sizeof (stampstr), "-%lld.%09lld", dursec, durnsec); else if (dursec <= 99999ULL) mdb_snprintf(stampstr, sizeof (stampstr), "-%lld.%06lld", dursec, durnsec / (NANOSEC / MICROSEC)); else if (dursec <= 99999999ULL) mdb_snprintf(stampstr, sizeof (stampstr), "-%lld.%03lld", dursec, NSEC2MSEC(durnsec)); else mdb_snprintf(stampstr, sizeof (stampstr), "-%lld", dursec); } else { (void) strcpy(stampstr, "-"); } mdb_printf("%0?x %4d T%13s %9s %-22s %-17s\n", addr, cur.rl_tid, stampstr, durstr, requstr, respstr); if (opt_v) { mdb_printf("\tclient: %?p (%d)\tptrs: %d\tstamp: %llx\n", cur.rl_client, cur.rl_clientid, cur.rl_num_ptrs, cur.rl_start); for (idx = 0; idx < MIN(MAX_PTRS, cur.rl_num_ptrs); idx++) { enum_lookup(typestr, sizeof (typestr), ptr_type_enum, cur.rl_ptrs[idx].rlp_type, "RC_PTR_TYPE_", ""); mdb_printf("\t\t%-7s %5d %?p %?p\n", typestr, cur.rl_ptrs[idx].rlp_id, cur.rl_ptrs[idx].rlp_ptr, cur.rl_ptrs[idx].rlp_data); } mdb_printf("\n"); } return (DCMD_OK); }
/* * Get a DLPI control message and/or data message from a stream. The inputs * for this function are: * dlpi_impl_t *dip: internal dlpi handle * int msec: timeout to wait for message * dlpi_msg_t *dlreplyp: reply message structure, the message size * member on return stores actual size received * t_uscalar_t dlreqprim: requested primitive * t_uscalar_t dlreplyprim:acknowledged primitive in response to request * size_t dlreplyminsz: minimum size of acknowledged primitive size * void *databuf: data buffer * size_t *datalenp: data buffer len * size_t *totdatalenp: total data received. Greater than 'datalenp' if * actual data received is larger than 'databuf' * Function returns DLPI_SUCCESS if requested message is retrieved * otherwise returns error code or timeouts. If a notification arrives on * the stream the callback is notified. However, error returned during the * handling of notification is ignored as it would be confusing to actual caller * of this function. */ static int i_dlpi_strgetmsg(dlpi_impl_t *dip, int msec, dlpi_msg_t *dlreplyp, t_uscalar_t dlreqprim, t_uscalar_t dlreplyprim, size_t dlreplyminsz, void *databuf, size_t *datalenp, size_t *totdatalenp) { int retval; int flags; int fd = dip->dli_fd; struct strbuf ctl, data; struct pollfd pfd; hrtime_t start, current; long bufc[DLPI_CHUNKSIZE / sizeof (long)]; long bufd[DLPI_CHUNKSIZE / sizeof (long)]; union DL_primitives *dlprim; dl_notify_ind_t *dlnotif; boolean_t infinite = (msec < 0); /* infinite timeout */ /* * dlreplyp and databuf can be NULL at the same time, to force a check * for pending events on the DLPI link instance; dlpi_enabnotify(3DLPI). * this will be true more so for DLPI_RAW mode with notifications * enabled. */ if ((databuf == NULL && datalenp != NULL) || (databuf != NULL && datalenp == NULL)) return (DLPI_EINVAL); pfd.fd = fd; pfd.events = POLLIN | POLLPRI; ctl.buf = (dlreplyp == NULL) ? bufc : (void *)dlreplyp->dlm_msg; ctl.len = 0; ctl.maxlen = (dlreplyp == NULL) ? sizeof (bufc) : dlreplyp->dlm_msgsz; data.buf = (databuf == NULL) ? bufd : databuf; data.len = 0; data.maxlen = (databuf == NULL) ? sizeof (bufd): *datalenp; for (;;) { if (!infinite) start = NSEC2MSEC(gethrtime()); switch (poll(&pfd, 1, msec)) { default: if (pfd.revents & POLLHUP) return (DL_SYSERR); break; case 0: return (DLPI_ETIMEDOUT); case -1: return (DL_SYSERR); } flags = 0; if ((retval = getmsg(fd, &ctl, &data, &flags)) < 0) return (DL_SYSERR); if (totdatalenp != NULL) *totdatalenp = data.len; /* * The supplied DLPI_CHUNKSIZE sized buffers are large enough * to retrieve all valid DLPI responses in one iteration. * If MORECTL or MOREDATA is set, we are not interested in the * remainder of the message. Temporary buffers are used to * drain the remainder of this message. * The special case we have to account for is if * a higher priority messages is enqueued whilst handling * this condition. We use a change in the flags parameter * returned by getmsg() to indicate the message has changed. */ while (retval & (MORECTL | MOREDATA)) { struct strbuf cscratch, dscratch; int oflags = flags; cscratch.buf = (char *)bufc; dscratch.buf = (char *)bufd; cscratch.len = dscratch.len = 0; cscratch.maxlen = dscratch.maxlen = sizeof (bufc); if ((retval = getmsg(fd, &cscratch, &dscratch, &flags)) < 0) return (DL_SYSERR); if (totdatalenp != NULL) *totdatalenp += dscratch.len; /* * In the special case of higher priority * message received, the low priority message * received earlier is discarded, if no data * or control message is left. */ if ((flags != oflags) && !(retval & (MORECTL | MOREDATA)) && (cscratch.len != 0)) { ctl.len = MIN(cscratch.len, DLPI_CHUNKSIZE); if (dlreplyp != NULL) (void) memcpy(dlreplyp->dlm_msg, bufc, ctl.len); break; } } /* * Check if DL_NOTIFY_IND message received. If there is one, * notify the callback function(s) and continue processing the * requested message. */ if (dip->dli_notifylistp != NULL && ctl.len >= (int)(sizeof (t_uscalar_t)) && *(t_uscalar_t *)(void *)ctl.buf == DL_NOTIFY_IND) { /* process properly-formed DL_NOTIFY_IND messages */ if (ctl.len >= DL_NOTIFY_IND_SIZE) { dlnotif = (dl_notify_ind_t *)(void *)ctl.buf; (void) i_dlpi_notifyind_process(dip, dlnotif); } goto update_timer; } /* * If we were expecting a data message, and we got one, set * *datalenp. If we aren't waiting on a control message, then * we're done. */ if (databuf != NULL && data.len >= 0) { *datalenp = data.len; if (dlreplyp == NULL) break; } /* * If we were expecting a control message, and the message * we received is at least big enough to be a DLPI message, * then verify it's a reply to something we sent. If it * is a reply to something we sent, also verify its size. */ if (dlreplyp != NULL && ctl.len >= sizeof (t_uscalar_t)) { dlprim = dlreplyp->dlm_msg; if (dlprim->dl_primitive == dlreplyprim) { if (ctl.len < dlreplyminsz) return (DLPI_EBADMSG); dlreplyp->dlm_msgsz = ctl.len; break; } else if (dlprim->dl_primitive == DL_ERROR_ACK) { if (ctl.len < DL_ERROR_ACK_SIZE) return (DLPI_EBADMSG); /* Is it ours? */ if (dlprim->error_ack.dl_error_primitive == dlreqprim) break; } } update_timer: if (!infinite) { current = NSEC2MSEC(gethrtime()); msec -= (current - start); if (msec <= 0) return (DLPI_ETIMEDOUT); } } return (DLPI_SUCCESS); }