minidump: De-duplicate the progress bar

The implementation of the progress bar is simple, but duplicated for
most minidump implementations. Extract the common bits to kern_dump.c.
Ensure that the bar is reset with each subsequent dump; this was only
done on some platforms previously.

Reviewed by:	markj
MFC after:	2 weeks
Sponsored by:	Juniper Networks, Inc.
Sponsored by:	Klara, Inc.
Differential Revision:	https://reviews.freebsd.org/D31885
This commit is contained in:
Mitchell Horne 2021-09-29 14:44:27 -03:00
parent 31991a5a45
commit ab4ed843a3
15 changed files with 113 additions and 248 deletions

View File

@ -60,14 +60,12 @@ static struct kerneldumpheader kdh;
/* Handle chunked writes. */
static size_t fragsz;
static void *dump_va;
static size_t counter, progress, dumpsize, wdog_next;
static size_t progress, dumpsize, wdog_next;
static int dump_retry_count = 5;
SYSCTL_INT(_machdep, OID_AUTO, dump_retry_count, CTLFLAG_RWTUN,
&dump_retry_count, 0, "Number of times dump has to retry before bailing out");
#define PG2MB(pgs) (((pgs) + (1 << 8) - 1) >> 8)
static int
blk_flush(struct dumperinfo *di)
{
@ -81,41 +79,6 @@ blk_flush(struct dumperinfo *di)
return (error);
}
static struct {
int min_per;
int max_per;
int visited;
} progress_track[10] = {
{ 0, 10, 0},
{ 10, 20, 0},
{ 20, 30, 0},
{ 30, 40, 0},
{ 40, 50, 0},
{ 50, 60, 0},
{ 60, 70, 0},
{ 70, 80, 0},
{ 80, 90, 0},
{ 90, 100, 0}
};
static void
report_progress(size_t progress, size_t dumpsize)
{
int sofar, i;
sofar = 100 - ((progress * 100) / dumpsize);
for (i = 0; i < nitems(progress_track); i++) {
if (sofar < progress_track[i].min_per ||
sofar > progress_track[i].max_per)
continue;
if (progress_track[i].visited)
return;
progress_track[i].visited = 1;
printf("..%d%%", sofar);
return;
}
}
/* Pat the watchdog approximately every 128MB of the dump. */
#define WDOG_DUMP_INTERVAL (128 * 1024 * 1024)
@ -152,12 +115,9 @@ blk_write(struct dumperinfo *di, char *ptr, vm_paddr_t pa, size_t sz)
len = maxdumpsz - fragsz;
if (len > sz)
len = sz;
counter += len;
progress -= len;
if (counter >> 24) {
report_progress(progress, dumpsize);
counter &= (1<<24) - 1;
}
dumpsys_pb_progress(len);
if (progress <= wdog_next) {
wdog_kern_pat(WD_LASTVAL);
if (wdog_next > WDOG_DUMP_INTERVAL)
@ -213,9 +173,7 @@ minidumpsys(struct dumperinfo *di)
retry_count = 0;
retry:
retry_count++;
counter = 0;
for (i = 0; i < nitems(progress_track); i++)
progress_track[i].visited = 0;
/* Walk page table pages, set bits in vm_page_dump */
pmapsize = 0;
for (va = VM_MIN_KERNEL_ADDRESS; va < MAX(KERNBASE + nkpt * NBPDR,
@ -298,6 +256,7 @@ minidumpsys(struct dumperinfo *di)
dumpsize += PAGE_SIZE;
wdog_next = progress = dumpsize;
dumpsys_pb_init(dumpsize);
/* Initialize mdhdr */
bzero(&mdhdr, sizeof(mdhdr));

View File

@ -63,9 +63,6 @@ static struct kerneldumpheader kdh;
/* Handle chunked writes. */
static size_t fragsz;
static void *dump_va;
static uint64_t counter, progress;
#define PG2MB(pgs) (((pgs) + (1 << 8) - 1) >> 8)
static int
blk_flush(struct dumperinfo *di)
@ -115,13 +112,8 @@ blk_write(struct dumperinfo *di, char *ptr, vm_paddr_t pa, size_t sz)
len = maxdumpsz - fragsz;
if (len > sz)
len = sz;
counter += len;
progress -= len;
if (counter >> 22) {
printf(" %lld", PG2MB(progress >> PAGE_SHIFT));
counter &= (1<<22) - 1;
}
dumpsys_pb_progress(len);
#ifdef SW_WATCHDOG
wdog_kern_pat(WD_LASTVAL);
#endif
@ -182,7 +174,6 @@ minidumpsys(struct dumperinfo *di)
*/
dcache_wbinv_poc_all();
counter = 0;
/* Walk page table pages, set bits in vm_page_dump */
ptesize = 0;
for (va = KERNBASE; va < kernel_vm_end; va += PAGE_SIZE) {
@ -206,7 +197,7 @@ minidumpsys(struct dumperinfo *di)
}
dumpsize += PAGE_SIZE;
progress = dumpsize;
dumpsys_pb_init(dumpsize);
/* Initialize mdhdr */
bzero(&mdhdr, sizeof(mdhdr));

View File

@ -36,6 +36,9 @@
#define DUMPSYS_MD_PA_NPAIRS 20
#define DUMPSYS_NUM_AUX_HDRS 1
/* How often to check the dump progress bar? */
#define DUMPSYS_PB_CHECK_BITS 22 /* Every 4MB */
void dumpsys_wbinv_all(void);
int dumpsys_write_aux_headers(struct dumperinfo *di);

View File

@ -62,7 +62,7 @@ static struct kerneldumpheader kdh;
/* Handle chunked writes. */
static size_t fragsz;
static void *dump_va;
static size_t counter, progress, dumpsize;
static size_t dumpsize;
static uint64_t tmpbuffer[Ln_ENTRIES];
@ -79,41 +79,6 @@ blk_flush(struct dumperinfo *di)
return (error);
}
static struct {
int min_per;
int max_per;
int visited;
} progress_track[10] = {
{ 0, 10, 0},
{ 10, 20, 0},
{ 20, 30, 0},
{ 30, 40, 0},
{ 40, 50, 0},
{ 50, 60, 0},
{ 60, 70, 0},
{ 70, 80, 0},
{ 80, 90, 0},
{ 90, 100, 0}
};
static void
report_progress(size_t progress, size_t dumpsize)
{
int sofar, i;
sofar = 100 - ((progress * 100) / dumpsize);
for (i = 0; i < nitems(progress_track); i++) {
if (sofar < progress_track[i].min_per ||
sofar > progress_track[i].max_per)
continue;
if (progress_track[i].visited)
return;
progress_track[i].visited = 1;
printf("..%d%%", sofar);
return;
}
}
static int
blk_write(struct dumperinfo *di, char *ptr, vm_paddr_t pa, size_t sz)
{
@ -150,13 +115,8 @@ blk_write(struct dumperinfo *di, char *ptr, vm_paddr_t pa, size_t sz)
len = maxdumpsz - fragsz;
if (len > sz)
len = sz;
counter += len;
progress -= len;
if (counter >> 22) {
report_progress(progress, dumpsize);
counter &= (1 << 22) - 1;
}
dumpsys_pb_progress(len);
wdog_kern_pat(WD_LASTVAL);
if (ptr) {
@ -245,7 +205,7 @@ minidumpsys(struct dumperinfo *di)
}
dumpsize += PAGE_SIZE;
progress = dumpsize;
dumpsys_pb_init(dumpsize);
/* Initialize mdhdr */
bzero(&mdhdr, sizeof(mdhdr));

View File

@ -40,6 +40,9 @@
#define DUMPSYS_MD_PA_NPAIRS 20
#define DUMPSYS_NUM_AUX_HDRS 1
/* How often to check the dump progress bar? */
#define DUMPSYS_PB_CHECK_BITS 22 /* Every 4MB */
void dumpsys_wbinv_all(void);
int dumpsys_write_aux_headers(struct dumperinfo *di);

View File

@ -60,9 +60,6 @@ static struct kerneldumpheader kdh;
/* Handle chunked writes. */
static size_t fragsz;
static void *dump_va;
static uint64_t counter, progress;
#define PG2MB(pgs) (((pgs) + (1 << 8) - 1) >> 8)
static int
blk_flush(struct dumperinfo *di)
@ -110,13 +107,8 @@ blk_write(struct dumperinfo *di, char *ptr, vm_paddr_t pa, size_t sz)
len = maxdumpsz - fragsz;
if (len > sz)
len = sz;
counter += len;
progress -= len;
if (counter >> 24) {
printf(" %lld", PG2MB(progress >> PAGE_SHIFT));
counter &= (1<<24) - 1;
}
dumpsys_pb_progress(len);
wdog_kern_pat(WD_LASTVAL);
if (ptr) {
@ -173,7 +165,6 @@ minidumpsys(struct dumperinfo *di)
int j, k;
struct minidumphdr mdhdr;
counter = 0;
/* Walk page table pages, set bits in vm_page_dump */
ptesize = 0;
for (va = KERNBASE; va < kernel_vm_end; va += NBPDR) {
@ -224,7 +215,7 @@ minidumpsys(struct dumperinfo *di)
}
dumpsize += PAGE_SIZE;
progress = dumpsize;
dumpsys_pb_init(dumpsize);
/* Initialize mdhdr */
bzero(&mdhdr, sizeof(mdhdr));

View File

@ -385,3 +385,72 @@ dumpsys_generic(struct dumperinfo *di)
printf("\n** DUMP FAILED (ERROR %d) **\n", error);
return (error);
}
/* Minidump progress bar */
static struct {
const int min_per;
const int max_per;
bool visited;
} progress_track[10] = {
{ 0, 10, false},
{ 10, 20, false},
{ 20, 30, false},
{ 30, 40, false},
{ 40, 50, false},
{ 50, 60, false},
{ 60, 70, false},
{ 70, 80, false},
{ 80, 90, false},
{ 90, 100, false}
};
static uint64_t dumpsys_pb_size;
static uint64_t dumpsys_pb_remaining;
static uint64_t dumpsys_pb_check;
/* Reset the progress bar for a dump of dumpsize. */
void
dumpsys_pb_init(uint64_t dumpsize)
{
int i;
dumpsys_pb_size = dumpsys_pb_remaining = dumpsize;
dumpsys_pb_check = 0;
for (i = 0; i < nitems(progress_track); i++)
progress_track[i].visited = false;
}
/*
* Update the progress according to the delta bytes that were written out.
* Check and print the progress percentage.
*/
void
dumpsys_pb_progress(size_t delta)
{
int sofar, i;
dumpsys_pb_remaining -= delta;
dumpsys_pb_check += delta;
/*
* To save time while dumping, only loop through progress_track
* occasionally.
*/
if ((dumpsys_pb_check >> DUMPSYS_PB_CHECK_BITS) == 0)
return;
else
dumpsys_pb_check &= (1 << DUMPSYS_PB_CHECK_BITS) - 1;
sofar = 100 - ((dumpsys_pb_remaining * 100) / dumpsys_pb_size);
for (i = 0; i < nitems(progress_track); i++) {
if (sofar < progress_track[i].min_per ||
sofar > progress_track[i].max_per)
continue;
if (!progress_track[i].visited) {
progress_track[i].visited = true;
printf("..%d%%", sofar);
}
break;
}
}

View File

@ -36,6 +36,9 @@
#define DUMPSYS_MD_PA_NPAIRS 20
#define DUMPSYS_NUM_AUX_HDRS 0
/* How often to check the dump progress bar? */
#define DUMPSYS_PB_CHECK_BITS 22 /* Every 4MB */
void dumpsys_wbinv_all(void);
static inline void

View File

@ -58,47 +58,12 @@ CTASSERT(sizeof(struct kerneldumpheader) == 512);
static struct kerneldumpheader kdh;
/* Handle chunked writes. */
static uint64_t counter, progress, dumpsize;
static uint64_t dumpsize;
/* Just auxiliary bufffer */
static char tmpbuffer[PAGE_SIZE] __aligned(sizeof(uint64_t));
extern pd_entry_t *kernel_segmap;
static struct {
int min_per;
int max_per;
int visited;
} progress_track[10] = {
{ 0, 10, 0},
{ 10, 20, 0},
{ 20, 30, 0},
{ 30, 40, 0},
{ 40, 50, 0},
{ 50, 60, 0},
{ 60, 70, 0},
{ 70, 80, 0},
{ 80, 90, 0},
{ 90, 100, 0}
};
static void
report_progress(uint64_t progress, uint64_t dumpsize)
{
int sofar, i;
sofar = 100 - ((progress * 100) / dumpsize);
for (i = 0; i < nitems(progress_track); i++) {
if (sofar < progress_track[i].min_per ||
sofar > progress_track[i].max_per)
continue;
if (progress_track[i].visited)
return;
progress_track[i].visited = 1;
printf("..%d%%", sofar);
return;
}
}
static int
write_buffer(struct dumperinfo *di, char *ptr, size_t sz)
{
@ -115,14 +80,8 @@ write_buffer(struct dumperinfo *di, char *ptr, size_t sz)
while (sz) {
len = min(maxdumpsz, sz);
counter += len;
progress -= len;
if (counter >> 22) {
report_progress(progress, dumpsize);
counter &= (1<<22) - 1;
}
dumpsys_pb_progress(len);
wdog_kern_pat(WD_LASTVAL);
if (ptr) {
@ -163,7 +122,6 @@ minidumpsys(struct dumperinfo *di)
/* Flush cache */
mips_dcache_wbinv_all();
counter = 0;
/* Walk page table pages, set bits in vm_page_dump */
ptesize = 0;
@ -203,7 +161,7 @@ minidumpsys(struct dumperinfo *di)
}
dumpsize += PAGE_SIZE;
progress = dumpsize;
dumpsys_pb_init(dumpsize);
/* Initialize mdhdr */
bzero(&mdhdr, sizeof(mdhdr));

View File

@ -35,6 +35,9 @@
#define DUMPSYS_MD_PA_NPAIRS (PHYS_AVAIL_SZ + 1)
#define DUMPSYS_NUM_AUX_HDRS 0
/* How often to check the dump progress bar? */
#define DUMPSYS_PB_CHECK_BITS 20 /* Every 1MB */
void dumpsys_pa_init(void);
void dumpsys_unmap_chunk(vm_paddr_t, size_t, void *);
size_t dumpsys_scan_pmap(void);

View File

@ -69,24 +69,7 @@ SYSCTL_INT(_machdep, OID_AUTO, dump_retry_count, CTLFLAG_RWTUN,
static struct kerneldumpheader kdh;
static char pgbuf[PAGE_SIZE];
static struct {
int min_per;
int max_per;
int visited;
} progress_track[10] = {
{ 0, 10, 0},
{ 10, 20, 0},
{ 20, 30, 0},
{ 30, 40, 0},
{ 40, 50, 0},
{ 50, 60, 0},
{ 60, 70, 0},
{ 70, 80, 0},
{ 80, 90, 0},
{ 90, 100, 0}
};
static size_t counter, dumpsize, progress;
static size_t dumpsize;
/* Handle chunked writes. */
static size_t fragsz;
@ -98,24 +81,6 @@ pmap_kenter_temporary(vm_offset_t va, vm_paddr_t pa)
pmap_kenter(va, pa);
}
static void
report_progress(void)
{
int sofar, i;
sofar = 100 - ((progress * 100) / dumpsize);
for (i = 0; i < nitems(progress_track); i++) {
if (sofar < progress_track[i].min_per ||
sofar > progress_track[i].max_per)
continue;
if (progress_track[i].visited)
return;
progress_track[i].visited = 1;
printf("..%d%%", sofar);
return;
}
}
static int
blk_flush(struct dumperinfo *di)
{
@ -165,12 +130,8 @@ blk_write(struct dumperinfo *di, char *ptr, vm_paddr_t pa, size_t sz)
len = maxdumpsz - fragsz;
if (len > sz)
len = sz;
counter += len;
progress -= len;
if (counter >> 20) {
report_progress();
counter &= (1<<20) - 1;
}
dumpsys_pb_progress(len);
if (ptr) {
error = dump_append(di, ptr, 0, len);
@ -231,7 +192,7 @@ int
minidumpsys(struct dumperinfo *di)
{
vm_paddr_t pa;
int error, i, retry_count;
int error, retry_count;
uint32_t pmapsize;
struct minidumphdr mdhdr;
@ -241,11 +202,6 @@ minidumpsys(struct dumperinfo *di)
fragsz = 0;
DBG(total = dumptotal = 0;)
/* Reset progress */
counter = 0;
for (i = 0; i < nitems(progress_track); i++)
progress_track[i].visited = 0;
/* Build set of dumpable pages from kernel pmap */
pmapsize = dumpsys_scan_pmap();
if (pmapsize % PAGE_SIZE != 0) {
@ -266,7 +222,7 @@ minidumpsys(struct dumperinfo *di)
else
dump_drop_page(pa);
}
progress = dumpsize;
dumpsys_pb_init(dumpsize);
/* Initialize mdhdr */
bzero(&mdhdr, sizeof(mdhdr));

View File

@ -37,6 +37,9 @@
#define DUMPSYS_MD_PA_NPAIRS 10
#define DUMPSYS_NUM_AUX_HDRS 0
/* How often to check the dump progress bar? */
#define DUMPSYS_PB_CHECK_BITS 22 /* Every 4MB */
static inline void
dumpsys_pa_init(void)
{

View File

@ -60,45 +60,10 @@ static struct kerneldumpheader kdh;
/* Handle chunked writes. */
static size_t fragsz;
static void *dump_va;
static size_t counter, progress, dumpsize;
static size_t dumpsize;
static uint64_t tmpbuffer[PAGE_SIZE / sizeof(uint64_t)];
static struct {
int min_per;
int max_per;
int visited;
} progress_track[10] = {
{ 0, 10, 0},
{ 10, 20, 0},
{ 20, 30, 0},
{ 30, 40, 0},
{ 40, 50, 0},
{ 50, 60, 0},
{ 60, 70, 0},
{ 70, 80, 0},
{ 80, 90, 0},
{ 90, 100, 0}
};
static void
report_progress(size_t progress, size_t dumpsize)
{
int sofar, i;
sofar = 100 - ((progress * 100) / dumpsize);
for (i = 0; i < nitems(progress_track); i++) {
if (sofar < progress_track[i].min_per ||
sofar > progress_track[i].max_per)
continue;
if (progress_track[i].visited)
return;
progress_track[i].visited = 1;
printf("..%d%%", sofar);
return;
}
}
static int
blk_flush(struct dumperinfo *di)
{
@ -156,13 +121,8 @@ blk_write(struct dumperinfo *di, char *ptr, vm_paddr_t pa, size_t sz)
len = maxdumpsz - fragsz;
if (len > sz)
len = sz;
counter += len;
progress -= len;
if (counter >> 22) {
report_progress(progress, dumpsize);
counter &= (1 << 22) - 1;
}
dumpsys_pb_progress(len);
wdog_kern_pat(WD_LASTVAL);
if (ptr) {
@ -253,7 +213,7 @@ minidumpsys(struct dumperinfo *di)
}
dumpsize += PAGE_SIZE;
progress = dumpsize;
dumpsys_pb_init(dumpsize);
/* Initialize mdhdr */
bzero(&mdhdr, sizeof(mdhdr));

View File

@ -151,6 +151,9 @@ void dumpsys_gen_wbinv_all(void);
void dumpsys_gen_unmap_chunk(vm_paddr_t, size_t, void *);
int dumpsys_gen_write_aux_headers(struct dumperinfo *);
void dumpsys_pb_init(uint64_t);
void dumpsys_pb_progress(size_t);
extern int do_minidump;
#endif

View File

@ -42,6 +42,9 @@
#define DUMPSYS_MD_PA_NPAIRS 10
#define DUMPSYS_NUM_AUX_HDRS 0
/* How often to check the dump progress bar? */
#define DUMPSYS_PB_CHECK_BITS 24 /* Every 16MB */
static inline void
dumpsys_pa_init(void)
{