Adapt ioclasses stats command to ocf stats builder.

Signed-off-by: Michal Mielewczyk <michal.mielewczyk@intel.com>
This commit is contained in:
Michal Mielewczyk 2019-08-29 08:25:16 -04:00
parent 30a52587f3
commit 1abb1e7c72
4 changed files with 54 additions and 364 deletions

View File

@ -70,7 +70,7 @@ static struct command_args command_args_values = {
.cache_mode = ocf_cache_mode_default,
.stats_filters = STATS_FILTER_DEFAULT,
.output_format = OUTPUT_FORMAT_DEFAULT,
.io_class_id = -1,
.io_class_id = OCF_IO_CLASS_INVALID,
.line_size = ocf_cache_line_size_default,
.cache_state_flush = UNDEFINED, /* three state logic: YES NO UNDEFINED */
.flush_data = 1,

View File

@ -408,128 +408,6 @@ static void print_stats_ioclass_conf(const struct kcas_io_class* io_class,
"Yes" : "No");
}
static void print_stats_ioclass_usage(uint32_t part_id,
const struct ocf_stats_io_class* part_stats,
const struct ocf_stats_io_class* denominators,
FILE *outfile, uint32_t cache_size,
ocf_cache_line_size_t cache_line_size)
{
float percent;
uint64_t clean;
print_table_header(outfile, 4, "Usage statistics", "Count", "%", "[Units]");
percent = percentage(part_stats->occupancy_clines, cache_size);
print_val_perc_table_section(outfile, "Occupancy", UNIT_BLOCKS, percent,
"%ld",
cache_line_in_4k(part_stats->occupancy_clines,
cache_line_size));
/* Occupancy, dirty, etc. information. */
/* For now free stat should be printed for the unclassified IO class. */
if (IOCLASS_UNCLASSIFIED == part_id) {
print_val_perc_table_row(outfile, "Free", UNIT_BLOCKS,
100.0f, "%ld",
cache_line_in_4k(part_stats->free_clines,
cache_line_size));
} else {
print_val_perc_table_row(outfile, "Free", UNIT_BLOCKS,
0.0f, "%d", 0);
}
clean = part_stats->occupancy_clines - part_stats->dirty_clines;
percent = percentage(clean, part_stats->occupancy_clines);
print_val_perc_table_row(outfile, "Clean", UNIT_BLOCKS, percent,
"%ld",
cache_line_in_4k(clean, cache_line_size));
percent = percentage(part_stats->dirty_clines, part_stats->occupancy_clines);
print_val_perc_table_row(outfile, "Dirty", UNIT_BLOCKS, percent,
"%ld",
cache_line_in_4k(part_stats->dirty_clines,
cache_line_size));
}
static void print_stats_ioclass_req(const struct ocf_stats_io_class* part_stats,
const struct ocf_stats_io_class* denominators,
FILE *outfile, uint64_t req_grand_total)
{
const struct ocf_stats_req *req_stats;
float percent;
uint64_t hits;
uint64_t serv_reqs = 0;
uint64_t total_reqs = 0;
print_table_header(outfile, 4, "Request statistics", "Count",
"%", "[Units]");
/* Handling read operations. */
req_stats = &part_stats->read_reqs;
hits = req_stats->total - (req_stats->partial_miss + req_stats->full_miss);
percent = percentage(hits, req_grand_total);
print_val_perc_table_section(outfile, "Read hits", UNIT_REQUESTS, percent,
"%ld", hits);
percent = percentage(req_stats->partial_miss, req_grand_total);
print_val_perc_table_row(outfile, "Read partial misses", UNIT_REQUESTS,
percent, "%ld", req_stats->partial_miss);
percent = percentage(req_stats->full_miss, req_grand_total);
print_val_perc_table_row(outfile, "Read full misses", UNIT_REQUESTS,
percent, "%ld", req_stats->full_miss);
percent = percentage(req_stats->total, req_grand_total);
print_val_perc_table_row(outfile, "Read total", UNIT_REQUESTS,
percent, "%ld", req_stats->total);
/* Handling write operations. */
req_stats = &part_stats->write_reqs;
hits = req_stats->total - (req_stats->partial_miss + req_stats->full_miss);
percent = percentage(hits, req_grand_total);
print_val_perc_table_section(outfile, "Write hits", UNIT_REQUESTS, percent,
"%ld", hits);
percent = percentage(req_stats->partial_miss, req_grand_total);
print_val_perc_table_row(outfile, "Write partial misses", UNIT_REQUESTS,
percent, "%ld", req_stats->partial_miss);
percent = percentage(req_stats->full_miss, req_grand_total);
print_val_perc_table_row(outfile, "Write full misses", UNIT_REQUESTS,
percent, "%ld", req_stats->full_miss);
percent = percentage(req_stats->total, req_grand_total);
print_val_perc_table_row(outfile, "Write total", UNIT_REQUESTS,
percent, "%ld", req_stats->total);
/* Pass-Through requests. */
percent = percentage(part_stats->read_reqs.pass_through, req_grand_total);
print_val_perc_table_section(outfile, "Pass-Through reads", UNIT_REQUESTS,
percent, "%lu",
part_stats->read_reqs.pass_through);
percent = percentage(part_stats->write_reqs.pass_through, req_grand_total);
print_val_perc_table_row(outfile, "Pass-Through writes", UNIT_REQUESTS,
percent, "%lu",
part_stats->write_reqs.pass_through);
/* Summary. */
serv_reqs += part_stats->read_reqs.total;
serv_reqs += part_stats->write_reqs.total;
total_reqs = serv_reqs + part_stats->read_reqs.pass_through +
part_stats->write_reqs.pass_through;
percent = percentage(serv_reqs, req_grand_total);
print_val_perc_table_row(outfile, "Serviced requests", UNIT_REQUESTS,
percent, "%lu", serv_reqs);
percent = percentage(total_reqs, req_grand_total);
print_val_perc_table_section(outfile, "Total requests", UNIT_REQUESTS,
percent, "%lu", total_reqs);
}
void cache_stats_inactive_usage(int ctrl_fd, const struct kcas_cache_info *cache_info,
unsigned int cache_id, FILE* outfile)
@ -561,107 +439,23 @@ void cache_stats_inactive_usage(int ctrl_fd, const struct kcas_cache_info *cache
cache_info->info.cache_line_size / KiB));
}
static void print_stats_ioclass_blk(const struct ocf_stats_io_class* part_stats,
const struct ocf_stats_io_class* denominators, FILE *outfile,
ocf_cache_line_size_t cache_line_size)
{
float percent;
print_table_header(outfile, 4, "Block statistics", "Count", "%",
"[Units]");
/* Handling read operations. */
percent = percentage(part_stats->blocks.read, denominators->blocks.read);
print_val_perc_table_section(outfile, "Blocks reads", UNIT_BLOCKS,
percent, "%ld",
bytes_to_4k(part_stats->blocks.read));
/* Handling write operations. */
percent = percentage(part_stats->blocks.write, denominators->blocks.write);
print_val_perc_table_section(outfile, "Blocks writes", UNIT_BLOCKS,
percent, "%ld",
bytes_to_4k(part_stats->blocks.write));
}
/**
* print statistics regarding single io class (partition)
*/
void print_stats_ioclass(const struct kcas_cache_info *cache_info,
const struct kcas_io_class *io_class,
FILE *outfile, unsigned int stats_filters,
struct ocf_stats_io_class *denominators, uint64_t req_grand_total,
ocf_cache_line_size_t cache_line_size)
void print_stats_ioclass(struct kcas_io_class *io_class,
struct kcas_get_stats *stats, FILE *outfile, unsigned int stats_filters)
{
const struct ocf_stats_io_class *part_stats;
uint32_t part_id;
part_id = io_class->class_id;
part_stats = &io_class->stats;
begin_record(outfile);
if (stats_filters & STATS_FILTER_CONF) {
if (stats_filters & STATS_FILTER_CONF)
print_stats_ioclass_conf(io_class, outfile);
}
if (stats_filters & STATS_FILTER_USAGE) {
print_stats_ioclass_usage(part_id, part_stats, denominators,
outfile, cache_info->info.size,
cache_line_size);
}
if (stats_filters & STATS_FILTER_USAGE)
print_usage_stats(&stats->usage, outfile);
if (stats_filters & STATS_FILTER_REQ) {
print_stats_ioclass_req(part_stats, denominators, outfile, req_grand_total);
}
if (stats_filters & STATS_FILTER_REQ)
print_req_stats(&stats->req, outfile);
if (stats_filters & STATS_FILTER_BLK) {
print_stats_ioclass_blk(part_stats, denominators, outfile,
cache_line_size);
}
}
static int read_io_class_stats(int ctrl_fd, int cache_id, int core_id,
int part_id,
struct kcas_io_class *io_class_tmp,
struct kcas_io_class *io_class_out)
{
memset(io_class_tmp, 0, sizeof(*io_class_tmp));
io_class_tmp->cache_id = cache_id;
io_class_tmp->class_id = part_id;
if (core_id != OCF_CORE_ID_INVALID) {
io_class_tmp->core_id = core_id;
io_class_tmp->get_stats = 1;
}
if (ioctl(ctrl_fd, KCAS_IOCTL_PARTITION_INFO, io_class_tmp) < 0) {
io_class_out->ext_err_code = io_class_tmp->ext_err_code;
return FAILURE;
}
io_class_out->ext_err_code = io_class_tmp->ext_err_code;
strncpy_s(io_class_out->info.name, sizeof(io_class_out->info.name),
io_class_tmp->info.name, sizeof(io_class_tmp->info.name) - 1);
io_class_out->class_id = io_class_tmp->class_id;
io_class_out->info.priority = io_class_tmp->info.priority;
io_class_out->info.cache_mode = io_class_tmp->info.cache_mode;
return SUCCESS;
}
static inline void accum_block_stats(struct ocf_stats_block *to, const struct ocf_stats_block *from)
{
to->read += from->read;
to->write += from->write;
}
static inline void accum_req_stats(struct ocf_stats_req *to, const struct ocf_stats_req *from)
{
to->full_miss += from->full_miss;
to->partial_miss += from->partial_miss;
to->total += from->total;
to->pass_through += from->pass_through;
if (stats_filters & STATS_FILTER_BLK)
print_blk_stats(&stats->blocks, true, outfile);
}
/**
@ -673,137 +467,54 @@ int cache_stats_ioclasses(int ctrl_fd, const struct kcas_cache_info *cache_info,
int io_class_id, FILE *outfile,
unsigned int stats_filters)
{
int i, j, _core_id;
struct ocf_stats_io_class denominators;
struct ocf_stats_io_class* part_stats_cum;
struct ocf_stats_io_class* part_stats_core;
struct kcas_io_class io_class_new[OCF_IO_CLASS_MAX] = {};
struct kcas_io_class io_class_tmp;
uint64_t req_grand_total = 0;
memset(&denominators, 0, sizeof(denominators));
struct kcas_io_class info = {};
struct kcas_get_stats stats = {};
int part_iter_id;
if (-1 != io_class_id && io_class_id >= OCF_IO_CLASS_MAX) {
cas_printf(LOG_ERR, "Partition %d does not exists\n", io_class_id);
return FAILURE;
}
if (io_class_id != OCF_IO_CLASS_INVALID) {
info.cache_id = cache_id;
info.class_id = io_class_id;
stats.cache_id = cache_id;
stats.core_id = core_id;
stats.part_id = io_class_id;
for (i = 0; i < OCF_IO_CLASS_MAX; ++i) {
/* print stats for each ioclass */
if (!cache_info->info.core_count) {
if (read_io_class_stats(ctrl_fd, cache_id, 0, i,
&io_class_tmp,
&io_class_new[i])) {
if (io_class_new[i].ext_err_code ==
OCF_ERR_IO_CLASS_NOT_EXIST) {
continue;
}
cas_printf(LOG_ERR,
"Error while retrieving stats for partition %d\n",
i);
print_err(io_class_new[i].ext_err_code);
goto cleanup;
}
} else {
for (j = 0; j < cache_info->info.core_count; ++j) {
_core_id = cache_info->core_id[j];
if (core_id != OCF_CORE_ID_INVALID && core_id != _core_id) {
continue;
}
if (read_io_class_stats(ctrl_fd, cache_id,
_core_id, i,
&io_class_tmp,
&io_class_new[i])) {
if (io_class_new[i].ext_err_code ==
OCF_ERR_IO_CLASS_NOT_EXIST) {
continue;
}
cas_printf(LOG_ERR,
"Error while retrieving stats for partition %d, core %d\n",
i, core_id);
print_err(io_class_new[i].ext_err_code);
goto cleanup;
}
part_stats_cum = &io_class_new[i].stats;
part_stats_core = &io_class_tmp.stats;
part_stats_cum->free_clines =
part_stats_core->free_clines;
part_stats_cum->occupancy_clines +=
part_stats_core->occupancy_clines;
part_stats_cum->dirty_clines +=
part_stats_core->dirty_clines;
accum_block_stats(&part_stats_cum->blocks,
&part_stats_core->blocks);
accum_req_stats(&part_stats_cum->read_reqs,
&part_stats_core->read_reqs);
accum_req_stats(&part_stats_cum->write_reqs,
&part_stats_core->write_reqs);
}
}
}
for (i = 0; i < OCF_IO_CLASS_MAX; ++i) {
if (io_class_new[i].ext_err_code == OCF_ERR_IO_CLASS_NOT_EXIST) {
continue;
}
const struct ocf_stats_io_class *ps = &io_class_new[i].stats;
denominators.occupancy_clines += ps->occupancy_clines;
denominators.dirty_clines += ps->dirty_clines;
accum_block_stats(&denominators.blocks, &ps->blocks);
accum_req_stats(&denominators.read_reqs, &ps->read_reqs);
accum_req_stats(&denominators.write_reqs, &ps->write_reqs);
}
req_grand_total += denominators.read_reqs.total;
req_grand_total += denominators.read_reqs.pass_through;
req_grand_total += denominators.write_reqs.total;
req_grand_total += denominators.write_reqs.pass_through;
if (-1 == io_class_id) {
for (i = 0; i < OCF_IO_CLASS_MAX; ++i) {
if (io_class_new[i].ext_err_code == OCF_ERR_IO_CLASS_NOT_EXIST) {
continue;
}
print_stats_ioclass(cache_info, &io_class_new[i],
outfile, stats_filters, &denominators, req_grand_total,
cache_info->info.cache_line_size / KiB);
}
} else {
if (io_class_new[io_class_id].ext_err_code == OCF_ERR_IO_CLASS_NOT_EXIST) {
cas_printf(LOG_ERR, "Partition %d does not exists\n", io_class_id);
if (ioctl(ctrl_fd, KCAS_IOCTL_PARTITION_INFO, &info) < 0)
return FAILURE;
}
print_stats_ioclass(cache_info, &io_class_new[io_class_id],
outfile, stats_filters, &denominators, req_grand_total,
cache_info->info.cache_line_size / KiB);
if (ioctl(ctrl_fd, KCAS_IOCTL_GET_STATS, &stats) < 0)
return FAILURE;
begin_record(outfile);
print_stats_ioclass(&info, &stats, outfile, stats_filters);
return SUCCESS;
}
for (part_iter_id = 0; part_iter_id < OCF_IO_CLASS_MAX; part_iter_id++) {
int ret;
info.cache_id = cache_id;
info.class_id = part_iter_id;
stats.cache_id = cache_id;
stats.core_id = core_id;
stats.part_id = part_iter_id;
ret = ioctl(ctrl_fd, KCAS_IOCTL_PARTITION_INFO, &info);
if (ret == -OCF_ERR_IO_CLASS_NOT_EXIST)
continue;
else if (ret)
return FAILURE;
ret = ioctl(ctrl_fd, KCAS_IOCTL_GET_STATS, &stats);
if (ret)
return FAILURE;
begin_record(outfile);
print_stats_ioclass(&info, &stats, outfile, stats_filters);
}
return SUCCESS;
cleanup:
close(ctrl_fd);
if (outfile != stdout) {
fclose(outfile);
}
return FAILURE;
}
static inline void accum_error_stats(struct ocf_stats_error *to,
const struct ocf_stats_error *from)
{
to->read += from->read;
to->write += from->write;
}
int cache_stats_conf(int ctrl_fd, const struct kcas_cache_info *cache_info,
@ -1047,7 +758,8 @@ int cache_status(unsigned int cache_id, unsigned int core_id, int io_class_id,
core_id, io_class_id,
intermediate_file[1],
stats_filters)) {
return FAILURE;
ret = FAILURE;
goto cleanup;
}
} else if (core_id == OCF_CORE_ID_INVALID) {
if (cache_stats(ctrl_fd, &cache_info, cache_id, intermediate_file[1],

View File

@ -1865,10 +1865,8 @@ int cache_mngt_get_io_class_info(struct kcas_io_class *part)
{
int result;
uint16_t cache_id = part->cache_id;
uint16_t core_id = part->core_id;
uint32_t io_class_id = part->class_id;
ocf_cache_t cache;
ocf_core_t core;
result = mngt_get_cache_by_id(cas_ctx, cache_id, &cache);
if (result)
@ -1884,17 +1882,6 @@ int cache_mngt_get_io_class_info(struct kcas_io_class *part)
if (result)
goto end;
if (part->get_stats) {
result = get_core_by_id(cache, core_id, &core);
if (result < 0) {
result = OCF_ERR_CORE_NOT_AVAIL;
goto end;
}
result = ocf_core_io_class_get_stats(core, io_class_id,
&part->stats);
}
end:
ocf_mngt_cache_read_unlock(cache);
ocf_mngt_cache_put(cache);

View File

@ -247,21 +247,12 @@ struct kcas_io_class {
/** Cache ID */
uint16_t cache_id;
/** Core ID */
uint16_t core_id;
/** IO class id for which info will be retrieved */
uint32_t class_id;
/** IO class info */
struct ocf_io_class_info info;
/** Flag indicating if partition counters should be fetched. */
uint8_t get_stats;
/** IO class statistics */
struct ocf_stats_io_class stats;
int ext_err_code;
};