/* * Tracks state while we parse memcg lru_gen stats. The file we're parsing is * structured like this (some extra whitespace elided): * * memcg (id) (path) * node (id) * (gen_nr) (age_in_ms) (nr_anon_pages) (nr_file_pages)
*/ struct memcg_stats_parse_context { bool consumed; /* Whether or not this line was consumed */ /* Next parse handler to invoke */ void (*next_handler)(struct memcg_stats *stats, struct memcg_stats_parse_context *ctx, char *line); int current_node_idx; /* Current index in nodes array */ constchar *name; /* The name of the memcg we're looking for */
};
ctx->current_node_idx = stats->nr_nodes++;
TEST_ASSERT(ctx->current_node_idx < MAX_NR_NODES, "memcg has stats for too many nodes, max is %d",
MAX_NR_NODES);
stats->nodes[ctx->current_node_idx].node = found_node_id;
if (!gen) goto out_consume; /* Skip empty lines */
if (!strcmp("memcg", gen) || !strcmp("node", gen)) { /* * Reached next memcg or node section. Don't consume, let the * other handler deal with this.
*/
ctx->next_handler = memcg_stats_handle_in_memcg; goto out;
}
node_stats = &stats->nodes[ctx->current_node_idx];
TEST_ASSERT(node_stats->nr_gens < MAX_NR_GENS, "found too many generation lines; max is %d",
MAX_NR_GENS);
gen_stats = &node_stats->gens[node_stats->nr_gens++];
age = split_next(&it);
nr_anon = split_next(&it);
nr_file = split_next(&it);
do {
ctx.next_handler(stats, &ctx, line); if (!ctx.next_handler) break;
} while (!ctx.consumed);
}
if (read < 0 && !feof(f))
TEST_ASSERT(false, "getline(%s) failed", LRU_GEN_DEBUGFS);
TEST_ASSERT(stats->memcg_id > 0, "Couldn't find memcg: %s\n" "Did the memcg get created in the proper mount?",
memcg); if (line)
free(line);
TEST_ASSERT(!fclose(f), "fclose(%s) failed", LRU_GEN_DEBUGFS);
print_memcg_stats(stats, memcg);
}
/* * Find all pages tracked by lru_gen for this memcg in generation @target_gen. * * If @target_gen is negative, look for all generations.
*/ long lru_gen_sum_memcg_stats_for_gen(int target_gen, conststruct memcg_stats *stats)
{ int node, gen; long total_nr = 0;
/* Find all pages tracked by lru_gen for this memcg. */ long lru_gen_sum_memcg_stats(conststruct memcg_stats *stats)
{ return lru_gen_sum_memcg_stats_for_gen(-1, stats);
}
/* * If lru_gen aging should force page table scanning. * * If you want to set this to false, you will need to do eviction * before doing extra aging passes.
*/ staticconstbool force_scan = true;
staticvoid run_aging_impl(unsignedlong memcg_id, int node_id, int max_gen)
{
FILE *f = fopen(LRU_GEN_DEBUGFS, "w"); char *command;
size_t sz;
/* Re-read so callers get updated information */
lru_gen_read_memcg_stats(stats, memcg);
}
/* * Find which generation contains at least @pages pages, assuming that * such a generation exists.
*/ int lru_gen_find_generation(conststruct memcg_stats *stats, unsignedlong pages)
{ int node, gen, gen_idx, min_gen = INT_MAX, max_gen = -1;
for (node = 0; node < stats->nr_nodes; ++node) for (gen_idx = 0; gen_idx < stats->nodes[node].nr_gens;
++gen_idx) {
gen = stats->nodes[node].gens[gen_idx].gen;
max_gen = gen > max_gen ? gen : max_gen;
min_gen = gen < min_gen ? gen : min_gen;
}
for (gen = min_gen; gen <= max_gen; ++gen) /* See if this generation has enough pages. */ if (lru_gen_sum_memcg_stats_for_gen(gen, stats) > pages) return gen;
return -1;
}
bool lru_gen_usable(void)
{ long required_features = LRU_GEN_ENABLED | LRU_GEN_MM_WALK; int lru_gen_fd, lru_gen_debug_fd; char mglru_feature_str[8] = {}; long mglru_features;
lru_gen_fd = open(LRU_GEN_ENABLED_PATH, O_RDONLY); if (lru_gen_fd < 0) {
puts("lru_gen: Could not open " LRU_GEN_ENABLED_PATH); returnfalse;
} if (read(lru_gen_fd, &mglru_feature_str, 7) < 7) {
puts("lru_gen: Could not read from " LRU_GEN_ENABLED_PATH);
close(lru_gen_fd); returnfalse;
}
close(lru_gen_fd);
lru_gen_debug_fd = open(LRU_GEN_DEBUGFS, O_RDWR);
__TEST_REQUIRE(lru_gen_debug_fd >= 0, "lru_gen: Could not open " LRU_GEN_DEBUGFS ", " "but lru_gen is enabled, so cannot use page_idle.");
close(lru_gen_debug_fd); returntrue;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.