Merge pull request #253 from mmichal10/stats-refactor

Stats builder for ioclasses
This commit is contained in:
Michal Rakowski
2019-09-10 14:56:26 +02:00
committed by GitHub
25 changed files with 832 additions and 534 deletions

View File

@@ -61,7 +61,7 @@ static void _ocf_backfill_complete(struct ocf_request *req, int error)
req->data = NULL;
if (req->error) {
env_atomic_inc(&req->core->counters->cache_errors.write);
ocf_core_stats_cache_error_update(req->core, OCF_WRITE);
ocf_engine_invalidate(req);
} else {
ocf_req_unlock(req);

View File

@@ -446,42 +446,14 @@ void ocf_engine_clean(struct ocf_request *req)
void ocf_engine_update_block_stats(struct ocf_request *req)
{
ocf_part_id_t part_id = req->part_id;
struct ocf_counters_block *blocks;
blocks = &req->core->counters->
part_counters[part_id].blocks;
if (req->rw == OCF_READ)
env_atomic64_add(req->byte_length, &blocks->read_bytes);
else if (req->rw == OCF_WRITE)
env_atomic64_add(req->byte_length, &blocks->write_bytes);
else
ENV_BUG();
ocf_core_stats_vol_block_update(req->core, req->part_id, req->rw,
req->byte_length);
}
void ocf_engine_update_request_stats(struct ocf_request *req)
{
ocf_part_id_t part_id = req->part_id;
struct ocf_counters_req *reqs;
switch (req->rw) {
case OCF_READ:
reqs = &req->core->counters->part_counters[part_id].read_reqs;
break;
case OCF_WRITE:
reqs = &req->core->counters->part_counters[part_id].write_reqs;
break;
default:
ENV_BUG();
}
env_atomic64_inc(&reqs->total);
if (req->info.hit_no == 0)
env_atomic64_inc(&reqs->full_miss);
else if (req->info.hit_no < req->core_line_count)
env_atomic64_inc(&reqs->partial_miss);
ocf_core_stats_request_update(req->core, req->part_id, req->rw,
req->info.hit_no, req->core_line_count);
}
void ocf_engine_push_req_back(struct ocf_request *req, bool allow_sync)

View File

@@ -16,17 +16,13 @@
static void _ocf_d2c_completion(struct ocf_request *req, int error)
{
ocf_core_t core = req->core;
req->error = error;
OCF_DEBUG_RQ(req, "Completion");
if (req->error) {
req->info.core_error = 1;
if (req->rw == OCF_READ)
env_atomic_inc(&core->counters->core_errors.read);
else
env_atomic_inc(&core->counters->core_errors.write);
ocf_core_stats_core_error_update(req->core, req->rw);
}
/* Complete request */
@@ -51,13 +47,8 @@ int ocf_io_d2c(struct ocf_request *req)
ocf_engine_update_block_stats(req);
if (req->rw == OCF_READ) {
env_atomic64_inc(&core->counters->
part_counters[req->part_id].read_reqs.pass_through);
} else {
env_atomic64_inc(&core->counters->
part_counters[req->part_id].write_reqs.pass_through);
}
ocf_core_stats_request_pt_update(req->core, req->part_id, req->rw,
req->info.hit_no, req->core_line_count);
/* Put OCF request - decrease reference counter */
ocf_req_put(req);

View File

@@ -43,7 +43,7 @@ static void _ocf_read_fast_complete(struct ocf_request *req, int error)
if (req->error) {
OCF_DEBUG_RQ(req, "ERROR");
env_atomic_inc(&req->core->counters->cache_errors.read);
ocf_core_stats_cache_error_update(req->core, OCF_READ);
ocf_engine_push_req_front_pt(req);
} else {
ocf_req_unlock(req);
@@ -91,7 +91,7 @@ static int _ocf_read_fast_do(struct ocf_request *req)
ocf_engine_io_count(req), _ocf_read_fast_complete);
/* Updata statistics */
/* Update statistics */
ocf_engine_update_request_stats(req);
ocf_engine_update_block_stats(req);

View File

@@ -20,7 +20,7 @@ static void _ocf_invalidate_req(struct ocf_request *req, int error)
{
if (error) {
req->error = error;
env_atomic_inc(&req->core->counters->cache_errors.write);
ocf_core_stats_cache_error_update(req->core, OCF_WRITE);
}
if (env_atomic_dec_return(&req->req_remaining))

View File

@@ -28,7 +28,7 @@ static void _ocf_read_pt_complete(struct ocf_request *req, int error)
if (req->error) {
req->info.core_error = 1;
env_atomic_inc(&req->core->counters->core_errors.read);
ocf_core_stats_core_error_update(req->core, OCF_READ);
}
/* Complete request */
@@ -87,8 +87,8 @@ int ocf_read_pt_do(struct ocf_request *req)
/* Update statistics */
ocf_engine_update_block_stats(req);
env_atomic64_inc(&req->core->counters->
part_counters[req->part_id].read_reqs.pass_through);
ocf_core_stats_request_pt_update(req->core, req->part_id, req->rw,
req->info.hit_no, req->core_line_count);
/* Put OCF request - decrease reference counter */
ocf_req_put(req);

View File

@@ -38,7 +38,7 @@ static void _ocf_read_generic_hit_complete(struct ocf_request *req, int error)
OCF_DEBUG_RQ(req, "HIT completion");
if (req->error) {
env_atomic_inc(&req->core->counters->cache_errors.read);
ocf_core_stats_cache_error_update(req->core, OCF_READ);
ocf_engine_push_req_front_pt(req);
} else {
@@ -77,7 +77,7 @@ static void _ocf_read_generic_miss_complete(struct ocf_request *req, int error)
req->complete(req, req->error);
req->info.core_error = 1;
env_atomic_inc(&req->core->counters->core_errors.read);
ocf_core_stats_core_error_update(req->core, OCF_READ);
ctx_data_free(cache->owner, req->cp_data);
req->cp_data = NULL;

View File

@@ -24,7 +24,7 @@ static void _ocf_read_wa_complete(struct ocf_request *req, int error)
if (req->error) {
req->info.core_error = 1;
env_atomic_inc(&req->core->counters->core_errors.write);
ocf_core_stats_core_error_update(req->core, OCF_WRITE);
}
/* Complete request */
@@ -76,8 +76,8 @@ int ocf_write_wa(struct ocf_request *req)
/* Update statistics */
ocf_engine_update_block_stats(req);
env_atomic64_inc(&req->core->counters->
part_counters[req->part_id].write_reqs.pass_through);
ocf_core_stats_request_pt_update(req->core, req->part_id, req->rw,
req->info.hit_no, req->core_line_count);
}
/* Put OCF request - decrease reference counter */

View File

@@ -89,7 +89,7 @@ static const struct ocf_io_if _io_if_wb_flush_metadata = {
static void _ocf_write_wb_complete(struct ocf_request *req, int error)
{
if (error) {
env_atomic_inc(&req->core->counters->cache_errors.write);
ocf_core_stats_cache_error_update(req->core, OCF_WRITE);
req->error |= error;
}
@@ -150,13 +150,13 @@ int ocf_write_wb_do(struct ocf_request *req)
/* Get OCF request - increase reference counter */
ocf_req_get(req);
/* Updata status bits */
/* Update status bits */
_ocf_write_wb_update_bits(req);
/* Submit IO */
_ocf_write_wb_submit(req);
/* Updata statistics */
/* Update statistics */
ocf_engine_update_request_stats(req);
ocf_engine_update_block_stats(req);

View File

@@ -26,7 +26,7 @@ static const struct ocf_io_if _io_if_wi_flush_metadata = {
static void _ocf_write_wi_io_flush_metadata(struct ocf_request *req, int error)
{
if (error) {
env_atomic_inc(&req->core->counters->cache_errors.write);
ocf_core_stats_cache_error_update(req->core, OCF_WRITE);
req->error |= error;
}
@@ -77,7 +77,7 @@ static void _ocf_write_wi_core_complete(struct ocf_request *req, int error)
if (error) {
req->error = error;
req->info.core_error = 1;
env_atomic_inc(&req->core->counters->core_errors.write);
ocf_core_stats_core_error_update(req->core, OCF_WRITE);
}
if (env_atomic_dec_return(&req->req_remaining))
@@ -112,8 +112,8 @@ static int _ocf_write_wi_do(struct ocf_request *req)
/* Update statistics */
ocf_engine_update_block_stats(req);
env_atomic64_inc(&req->core->counters->
part_counters[req->part_id].write_reqs.pass_through);
ocf_core_stats_request_pt_update(req->core, req->part_id, req->rw,
req->info.hit_no, req->core_line_count);
/* Put OCF request - decrease reference counter */
ocf_req_put(req);

View File

@@ -21,7 +21,7 @@
static void ocf_read_wo_cache_complete(struct ocf_request *req, int error)
{
if (error) {
env_atomic_inc(&req->core->counters->cache_errors.read);
ocf_core_stats_cache_error_update(req->core, OCF_READ);
req->error |= error;
}
@@ -148,7 +148,7 @@ static void _ocf_read_wo_core_complete(struct ocf_request *req, int error)
if (error) {
req->error |= error;
req->info.core_error = 1;
env_atomic_inc(&req->core->counters->core_errors.read);
ocf_core_stats_core_error_update(req->core, OCF_READ);
}
/* if all mapped cachelines are clean, the data we've read from core

View File

@@ -48,7 +48,7 @@ static void _ocf_write_wt_cache_complete(struct ocf_request *req, int error)
{
if (error) {
req->error = req->error ?: error;
env_atomic_inc(&req->core->counters->cache_errors.write);
ocf_core_stats_cache_error_update(req->core, OCF_WRITE);
if (req->error)
inc_fallback_pt_error_counter(req->cache);
@@ -62,7 +62,7 @@ static void _ocf_write_wt_core_complete(struct ocf_request *req, int error)
if (error) {
req->error = error;
req->info.core_error = 1;
env_atomic_inc(&req->core->counters->core_errors.write);
ocf_core_stats_core_error_update(req->core, OCF_WRITE);
}
_ocf_write_wt_req_complete(req);

View File

@@ -50,7 +50,7 @@ static const struct ocf_io_if _io_if_zero_purge = {
static void _ocf_zero_io_flush_metadata(struct ocf_request *req, int error)
{
if (error) {
env_atomic_inc(&req->core->counters->cache_errors.write);
ocf_core_stats_cache_error_update(req->core, OCF_WRITE);
req->error = error;
}

View File

@@ -143,6 +143,13 @@ int ocf_core_visit(ocf_cache_t cache, ocf_core_visitor_t visitor, void *cntx,
/* *** HELPER FUNCTIONS *** */
static uint32_t _calc_dirty_for(uint64_t dirty_since)
{
return dirty_since ?
(env_ticks_to_msecs(env_get_tick_count() - dirty_since) / 1000)
: 0;
}
static inline struct ocf_request *ocf_io_to_req(struct ocf_io *io)
{
struct ocf_io_internal *ioi;
@@ -585,3 +592,31 @@ int ocf_core_volume_type_init(ocf_ctx_t ctx)
&ocf_core_volume_properties,
&ocf_core_volume_extended);
}
int ocf_core_get_info(ocf_core_t core, struct ocf_core_info *info)
{
ocf_cache_t cache;
OCF_CHECK_NULL(core);
cache = ocf_core_get_cache(core);
if (!info)
return -OCF_ERR_INVAL;
ENV_BUG_ON(env_memset(info, sizeof(*info), 0));
info->core_size_bytes = ocf_volume_get_length(&core->volume);
info->core_size = ocf_bytes_2_lines_round_up(cache,
info->core_size_bytes);
info->seq_cutoff_threshold = ocf_core_get_seq_cutoff_threshold(core);
info->seq_cutoff_policy = ocf_core_get_seq_cutoff_policy(core);
info->flushed = env_atomic_read(&core->flushed);
info->dirty = env_atomic_read(&core->runtime_meta->dirty_clines);
info->dirty_for = _calc_dirty_for(
env_atomic64_read(&core->runtime_meta->dirty_since));
return 0;
}

View File

@@ -47,6 +47,8 @@ static void ocf_stats_part_init(struct ocf_counters_part *stats)
ocf_stats_req_init(&stats->write_reqs);
ocf_stats_block_init(&stats->blocks);
ocf_stats_block_init(&stats->core_blocks);
ocf_stats_block_init(&stats->cache_blocks);
}
static void ocf_stats_error_init(struct ocf_counters_error *stats)
@@ -55,6 +57,119 @@ static void ocf_stats_error_init(struct ocf_counters_error *stats)
env_atomic_set(&stats->write, 0);
}
static void _ocf_stats_block_update(struct ocf_counters_block *counters, int dir,
uint64_t bytes)
{
switch (dir) {
case OCF_READ:
env_atomic64_add(bytes, &counters->read_bytes);
break;
case OCF_WRITE:
env_atomic64_add(bytes, &counters->write_bytes);
break;
default:
ENV_BUG();
}
}
void ocf_core_stats_vol_block_update(ocf_core_t core, ocf_part_id_t part_id,
int dir, uint64_t bytes)
{
struct ocf_counters_block *counters =
&core->counters->part_counters[part_id].blocks;
_ocf_stats_block_update(counters, dir, bytes);
}
void ocf_core_stats_cache_block_update(ocf_core_t core, ocf_part_id_t part_id,
int dir, uint64_t bytes)
{
struct ocf_counters_block *counters =
&core->counters->part_counters[part_id].cache_blocks;
_ocf_stats_block_update(counters, dir, bytes);
}
void ocf_core_stats_core_block_update(ocf_core_t core, ocf_part_id_t part_id,
int dir, uint64_t bytes)
{
struct ocf_counters_block *counters =
&core->counters->part_counters[part_id].core_blocks;
_ocf_stats_block_update(counters, dir, bytes);
}
void ocf_core_stats_request_update(ocf_core_t core, ocf_part_id_t part_id,
uint8_t dir, uint64_t hit_no, uint64_t core_line_count)
{
struct ocf_counters_req *counters;
switch (dir) {
case OCF_READ:
counters = &core->counters->part_counters[part_id].read_reqs;
break;
case OCF_WRITE:
counters = &core->counters->part_counters[part_id].write_reqs;
break;
default:
ENV_BUG();
}
env_atomic64_inc(&counters->total);
if (hit_no == 0)
env_atomic64_inc(&counters->full_miss);
else if (hit_no < core_line_count)
env_atomic64_inc(&counters->partial_miss);
}
void ocf_core_stats_request_pt_update(ocf_core_t core, ocf_part_id_t part_id,
uint8_t dir, uint64_t hit_no, uint64_t core_line_count)
{
struct ocf_counters_req *counters;
switch (dir) {
case OCF_READ:
counters = &core->counters->part_counters[part_id].read_reqs;
break;
case OCF_WRITE:
counters = &core->counters->part_counters[part_id].write_reqs;
break;
default:
ENV_BUG();
}
env_atomic64_inc(&counters->pass_through);
}
static void _ocf_core_stats_error_update(struct ocf_counters_error *counters,
uint8_t dir)
{
switch (dir) {
case OCF_READ:
env_atomic_inc(&counters->read);
break;
case OCF_WRITE:
env_atomic_inc(&counters->write);
break;
default:
ENV_BUG();
}
}
void ocf_core_stats_core_error_update(ocf_core_t core, uint8_t dir)
{
struct ocf_counters_error *counters = &core->counters->core_errors;
_ocf_core_stats_error_update(counters, dir);
}
void ocf_core_stats_cache_error_update(ocf_core_t core, uint8_t dir)
{
struct ocf_counters_error *counters = &core->counters->cache_errors;
_ocf_core_stats_error_update(counters, dir);
}
/********************************************************************
* Function that resets stats, debug and breakdown counters.
@@ -77,9 +192,6 @@ void ocf_core_stats_initialize(ocf_core_t core)
exp_obj_stats = core->counters;
ocf_stats_block_init(&exp_obj_stats->core_blocks);
ocf_stats_block_init(&exp_obj_stats->cache_blocks);
ocf_stats_error_init(&exp_obj_stats->cache_errors);
ocf_stats_error_init(&exp_obj_stats->core_errors);
@@ -199,30 +311,20 @@ int ocf_core_io_class_get_stats(ocf_core_t core, ocf_part_id_t part_id,
copy_req_stats(&stats->write_reqs, &part_stat->write_reqs);
copy_block_stats(&stats->blocks, &part_stat->blocks);
copy_block_stats(&stats->cache_blocks, &part_stat->cache_blocks);
copy_block_stats(&stats->core_blocks, &part_stat->core_blocks);
return 0;
}
static uint32_t _calc_dirty_for(uint64_t dirty_since)
{
return dirty_since ?
(env_ticks_to_msecs(env_get_tick_count() - dirty_since) / 1000)
: 0;
}
int ocf_core_get_stats(ocf_core_t core, struct ocf_stats_core *stats)
{
uint32_t i;
ocf_core_id_t core_id;
ocf_cache_t cache;
struct ocf_counters_core *core_stats = NULL;
struct ocf_counters_part *curr = NULL;
OCF_CHECK_NULL(core);
core_id = ocf_core_get_id(core);
cache = ocf_core_get_cache(core);
if (!stats)
return -OCF_ERR_INVAL;
@@ -230,19 +332,6 @@ int ocf_core_get_stats(ocf_core_t core, struct ocf_stats_core *stats)
ENV_BUG_ON(env_memset(stats, sizeof(*stats), 0));
stats->core_size_bytes = ocf_volume_get_length(
&cache->core[core_id].volume);
stats->core_size = ocf_bytes_2_lines_round_up(cache,
stats->core_size_bytes);
stats->seq_cutoff_threshold = ocf_core_get_seq_cutoff_threshold(core);
stats->seq_cutoff_policy = ocf_core_get_seq_cutoff_policy(core);
env_atomic_read(&core->runtime_meta->cached_clines);
copy_block_stats(&stats->core_volume, &core_stats->core_blocks);
copy_block_stats(&stats->cache_volume, &core_stats->cache_blocks);
copy_error_stats(&stats->core_errors,
&core_stats->core_errors);
copy_error_stats(&stats->cache_errors,
@@ -262,6 +351,8 @@ int ocf_core_get_stats(ocf_core_t core, struct ocf_stats_core *stats)
&curr->write_reqs);
accum_block_stats(&stats->core, &curr->blocks);
accum_block_stats(&stats->core_volume, &curr->core_blocks);
accum_block_stats(&stats->cache_volume, &curr->cache_blocks);
stats->cache_occupancy += env_atomic_read(&core->runtime_meta->
part_counters[i].cached_clines);
@@ -269,11 +360,6 @@ int ocf_core_get_stats(ocf_core_t core, struct ocf_stats_core *stats)
part_counters[i].dirty_clines);
}
stats->flushed = env_atomic_read(&core->flushed);
stats->dirty_for = _calc_dirty_for(
env_atomic64_read(&core->runtime_meta->dirty_since));
return 0;
}

View File

@@ -18,11 +18,11 @@
} \
} while (0)
static uint64_t _percentage(uint64_t numerator, uint64_t denominator)
static uint64_t _fraction(uint64_t numerator, uint64_t denominator)
{
uint64_t result;
if (denominator) {
result = 1000 * numerator / denominator;
result = 10000 * numerator / denominator;
} else {
result = 0;
}
@@ -47,7 +47,7 @@ static uint64_t _bytes4k(uint64_t bytes)
static void _set(struct ocf_stat *stat, uint64_t value, uint64_t denominator)
{
stat->value = value;
stat->percent = _percentage(value, denominator);
stat->fraction = _fraction(value, denominator);
}
static void _fill_req(struct ocf_stats_requests *req, struct ocf_stats_core *s)
@@ -82,6 +82,39 @@ static void _fill_req(struct ocf_stats_requests *req, struct ocf_stats_core *s)
_set(&req->total, total, total);
}
static void _fill_req_part(struct ocf_stats_requests *req,
struct ocf_stats_io_class *s)
{
uint64_t serviced = s->read_reqs.total + s->write_reqs.total;
uint64_t total = serviced + s->read_reqs.pass_through +
s->write_reqs.pass_through;
uint64_t hit;
/* Reads Section */
hit = s->read_reqs.total - (s->read_reqs.full_miss +
s->read_reqs.partial_miss);
_set(&req->rd_hits, hit, total);
_set(&req->rd_partial_misses, s->read_reqs.partial_miss, total);
_set(&req->rd_full_misses, s->read_reqs.full_miss, total);
_set(&req->rd_total, s->read_reqs.total, total);
/* Write Section */
hit = s->write_reqs.total - (s->write_reqs.full_miss +
s->write_reqs.partial_miss);
_set(&req->wr_hits, hit, total);
_set(&req->wr_partial_misses, s->write_reqs.partial_miss, total);
_set(&req->wr_full_misses, s->write_reqs.full_miss, total);
_set(&req->wr_total, s->write_reqs.total, total);
/* Pass-Through section */
_set(&req->rd_pt, s->read_reqs.pass_through, total);
_set(&req->wr_pt, s->write_reqs.pass_through, total);
/* Summary */
_set(&req->serviced, serviced, total);
_set(&req->total, total, total);
}
static void _fill_blocks(struct ocf_stats_blocks *blocks,
struct ocf_stats_core *s)
{
@@ -112,6 +145,36 @@ static void _fill_blocks(struct ocf_stats_blocks *blocks,
_set(&blocks->volume_total, total, total);
}
static void _fill_blocks_part(struct ocf_stats_blocks *blocks,
struct ocf_stats_io_class *s)
{
uint64_t rd, wr, total;
/* Core volume */
rd = _bytes4k(s->core_blocks.read);
wr = _bytes4k(s->core_blocks.write);
total = rd + wr;
_set(&blocks->core_volume_rd, rd, total);
_set(&blocks->core_volume_wr, wr, total);
_set(&blocks->core_volume_total, total, total);
/* Cache volume */
rd = _bytes4k(s->cache_blocks.read);
wr = _bytes4k(s->cache_blocks.write);
total = rd + wr;
_set(&blocks->cache_volume_rd, rd, total);
_set(&blocks->cache_volume_wr, wr, total);
_set(&blocks->cache_volume_total, total, total);
/* Core (cache volume) */
rd = _bytes4k(s->blocks.read);
wr = _bytes4k(s->blocks.write);
total = rd + wr;
_set(&blocks->volume_rd, rd, total);
_set(&blocks->volume_wr, wr, total);
_set(&blocks->volume_total, total, total);
}
static void _fill_errors(struct ocf_stats_errors *errors,
struct ocf_stats_core *s)
{
@@ -137,6 +200,152 @@ static void _fill_errors(struct ocf_stats_errors *errors,
_set(&errors->total, total, total);
}
static void _accumulate_block(struct ocf_stats_block *to,
const struct ocf_stats_block *from)
{
to->read += from->read;
to->write += from->write;
}
static void _accumulate_reqs(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;
}
static void _accumulate_errors(struct ocf_stats_error *to,
const struct ocf_stats_error *from)
{
to->read += from->read;
to->write += from->write;
}
struct io_class_stats_context {
struct ocf_stats_io_class *stats;
ocf_part_id_t part_id;
};
static int _accumulate_io_class_stats(ocf_core_t core, void *cntx)
{
int result;
struct ocf_stats_io_class stats;
struct ocf_stats_io_class *total =
((struct io_class_stats_context*)cntx)->stats;
ocf_part_id_t part_id = ((struct io_class_stats_context*)cntx)->part_id;
result = ocf_core_io_class_get_stats(core, part_id, &stats);
if (result)
return result;
total->occupancy_clines += stats.occupancy_clines;
total->dirty_clines += stats.dirty_clines;
total->free_clines = stats.free_clines;
_accumulate_block(&total->cache_blocks, &stats.cache_blocks);
_accumulate_block(&total->core_blocks, &stats.core_blocks);
_accumulate_block(&total->blocks, &stats.blocks);
_accumulate_reqs(&total->read_reqs, &stats.read_reqs);
_accumulate_reqs(&total->write_reqs, &stats.write_reqs);
return 0;
}
static void _ocf_stats_part_fill(ocf_cache_t cache, ocf_part_id_t part_id,
struct ocf_stats_io_class *stats , struct ocf_stats_usage *usage,
struct ocf_stats_requests *req, struct ocf_stats_blocks *blocks)
{
uint64_t cache_size, cache_line_size;
cache_line_size = ocf_cache_get_line_size(cache);
cache_size = cache->conf_meta->cachelines;
if (usage) {
_set(&usage->occupancy,
_lines4k(stats->occupancy_clines, cache_line_size),
_lines4k(cache_size, cache_line_size));
if (part_id == PARTITION_DEFAULT) {
_set(&usage->free,
_lines4k(stats->free_clines, cache_line_size),
_lines4k(cache_size, cache_line_size));
} else {
_set(&usage->free,
_lines4k(0, cache_line_size),
_lines4k(0, cache_line_size));
}
_set(&usage->clean,
_lines4k(stats->occupancy_clines - stats->dirty_clines,
cache_line_size),
_lines4k(stats->occupancy_clines, cache_line_size));
_set(&usage->dirty,
_lines4k(stats->dirty_clines, cache_line_size),
_lines4k(stats->occupancy_clines, cache_line_size));
}
if (req)
_fill_req_part(req, stats);
if (blocks)
_fill_blocks_part(blocks, stats);
}
int ocf_stats_collect_part_core(ocf_core_t core, ocf_part_id_t part_id,
struct ocf_stats_usage *usage, struct ocf_stats_requests *req,
struct ocf_stats_blocks *blocks)
{
struct ocf_stats_io_class s;
ocf_cache_t cache;
int result = 0;
OCF_CHECK_NULL(core);
cache = ocf_core_get_cache(core);
_ocf_stats_zero(usage);
_ocf_stats_zero(req);
_ocf_stats_zero(blocks);
result = ocf_core_io_class_get_stats(core, part_id, &s);
if (result)
return result;
_ocf_stats_part_fill(cache, part_id, &s, usage, req, blocks);
return result;
}
int ocf_stats_collect_part_cache(ocf_cache_t cache, ocf_part_id_t part_id,
struct ocf_stats_usage *usage, struct ocf_stats_requests *req,
struct ocf_stats_blocks *blocks)
{
struct io_class_stats_context ctx;
struct ocf_stats_io_class s;
int result = 0;
OCF_CHECK_NULL(cache);
_ocf_stats_zero(usage);
_ocf_stats_zero(req);
_ocf_stats_zero(blocks);
ctx.part_id = part_id;
ctx.stats = &s;
result = ocf_core_visit(cache, _accumulate_io_class_stats, &ctx, true);
if (result)
return result;
_ocf_stats_part_fill(cache, part_id, &s, usage, req, blocks);
return result;
}
int ocf_stats_collect_core(ocf_core_t core,
struct ocf_stats_usage *usage,
struct ocf_stats_requests *req,
@@ -194,29 +403,6 @@ int ocf_stats_collect_core(ocf_core_t core,
return 0;
}
static void _accumulate_block(struct ocf_stats_block *to,
const struct ocf_stats_block *from)
{
to->read += from->read;
to->write += from->write;
}
static void _accumulate_reqs(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;
}
static void _accumulate_errors(struct ocf_stats_error *to,
const struct ocf_stats_error *from)
{
to->read += from->read;
to->write += from->write;
}
static int _accumulate_stats(ocf_core_t core, void *cntx)
{
struct ocf_stats_core stats, *total = cntx;

View File

@@ -23,6 +23,132 @@ struct ocf_counters_req {
env_atomic64 pass_through;
};
/**
* @brief OCF requests statistics like hit, miss, etc...
*
* @note To calculate number of hits request do:
* total - (partial_miss + full_miss)
*/
struct ocf_stats_req {
/** Number of partial misses */
uint64_t partial_miss;
/** Number of full misses */
uint64_t full_miss;
/** Total of requests */
uint64_t total;
/** Pass-through requests */
uint64_t pass_through;
};
/**
* @brief OCF error statistics
*/
struct ocf_stats_error {
/** Read errors */
uint32_t read;
/** Write errors */
uint32_t write;
};
/**
* @brief OCF block statistics in bytes
*/
struct ocf_stats_block {
/** Number of blocks read */
uint64_t read;
/** Number of blocks written */
uint64_t write;
};
/**
* Statistics appropriate for given IO class
*/
struct ocf_stats_io_class {
/** Number of cache lines available for given partition */
uint64_t free_clines;
/** Number of cache lines within lru list */
uint64_t occupancy_clines;
/** Number of dirty cache lines assigned to specific partition */
uint64_t dirty_clines;
/** Read requests statistics */
struct ocf_stats_req read_reqs;
/** Writes requests statistics */
struct ocf_stats_req write_reqs;
/** Block requests for ocf volume statistics */
struct ocf_stats_block blocks;
/** Block requests for cache volume statistics */
struct ocf_stats_block cache_blocks;
/** Block requests for core volume statistics */
struct ocf_stats_block core_blocks;
};
#define IO_PACKET_NO 12
#define IO_ALIGN_NO 4
/**
* @brief Core debug statistics
*/
struct ocf_stats_core_debug {
/** I/O sizes being read (grouped by packets) */
uint64_t read_size[IO_PACKET_NO];
/** I/O sizes being written (grouped by packets) */
uint64_t write_size[IO_PACKET_NO];
/** I/O alignment for reads */
uint64_t read_align[IO_ALIGN_NO];
/** I/O alignment for writes */
uint64_t write_align[IO_ALIGN_NO];
};
/**
* @brief OCF core statistics
*/
struct ocf_stats_core {
/** Number of cache lines allocated in the cache for this core */
uint32_t cache_occupancy;
/** Number of dirty cache lines allocated in the cache for this core */
uint32_t dirty;
/** Read requests statistics */
struct ocf_stats_req read_reqs;
/** Write requests statistics */
struct ocf_stats_req write_reqs;
/** Block requests for cache volume statistics */
struct ocf_stats_block cache_volume;
/** Block requests for core volume statistics */
struct ocf_stats_block core_volume;
/** Block requests submitted by user to this core */
struct ocf_stats_block core;
/** Cache volume error statistics */
struct ocf_stats_error cache_errors;
/** Core volume error statistics */
struct ocf_stats_error core_errors;
/** Debug statistics */
struct ocf_stats_core_debug debug_stat;
};
/**
* statistics appropriate for given io class.
*/
@@ -31,6 +157,9 @@ struct ocf_counters_part {
struct ocf_counters_req write_reqs;
struct ocf_counters_block blocks;
struct ocf_counters_block core_blocks;
struct ocf_counters_block cache_blocks;
};
#ifdef OCF_DEBUG_STATS
@@ -44,9 +173,6 @@ struct ocf_counters_debug {
#endif
struct ocf_counters_core {
struct ocf_counters_block core_blocks;
struct ocf_counters_block cache_blocks;
struct ocf_counters_error core_errors;
struct ocf_counters_error cache_errors;
@@ -56,4 +182,60 @@ struct ocf_counters_core {
#endif
};
void ocf_core_stats_core_block_update(ocf_core_t core, ocf_part_id_t part_id,
int dir, uint64_t bytes);
void ocf_core_stats_cache_block_update(ocf_core_t core, ocf_part_id_t part_id,
int dir, uint64_t bytes);
void ocf_core_stats_vol_block_update(ocf_core_t core, ocf_part_id_t part_id,
int dir, uint64_t bytes);
void ocf_core_stats_request_update(ocf_core_t core, ocf_part_id_t part_id,
uint8_t dir, uint64_t hit_no, uint64_t core_line_count);
void ocf_core_stats_request_pt_update(ocf_core_t core, ocf_part_id_t part_id,
uint8_t dir, uint64_t hit_no, uint64_t core_line_count);
void ocf_core_stats_core_error_update(ocf_core_t core, uint8_t dir);
void ocf_core_stats_cache_error_update(ocf_core_t core, uint8_t dir);
/**
* @brief ocf_core_io_class_get_stats retrieve io class statistics
* for given core
*
* Retrieve buffer of cache statistics for given cache instance.
*
* @param[in] core core handle to which request pertains
* @param[in] part_id IO class, stats of which are requested
* @param[out] stats statistic structure that shall be filled as
* a result of this function invocation.
*
* @result zero upon successful completion; error code otherwise
*/
int ocf_core_io_class_get_stats(ocf_core_t core, ocf_part_id_t part_id,
struct ocf_stats_io_class *stats);
/**
* @brief retrieve core stats
*
* Retrieve ocf per core stats (for all IO classes together)
*
* @param[in] core core ID to which request pertains
* @param[out] stats statistics structure that shall be filled as
* a result of this function invocation.
*
* @result zero upon successful completion; error code otherwise
*/
int ocf_core_get_stats(ocf_core_t core, struct ocf_stats_core *stats);
/**
* @brief update DEBUG stats given IO request
*
* Function meant to update DEBUG stats for IO request.
*
* @note This function shall be invoked for each IO request processed
*
* @param[in] core to which request pertains
* @param[in] io request for which stats are being updated
*/
void ocf_core_update_stats(ocf_core_t core, struct ocf_io *io);
#endif

View File

@@ -465,8 +465,7 @@ static void _ocf_cleaner_core_io_cmpl(struct ocf_io *io, int error)
if (error) {
map->invalid |= 1;
_ocf_cleaner_set_error(req);
env_atomic_inc(&req->cache->core[map->core_id].counters->
core_errors.write);
ocf_core_stats_core_error_update(req->core, OCF_WRITE);
}
_ocf_cleaner_core_io_end(req);
@@ -480,10 +479,8 @@ static void _ocf_cleaner_core_io_for_dirty_range(struct ocf_request *req,
uint64_t addr, offset;
int err;
ocf_cache_t cache = req->cache;
ocf_core_t core = ocf_cache_get_core(cache, iter->core_id);
struct ocf_io *io;
struct ocf_counters_block *core_stats =
&cache->core[iter->core_id].counters->core_blocks;
ocf_core_t core = ocf_cache_get_core(cache, iter->core_id);
ocf_part_id_t part_id = ocf_metadata_get_partition_id(cache,
iter->coll_idx);
@@ -505,7 +502,8 @@ static void _ocf_cleaner_core_io_for_dirty_range(struct ocf_request *req,
ocf_io_set_cmpl(io, iter, req, _ocf_cleaner_core_io_cmpl);
env_atomic64_add(SECTORS_TO_BYTES(end - begin), &core_stats->write_bytes);
ocf_core_stats_core_block_update(core, part_id, OCF_WRITE,
SECTORS_TO_BYTES(end - begin));
OCF_DEBUG_PARAM(req->cache, "Core write, line = %llu, "
"sector = %llu, count = %llu", iter->core_line, begin,
@@ -622,8 +620,7 @@ static void _ocf_cleaner_cache_io_cmpl(struct ocf_io *io, int error)
if (error) {
map->invalid |= 1;
_ocf_cleaner_set_error(req);
env_atomic_inc(&req->cache->core[map->core_id].counters->
cache_errors.read);
ocf_core_stats_cache_error_update(req->core, OCF_READ);
}
_ocf_cleaner_cache_io_end(req);
@@ -637,27 +634,25 @@ static void _ocf_cleaner_cache_io_cmpl(struct ocf_io *io, int error)
*/
static int _ocf_cleaner_fire_cache(struct ocf_request *req)
{
struct ocf_cache *cache = req->cache;
ocf_cache_t cache = req->cache;
ocf_core_t core;
uint32_t i;
struct ocf_map_info *iter = req->map;
uint64_t addr, offset;
ocf_part_id_t part_id;
struct ocf_io *io;
int err;
struct ocf_counters_block *cache_stats;
/* Protect IO completion race */
env_atomic_inc(&req->req_remaining);
for (i = 0; i < req->core_line_count; i++, iter++) {
if (iter->core_id == OCF_CORE_MAX)
core = ocf_cache_get_core(cache, iter->core_id);
if (!core)
continue;
if (iter->status == LOOKUP_MISS)
continue;
cache_stats = &cache->core[iter->core_id].
counters->cache_blocks;
OCF_DEBUG_PARAM(req->cache, "Cache read, line = %u",
iter->coll_idx);
@@ -689,7 +684,8 @@ static int _ocf_cleaner_fire_cache(struct ocf_request *req)
continue;
}
env_atomic64_add(ocf_line_size(cache), &cache_stats->read_bytes);
ocf_core_stats_cache_block_update(core, part_id, OCF_READ,
ocf_line_size(cache));
ocf_volume_submit_io(io);
}

View File

@@ -227,9 +227,8 @@ void ocf_submit_cache_reqs(struct ocf_cache *cache,
struct ocf_request *req, int dir, uint64_t offset,
uint64_t size, unsigned int reqs, ocf_req_end_t callback)
{
struct ocf_counters_block *cache_stats;
uint64_t flags = req->ioi.io.flags;
uint32_t class = req->ioi.io.io_class;
uint32_t io_class = req->ioi.io.io_class;
uint64_t addr, bytes, total_bytes = 0;
struct ocf_io *io;
int err;
@@ -240,8 +239,6 @@ void ocf_submit_cache_reqs(struct ocf_cache *cache,
ENV_BUG_ON(req->byte_length < offset + size);
ENV_BUG_ON(first_cl + reqs > req->core_line_count);
cache_stats = &req->core->counters->cache_blocks;
if (reqs == 1) {
addr = ocf_metadata_map_lg2phy(cache,
req->map[first_cl].coll_idx);
@@ -251,7 +248,7 @@ void ocf_submit_cache_reqs(struct ocf_cache *cache,
bytes = size;
io = ocf_new_cache_io(cache, req->io_queue,
addr, bytes, dir, class, flags);
addr, bytes, dir, io_class, flags);
if (!io) {
callback(req, -OCF_ERR_NO_MEM);
goto update_stats;
@@ -298,7 +295,7 @@ void ocf_submit_cache_reqs(struct ocf_cache *cache,
ENV_BUG_ON(bytes == 0);
io = ocf_new_cache_io(cache, req->io_queue,
addr, bytes, dir, class, flags);
addr, bytes, dir, io_class, flags);
if (!io) {
/* Finish all IOs which left with ERROR */
for (; i < reqs; i++)
@@ -323,30 +320,23 @@ void ocf_submit_cache_reqs(struct ocf_cache *cache,
ENV_BUG_ON(total_bytes != size);
update_stats:
if (dir == OCF_WRITE)
env_atomic64_add(total_bytes, &cache_stats->write_bytes);
else if (dir == OCF_READ)
env_atomic64_add(total_bytes, &cache_stats->read_bytes);
ocf_core_stats_cache_block_update(req->core, io_class, dir, total_bytes);
}
void ocf_submit_volume_req(ocf_volume_t volume, struct ocf_request *req,
ocf_req_end_t callback)
{
struct ocf_counters_block *core_stats;
uint64_t flags = req->ioi.io.flags;
uint32_t class = req->ioi.io.io_class;
uint32_t io_class = req->ioi.io.io_class;
int dir = req->rw;
struct ocf_io *io;
int err;
core_stats = &req->core->counters->core_blocks;
if (dir == OCF_WRITE)
env_atomic64_add(req->byte_length, &core_stats->write_bytes);
else if (dir == OCF_READ)
env_atomic64_add(req->byte_length, &core_stats->read_bytes);
ocf_core_stats_core_block_update(req->core, io_class, dir,
req->byte_length);
io = ocf_volume_new_io(volume, req->io_queue, req->byte_position,
req->byte_length, dir, class, flags);
req->byte_length, dir, io_class, flags);
if (!io) {
callback(req, -OCF_ERR_NO_MEM);
return;