mirror of
https://github.com/crash-utility/crash
synced 2024-12-15 13:44:30 +00:00
Increase the internal hash queue head count from 128 to 32768.
The hash queue is used for gathering and verifying lists, and the original count of 128 may be overwhelmed if a list is extremely large. For example, on a 256GB system with 192GB of free pages, the "kmem -f" command takes hours to complete; with this patch, the time is reduced to a few minutes. In addition, a new command line option "--hash <count>" has been added to allow a user to override the default hash queue head count of 32768. (anderson@redhat.com)
This commit is contained in:
parent
dc7fea0128
commit
5645af9598
4
crash.8
4
crash.8
@ -463,6 +463,10 @@ value that is larger than its
|
||||
value, then it will be necessary to enter
|
||||
a relocation size equal to the difference between the two values.
|
||||
.TP
|
||||
.BI --hash \ count
|
||||
Set the number of internal hash queue heads used for list gathering
|
||||
and verification. The default count is 32768.
|
||||
.TP
|
||||
.B --minimal
|
||||
Bring up a session that is restricted to the
|
||||
.I log, dis, rd, sym, eval, set
|
||||
|
1
defs.h
1
defs.h
@ -513,6 +513,7 @@ struct program_context {
|
||||
void (*cmd_cleanup)(void *); /* per-command cleanup function */
|
||||
void *cmd_cleanup_arg; /* optional cleanup function argument */
|
||||
ulong scope; /* optional text context address */
|
||||
ulong nr_hash_queues; /* hash queue head count */
|
||||
};
|
||||
|
||||
#define READMEM pc->readmem
|
||||
|
4
help.c
4
help.c
@ -297,6 +297,10 @@ char *program_usage_info[] = {
|
||||
" be necessary to enter a relocation size equal to the difference between",
|
||||
" the two values.",
|
||||
"",
|
||||
" --hash count",
|
||||
" Set the number of internal hash queue heads used for list gathering",
|
||||
" and verification. The default count is 32768.",
|
||||
"",
|
||||
" --kaslr offset | auto",
|
||||
" If an x86_64 kernel was configured with CONFIG_RANDOMIZE_BASE, the",
|
||||
" offset value is equal to the difference between the symbol values ",
|
||||
|
9
main.c
9
main.c
@ -69,6 +69,7 @@ static struct option long_options[] = {
|
||||
{"hex", 0, 0, 0},
|
||||
{"dec", 0, 0, 0},
|
||||
{"no_strip", 0, 0, 0},
|
||||
{"hash", required_argument, 0, 0},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
@ -217,7 +218,12 @@ main(int argc, char **argv)
|
||||
else if (STREQ(long_options[option_index].name, "mod"))
|
||||
kt->module_tree = optarg;
|
||||
|
||||
else if (STREQ(long_options[option_index].name, "kaslr")) {
|
||||
else if (STREQ(long_options[option_index].name, "hash")) {
|
||||
if (!calculate(optarg, &pc->nr_hash_queues, NULL, 0)) {
|
||||
error(INFO, "invalid --hash argument: %s\n",
|
||||
optarg);
|
||||
}
|
||||
} else if (STREQ(long_options[option_index].name, "kaslr")) {
|
||||
if (!machine_type("X86_64"))
|
||||
error(INFO, "--kaslr only valid "
|
||||
"with X86_64 machine type.\n");
|
||||
@ -1594,6 +1600,7 @@ dump_program_context(void)
|
||||
fprintf(fp, " cleanup: %s\n", pc->cleanup);
|
||||
fprintf(fp, " scope: %lx %s\n", pc->scope,
|
||||
pc->scope ? "" : "(not set)");
|
||||
fprintf(fp, " nr_hash_queues: %ld\n", pc->nr_hash_queues);
|
||||
}
|
||||
|
||||
char *
|
||||
|
32
tools.c
32
tools.c
@ -1,8 +1,8 @@
|
||||
/* tools.c - core analysis suite
|
||||
*
|
||||
* Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc.
|
||||
* Copyright (C) 2002-2013 David Anderson
|
||||
* Copyright (C) 2002-2013 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2002-2014 David Anderson
|
||||
* Copyright (C) 2002-2014 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -4126,9 +4126,9 @@ dump_struct_members_for_tree(struct tree_data *td, int idx, ulong struct_p)
|
||||
#define HASH_QUEUE_CLOSED (0x8)
|
||||
|
||||
#define HQ_ENTRY_CHUNK (1024)
|
||||
#define NR_HASH_QUEUES (HQ_ENTRY_CHUNK/8)
|
||||
#define NR_HASH_QUEUES_DEFAULT (32768UL)
|
||||
#define HQ_SHIFT (machdep->pageshift)
|
||||
#define HQ_INDEX(X) (((X) >> HQ_SHIFT) % NR_HASH_QUEUES)
|
||||
#define HQ_INDEX(X) (((X) >> HQ_SHIFT) % pc->nr_hash_queues)
|
||||
|
||||
struct hq_entry {
|
||||
int next;
|
||||
@ -4143,7 +4143,7 @@ struct hq_head {
|
||||
|
||||
struct hash_table {
|
||||
ulong flags;
|
||||
struct hq_head queue_heads[NR_HASH_QUEUES];
|
||||
struct hq_head *queue_heads;
|
||||
struct hq_entry *memptr;
|
||||
long count;
|
||||
long index;
|
||||
@ -4161,6 +4161,18 @@ hq_init(void)
|
||||
|
||||
ht = &hash_table;
|
||||
|
||||
if (pc->nr_hash_queues == 0)
|
||||
pc->nr_hash_queues = NR_HASH_QUEUES_DEFAULT;
|
||||
|
||||
if ((ht->queue_heads = (struct hq_head *)malloc(pc->nr_hash_queues *
|
||||
sizeof(struct hq_head))) == NULL) {
|
||||
error(INFO, "cannot malloc memory for hash queue heads: %s\n",
|
||||
strerror(errno));
|
||||
ht->flags = HASH_QUEUE_NONE;
|
||||
pc->flags &= ~HASH;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((ht->memptr = (struct hq_entry *)malloc(HQ_ENTRY_CHUNK *
|
||||
sizeof(struct hq_entry))) == NULL) {
|
||||
error(INFO, "cannot malloc memory for hash queues: %s\n",
|
||||
@ -4241,7 +4253,7 @@ hq_open(void)
|
||||
return FALSE;
|
||||
|
||||
ht->flags &= ~(HASH_QUEUE_FULL|HASH_QUEUE_CLOSED);
|
||||
BZERO(ht->queue_heads, sizeof(struct hq_head) * NR_HASH_QUEUES);
|
||||
BZERO(ht->queue_heads, sizeof(struct hq_head) * pc->nr_hash_queues);
|
||||
BZERO(ht->memptr, ht->count * sizeof(struct hq_entry));
|
||||
ht->index = 0;
|
||||
|
||||
@ -4403,7 +4415,7 @@ dump_hash_table(int verbose)
|
||||
if (ht->flags & HASH_QUEUE_FULL)
|
||||
fprintf(fp, "%sHASH_QUEUE_FULL", others++ ? "|" : "");
|
||||
fprintf(fp, ")\n");
|
||||
fprintf(fp, " queue_heads[%d]: %lx\n", NR_HASH_QUEUES,
|
||||
fprintf(fp, " queue_heads[%ld]: %lx\n", pc->nr_hash_queues,
|
||||
(ulong)ht->queue_heads);
|
||||
fprintf(fp, " memptr: %lx\n", (ulong)ht->memptr);
|
||||
fprintf(fp, " count: %ld ", ht->count);
|
||||
@ -4416,7 +4428,7 @@ dump_hash_table(int verbose)
|
||||
minq = ~(0);
|
||||
maxq = 0;
|
||||
|
||||
for (i = 0; i < NR_HASH_QUEUES; i++) {
|
||||
for (i = 0; i < pc->nr_hash_queues; i++) {
|
||||
if (ht->queue_heads[i].next == 0) {
|
||||
minq = 0;
|
||||
continue;
|
||||
@ -4448,8 +4460,8 @@ dump_hash_table(int verbose)
|
||||
if (elements != ht->index)
|
||||
fprintf(fp, " elements found: %ld (expected %ld)\n",
|
||||
elements, ht->index);
|
||||
fprintf(fp, " queues in use: %ld of %d\n", queues_in_use,
|
||||
NR_HASH_QUEUES);
|
||||
fprintf(fp, " queues in use: %ld of %ld\n", queues_in_use,
|
||||
pc->nr_hash_queues);
|
||||
fprintf(fp, " queue length range: %d to %d\n", minq, maxq);
|
||||
|
||||
if (verbose) {
|
||||
|
Loading…
Reference in New Issue
Block a user