From bda0eb41a9802d69fec686e3258d043b87ebefb7 Mon Sep 17 00:00:00 2001 From: Michal Mielewczyk Date: Mon, 26 Aug 2019 06:27:04 -0400 Subject: [PATCH 1/9] Rename KCAS_IOCTL_PARTITION_STATS with KCAS_IOCTL_PARTITION_INFO. Signed-off-by: Michal Mielewczyk --- casadm/cas_lib.c | 2 +- casadm/statistics_model.c | 2 +- modules/cas_cache/service_ui_ioctl.c | 4 ++-- modules/include/cas_ioctl_codes.h | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/casadm/cas_lib.c b/casadm/cas_lib.c index 36218fa..2aaeba8 100644 --- a/casadm/cas_lib.c +++ b/casadm/cas_lib.c @@ -2028,7 +2028,7 @@ int partition_list(unsigned int cache_id, unsigned int output_format) io_class.cache_id = cache_id; io_class.class_id = i; - result = run_ioctl(fd, KCAS_IOCTL_PARTITION_STATS, &io_class); + result = run_ioctl(fd, KCAS_IOCTL_PARTITION_INFO, &io_class); if (result) { if (OCF_ERR_IO_CLASS_NOT_EXIST == io_class.ext_err_code) { result = SUCCESS; diff --git a/casadm/statistics_model.c b/casadm/statistics_model.c index d926b4d..be90456 100644 --- a/casadm/statistics_model.c +++ b/casadm/statistics_model.c @@ -665,7 +665,7 @@ static int read_io_class_stats(int ctrl_fd, int cache_id, int core_id, io_class_tmp->get_stats = 1; } - if (ioctl(ctrl_fd, KCAS_IOCTL_PARTITION_STATS, io_class_tmp) < 0) { + 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; } diff --git a/modules/cas_cache/service_ui_ioctl.c b/modules/cas_cache/service_ui_ioctl.c index 36b8e9e..62a4ac0 100644 --- a/modules/cas_cache/service_ui_ioctl.c +++ b/modules/cas_cache/service_ui_ioctl.c @@ -51,7 +51,7 @@ long cas_service_ioctl_ctrl(struct file *filp, unsigned int cmd, cmd != KCAS_IOCTL_LIST_CACHE && cmd != KCAS_IOCTL_GET_CACHE_COUNT && cmd != KCAS_IOCTL_CORE_INFO && - cmd != KCAS_IOCTL_PARTITION_STATS && + cmd != KCAS_IOCTL_PARTITION_INFO && cmd != KCAS_IOCTL_GET_CAPABILITIES) { return -EFAULT; } @@ -213,7 +213,7 @@ long cas_service_ioctl_ctrl(struct file *filp, unsigned int cmd, RETURN_CMD_RESULT(cmd_info, arg, retval); } - case KCAS_IOCTL_PARTITION_STATS: { + case KCAS_IOCTL_PARTITION_INFO: { struct kcas_io_class *cmd_info; GET_CMD_INFO(cmd_info, arg); diff --git a/modules/include/cas_ioctl_codes.h b/modules/include/cas_ioctl_codes.h index afbcc4b..451a26e 100644 --- a/modules/include/cas_ioctl_codes.h +++ b/modules/include/cas_ioctl_codes.h @@ -385,7 +385,7 @@ struct kcas_get_cache_param { * 11 * KCAS_IOCTL_FLUSH_CORE * OK * * 12 * KCAS_IOCTL_CACHE_INFO * DEPRECATED * * 13 * KCAS_IOCTL_CORE_INFO * DEPRECATED * - * 14 * KCAS_IOCTL_PARTITION_STATS * OK * + * 14 * KCAS_IOCTL_PARTITION_INFO * OK * * 15 * KCAS_IOCTL_PARTITION_SET * OK * * 16 * KCAS_IOCTL_GET_CACHE_COUNT * OK * * 17 * KCAS_IOCTL_LIST_CACHE * OK * @@ -433,7 +433,7 @@ struct kcas_get_cache_param { #define KCAS_IOCTL_FLUSH_CORE _IOR(KCAS_IOCTL_MAGIC, 11, struct kcas_flush_core) /** Retrieving partition status for specified cache id and partition id */ -#define KCAS_IOCTL_PARTITION_STATS _IOWR(KCAS_IOCTL_MAGIC, 14, struct kcas_io_class) +#define KCAS_IOCTL_PARTITION_INFO _IOWR(KCAS_IOCTL_MAGIC, 14, struct kcas_io_class) /** Configure partitions for specified cache id */ #define KCAS_IOCTL_PARTITION_SET _IOWR(KCAS_IOCTL_MAGIC, 15, struct kcas_io_classes) From 4726bedb505859826d8ddb376e31d6e79b2a1e13 Mon Sep 17 00:00:00 2001 From: Michal Mielewczyk Date: Mon, 26 Aug 2019 07:21:09 -0400 Subject: [PATCH 2/9] New ioctl for retriveing ocf stats. Signed-off-by: Michal Mielewczyk --- modules/cas_cache/layer_cache_management.c | 52 ++++++++++++++++++++++ modules/cas_cache/layer_cache_management.h | 2 + modules/cas_cache/service_ui_ioctl.c | 10 +++++ modules/include/cas_ioctl_codes.h | 26 +++++++++++ ocf | 2 +- 5 files changed, 91 insertions(+), 1 deletion(-) diff --git a/modules/cas_cache/layer_cache_management.c b/modules/cas_cache/layer_cache_management.c index 0d062bd..9181eb1 100644 --- a/modules/cas_cache/layer_cache_management.c +++ b/modules/cas_cache/layer_cache_management.c @@ -1753,6 +1753,58 @@ int cache_mngt_interrupt_flushing(const char *cache_name) } +int cache_mngt_get_stats(struct kcas_get_stats *stats) +{ + int result; + ocf_cache_t cache; + ocf_core_t core = NULL; + + result = mngt_get_cache_by_id(cas_ctx, stats->cache_id, &cache); + if (result) + return result; + + result = _cache_mngt_read_lock_sync(cache); + if (result) + goto put; + + if (stats->core_id == OCF_CORE_ID_INVALID && + stats->part_id == OCF_IO_CLASS_INVALID) { + result = ocf_stats_collect_cache(cache, &stats->usage, &stats->req, + &stats->blocks, &stats->errors); + if (result) + goto unlock; + + } else if (stats->part_id == OCF_IO_CLASS_INVALID) { + result = get_core_by_id(cache, stats->core_id, &core); + if (result) + goto unlock; + + result = ocf_stats_collect_core(core, &stats->usage, &stats->req, + &stats->blocks, &stats->errors); + if (result) + goto unlock; + + } else { + if (stats->core_id == OCF_CORE_ID_INVALID) { + result = ocf_stats_collect_part_cache(cache, stats->part_id, + &stats->usage, &stats->req, &stats->blocks); + } else { + result = get_core_by_id(cache, stats->core_id, &core); + if (result) + goto unlock; + + result = ocf_stats_collect_part_core(core, stats->part_id, + &stats->usage, &stats->req, &stats->blocks); + } + } + +unlock: + ocf_mngt_cache_read_unlock(cache); +put: + ocf_mngt_cache_put(cache); + return result; +} + int cache_mngt_get_info(struct kcas_cache_info *info) { uint32_t i, j; diff --git a/modules/cas_cache/layer_cache_management.h b/modules/cas_cache/layer_cache_management.h index 6ac0e8a..bd1babd 100644 --- a/modules/cas_cache/layer_cache_management.h +++ b/modules/cas_cache/layer_cache_management.h @@ -73,6 +73,8 @@ int cache_mngt_list_caches(struct kcas_cache_list *list); int cache_mngt_interrupt_flushing(const char *cache_name); +int cache_mngt_get_stats(struct kcas_get_stats *stats); + int cache_mngt_get_info(struct kcas_cache_info *info); int cache_mngt_get_io_class_info(struct kcas_io_class *part); diff --git a/modules/cas_cache/service_ui_ioctl.c b/modules/cas_cache/service_ui_ioctl.c index 62a4ac0..a3cb6df 100644 --- a/modules/cas_cache/service_ui_ioctl.c +++ b/modules/cas_cache/service_ui_ioctl.c @@ -193,6 +193,16 @@ long cas_service_ioctl_ctrl(struct file *filp, unsigned int cmd, RETURN_CMD_RESULT(cmd_info, arg, retval); } + case KCAS_IOCTL_GET_STATS: { + struct kcas_get_stats *cmd_info; + + GET_CMD_INFO(cmd_info, arg); + + retval = cache_mngt_get_stats(cmd_info); + + RETURN_CMD_RESULT(cmd_info, arg, retval); + } + case KCAS_IOCTL_CACHE_INFO: { struct kcas_cache_info *cmd_info; diff --git a/modules/include/cas_ioctl_codes.h b/modules/include/cas_ioctl_codes.h index 451a26e..6e60adc 100644 --- a/modules/include/cas_ioctl_codes.h +++ b/modules/include/cas_ioctl_codes.h @@ -157,6 +157,28 @@ struct kcas_flush_core { int ext_err_code; }; +struct kcas_get_stats { + /** id of a cache */ + uint16_t cache_id; + + /** id of a core */ + uint16_t core_id; + + /** id of an ioclass */ + uint16_t part_id; + + /** fields to be filled with statistics */ + struct ocf_stats_usage usage; + + struct ocf_stats_requests req; + + struct ocf_stats_blocks blocks; + + struct ocf_stats_errors errors; + + int ext_err_code; +}; + struct kcas_cache_info { /** id of a cache */ uint16_t cache_id; @@ -405,6 +427,7 @@ struct kcas_get_cache_param { * 31 * KCAS_IOCTL_GET_CORE_PARAM * OK * * 32 * KCAS_IOCTL_SET_CACHE_PARAM * OK * * 33 * KCAS_IOCTL_GET_CACHE_PARAM * OK * + * 34 * KCAS_IOCTL_GET_STATS * OK * ******************************************************************************* */ @@ -492,6 +515,9 @@ struct kcas_get_cache_param { /** Get various cache runtime parameters */ #define KCAS_IOCTL_GET_CACHE_PARAM _IOW(KCAS_IOCTL_MAGIC, 33, struct kcas_get_cache_param) +/** Get stats of particular OCF object */ +#define KCAS_IOCTL_GET_STATS _IOR(KCAS_IOCTL_MAGIC, 34, struct kcas_get_stats) + /** * Extended kernel CAS error codes */ diff --git a/ocf b/ocf index 9a46c40..c2da038 160000 --- a/ocf +++ b/ocf @@ -1 +1 @@ -Subproject commit 9a46c402b2e8398da7a3ee212faf041b3f01f958 +Subproject commit c2da038c03693a9105bee67952614db1a5cf1a37 From a9e891da6338e05f80823f4f2bb258237982ab52 Mon Sep 17 00:00:00 2001 From: Michal Mielewczyk Date: Tue, 27 Aug 2019 02:29:12 -0400 Subject: [PATCH 3/9] Adopt cache stats command to ocf stats builder. Signed-off-by: Michal Mielewczyk --- casadm/statistics_model.c | 475 ++++++++++++-------------------------- 1 file changed, 145 insertions(+), 330 deletions(-) diff --git a/casadm/statistics_model.c b/casadm/statistics_model.c index be90456..f4f2a13 100644 --- a/casadm/statistics_model.c +++ b/casadm/statistics_model.c @@ -220,208 +220,133 @@ static void print_usage_header(FILE* outfile) "%", "[Units]"); } -static void print_core_usage(const struct ocf_stats_core* exp_obj_stats, - uint32_t cache_size, uint32_t cache_occupancy, - FILE* outfile, ocf_cache_line_size_t line_size) +static void print_usage_stats(struct ocf_stats_usage *stats, FILE* outfile) { print_usage_header(outfile); print_val_perc_table_row(outfile, "Occupancy", UNIT_BLOCKS, - percentage(exp_obj_stats->cache_occupancy, - cache_size), - "%lu", - cache_line_in_4k(exp_obj_stats->cache_occupancy, - line_size)); + stats->occupancy.percent/10, "%lu", stats->occupancy.value); print_val_perc_table_row(outfile, "Free", UNIT_BLOCKS, - percentage(cache_size - cache_occupancy, cache_size), - "%lu", - cache_line_in_4k(cache_size - cache_occupancy, - line_size)); + stats->free.percent/10, "%lu", stats->free.value); print_val_perc_table_row(outfile, "Clean", UNIT_BLOCKS, - percentage(exp_obj_stats->cache_occupancy - exp_obj_stats->dirty, - exp_obj_stats->cache_occupancy), - "%lu", - cache_line_in_4k(exp_obj_stats->cache_occupancy - exp_obj_stats->dirty, - line_size)); + stats->clean.percent/10, "%lu", stats->clean.value); print_val_perc_table_row(outfile, "Dirty", UNIT_BLOCKS, - percentage(exp_obj_stats->dirty, - exp_obj_stats->cache_occupancy), - "%lu", - cache_line_in_4k(exp_obj_stats->dirty, - line_size)); + stats->dirty.percent/10, "%lu", stats->dirty.value); } -static void print_req_section(const struct ocf_stats_req *stats, const char *op_name, - FILE *outfile, uint64_t total_reqs) +static void print_req_stats(const struct ocf_stats_requests *stats, + FILE *outfile) { - uint64_t cache_hits; - float percent; - - cache_hits = stats->total - (stats->full_miss + stats->partial_miss); - - percent = percentage(cache_hits, total_reqs); - print_val_perc_table_section(outfile, make_row_title(op_name, "hits"), - UNIT_REQUESTS, percent, "%lu", cache_hits); - - percent = percentage(stats->partial_miss, total_reqs); - print_val_perc_table_row(outfile, make_row_title(op_name, "partial misses"), - UNIT_REQUESTS, percent, "%lu", stats->partial_miss); - - percent = percentage(stats->full_miss, total_reqs); - print_val_perc_table_row(outfile, make_row_title(op_name, "full misses"), - UNIT_REQUESTS, percent, "%lu", stats->full_miss); - - percent = percentage(stats->total, total_reqs); - print_val_perc_table_row(outfile, make_row_title(op_name, "total"), - UNIT_REQUESTS, percent, "%lu", stats->total); -} - -static void print_req_stats(const struct ocf_stats_core *exp_obj_stats, - FILE *outfile) -{ - const struct ocf_stats_req *req_stats; - float percent; - uint64_t total_reqs = 0, serv_reqs = 0; - print_table_header(outfile, 4, "Request statistics", "Count", "%", "[Units]"); - total_reqs += exp_obj_stats->read_reqs.total; - total_reqs += exp_obj_stats->write_reqs.total; + print_val_perc_table_section(outfile, "Read hits", + UNIT_REQUESTS, stats->rd_hits.percent/10, "%lu", + stats->rd_hits.value); + print_val_perc_table_row(outfile, "Read partial misses", + UNIT_REQUESTS, stats->rd_partial_misses.percent/10, "%lu", + stats->rd_partial_misses.value); + print_val_perc_table_row(outfile, "Read full misses", + UNIT_REQUESTS, stats->rd_full_misses.percent/10, "%lu", + stats->rd_full_misses.value); + print_val_perc_table_row(outfile, "Read total", + UNIT_REQUESTS, stats->rd_total.percent/10, "%lu", + stats->rd_total.value); - serv_reqs = total_reqs; + print_val_perc_table_section(outfile, "Write hits", + UNIT_REQUESTS, stats->wr_hits.percent/10, "%lu", + stats->wr_hits.value); + print_val_perc_table_row(outfile, "Write partial misses", + UNIT_REQUESTS, stats->wr_partial_misses.percent/10, "%lu", + stats->wr_partial_misses.value); + print_val_perc_table_row(outfile, "Write full misses", + UNIT_REQUESTS, stats->wr_full_misses.percent/10, "%lu", + stats->wr_full_misses.value); + print_val_perc_table_row(outfile, "Write total", + UNIT_REQUESTS, stats->wr_total.percent/10, "%lu", + stats->wr_total.value); - total_reqs += exp_obj_stats->read_reqs.pass_through; - total_reqs += exp_obj_stats->write_reqs.pass_through; + print_val_perc_table_section(outfile, "Pass-Through reads", + UNIT_REQUESTS, stats->rd_pt.percent/10, "%lu", + stats->rd_pt.value); + print_val_perc_table_row(outfile, "Pass-Through writes", + UNIT_REQUESTS, stats->wr_pt.percent/10, "%lu", + stats->wr_pt.value); + print_val_perc_table_row(outfile, "Serviced requests", + UNIT_REQUESTS, stats->serviced.percent/10, "%lu", + stats->serviced.value); - /* Section for reads. */ - req_stats = &exp_obj_stats->read_reqs; - print_req_section(req_stats, "Read", outfile, total_reqs); - - /* Section for writes. */ - req_stats = &exp_obj_stats->write_reqs; - print_req_section(req_stats, "Write", outfile, total_reqs); - - /* Pass-Through requests. */ - percent = percentage(exp_obj_stats->read_reqs.pass_through, total_reqs); - print_val_perc_table_section(outfile, "Pass-Through reads", UNIT_REQUESTS, - percent, "%lu", - exp_obj_stats->read_reqs.pass_through); - - percent = percentage(exp_obj_stats->write_reqs.pass_through, total_reqs); - print_val_perc_table_row(outfile, "Pass-Through writes", UNIT_REQUESTS, - percent, "%lu", - exp_obj_stats->write_reqs.pass_through); - - /* Summary. */ - percent = percentage(serv_reqs, total_reqs); - print_val_perc_table_row(outfile, "Serviced requests", UNIT_REQUESTS, - percent, "%lu", serv_reqs); - - print_val_perc_table_section(outfile, "Total requests", UNIT_REQUESTS, - total_reqs ? 100.0f : 0.0f, "%lu", - total_reqs); + print_val_perc_table_section(outfile, "Total requests", + UNIT_REQUESTS, stats->total.percent/10, "%lu", + stats->total.value); } -static void print_block_section(const struct ocf_stats_block *stats_4k, - const char *dev_name, FILE *outfile, - ocf_cache_line_size_t cache_line_size) +static void print_blk_stats(const struct ocf_stats_blocks *stats, + bool cache_stats, FILE *outfile) { - uint64_t total_4k; - float percent; - - total_4k = stats_4k->read + stats_4k->write; - - percent = percentage(stats_4k->read, total_4k); - print_val_perc_table_section(outfile, - make_row_title("Reads from", dev_name), - UNIT_BLOCKS, percent, "%lu", stats_4k->read); - - percent = percentage(stats_4k->write, total_4k); - print_val_perc_table_row(outfile, - make_row_title("Writes to", dev_name), - UNIT_BLOCKS, percent, "%lu", stats_4k->write); - - print_val_perc_table_row(outfile, - make_row_title("Total to/from", dev_name), - UNIT_BLOCKS, total_4k ? 100.0f : 0.0f, "%lu", - total_4k); -} - -static struct ocf_stats_block convert_block_stats_to_4k( - const struct ocf_stats_block *stats) -{ - struct ocf_stats_block stats_4k; - stats_4k.read = bytes_to_4k(stats->read); - stats_4k.write = bytes_to_4k(stats->write); - return stats_4k; -} - -void print_block_stats(const struct ocf_stats_core *exp_obj_stats, - FILE *outfile, ocf_cache_line_size_t cache_line_size) -{ - struct ocf_stats_block cache_volume_stats_4k = - convert_block_stats_to_4k(&exp_obj_stats->cache_volume); - struct ocf_stats_block core_volume_stats_4k = - convert_block_stats_to_4k(&exp_obj_stats->core_volume); - struct ocf_stats_block core_stats_4k = - convert_block_stats_to_4k(&exp_obj_stats->core); - print_table_header(outfile, 4, "Block statistics", "Count", - "%", "[Units]"); + "%", "[Units]"); - print_block_section(&core_volume_stats_4k, "core", outfile, - cache_line_size); - print_block_section(&cache_volume_stats_4k, "cache", outfile, - cache_line_size); - print_block_section(&core_stats_4k, "exported object", outfile, - cache_line_size); + print_val_perc_table_section(outfile, "Reads from core(s)", + UNIT_BLOCKS, stats->core_volume_rd.percent/10, "%lu", + stats->core_volume_rd.value); + print_val_perc_table_row(outfile, "Writes to core(s)", + UNIT_BLOCKS, stats->core_volume_wr.percent/10, "%lu", + stats->core_volume_wr.value); + print_val_perc_table_row(outfile, "Total to/from core(s)", + UNIT_BLOCKS, stats->core_volume_total.percent/10, "%lu", + stats->core_volume_total.value); + + print_val_perc_table_section(outfile, "Reads from cache", + UNIT_BLOCKS, stats->cache_volume_rd.percent/10, "%lu", + stats->cache_volume_rd.value); + print_val_perc_table_row(outfile, "Writes to cache", + UNIT_BLOCKS, stats->cache_volume_wr.percent/10, "%lu", + stats->cache_volume_wr.value); + print_val_perc_table_row(outfile, "Total to/from cache", + UNIT_BLOCKS, stats->cache_volume_total.percent/10, "%lu", + stats->cache_volume_total.value); + + print_val_perc_table_section(outfile, "Reads from exported object(s)", + UNIT_BLOCKS, stats->volume_rd.percent/10, "%lu", + stats->volume_rd.value); + print_val_perc_table_row(outfile, "Writes to exported object(s)", + UNIT_BLOCKS, stats->volume_wr.percent/10, "%lu", + stats->volume_wr.value); + print_val_perc_table_row(outfile, "Total to/from exported object(s)", + UNIT_BLOCKS, stats->volume_total.percent/10, "%lu", + stats->volume_total.value); } -static void print_error_section(const struct ocf_stats_error *stats, - const char *section_name, FILE *outfile) +static void print_err_stats(const struct ocf_stats_errors *stats, + FILE *outfile) { - uint64_t total = 0; - float percent; + print_table_header(outfile, 4, "Error statistics", "Count", "%", + "[Units]"); - total = stats->read + stats->write; + print_val_perc_table_section(outfile, "Cache read errors", + UNIT_REQUESTS, stats->cache_volume_rd.percent/10, "%lu", + stats->cache_volume_rd.value); + print_val_perc_table_row(outfile, "Cache write errors", + UNIT_REQUESTS, stats->cache_volume_wr.percent/10, "%lu", + stats->cache_volume_wr.value); + print_val_perc_table_row(outfile, "Cache total errors", + UNIT_REQUESTS, stats->cache_volume_total.percent/10, "%lu", + stats->cache_volume_total.value); - percent = percentage(stats->read, total); - print_val_perc_table_section(outfile, - make_row_title(section_name , "read errors"), - UNIT_REQUESTS, percent, "%u", stats->read); - percent = percentage(stats->write, total); - print_val_perc_table_row(outfile, - make_row_title(section_name, "write errors"), - UNIT_REQUESTS, percent, "%u", stats->write); - print_val_perc_table_row(outfile, - make_row_title(section_name, "total errors"), - UNIT_REQUESTS, total ? 100.0f : 0.0f, "%lu", total); -} + print_val_perc_table_section(outfile, "Core read errors", + UNIT_REQUESTS, stats->core_volume_rd.percent/10, "%lu", + stats->core_volume_rd.value); + print_val_perc_table_row(outfile, "Core write errors", + UNIT_REQUESTS, stats->core_volume_wr.percent/10, "%lu", + stats->core_volume_wr.value); + print_val_perc_table_row(outfile, "Core total errors", + UNIT_REQUESTS, stats->core_volume_total.percent/10, "%lu", + stats->core_volume_total.value); -static void print_error_stats_total(const struct ocf_stats_error *cache_stats, - const struct ocf_stats_error *core_stats, - FILE *outfile) -{ - uint64_t total; - - total = cache_stats->read + cache_stats->write + - core_stats->read + core_stats->write; - - print_val_perc_table_section(outfile, "Total errors", UNIT_REQUESTS, - total ? 100.0f : 0.0f, "%lu", total); -} - -static void print_error_stats(const struct ocf_stats_core *exp_obj_stats, - FILE *outfile) -{ - print_table_header(outfile, 4, "Error statistics", "Count", "%", "[Units]"); - - print_error_section(&exp_obj_stats->cache_errors, "Cache", outfile); - print_error_section(&exp_obj_stats->core_errors, "Core", outfile); - - print_error_stats_total(&exp_obj_stats->cache_errors, - &exp_obj_stats->core_errors, outfile); + print_val_perc_table_section(outfile, "Total errors", + UNIT_REQUESTS, stats->total.percent/10, "%lu", + stats->total.value); } void cache_stats_core_counters(const struct kcas_core_info *info, @@ -841,40 +766,32 @@ int cache_stats_cores(int ctrl_fd, const struct kcas_cache_info *cache_info, unsigned int cache_id, unsigned int core_id, int io_class_id, FILE *outfile, unsigned int stats_filters) { - int i; - int _core_id; - uint32_t cache_size; - ocf_cache_line_size_t cache_line_size; struct kcas_core_info core_info; + struct kcas_get_stats stats; - for (i = 0; i < cache_info->info.core_count; ++i) { - /* if user only requested stats pertaining to a specific core, - skip all other cores */ - _core_id = cache_info->core_id[i]; - if ((core_id != OCF_CORE_ID_INVALID) && (core_id != _core_id)) { - continue; - } - /* call function to print stats */ - if (get_core_info(ctrl_fd, cache_id, _core_id, &core_info)) { - cas_printf(LOG_ERR, "Error while retrieving stats for core %d\n", _core_id); - print_err(core_info.ext_err_code); - return FAILURE; - } - - cache_size = cache_info->info.size; - cache_line_size = cache_info->info.cache_line_size / KiB; - - cache_stats_core_counters(&core_info, cache_size, - cache_info->info.occupancy, - stats_filters, outfile, cache_line_size); + if (get_core_info(ctrl_fd, cache_id, core_id, &core_info)) { + cas_printf(LOG_ERR, "Error while retrieving stats for core %d\n", core_id); + print_err(core_info.ext_err_code); + return FAILURE; } + stats.cache_id = cache_id; + stats.core_id = core_id; + stats.part_id = OCF_IO_CLASS_INVALID; + + if (ioctl(ctrl_fd, KCAS_IOCTL_GET_STATS, &stats) < 0) { + cas_printf(LOG_ERR, "Error while retrieving stats for core %d\n", core_id); + print_err(core_info.ext_err_code); + return FAILURE; + } + + cache_stats_core_counters(&core_info, &stats, stats_filters, outfile); + return SUCCESS; } int cache_stats_conf(int ctrl_fd, const struct kcas_cache_info *cache_info, - unsigned int cache_id, FILE *outfile, - unsigned int stats_filters) + unsigned int cache_id, FILE *outfile) { float flush_progress = 0; float value; @@ -941,46 +858,6 @@ int cache_stats_conf(int ctrl_fd, const struct kcas_cache_info *cache_info, return SUCCESS; } -int cache_stats_usage(int ctrl_fd, const struct kcas_cache_info *cache_info, - unsigned int cache_id, FILE* outfile) -{ - print_usage_header(outfile); - - print_val_perc_table_row(outfile, "Occupancy", UNIT_BLOCKS, - percentage(cache_info->info.occupancy, - cache_info->info.size), - "%lu", - cache_line_in_4k(cache_info->info.occupancy, - cache_info->info.cache_line_size / KiB)); - - print_val_perc_table_row(outfile, "Free", UNIT_BLOCKS, - percentage(cache_info->info.size - - cache_info->info.occupancy, - cache_info->info.size), - "%lu", - cache_line_in_4k(cache_info->info.size - - cache_info->info.occupancy, - cache_info->info.cache_line_size / KiB)); - - print_val_perc_table_row(outfile, "Clean", UNIT_BLOCKS, - percentage(cache_info->info.occupancy - - cache_info->info.dirty, - cache_info->info.occupancy), - "%lu", - cache_line_in_4k(cache_info->info.occupancy - - cache_info->info.dirty, - cache_info->info.cache_line_size / KiB)); - - print_val_perc_table_row(outfile, "Dirty", UNIT_BLOCKS, - percentage(cache_info->info.dirty, - cache_info->info.occupancy), - "%lu", - cache_line_in_4k(cache_info->info.dirty, - cache_info->info.cache_line_size / KiB)); - - return SUCCESS; -} - int cache_stats_inactive_usage(int ctrl_fd, const struct kcas_cache_info *cache_info, unsigned int cache_id, FILE* outfile) { @@ -1013,83 +890,20 @@ int cache_stats_inactive_usage(int ctrl_fd, const struct kcas_cache_info *cache_ return SUCCESS; } -int cache_stats_counters(int ctrl_fd, const struct kcas_cache_info *cache_info, - unsigned int cache_id, FILE *outfile, - unsigned int stats_filters) +void cache_stats_counters(struct kcas_get_stats *cache_stats, FILE *outfile, + unsigned int stats_filters) { - int i; - int _core_id; - struct ocf_stats_core *stats; - struct ocf_stats_core total_stats; - struct kcas_core_info core_info; - - struct ocf_stats_error total_cache_errors, total_core_errors; - - memset(&total_stats, 0, sizeof(total_stats)); - - memset(&total_cache_errors, 0, sizeof(total_cache_errors)); - memset(&total_core_errors, 0, sizeof(total_core_errors)); - - for (i = 0; i < cache_info->info.core_count; ++i) { - /* if user only requested stats pertaining to a specific core, - skip all other cores */ - _core_id = cache_info->core_id[i]; - /* call function to print stats */ - if (get_core_info(ctrl_fd, cache_id, _core_id, &core_info)) { - cas_printf(LOG_ERR, "Error while retrieving stats for core %d\n", _core_id); - print_err(core_info.ext_err_code); - return FAILURE; - } - - stats = &core_info.stats; - - /* Convert block stats to 4k before adding them up. This way - sum of block stats for cores is consistent with cache - stats */ - stats->cache_volume = convert_block_stats_to_4k(&stats->cache_volume); - stats->core_volume = convert_block_stats_to_4k(&stats->core_volume); - stats->core = convert_block_stats_to_4k(&stats->core); - - accum_block_stats(&total_stats.cache_volume, &stats->cache_volume); - accum_block_stats(&total_stats.core_volume, &stats->core_volume); - accum_block_stats(&total_stats.core, &stats->core); - - accum_req_stats(&total_stats.read_reqs, &stats->read_reqs); - accum_req_stats(&total_stats.write_reqs, &stats->write_reqs); - - accum_error_stats(&total_cache_errors, &stats->cache_errors); - accum_error_stats(&total_core_errors, &stats->core_errors); - } - /* Totals for requests stats. */ - if (stats_filters & STATS_FILTER_REQ) { - print_req_stats(&total_stats, outfile); - } + if (stats_filters & STATS_FILTER_REQ) + print_req_stats(&cache_stats->req, outfile); /* Totals for blocks stats. */ - if (stats_filters & STATS_FILTER_BLK) { - print_table_header(outfile, 4, "Block statistics", "Count", - "%", "[Units]"); - print_block_section(&total_stats.core_volume, "core(s)", outfile, - cache_info->info.cache_line_size / KiB); - print_block_section(&total_stats.cache_volume, "cache", outfile, - cache_info->info.cache_line_size / KiB); - print_block_section(&total_stats.core, "exported object(s)", outfile, - cache_info->info.cache_line_size / KiB); - } + if (stats_filters & STATS_FILTER_BLK) + print_blk_stats(&cache_stats->blocks, true, outfile); /* Totals for error stats. */ - if (stats_filters & STATS_FILTER_ERR) { - print_table_header(outfile, 4, "Error statistics", "Count", "%", - "[Units]"); - print_error_section(&total_cache_errors, "Cache", outfile); - print_error_section(&total_core_errors, "Core", outfile); - - print_error_stats_total(&total_cache_errors, &total_core_errors, - outfile); - } - - return SUCCESS; + if (stats_filters & STATS_FILTER_ERR) + print_err_stats(&cache_stats->errors, outfile); } @@ -1139,6 +953,7 @@ int cache_status(unsigned int cache_id, unsigned int core_id, int io_class_id, int ret = SUCCESS; int attempt_no = 0; struct kcas_cache_info cache_info; + struct kcas_get_stats cache_stats = {}; ctrl_fd = open_ctrl_device(); @@ -1147,6 +962,7 @@ int cache_status(unsigned int cache_id, unsigned int core_id, int io_class_id, return FAILURE; } + /** * * Procedure of printing out statistics is as follows: @@ -1228,25 +1044,29 @@ int cache_status(unsigned int cache_id, unsigned int core_id, int io_class_id, } } else if (core_id == OCF_CORE_ID_INVALID) { - begin_record(intermediate_file[1]); - if (stats_filters & STATS_FILTER_CONF) { - if (cache_stats_conf(ctrl_fd, &cache_info, - cache_id, - intermediate_file[1], - stats_filters)) { - ret = FAILURE; - goto cleanup; - } + cache_stats.cache_id = cache_id; + cache_stats.core_id = OCF_CORE_ID_INVALID; + cache_stats.part_id = OCF_IO_CLASS_INVALID; + + if (ioctl(ctrl_fd, KCAS_IOCTL_GET_STATS, &cache_stats) < 0) { + ret = FAILURE; + goto cleanup; } - if (stats_filters & STATS_FILTER_USAGE) { - if (cache_stats_usage(ctrl_fd, &cache_info, + begin_record(intermediate_file[1]); + + if (stats_filters & STATS_FILTER_CONF) { + if (cache_stats_conf(ctrl_fd, &cache_info, cache_id, intermediate_file[1])) { ret = FAILURE; goto cleanup; } } + + if (stats_filters & STATS_FILTER_USAGE) + print_usage_stats(&cache_stats.usage, intermediate_file[1]); + if ((cache_info.info.state & (1 << ocf_cache_state_incomplete)) && stats_filters & STATS_FILTER_USAGE) { if (cache_stats_inactive_usage(ctrl_fd, &cache_info, @@ -1258,13 +1078,8 @@ int cache_status(unsigned int cache_id, unsigned int core_id, int io_class_id, } if (stats_filters & STATS_FILTER_COUNTERS) { - if (cache_stats_counters(ctrl_fd, &cache_info, - cache_id, - intermediate_file[1], - stats_filters)) { - ret = FAILURE; - goto cleanup; - } + cache_stats_counters(&cache_stats, intermediate_file[1], + stats_filters); } } else { From 37d6d565fad3f0d677272491e14a9a2c1fda9723 Mon Sep 17 00:00:00 2001 From: Michal Mielewczyk Date: Tue, 27 Aug 2019 02:31:34 -0400 Subject: [PATCH 4/9] Adopt core stats command to ocf stats builder api. Signed-off-by: Michal Mielewczyk --- casadm/statistics_model.c | 81 +++++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 37 deletions(-) diff --git a/casadm/statistics_model.c b/casadm/statistics_model.c index f4f2a13..df426f5 100644 --- a/casadm/statistics_model.c +++ b/casadm/statistics_model.c @@ -185,9 +185,7 @@ static inline const char *make_row_title(const char *s1, const char *s2) return buffer; } -static void print_core_conf(const struct kcas_core_info *info, - uint32_t cache_size, FILE *outfile, - ocf_cache_line_size_t cache_line_size) +static void print_core_conf(const struct kcas_core_info *info, FILE *outfile) { uint64_t core_size; float core_size_gb; @@ -281,39 +279,63 @@ static void print_req_stats(const struct ocf_stats_requests *stats, stats->total.value); } +#define get_stat_name(__dst, __len, __name, __postfix) \ + memset(__dst, 0, __len); \ + snprintf(__dst, __len, "%s%s", __name, __postfix); + + static void print_blk_stats(const struct ocf_stats_blocks *stats, bool cache_stats, FILE *outfile) { print_table_header(outfile, 4, "Block statistics", "Count", "%", "[Units]"); - print_val_perc_table_section(outfile, "Reads from core(s)", + char *postfix = (cache_stats ? "(s)" : ""); + size_t max_stat_len = 128; + char stat_name[max_stat_len]; + + get_stat_name(stat_name, max_stat_len, "Reads from core", postfix); + print_val_perc_table_section(outfile, stat_name, UNIT_BLOCKS, stats->core_volume_rd.percent/10, "%lu", stats->core_volume_rd.value); - print_val_perc_table_row(outfile, "Writes to core(s)", + + get_stat_name(stat_name, max_stat_len, "Writes to core", postfix); + print_val_perc_table_row(outfile, stat_name, UNIT_BLOCKS, stats->core_volume_wr.percent/10, "%lu", stats->core_volume_wr.value); - print_val_perc_table_row(outfile, "Total to/from core(s)", + + get_stat_name(stat_name, max_stat_len, "Total to/from core", postfix); + print_val_perc_table_row(outfile, stat_name, UNIT_BLOCKS, stats->core_volume_total.percent/10, "%lu", stats->core_volume_total.value); print_val_perc_table_section(outfile, "Reads from cache", UNIT_BLOCKS, stats->cache_volume_rd.percent/10, "%lu", stats->cache_volume_rd.value); + print_val_perc_table_row(outfile, "Writes to cache", UNIT_BLOCKS, stats->cache_volume_wr.percent/10, "%lu", stats->cache_volume_wr.value); + print_val_perc_table_row(outfile, "Total to/from cache", UNIT_BLOCKS, stats->cache_volume_total.percent/10, "%lu", stats->cache_volume_total.value); - print_val_perc_table_section(outfile, "Reads from exported object(s)", + get_stat_name(stat_name, max_stat_len, "Reads from exported object", + postfix); + print_val_perc_table_section(outfile, stat_name, UNIT_BLOCKS, stats->volume_rd.percent/10, "%lu", stats->volume_rd.value); - print_val_perc_table_row(outfile, "Writes to exported object(s)", + + get_stat_name(stat_name, max_stat_len, "Writes to exported object", + postfix); + print_val_perc_table_row(outfile, stat_name, UNIT_BLOCKS, stats->volume_wr.percent/10, "%lu", stats->volume_wr.value); - print_val_perc_table_row(outfile, "Total to/from exported object(s)", + + get_stat_name(stat_name, max_stat_len, "Total to/from exported object", + postfix); + print_val_perc_table_row(outfile, stat_name, UNIT_BLOCKS, stats->volume_total.percent/10, "%lu", stats->volume_total.value); } @@ -350,33 +372,25 @@ static void print_err_stats(const struct ocf_stats_errors *stats, } void cache_stats_core_counters(const struct kcas_core_info *info, - uint32_t cache_size, uint32_t cache_occupancy, - unsigned int stats_filters, FILE *outfile, - ocf_cache_line_size_t cache_line_size) + struct kcas_get_stats *stats, + unsigned int stats_filters, FILE *outfile) { - const struct ocf_stats_core *stats = &info->stats; - begin_record(outfile); - if (stats_filters & STATS_FILTER_CONF) { - print_core_conf(info, cache_size, outfile, cache_line_size); - } - if (stats_filters & STATS_FILTER_USAGE) { - print_core_usage(stats, cache_size, cache_occupancy, - outfile, cache_line_size); - } + if (stats_filters & STATS_FILTER_CONF) + print_core_conf(info, outfile); - if (stats_filters & STATS_FILTER_REQ) { - print_req_stats(stats, outfile); - } + if (stats_filters & STATS_FILTER_USAGE) + print_usage_stats(&stats->usage, outfile); - if (stats_filters & STATS_FILTER_BLK) { - print_block_stats(stats, outfile, cache_line_size); - } + if (stats_filters & STATS_FILTER_REQ) + print_req_stats(&stats->req, outfile); - if (stats_filters & STATS_FILTER_ERR) { - print_error_stats(stats, outfile); - } + if (stats_filters & STATS_FILTER_BLK) + print_blk_stats(&stats->blocks, false, outfile); + + if (stats_filters & STATS_FILTER_ERR) + print_err_stats(&stats->errors, outfile); } static void print_stats_ioclass_conf(const struct kcas_io_class* io_class, @@ -1083,13 +1097,6 @@ int cache_status(unsigned int cache_id, unsigned int core_id, int io_class_id, } } else { - /* print per core statistics. this may include: - * - core header - * - core counters - * - core per io class statistics - * - * depending on which set of statistics is enabled via -f/-d switches. - */ if (cache_stats_cores(ctrl_fd, &cache_info, cache_id, core_id, io_class_id, intermediate_file[1], stats_filters)) { From 30c4e5c82ffdda6056c8c8137b78d4e791ad202a Mon Sep 17 00:00:00 2001 From: Michal Mielewczyk Date: Wed, 28 Aug 2019 09:08:58 -0400 Subject: [PATCH 5/9] casadm: Refactor code responsible for printing stats. Signed-off-by: Michal Mielewczyk --- casadm/statistics_model.c | 258 ++++++++++++++++---------------------- 1 file changed, 107 insertions(+), 151 deletions(-) diff --git a/casadm/statistics_model.c b/casadm/statistics_model.c index df426f5..51094c0 100644 --- a/casadm/statistics_model.c +++ b/casadm/statistics_model.c @@ -39,8 +39,6 @@ #define UNIT_REQUESTS "Requests" #define UNIT_BLOCKS "4KiB blocks" -#define ALLOWED_NUMBER_OF_ATTEMPTS 10 - static inline float percentage(uint64_t numerator, uint64_t denominator) { float result; @@ -531,6 +529,37 @@ static void print_stats_ioclass_req(const struct ocf_stats_io_class* part_stats, } + +void cache_stats_inactive_usage(int ctrl_fd, const struct kcas_cache_info *cache_info, + unsigned int cache_id, FILE* outfile) +{ + print_table_header(outfile, 4, "Inactive usage statistics", "Count", + "%", "[Units]"); + + print_val_perc_table_row(outfile, "Inactive Occupancy", UNIT_BLOCKS, + percentage(cache_info->info.inactive.occupancy, + cache_info->info.size), + "%lu", + cache_line_in_4k(cache_info->info.inactive.occupancy, + cache_info->info.cache_line_size / KiB)); + + print_val_perc_table_row(outfile, "Inactive Clean", UNIT_BLOCKS, + percentage(cache_info->info.inactive.occupancy - + cache_info->info.inactive.dirty, + cache_info->info.occupancy), + "%lu", + cache_line_in_4k(cache_info->info.inactive.occupancy - + cache_info->info.inactive.dirty, + cache_info->info.cache_line_size / KiB)); + + print_val_perc_table_row(outfile, "Inactive Dirty", UNIT_BLOCKS, + percentage(cache_info->info.inactive.dirty, + cache_info->info.occupancy), + "%lu", + cache_line_in_4k(cache_info->info.inactive.dirty, + 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) @@ -776,34 +805,6 @@ static inline void accum_error_stats(struct ocf_stats_error *to, to->write += from->write; } -int cache_stats_cores(int ctrl_fd, const struct kcas_cache_info *cache_info, - unsigned int cache_id, unsigned int core_id, int io_class_id, - FILE *outfile, unsigned int stats_filters) -{ - struct kcas_core_info core_info; - struct kcas_get_stats stats; - - if (get_core_info(ctrl_fd, cache_id, core_id, &core_info)) { - cas_printf(LOG_ERR, "Error while retrieving stats for core %d\n", core_id); - print_err(core_info.ext_err_code); - return FAILURE; - } - - stats.cache_id = cache_id; - stats.core_id = core_id; - stats.part_id = OCF_IO_CLASS_INVALID; - - if (ioctl(ctrl_fd, KCAS_IOCTL_GET_STATS, &stats) < 0) { - cas_printf(LOG_ERR, "Error while retrieving stats for core %d\n", core_id); - print_err(core_info.ext_err_code); - return FAILURE; - } - - cache_stats_core_counters(&core_info, &stats, stats_filters, outfile); - - return SUCCESS; -} - int cache_stats_conf(int ctrl_fd, const struct kcas_cache_info *cache_info, unsigned int cache_id, FILE *outfile) { @@ -872,38 +873,6 @@ int cache_stats_conf(int ctrl_fd, const struct kcas_cache_info *cache_info, return SUCCESS; } -int cache_stats_inactive_usage(int ctrl_fd, const struct kcas_cache_info *cache_info, - unsigned int cache_id, FILE* outfile) -{ - print_table_header(outfile, 4, "Inactive usage statistics", "Count", - "%", "[Units]"); - - print_val_perc_table_row(outfile, "Inactive Occupancy", UNIT_BLOCKS, - percentage(cache_info->info.inactive.occupancy, - cache_info->info.size), - "%lu", - cache_line_in_4k(cache_info->info.inactive.occupancy, - cache_info->info.cache_line_size / KiB)); - - print_val_perc_table_row(outfile, "Inactive Clean", UNIT_BLOCKS, - percentage(cache_info->info.inactive.occupancy - - cache_info->info.inactive.dirty, - cache_info->info.occupancy), - "%lu", - cache_line_in_4k(cache_info->info.inactive.occupancy - - cache_info->info.inactive.dirty, - cache_info->info.cache_line_size / KiB)); - - print_val_perc_table_row(outfile, "Inactive Dirty", UNIT_BLOCKS, - percentage(cache_info->info.inactive.dirty, - cache_info->info.occupancy), - "%lu", - cache_line_in_4k(cache_info->info.inactive.dirty, - cache_info->info.cache_line_size / KiB)); - - return SUCCESS; -} - void cache_stats_counters(struct kcas_get_stats *cache_stats, FILE *outfile, unsigned int stats_filters) { @@ -920,6 +889,63 @@ void cache_stats_counters(struct kcas_get_stats *cache_stats, FILE *outfile, print_err_stats(&cache_stats->errors, outfile); } +static int cache_stats(int ctrl_fd, const struct kcas_cache_info *cache_info, + unsigned int cache_id, FILE *outfile, unsigned int stats_filters) +{ + struct kcas_get_stats cache_stats = {}; + cache_stats.cache_id = cache_id; + cache_stats.core_id = OCF_CORE_ID_INVALID; + cache_stats.part_id = OCF_IO_CLASS_INVALID; + + if (ioctl(ctrl_fd, KCAS_IOCTL_GET_STATS, &cache_stats) < 0) + return FAILURE; + + begin_record(outfile); + + if (stats_filters & STATS_FILTER_CONF) + cache_stats_conf(ctrl_fd, cache_info, cache_id, outfile); + + if (stats_filters & STATS_FILTER_USAGE) + print_usage_stats(&cache_stats.usage, outfile); + + if ((cache_info->info.state & (1 << ocf_cache_state_incomplete)) + && (stats_filters & STATS_FILTER_USAGE)) { + cache_stats_inactive_usage(ctrl_fd, cache_info, cache_id, outfile); + } + + if (stats_filters & STATS_FILTER_COUNTERS) + cache_stats_counters(&cache_stats, outfile, stats_filters); + + return SUCCESS; +} + +int cache_stats_cores(int ctrl_fd, const struct kcas_cache_info *cache_info, + unsigned int cache_id, unsigned int core_id, int io_class_id, + FILE *outfile, unsigned int stats_filters) +{ + struct kcas_core_info core_info; + struct kcas_get_stats stats; + + if (get_core_info(ctrl_fd, cache_id, core_id, &core_info)) { + cas_printf(LOG_ERR, "Error while retrieving stats for core %d\n", core_id); + print_err(core_info.ext_err_code); + return FAILURE; + } + + stats.cache_id = cache_id; + stats.core_id = core_id; + stats.part_id = OCF_IO_CLASS_INVALID; + + if (ioctl(ctrl_fd, KCAS_IOCTL_GET_STATS, &stats) < 0) { + cas_printf(LOG_ERR, "Error while retrieving stats for core %d\n", core_id); + print_err(core_info.ext_err_code); + return FAILURE; + } + + cache_stats_core_counters(&core_info, &stats, stats_filters, outfile); + + return SUCCESS; +} struct stats_printout_ctx { @@ -942,10 +968,6 @@ void *stats_printout(void *ctx) return 0; } -bool _usage_stats_is_valid(struct kcas_cache_info *cmd_info) -{ - return (cmd_info->info.size >= cmd_info->info.occupancy); -} /** * @brief print cache statistics in various variants * @@ -965,9 +987,7 @@ int cache_status(unsigned int cache_id, unsigned int core_id, int io_class_id, { int ctrl_fd, i; int ret = SUCCESS; - int attempt_no = 0; struct kcas_cache_info cache_info; - struct kcas_get_stats cache_stats = {}; ctrl_fd = open_ctrl_device(); @@ -976,25 +996,6 @@ int cache_status(unsigned int cache_id, unsigned int core_id, int io_class_id, return FAILURE; } - - /** - * - * Procedure of printing out statistics is as follows: - * - * - * statistics_model.c (retrieve structures from kernel, don't do formatting) - * | - * v - * abstract CSV notation with prefixes (as a temporary file) - * | - * v - * statistics_view (parse basic csv notation, generate proper output) - * | - * v - * desired output format - * - */ - /* 1 is writing end, 0 is reading end of a pipe */ FILE *intermediate_file[2]; @@ -1020,34 +1021,25 @@ int cache_status(unsigned int cache_id, unsigned int core_id, int io_class_id, cache_info.cache_id = cache_id; - do { - if (0 != attempt_no) { - usleep(300 * 1000); - } + if (ioctl(ctrl_fd, KCAS_IOCTL_CACHE_INFO, &cache_info) < 0) { + cas_printf(LOG_ERR, "Cache Id %d not running\n", cache_id); + ret = FAILURE; + goto cleanup; + } - if (ioctl(ctrl_fd, KCAS_IOCTL_CACHE_INFO, &cache_info) < 0) { - cas_printf(LOG_ERR, "Cache Id %d not running\n", cache_id); + /* Check if core exists in cache */ + if (core_id != OCF_CORE_ID_INVALID) { + for (i = 0; i < cache_info.info.core_count; ++i) { + if (core_id == cache_info.core_id[i]) { + break; + } + } + if (i == cache_info.info.core_count) { + cas_printf(LOG_ERR, "No such core device in cache.\n"); ret = FAILURE; goto cleanup; } - - /* Check if core exists in cache */ - if (core_id != OCF_CORE_ID_INVALID) { - for (i = 0; i < cache_info.info.core_count; ++i) { - if (core_id == cache_info.core_id[i]) { - break; - } - } - if (i == cache_info.info.core_count) { - cas_printf(LOG_ERR, "No such core device in cache.\n"); - ret = FAILURE; - goto cleanup; - } - } - - attempt_no++; - } while (false == _usage_stats_is_valid(&cache_info) && - (attempt_no < ALLOWED_NUMBER_OF_ATTEMPTS)); + } if (stats_filters & STATS_FILTER_IOCLASS) { if (cache_stats_ioclasses(ctrl_fd, &cache_info, cache_id, @@ -1057,50 +1049,14 @@ int cache_status(unsigned int cache_id, unsigned int core_id, int io_class_id, return FAILURE; } } else if (core_id == OCF_CORE_ID_INVALID) { - - cache_stats.cache_id = cache_id; - cache_stats.core_id = OCF_CORE_ID_INVALID; - cache_stats.part_id = OCF_IO_CLASS_INVALID; - - if (ioctl(ctrl_fd, KCAS_IOCTL_GET_STATS, &cache_stats) < 0) { + if (cache_stats(ctrl_fd, &cache_info, cache_id, intermediate_file[1], + stats_filters)) { ret = FAILURE; goto cleanup; } - - begin_record(intermediate_file[1]); - - if (stats_filters & STATS_FILTER_CONF) { - if (cache_stats_conf(ctrl_fd, &cache_info, - cache_id, - intermediate_file[1])) { - ret = FAILURE; - goto cleanup; - } - } - - if (stats_filters & STATS_FILTER_USAGE) - print_usage_stats(&cache_stats.usage, intermediate_file[1]); - - if ((cache_info.info.state & (1 << ocf_cache_state_incomplete)) - && stats_filters & STATS_FILTER_USAGE) { - if (cache_stats_inactive_usage(ctrl_fd, &cache_info, - cache_id, - intermediate_file[1])) { - ret = FAILURE; - goto cleanup; - } - } - - if (stats_filters & STATS_FILTER_COUNTERS) { - cache_stats_counters(&cache_stats, intermediate_file[1], - stats_filters); - } - } else { - if (cache_stats_cores(ctrl_fd, &cache_info, cache_id, - core_id, io_class_id, - intermediate_file[1], stats_filters)) { - + if (cache_stats_cores(ctrl_fd, &cache_info, cache_id, core_id, + io_class_id, intermediate_file[1], stats_filters)) { ret = FAILURE; goto cleanup; } From 30a52587f38c91d16529c8602dfd93d1ac316c99 Mon Sep 17 00:00:00 2001 From: Michal Mielewczyk Date: Thu, 29 Aug 2019 08:21:23 -0400 Subject: [PATCH 6/9] Cast percentage stats value to float. Signed-off-by: Michal Mielewczyk --- casadm/statistics_model.c | 71 ++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 35 deletions(-) diff --git a/casadm/statistics_model.c b/casadm/statistics_model.c index 51094c0..b889642 100644 --- a/casadm/statistics_model.c +++ b/casadm/statistics_model.c @@ -140,12 +140,13 @@ static void print_table_header(FILE *outfile, uint32_t ncols, ...) static void print_val_perc_table_elem(FILE *outfile, const char *tag, const char *title, const char *unit, - float percent, const char * fmt, + uint64_t percent, const char * fmt, va_list ap) { + float percent_val = (percent % 10 >= 5 ? percent+5 : percent) / 100.f; fprintf(outfile, "%s\"%s\",", tag, title); vfprintf(outfile, fmt, ap); - fprintf(outfile, ",%.1f", percent); + fprintf(outfile, ",%.1f", percent_val); if (unit) { fprintf(outfile, ",\"[%s]\"", unit); } @@ -166,7 +167,7 @@ static inline void print_val_perc_table_row(FILE *outfile, const char *title, __attribute__((format(printf, 5, 6))) static inline void print_val_perc_table_section(FILE *outfile, const char *title, - const char *unit, float percent, + const char *unit, uint64_t percent, const char *fmt, ...) { va_list ap; @@ -221,13 +222,13 @@ static void print_usage_stats(struct ocf_stats_usage *stats, FILE* outfile) print_usage_header(outfile); print_val_perc_table_row(outfile, "Occupancy", UNIT_BLOCKS, - stats->occupancy.percent/10, "%lu", stats->occupancy.value); + stats->occupancy.fraction, "%lu", stats->occupancy.value); print_val_perc_table_row(outfile, "Free", UNIT_BLOCKS, - stats->free.percent/10, "%lu", stats->free.value); + stats->free.fraction, "%lu", stats->free.value); print_val_perc_table_row(outfile, "Clean", UNIT_BLOCKS, - stats->clean.percent/10, "%lu", stats->clean.value); + stats->clean.fraction, "%lu", stats->clean.value); print_val_perc_table_row(outfile, "Dirty", UNIT_BLOCKS, - stats->dirty.percent/10, "%lu", stats->dirty.value); + stats->dirty.fraction, "%lu", stats->dirty.value); } static void print_req_stats(const struct ocf_stats_requests *stats, @@ -237,43 +238,43 @@ static void print_req_stats(const struct ocf_stats_requests *stats, "%", "[Units]"); print_val_perc_table_section(outfile, "Read hits", - UNIT_REQUESTS, stats->rd_hits.percent/10, "%lu", + UNIT_REQUESTS, stats->rd_hits.fraction, "%lu", stats->rd_hits.value); print_val_perc_table_row(outfile, "Read partial misses", - UNIT_REQUESTS, stats->rd_partial_misses.percent/10, "%lu", + UNIT_REQUESTS, stats->rd_partial_misses.fraction, "%lu", stats->rd_partial_misses.value); print_val_perc_table_row(outfile, "Read full misses", - UNIT_REQUESTS, stats->rd_full_misses.percent/10, "%lu", + UNIT_REQUESTS, stats->rd_full_misses.fraction, "%lu", stats->rd_full_misses.value); print_val_perc_table_row(outfile, "Read total", - UNIT_REQUESTS, stats->rd_total.percent/10, "%lu", + UNIT_REQUESTS, stats->rd_total.fraction, "%lu", stats->rd_total.value); print_val_perc_table_section(outfile, "Write hits", - UNIT_REQUESTS, stats->wr_hits.percent/10, "%lu", + UNIT_REQUESTS, stats->wr_hits.fraction, "%lu", stats->wr_hits.value); print_val_perc_table_row(outfile, "Write partial misses", - UNIT_REQUESTS, stats->wr_partial_misses.percent/10, "%lu", + UNIT_REQUESTS, stats->wr_partial_misses.fraction, "%lu", stats->wr_partial_misses.value); print_val_perc_table_row(outfile, "Write full misses", - UNIT_REQUESTS, stats->wr_full_misses.percent/10, "%lu", + UNIT_REQUESTS, stats->wr_full_misses.fraction, "%lu", stats->wr_full_misses.value); print_val_perc_table_row(outfile, "Write total", - UNIT_REQUESTS, stats->wr_total.percent/10, "%lu", + UNIT_REQUESTS, stats->wr_total.fraction, "%lu", stats->wr_total.value); print_val_perc_table_section(outfile, "Pass-Through reads", - UNIT_REQUESTS, stats->rd_pt.percent/10, "%lu", + UNIT_REQUESTS, stats->rd_pt.fraction, "%lu", stats->rd_pt.value); print_val_perc_table_row(outfile, "Pass-Through writes", - UNIT_REQUESTS, stats->wr_pt.percent/10, "%lu", + UNIT_REQUESTS, stats->wr_pt.fraction, "%lu", stats->wr_pt.value); print_val_perc_table_row(outfile, "Serviced requests", - UNIT_REQUESTS, stats->serviced.percent/10, "%lu", + UNIT_REQUESTS, stats->serviced.fraction, "%lu", stats->serviced.value); print_val_perc_table_section(outfile, "Total requests", - UNIT_REQUESTS, stats->total.percent/10, "%lu", + UNIT_REQUESTS, stats->total.fraction, "%lu", stats->total.value); } @@ -294,47 +295,47 @@ static void print_blk_stats(const struct ocf_stats_blocks *stats, get_stat_name(stat_name, max_stat_len, "Reads from core", postfix); print_val_perc_table_section(outfile, stat_name, - UNIT_BLOCKS, stats->core_volume_rd.percent/10, "%lu", + UNIT_BLOCKS, stats->core_volume_rd.fraction, "%lu", stats->core_volume_rd.value); get_stat_name(stat_name, max_stat_len, "Writes to core", postfix); print_val_perc_table_row(outfile, stat_name, - UNIT_BLOCKS, stats->core_volume_wr.percent/10, "%lu", + UNIT_BLOCKS, stats->core_volume_wr.fraction, "%lu", stats->core_volume_wr.value); get_stat_name(stat_name, max_stat_len, "Total to/from core", postfix); print_val_perc_table_row(outfile, stat_name, - UNIT_BLOCKS, stats->core_volume_total.percent/10, "%lu", + UNIT_BLOCKS, stats->core_volume_total.fraction, "%lu", stats->core_volume_total.value); print_val_perc_table_section(outfile, "Reads from cache", - UNIT_BLOCKS, stats->cache_volume_rd.percent/10, "%lu", + UNIT_BLOCKS, stats->cache_volume_rd.fraction, "%lu", stats->cache_volume_rd.value); print_val_perc_table_row(outfile, "Writes to cache", - UNIT_BLOCKS, stats->cache_volume_wr.percent/10, "%lu", + UNIT_BLOCKS, stats->cache_volume_wr.fraction, "%lu", stats->cache_volume_wr.value); print_val_perc_table_row(outfile, "Total to/from cache", - UNIT_BLOCKS, stats->cache_volume_total.percent/10, "%lu", + UNIT_BLOCKS, stats->cache_volume_total.fraction, "%lu", stats->cache_volume_total.value); get_stat_name(stat_name, max_stat_len, "Reads from exported object", postfix); print_val_perc_table_section(outfile, stat_name, - UNIT_BLOCKS, stats->volume_rd.percent/10, "%lu", + UNIT_BLOCKS, stats->volume_rd.fraction, "%lu", stats->volume_rd.value); get_stat_name(stat_name, max_stat_len, "Writes to exported object", postfix); print_val_perc_table_row(outfile, stat_name, - UNIT_BLOCKS, stats->volume_wr.percent/10, "%lu", + UNIT_BLOCKS, stats->volume_wr.fraction, "%lu", stats->volume_wr.value); get_stat_name(stat_name, max_stat_len, "Total to/from exported object", postfix); print_val_perc_table_row(outfile, stat_name, - UNIT_BLOCKS, stats->volume_total.percent/10, "%lu", + UNIT_BLOCKS, stats->volume_total.fraction, "%lu", stats->volume_total.value); } @@ -345,27 +346,27 @@ static void print_err_stats(const struct ocf_stats_errors *stats, "[Units]"); print_val_perc_table_section(outfile, "Cache read errors", - UNIT_REQUESTS, stats->cache_volume_rd.percent/10, "%lu", + UNIT_REQUESTS, stats->cache_volume_rd.fraction, "%lu", stats->cache_volume_rd.value); print_val_perc_table_row(outfile, "Cache write errors", - UNIT_REQUESTS, stats->cache_volume_wr.percent/10, "%lu", + UNIT_REQUESTS, stats->cache_volume_wr.fraction, "%lu", stats->cache_volume_wr.value); print_val_perc_table_row(outfile, "Cache total errors", - UNIT_REQUESTS, stats->cache_volume_total.percent/10, "%lu", + UNIT_REQUESTS, stats->cache_volume_total.fraction, "%lu", stats->cache_volume_total.value); print_val_perc_table_section(outfile, "Core read errors", - UNIT_REQUESTS, stats->core_volume_rd.percent/10, "%lu", + UNIT_REQUESTS, stats->core_volume_rd.fraction, "%lu", stats->core_volume_rd.value); print_val_perc_table_row(outfile, "Core write errors", - UNIT_REQUESTS, stats->core_volume_wr.percent/10, "%lu", + UNIT_REQUESTS, stats->core_volume_wr.fraction, "%lu", stats->core_volume_wr.value); print_val_perc_table_row(outfile, "Core total errors", - UNIT_REQUESTS, stats->core_volume_total.percent/10, "%lu", + UNIT_REQUESTS, stats->core_volume_total.fraction, "%lu", stats->core_volume_total.value); print_val_perc_table_section(outfile, "Total errors", - UNIT_REQUESTS, stats->total.percent/10, "%lu", + UNIT_REQUESTS, stats->total.fraction, "%lu", stats->total.value); } From 1abb1e7c72828a3ab0244873444d9165fd8671b8 Mon Sep 17 00:00:00 2001 From: Michal Mielewczyk Date: Thu, 29 Aug 2019 08:25:16 -0400 Subject: [PATCH 7/9] Adapt ioclasses stats command to ocf stats builder. Signed-off-by: Michal Mielewczyk --- casadm/cas_main.c | 2 +- casadm/statistics_model.c | 394 +++------------------ modules/cas_cache/layer_cache_management.c | 13 - modules/include/cas_ioctl_codes.h | 9 - 4 files changed, 54 insertions(+), 364 deletions(-) diff --git a/casadm/cas_main.c b/casadm/cas_main.c index b901d4f..8fb8393 100644 --- a/casadm/cas_main.c +++ b/casadm/cas_main.c @@ -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, diff --git a/casadm/statistics_model.c b/casadm/statistics_model.c index b889642..c2721a9 100644 --- a/casadm/statistics_model.c +++ b/casadm/statistics_model.c @@ -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], diff --git a/modules/cas_cache/layer_cache_management.c b/modules/cas_cache/layer_cache_management.c index 9181eb1..b2e6152 100644 --- a/modules/cas_cache/layer_cache_management.c +++ b/modules/cas_cache/layer_cache_management.c @@ -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); diff --git a/modules/include/cas_ioctl_codes.h b/modules/include/cas_ioctl_codes.h index 6e60adc..f522b1e 100644 --- a/modules/include/cas_ioctl_codes.h +++ b/modules/include/cas_ioctl_codes.h @@ -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; }; From 39a3d04c93ba6f86fb16407b3b978fe0bea42181 Mon Sep 17 00:00:00 2001 From: Michal Mielewczyk Date: Mon, 2 Sep 2019 09:14:53 -0400 Subject: [PATCH 8/9] Handle separate functons for retrieving core stats and info. Signed-off-by: Michal Mielewczyk --- casadm/cas_lib.c | 6 +++--- casadm/cas_lib_utils.c | 6 +++--- casadm/statistics_model.c | 8 ++++---- modules/cas_cache/layer_cache_management.c | 2 +- modules/include/cas_ioctl_codes.h | 3 +-- 5 files changed, 12 insertions(+), 13 deletions(-) diff --git a/casadm/cas_lib.c b/casadm/cas_lib.c index 2aaeba8..ef0a33b 100644 --- a/casadm/cas_lib.c +++ b/casadm/cas_lib.c @@ -2683,11 +2683,11 @@ int list_caches(unsigned int list_format) curr_core = &curr_cache->cores[j]; core_path = curr_core->path; - core_flush_prog = calculate_flush_progress(curr_core->info.stats.dirty, - curr_core->info.stats.flushed); + core_flush_prog = calculate_flush_progress(curr_core->info.info.dirty, + curr_core->info.info.flushed); if (!core_flush_prog && cache_flush_prog) { - core_flush_prog = curr_core->info.stats.dirty ? 0 : 100; + core_flush_prog = curr_core->info.info.dirty ? 0 : 100; } if (core_flush_prog || cache_flush_prog) { diff --git a/casadm/cas_lib_utils.c b/casadm/cas_lib_utils.c index 3a080b8..a6bdf54 100644 --- a/casadm/cas_lib_utils.c +++ b/casadm/cas_lib_utils.c @@ -295,8 +295,8 @@ void get_core_flush_progress(int fd, int cache_id, int core_id, float *prog) cmd_info.core_id = core_id; if (0 == ioctl(fd, KCAS_IOCTL_CORE_INFO, &cmd_info)) { - *prog = calculate_flush_progress(cmd_info.stats.dirty, - cmd_info.stats.flushed); + *prog = calculate_flush_progress(cmd_info.info.dirty, + cmd_info.info.flushed); } } @@ -367,7 +367,7 @@ void *print_command_progress(void *th_arg) } else if (EINTR == errno) { interrupted = 1; } else { /* other error conditions are EFAULT or EINVAL - * cannot happen in realistic conditions, + * cannot happen in realistic conditions, * and are likely to refer to OS errors, which * cannot possibly be handled. Perform abortion. */ diff --git a/casadm/statistics_model.c b/casadm/statistics_model.c index c2721a9..400986f 100644 --- a/casadm/statistics_model.c +++ b/casadm/statistics_model.c @@ -189,7 +189,7 @@ static void print_core_conf(const struct kcas_core_info *info, FILE *outfile) uint64_t core_size; float core_size_gb; - core_size = info->stats.core_size_bytes / KiB / 4; + core_size = info->info.core_size_bytes / KiB / 4; core_size_gb = calc_gb(core_size); print_kv_pair(outfile, "Core Id", "%i", info->core_id); @@ -199,16 +199,16 @@ static void print_core_conf(const struct kcas_core_info *info, FILE *outfile) info->cache_id, info->core_id); print_kv_pair(outfile, "Core Size", "%lu, [4KiB Blocks], %.2f, [GiB]", core_size, core_size_gb); - print_kv_pair_time(outfile, "Dirty for", info->stats.dirty_for); + print_kv_pair_time(outfile, "Dirty for", info->info.dirty_for); print_kv_pair(outfile, "Status", "%s", get_core_state_name(info->state)); print_kv_pair(outfile, "Seq cutoff threshold", "%llu, [KiB]", - info->stats.seq_cutoff_threshold / KiB); + info->info.seq_cutoff_threshold / KiB); print_kv_pair(outfile, "Seq cutoff policy", "%s", - seq_cutoff_policy_to_name(info->stats.seq_cutoff_policy)); + seq_cutoff_policy_to_name(info->info.seq_cutoff_policy)); } static void print_usage_header(FILE* outfile) diff --git a/modules/cas_cache/layer_cache_management.c b/modules/cas_cache/layer_cache_management.c index b2e6152..770d0d2 100644 --- a/modules/cas_cache/layer_cache_management.c +++ b/modules/cas_cache/layer_cache_management.c @@ -1909,7 +1909,7 @@ int cache_mngt_get_core_info(struct kcas_core_info *info) goto unlock; } - result = ocf_core_get_stats(core, &info->stats); + result = ocf_core_get_info(core, &info->info); if (result) goto unlock; diff --git a/modules/include/cas_ioctl_codes.h b/modules/include/cas_ioctl_codes.h index f522b1e..b438d14 100644 --- a/modules/include/cas_ioctl_codes.h +++ b/modules/include/cas_ioctl_codes.h @@ -208,8 +208,7 @@ struct kcas_core_info { /** Core id */ uint16_t core_id; - /** CAS statistics of core */ - struct ocf_stats_core stats; + struct ocf_core_info info; ocf_core_state_t state; From 078a31fbf245bebe0ea70f0038c2bc810159633a Mon Sep 17 00:00:00 2001 From: Michal Mielewczyk Date: Thu, 12 Sep 2019 09:25:35 -0400 Subject: [PATCH 9/9] Inactive cores stats in stats-builder-like form. Signed-off-by: Michal Mielewczyk --- casadm/statistics_model.c | 35 +++++++++++------------------------ 1 file changed, 11 insertions(+), 24 deletions(-) diff --git a/casadm/statistics_model.c b/casadm/statistics_model.c index 400986f..72c0a77 100644 --- a/casadm/statistics_model.c +++ b/casadm/statistics_model.c @@ -39,11 +39,11 @@ #define UNIT_REQUESTS "Requests" #define UNIT_BLOCKS "4KiB blocks" -static inline float percentage(uint64_t numerator, uint64_t denominator) +static inline float fraction(uint64_t numerator, uint64_t denominator) { float result; if (denominator) { - result = 100.0 * numerator / denominator; + result = 10000.0 * numerator / denominator; } else { result = 0; } @@ -415,28 +415,15 @@ void cache_stats_inactive_usage(int ctrl_fd, const struct kcas_cache_info *cache print_table_header(outfile, 4, "Inactive usage statistics", "Count", "%", "[Units]"); - print_val_perc_table_row(outfile, "Inactive Occupancy", UNIT_BLOCKS, - percentage(cache_info->info.inactive.occupancy, - cache_info->info.size), - "%lu", - cache_line_in_4k(cache_info->info.inactive.occupancy, - cache_info->info.cache_line_size / KiB)); - - print_val_perc_table_row(outfile, "Inactive Clean", UNIT_BLOCKS, - percentage(cache_info->info.inactive.occupancy - - cache_info->info.inactive.dirty, - cache_info->info.occupancy), - "%lu", - cache_line_in_4k(cache_info->info.inactive.occupancy - - cache_info->info.inactive.dirty, - cache_info->info.cache_line_size / KiB)); - - print_val_perc_table_row(outfile, "Inactive Dirty", UNIT_BLOCKS, - percentage(cache_info->info.inactive.dirty, - cache_info->info.occupancy), - "%lu", - cache_line_in_4k(cache_info->info.inactive.dirty, - cache_info->info.cache_line_size / KiB)); + print_val_perc_table_row(outfile, "Inactive Occupancy", UNIT_BLOCKS, + cache_info->info.inactive.occupancy.fraction, "%lu", + cache_info->info.inactive.occupancy.value); + print_val_perc_table_row(outfile, "Inactive Clean", UNIT_BLOCKS, + cache_info->info.inactive.clean.fraction, "%lu", + cache_info->info.inactive.clean.value); + print_val_perc_table_row(outfile, "Inactive Dirty", UNIT_BLOCKS, + cache_info->info.inactive.dirty.fraction, "%lu", + cache_info->info.inactive.dirty.value); } /**