Changeset View
Changeset View
Standalone View
Standalone View
cddl/contrib/opensolaris/cmd/zpool/zpool_main.c
Show First 20 Lines • Show All 1,637 Lines • ▼ Show 20 Lines | if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, | ||||
(void) printf( | (void) printf( | ||||
gettext(" block size: %dB configured, %dB native"), | gettext(" block size: %dB configured, %dB native"), | ||||
1 << vs->vs_configured_ashift, 1 << vs->vs_physical_ashift); | 1 << vs->vs_configured_ashift, 1 << vs->vs_physical_ashift); | ||||
} | } | ||||
(void) nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_SCAN_STATS, | (void) nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_SCAN_STATS, | ||||
(uint64_t **)&ps, &c); | (uint64_t **)&ps, &c); | ||||
if (ps && ps->pss_state == DSS_SCANNING && | if (ps != NULL && ps->pss_state == DSS_SCANNING && | ||||
vs->vs_scan_processed != 0 && children == 0) { | vs->vs_scan_processed != 0 && children == 0) { | ||||
(void) printf(gettext(" (%s)"), | (void) printf(gettext(" (%s)"), | ||||
(ps->pss_func == POOL_SCAN_RESILVER) ? | (ps->pss_func == POOL_SCAN_RESILVER) ? | ||||
"resilvering" : "repairing"); | "resilvering" : "repairing"); | ||||
} | } | ||||
(void) printf("\n"); | (void) printf("\n"); | ||||
▲ Show 20 Lines • Show All 2,594 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* Print out detailed scrub status. | * Print out detailed scrub status. | ||||
*/ | */ | ||||
static void | static void | ||||
print_scan_status(pool_scan_stat_t *ps) | print_scan_status(pool_scan_stat_t *ps) | ||||
{ | { | ||||
time_t start, end, pause; | time_t start, end, pause; | ||||
uint64_t elapsed, mins_left, hours_left; | uint64_t total_secs_left; | ||||
uint64_t pass_exam, examined, total; | uint64_t elapsed, secs_left, mins_left, hours_left, days_left; | ||||
uint_t rate; | uint64_t pass_scanned, scanned, pass_issued, issued, total; | ||||
uint_t scan_rate, issue_rate; | |||||
double fraction_done; | double fraction_done; | ||||
char processed_buf[7], examined_buf[7], total_buf[7], rate_buf[7]; | char processed_buf[7], scanned_buf[7], issued_buf[7], total_buf[7]; | ||||
char srate_buf[7], irate_buf[7]; | |||||
(void) printf(gettext(" scan: ")); | (void) printf(gettext(" scan: ")); | ||||
/* If there's never been a scan, there's not much to say. */ | /* If there's never been a scan, there's not much to say. */ | ||||
if (ps == NULL || ps->pss_func == POOL_SCAN_NONE || | if (ps == NULL || ps->pss_func == POOL_SCAN_NONE || | ||||
ps->pss_func >= POOL_SCAN_FUNCS) { | ps->pss_func >= POOL_SCAN_FUNCS) { | ||||
(void) printf(gettext("none requested\n")); | (void) printf(gettext("none requested\n")); | ||||
return; | return; | ||||
} | } | ||||
start = ps->pss_start_time; | start = ps->pss_start_time; | ||||
end = ps->pss_end_time; | end = ps->pss_end_time; | ||||
pause = ps->pss_pass_scrub_pause; | pause = ps->pss_pass_scrub_pause; | ||||
zfs_nicenum(ps->pss_processed, processed_buf, sizeof (processed_buf)); | zfs_nicenum(ps->pss_processed, processed_buf, sizeof (processed_buf)); | ||||
assert(ps->pss_func == POOL_SCAN_SCRUB || | assert(ps->pss_func == POOL_SCAN_SCRUB || | ||||
ps->pss_func == POOL_SCAN_RESILVER); | ps->pss_func == POOL_SCAN_RESILVER); | ||||
/* | |||||
* Scan is finished or canceled. | /* Scan is finished or canceled. */ | ||||
*/ | |||||
if (ps->pss_state == DSS_FINISHED) { | if (ps->pss_state == DSS_FINISHED) { | ||||
uint64_t minutes_taken = (end - start) / 60; | total_secs_left = end - start; | ||||
char *fmt = NULL; | days_left = total_secs_left / 60 / 60 / 24; | ||||
hours_left = (total_secs_left / 60 / 60) % 24; | |||||
mins_left = (total_secs_left / 60) % 60; | |||||
secs_left = (total_secs_left % 60); | |||||
if (ps->pss_func == POOL_SCAN_SCRUB) { | if (ps->pss_func == POOL_SCAN_SCRUB) { | ||||
fmt = gettext("scrub repaired %s in %lluh%um with " | (void) printf(gettext("scrub repaired %s " | ||||
"%llu errors on %s"); | "in %llu days %02llu:%02llu:%02llu " | ||||
"with %llu errors on %s"), processed_buf, | |||||
(u_longlong_t)days_left, (u_longlong_t)hours_left, | |||||
(u_longlong_t)mins_left, (u_longlong_t)secs_left, | |||||
(u_longlong_t)ps->pss_errors, ctime(&end)); | |||||
} else if (ps->pss_func == POOL_SCAN_RESILVER) { | } else if (ps->pss_func == POOL_SCAN_RESILVER) { | ||||
fmt = gettext("resilvered %s in %lluh%um with " | (void) printf(gettext("resilvered %s " | ||||
"%llu errors on %s"); | "in %llu days %02llu:%02llu:%02llu " | ||||
"with %llu errors on %s"), processed_buf, | |||||
(u_longlong_t)days_left, (u_longlong_t)hours_left, | |||||
(u_longlong_t)mins_left, (u_longlong_t)secs_left, | |||||
(u_longlong_t)ps->pss_errors, ctime(&end)); | |||||
} | } | ||||
/* LINTED */ | |||||
(void) printf(fmt, processed_buf, | |||||
(u_longlong_t)(minutes_taken / 60), | |||||
(uint_t)(minutes_taken % 60), | |||||
(u_longlong_t)ps->pss_errors, | |||||
ctime((time_t *)&end)); | |||||
return; | return; | ||||
} else if (ps->pss_state == DSS_CANCELED) { | } else if (ps->pss_state == DSS_CANCELED) { | ||||
if (ps->pss_func == POOL_SCAN_SCRUB) { | if (ps->pss_func == POOL_SCAN_SCRUB) { | ||||
(void) printf(gettext("scrub canceled on %s"), | (void) printf(gettext("scrub canceled on %s"), | ||||
ctime(&end)); | ctime(&end)); | ||||
} else if (ps->pss_func == POOL_SCAN_RESILVER) { | } else if (ps->pss_func == POOL_SCAN_RESILVER) { | ||||
(void) printf(gettext("resilver canceled on %s"), | (void) printf(gettext("resilver canceled on %s"), | ||||
ctime(&end)); | ctime(&end)); | ||||
} | } | ||||
return; | return; | ||||
} | } | ||||
assert(ps->pss_state == DSS_SCANNING); | assert(ps->pss_state == DSS_SCANNING); | ||||
/* | /* Scan is in progress. Resilvers can't be paused. */ | ||||
* Scan is in progress. | |||||
*/ | |||||
if (ps->pss_func == POOL_SCAN_SCRUB) { | if (ps->pss_func == POOL_SCAN_SCRUB) { | ||||
if (pause == 0) { | if (pause == 0) { | ||||
(void) printf(gettext("scrub in progress since %s"), | (void) printf(gettext("scrub in progress since %s"), | ||||
ctime(&start)); | ctime(&start)); | ||||
} else { | } else { | ||||
char buf[32]; | (void) printf(gettext("scrub paused since %s"), | ||||
struct tm *p = localtime(&pause); | ctime(&pause)); | ||||
(void) strftime(buf, sizeof (buf), "%a %b %e %T %Y", p); | |||||
(void) printf(gettext("scrub paused since %s\n"), buf); | |||||
(void) printf(gettext("\tscrub started on %s"), | (void) printf(gettext("\tscrub started on %s"), | ||||
ctime(&start)); | ctime(&start)); | ||||
} | } | ||||
} else if (ps->pss_func == POOL_SCAN_RESILVER) { | } else if (ps->pss_func == POOL_SCAN_RESILVER) { | ||||
(void) printf(gettext("resilver in progress since %s"), | (void) printf(gettext("resilver in progress since %s"), | ||||
ctime(&start)); | ctime(&start)); | ||||
} | } | ||||
examined = ps->pss_examined ? ps->pss_examined : 1; | scanned = ps->pss_examined; | ||||
pass_scanned = ps->pss_pass_exam; | |||||
issued = ps->pss_issued; | |||||
pass_issued = ps->pss_pass_issued; | |||||
total = ps->pss_to_examine; | total = ps->pss_to_examine; | ||||
fraction_done = (double)examined / total; | |||||
/* elapsed time for this pass */ | /* we are only done with a block once we have issued the IO for it */ | ||||
fraction_done = (double)issued / total; | |||||
/* elapsed time for this pass, rounding up to 1 if it's 0 */ | |||||
elapsed = time(NULL) - ps->pss_pass_start; | elapsed = time(NULL) - ps->pss_pass_start; | ||||
elapsed -= ps->pss_pass_scrub_spent_paused; | elapsed -= ps->pss_pass_scrub_spent_paused; | ||||
elapsed = elapsed ? elapsed : 1; | elapsed = (elapsed != 0) ? elapsed : 1; | ||||
pass_exam = ps->pss_pass_exam ? ps->pss_pass_exam : 1; | |||||
rate = pass_exam / elapsed; | |||||
rate = rate ? rate : 1; | |||||
mins_left = ((total - examined) / rate) / 60; | |||||
hours_left = mins_left / 60; | |||||
zfs_nicenum(examined, examined_buf, sizeof (examined_buf)); | scan_rate = pass_scanned / elapsed; | ||||
issue_rate = pass_issued / elapsed; | |||||
total_secs_left = (issue_rate != 0) ? | |||||
((total - issued) / issue_rate) : UINT64_MAX; | |||||
days_left = total_secs_left / 60 / 60 / 24; | |||||
hours_left = (total_secs_left / 60 / 60) % 24; | |||||
mins_left = (total_secs_left / 60) % 60; | |||||
secs_left = (total_secs_left % 60); | |||||
/* format all of the numbers we will be reporting */ | |||||
zfs_nicenum(scanned, scanned_buf, sizeof (scanned_buf)); | |||||
zfs_nicenum(issued, issued_buf, sizeof (issued_buf)); | |||||
zfs_nicenum(total, total_buf, sizeof (total_buf)); | zfs_nicenum(total, total_buf, sizeof (total_buf)); | ||||
zfs_nicenum(scan_rate, srate_buf, sizeof (srate_buf)); | |||||
zfs_nicenum(issue_rate, irate_buf, sizeof (irate_buf)); | |||||
/* | /* doo not print estimated time if we have a paused scrub */ | ||||
* do not print estimated time if hours_left is more than 30 days | |||||
* or we have a paused scrub | |||||
*/ | |||||
if (pause == 0) { | if (pause == 0) { | ||||
zfs_nicenum(rate, rate_buf, sizeof (rate_buf)); | (void) printf(gettext("\t%s scanned at %s/s, " | ||||
(void) printf(gettext("\t%s scanned out of %s at %s/s"), | "%s issued at %s/s, %s total\n"), | ||||
examined_buf, total_buf, rate_buf); | scanned_buf, srate_buf, issued_buf, irate_buf, total_buf); | ||||
if (hours_left < (30 * 24)) { | |||||
(void) printf(gettext(", %lluh%um to go\n"), | |||||
(u_longlong_t)hours_left, (uint_t)(mins_left % 60)); | |||||
} else { | } else { | ||||
(void) printf(gettext( | (void) printf(gettext("\t%s scanned, %s issued, %s total\n"), | ||||
", (scan is slow, no estimated time)\n")); | scanned_buf, issued_buf, total_buf); | ||||
} | } | ||||
} else { | |||||
(void) printf(gettext("\t%s scanned out of %s\n"), | |||||
examined_buf, total_buf); | |||||
} | |||||
if (ps->pss_func == POOL_SCAN_RESILVER) { | if (ps->pss_func == POOL_SCAN_RESILVER) { | ||||
(void) printf(gettext(" %s resilvered, %.2f%% done\n"), | (void) printf(gettext("\t%s resilvered, %.2f%% done"), | ||||
processed_buf, 100 * fraction_done); | processed_buf, 100 * fraction_done); | ||||
} else if (ps->pss_func == POOL_SCAN_SCRUB) { | } else if (ps->pss_func == POOL_SCAN_SCRUB) { | ||||
(void) printf(gettext(" %s repaired, %.2f%% done\n"), | (void) printf(gettext("\t%s repaired, %.2f%% done"), | ||||
processed_buf, 100 * fraction_done); | processed_buf, 100 * fraction_done); | ||||
} | |||||
if (pause == 0) { | |||||
if (issue_rate >= 10 * 1024 * 1024) { | |||||
(void) printf(gettext(", %llu days " | |||||
"%02llu:%02llu:%02llu to go\n"), | |||||
(u_longlong_t)days_left, (u_longlong_t)hours_left, | |||||
(u_longlong_t)mins_left, (u_longlong_t)secs_left); | |||||
} else { | |||||
(void) printf(gettext(", no estimated " | |||||
"completion time\n")); | |||||
} | |||||
} else { | |||||
(void) printf(gettext("\n")); | |||||
} | } | ||||
} | } | ||||
/* | /* | ||||
* As we don't scrub checkpointed blocks, we want to warn the | * As we don't scrub checkpointed blocks, we want to warn the | ||||
* user that we skipped scanning some blocks if a checkpoint exists | * user that we skipped scanning some blocks if a checkpoint exists | ||||
* or existed at any time during the scan. | * or existed at any time during the scan. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 1,811 Lines • Show Last 20 Lines |