Merge pull request #253 from mmichal10/stats-refactor
Stats builder for ioclasses
This commit is contained in:
commit
29c1c7f9e8
@ -29,7 +29,6 @@
|
|||||||
#include "ocf_metadata_updater.h"
|
#include "ocf_metadata_updater.h"
|
||||||
#include "ocf_io_class.h"
|
#include "ocf_io_class.h"
|
||||||
#include "ocf_stats.h"
|
#include "ocf_stats.h"
|
||||||
#include "ocf_stats_builder.h"
|
|
||||||
#include "ocf_mngt.h"
|
#include "ocf_mngt.h"
|
||||||
#include "ocf_ctx.h"
|
#include "ocf_ctx.h"
|
||||||
#include "ocf_err.h"
|
#include "ocf_err.h"
|
||||||
|
@ -16,6 +16,32 @@
|
|||||||
#include "ocf_io.h"
|
#include "ocf_io.h"
|
||||||
#include "ocf_mngt.h"
|
#include "ocf_mngt.h"
|
||||||
|
|
||||||
|
struct ocf_core_info {
|
||||||
|
/** Core size in cache line size unit */
|
||||||
|
uint64_t core_size;
|
||||||
|
|
||||||
|
/** Core size in bytes unit */
|
||||||
|
uint64_t core_size_bytes;
|
||||||
|
|
||||||
|
/** Fields refers ongoing flush operation */
|
||||||
|
struct {
|
||||||
|
/** Number of blocks flushed in ongoing flush operation */
|
||||||
|
uint32_t flushed;
|
||||||
|
|
||||||
|
/** Number of blocks left to flush in ongoing flush operation */
|
||||||
|
uint32_t dirty;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** How long core is dirty in seconds unit */
|
||||||
|
uint32_t dirty_for;
|
||||||
|
|
||||||
|
/** Sequential cutoff threshold (in bytes) */
|
||||||
|
uint32_t seq_cutoff_threshold;
|
||||||
|
|
||||||
|
/** Sequential cutoff policy */
|
||||||
|
ocf_seq_cutoff_policy seq_cutoff_policy;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get OCF core by name
|
* @brief Get OCF core by name
|
||||||
*
|
*
|
||||||
@ -202,4 +228,15 @@ typedef int (*ocf_core_visitor_t)(ocf_core_t core, void *cntx);
|
|||||||
int ocf_core_visit(ocf_cache_t cache, ocf_core_visitor_t visitor, void *cntx,
|
int ocf_core_visit(ocf_cache_t cache, ocf_core_visitor_t visitor, void *cntx,
|
||||||
bool only_opened);
|
bool only_opened);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get info of given core object
|
||||||
|
*
|
||||||
|
* @param[in] core Core object
|
||||||
|
* @param[out] info Core info structure
|
||||||
|
*
|
||||||
|
* @retval 0 Success
|
||||||
|
* @retval Non-zero Fail
|
||||||
|
*/
|
||||||
|
int ocf_core_get_info(ocf_core_t core, struct ocf_core_info *info);
|
||||||
|
|
||||||
#endif /* __OCF_CORE_H__ */
|
#endif /* __OCF_CORE_H__ */
|
||||||
|
343
inc/ocf_stats.h
343
inc/ocf_stats.h
@ -5,154 +5,218 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @file
|
* @file
|
||||||
* @brief OCF API for getting and reseting statistics
|
* @brief OCF API for updating and reseting statistics
|
||||||
*
|
*
|
||||||
* This file contains routines pertaining to retrieval and
|
* This file contains routines pertaining to manipulation of OCF IO statistics.
|
||||||
* manipulation of OCF IO statistics.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __OCF_STATS_H__
|
#ifndef __OCF_STATS_H__
|
||||||
#define __OCF_STATS_H__
|
#define __OCF_STATS_H__
|
||||||
|
|
||||||
struct ocf_io;
|
/**
|
||||||
|
* Entire row of statistcs
|
||||||
|
*/
|
||||||
|
struct ocf_stat {
|
||||||
|
/** Value */
|
||||||
|
uint64_t value;
|
||||||
|
/** percent x100 */
|
||||||
|
uint64_t fraction;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief OCF requests statistics like hit, miss, etc...
|
* @brief Usage statistics in 4 KiB unit
|
||||||
*
|
*
|
||||||
* @note To calculate number of hits request do:
|
* An example of presenting statistics:
|
||||||
* total - (partial_miss + full_miss)
|
* <pre>
|
||||||
|
* ╔══════════════════╤══════════╤═══════╤═════════════╗
|
||||||
|
* ║ Usage statistics │ Count │ % │ Units ║
|
||||||
|
* ╠══════════════════╪══════════╪═══════╪═════════════╣
|
||||||
|
* ║ Occupancy │ 20 │ 50.0 │ 4KiB blocks ║
|
||||||
|
* ║ Free │ 20 │ 50.0 │ 4KiB blocks ║
|
||||||
|
* ║ Clean │ 15 │ 75.0 │ 4KiB blocks ║
|
||||||
|
* ║ Dirty │ 5 │ 25.0 │ 4KiB blocks ║
|
||||||
|
* ╚══════════════════╧══════════╧═══════╧═════════════╝
|
||||||
|
* </pre>
|
||||||
*/
|
*/
|
||||||
struct ocf_stats_req {
|
struct ocf_stats_usage {
|
||||||
/** Number of partial misses */
|
struct ocf_stat occupancy;
|
||||||
uint64_t partial_miss;
|
struct ocf_stat free;
|
||||||
|
struct ocf_stat clean;
|
||||||
/** Number of full misses */
|
struct ocf_stat dirty;
|
||||||
uint64_t full_miss;
|
|
||||||
|
|
||||||
/** Total of requests */
|
|
||||||
uint64_t total;
|
|
||||||
|
|
||||||
/** Pass-through requests */
|
|
||||||
uint64_t pass_through;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief OCF error statistics
|
* @brief Requests statistcs
|
||||||
|
*
|
||||||
|
* An example of presenting statistics:
|
||||||
|
* <pre>
|
||||||
|
* ╔══════════════════════╤═══════╤═══════╤══════════╗
|
||||||
|
* ║ Request statistics │ Count │ % │ Units ║
|
||||||
|
* ╠══════════════════════╪═══════╪═══════╪══════════╣
|
||||||
|
* ║ Read hits │ 10 │ 4.5 │ Requests ║
|
||||||
|
* ║ Read partial misses │ 1 │ 0.5 │ Requests ║
|
||||||
|
* ║ Read full misses │ 211 │ 95.0 │ Requests ║
|
||||||
|
* ║ Read total │ 222 │ 100.0 │ Requests ║
|
||||||
|
* ╟──────────────────────┼───────┼───────┼──────────╢
|
||||||
|
* ║ Write hits │ 0 │ 0.0 │ Requests ║
|
||||||
|
* ║ Write partial misses │ 0 │ 0.0 │ Requests ║
|
||||||
|
* ║ Write full misses │ 0 │ 0.0 │ Requests ║
|
||||||
|
* ║ Write total │ 0 │ 0.0 │ Requests ║
|
||||||
|
* ╟──────────────────────┼───────┼───────┼──────────╢
|
||||||
|
* ║ Pass-Through reads │ 0 │ 0.0 │ Requests ║
|
||||||
|
* ║ Pass-Through writes │ 0 │ 0.0 │ Requests ║
|
||||||
|
* ║ Serviced requests │ 222 │ 100.0 │ Requests ║
|
||||||
|
* ╟──────────────────────┼───────┼───────┼──────────╢
|
||||||
|
* ║ Total requests │ 222 │ 100.0 │ Requests ║
|
||||||
|
* ╚══════════════════════╧═══════╧═══════╧══════════╝
|
||||||
|
* </pre>
|
||||||
*/
|
*/
|
||||||
struct ocf_stats_error {
|
struct ocf_stats_requests {
|
||||||
/** Read errors */
|
struct ocf_stat rd_hits;
|
||||||
uint32_t read;
|
struct ocf_stat rd_partial_misses;
|
||||||
|
struct ocf_stat rd_full_misses;
|
||||||
/** Write errors */
|
struct ocf_stat rd_total;
|
||||||
uint32_t write;
|
struct ocf_stat wr_hits;
|
||||||
|
struct ocf_stat wr_partial_misses;
|
||||||
|
struct ocf_stat wr_full_misses;
|
||||||
|
struct ocf_stat wr_total;
|
||||||
|
struct ocf_stat rd_pt;
|
||||||
|
struct ocf_stat wr_pt;
|
||||||
|
struct ocf_stat serviced;
|
||||||
|
struct ocf_stat total;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief OCF block statistics in bytes
|
* @brief Block statistics
|
||||||
|
*
|
||||||
|
* An example of presenting statistics:
|
||||||
|
* <pre>
|
||||||
|
* ╔════════════════════════════════════╤═══════╤═══════╤═════════════╗
|
||||||
|
* ║ Block statistics │ Count │ % │ Units ║
|
||||||
|
* ╠════════════════════════════════════╪═══════╪═══════╪═════════════╣
|
||||||
|
* ║ Reads from core volume(s) │ 426 │ 100.0 │ 4KiB blocks ║
|
||||||
|
* ║ Writes to core volume(s) │ 0 │ 0.0 │ 4KiB blocks ║
|
||||||
|
* ║ Total to/from core volume (s) │ 426 │ 100.0 │ 4KiB blocks ║
|
||||||
|
* ╟────────────────────────────────────┼───────┼───────┼─────────────╢
|
||||||
|
* ║ Reads from cache volume │ 13 │ 3.0 │ 4KiB blocks ║
|
||||||
|
* ║ Writes to cache volume │ 426 │ 97.0 │ 4KiB blocks ║
|
||||||
|
* ║ Total to/from cache volume │ 439 │ 100.0 │ 4KiB blocks ║
|
||||||
|
* ╟────────────────────────────────────┼───────┼───────┼─────────────╢
|
||||||
|
* ║ Reads from core(s) │ 439 │ 100.0 │ 4KiB blocks ║
|
||||||
|
* ║ Writes to core(s) │ 0 │ 0.0 │ 4KiB blocks ║
|
||||||
|
* ║ Total to/from core(s) │ 439 │ 100.0 │ 4KiB blocks ║
|
||||||
|
* ╚════════════════════════════════════╧═══════╧═══════╧═════════════╝
|
||||||
|
* </pre>
|
||||||
*/
|
*/
|
||||||
struct ocf_stats_block {
|
struct ocf_stats_blocks {
|
||||||
/** Number of blocks read */
|
struct ocf_stat core_volume_rd;
|
||||||
uint64_t read;
|
struct ocf_stat core_volume_wr;
|
||||||
|
struct ocf_stat core_volume_total;
|
||||||
/** Number of blocks written */
|
struct ocf_stat cache_volume_rd;
|
||||||
uint64_t write;
|
struct ocf_stat cache_volume_wr;
|
||||||
|
struct ocf_stat cache_volume_total;
|
||||||
|
struct ocf_stat volume_rd;
|
||||||
|
struct ocf_stat volume_wr;
|
||||||
|
struct ocf_stat volume_total;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Statistics appropriate for given IO class
|
* @brief Errors statistics
|
||||||
|
*
|
||||||
|
* An example of presenting statistics:
|
||||||
|
* <pre>
|
||||||
|
* ╔════════════════════╤═══════╤═════╤══════════╗
|
||||||
|
* ║ Error statistics │ Count │ % │ Units ║
|
||||||
|
* ╠════════════════════╪═══════╪═════╪══════════╣
|
||||||
|
* ║ Cache read errors │ 0 │ 0.0 │ Requests ║
|
||||||
|
* ║ Cache write errors │ 0 │ 0.0 │ Requests ║
|
||||||
|
* ║ Cache total errors │ 0 │ 0.0 │ Requests ║
|
||||||
|
* ╟────────────────────┼───────┼─────┼──────────╢
|
||||||
|
* ║ Core read errors │ 0 │ 0.0 │ Requests ║
|
||||||
|
* ║ Core write errors │ 0 │ 0.0 │ Requests ║
|
||||||
|
* ║ Core total errors │ 0 │ 0.0 │ Requests ║
|
||||||
|
* ╟────────────────────┼───────┼─────┼──────────╢
|
||||||
|
* ║ Total errors │ 0 │ 0.0 │ Requests ║
|
||||||
|
* ╚════════════════════╧═══════╧═════╧══════════╝
|
||||||
|
* </pre>
|
||||||
*/
|
*/
|
||||||
struct ocf_stats_io_class {
|
struct ocf_stats_errors {
|
||||||
/** Read requests statistics */
|
struct ocf_stat core_volume_rd;
|
||||||
struct ocf_stats_req read_reqs;
|
struct ocf_stat core_volume_wr;
|
||||||
|
struct ocf_stat core_volume_total;
|
||||||
/** Writes requests statistics */
|
struct ocf_stat cache_volume_rd;
|
||||||
struct ocf_stats_req write_reqs;
|
struct ocf_stat cache_volume_wr;
|
||||||
|
struct ocf_stat cache_volume_total;
|
||||||
/** Block requests statistics */
|
struct ocf_stat total;
|
||||||
struct ocf_stats_block blocks;
|
|
||||||
|
|
||||||
/** 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;
|
|
||||||
};
|
|
||||||
|
|
||||||
#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
|
* @param Collect statistics for given cache
|
||||||
|
*
|
||||||
|
* @param cache Cache instance for which statistics will be collected
|
||||||
|
* @param usage Usage statistics
|
||||||
|
* @param req Request statistics
|
||||||
|
* @param blocks Blocks statistics
|
||||||
|
* @param errors Errors statistics
|
||||||
|
*
|
||||||
|
* @retval 0 Success
|
||||||
|
* @retval Non-zero Error
|
||||||
*/
|
*/
|
||||||
struct ocf_stats_core {
|
int ocf_stats_collect_cache(ocf_cache_t cache,
|
||||||
/** Core size in cache line size unit */
|
struct ocf_stats_usage *usage,
|
||||||
uint64_t core_size;
|
struct ocf_stats_requests *req,
|
||||||
|
struct ocf_stats_blocks *blocks,
|
||||||
|
struct ocf_stats_errors *errors);
|
||||||
|
|
||||||
/** Core size in bytes unit */
|
/**
|
||||||
uint64_t core_size_bytes;
|
* @param Collect statistics for given core
|
||||||
|
*
|
||||||
|
* @param core Core for which statistics will be collected
|
||||||
|
* @param usage Usage statistics
|
||||||
|
* @param req Request statistics
|
||||||
|
* @param blocks Blocks statistics
|
||||||
|
* @param errors Errors statistics
|
||||||
|
*
|
||||||
|
* @retval 0 Success
|
||||||
|
* @retval Non-zero Error
|
||||||
|
*/
|
||||||
|
int ocf_stats_collect_core(ocf_core_t core,
|
||||||
|
struct ocf_stats_usage *usage,
|
||||||
|
struct ocf_stats_requests *req,
|
||||||
|
struct ocf_stats_blocks *blocks,
|
||||||
|
struct ocf_stats_errors *errors);
|
||||||
|
|
||||||
/** Number of cache lines allocated in the cache for this core */
|
/**
|
||||||
uint32_t cache_occupancy;
|
* @param Collect statistics for given ioclass
|
||||||
|
*
|
||||||
|
* @param core Core handle for which statistics will be collected
|
||||||
|
* @param part_id Ioclass id for which statistics will be collected
|
||||||
|
* @param usage Usage statistics
|
||||||
|
* @param req Request statistics
|
||||||
|
* @param blocks Blocks statistics
|
||||||
|
*
|
||||||
|
* @retval 0 Success
|
||||||
|
* @retval Non-zero Error
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
|
||||||
/** Number of dirty cache lines allocated in the cache for this core */
|
/**
|
||||||
uint32_t dirty;
|
* @param Collect statistics for given ioclass
|
||||||
|
*
|
||||||
/** Number of block flushed in ongoing flush operation */
|
* @param cache Cache instance for which statistics will be collected
|
||||||
uint32_t flushed;
|
* @param part_id Ioclass id for which statistics will be collected
|
||||||
|
* @param usage Usage statistics
|
||||||
/** How long core is dirty in seconds unit */
|
* @param req Request statistics
|
||||||
uint32_t dirty_for;
|
* @param blocks Blocks statistics
|
||||||
|
*
|
||||||
/** Read requests statistics */
|
* @retval 0 Success
|
||||||
struct ocf_stats_req read_reqs;
|
* @retval Non-zero Error
|
||||||
|
*/
|
||||||
/** Write requests statistics */
|
int ocf_stats_collect_part_cache(ocf_cache_t cache, ocf_part_id_t part_id,
|
||||||
struct ocf_stats_req write_reqs;
|
struct ocf_stats_usage *usage, struct ocf_stats_requests *req,
|
||||||
|
struct ocf_stats_blocks *blocks);
|
||||||
/** 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;
|
|
||||||
|
|
||||||
/** Sequential cutoff threshold (in bytes) */
|
|
||||||
uint32_t seq_cutoff_threshold;
|
|
||||||
|
|
||||||
/** Sequential cutoff policy */
|
|
||||||
ocf_seq_cutoff_policy seq_cutoff_policy;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Initialize or reset core statistics
|
* @brief Initialize or reset core statistics
|
||||||
@ -172,45 +236,4 @@ void ocf_core_stats_initialize(ocf_core_t core);
|
|||||||
*/
|
*/
|
||||||
void ocf_core_stats_initialize_all(ocf_cache_t cache);
|
void ocf_core_stats_initialize_all(ocf_cache_t cache);
|
||||||
|
|
||||||
/**
|
|
||||||
* @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 stats given IO request
|
|
||||||
*
|
|
||||||
* Function meant to update stats for IO request.
|
|
||||||
*
|
|
||||||
* @note This function shall be invoked for eac 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 /* __OCF_STATS_H__ */
|
#endif /* __OCF_STATS_H__ */
|
||||||
|
@ -1,190 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright(c) 2012-2018 Intel Corporation
|
|
||||||
* SPDX-License-Identifier: BSD-3-Clause-Clear
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
* @brief OCF API for collecting statistics
|
|
||||||
*
|
|
||||||
* This file contains routines pertaining to retrieval and
|
|
||||||
* manipulation of OCF IO statistics.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __OCF_STATS_BUILDER_H__
|
|
||||||
#define __OCF_STATS_BUILDER_H__
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Entire row of statistcs
|
|
||||||
*/
|
|
||||||
struct ocf_stat {
|
|
||||||
/** Value */
|
|
||||||
uint64_t value;
|
|
||||||
/** percent x10 */
|
|
||||||
uint64_t percent;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Usage statistics in 4 KiB unit
|
|
||||||
*
|
|
||||||
* An example of presenting statistics:
|
|
||||||
* <pre>
|
|
||||||
* ╔══════════════════╤══════════╤═══════╤═════════════╗
|
|
||||||
* ║ Usage statistics │ Count │ % │ Units ║
|
|
||||||
* ╠══════════════════╪══════════╪═══════╪═════════════╣
|
|
||||||
* ║ Occupancy │ 20 │ 50.0 │ 4KiB blocks ║
|
|
||||||
* ║ Free │ 20 │ 50.0 │ 4KiB blocks ║
|
|
||||||
* ║ Clean │ 15 │ 75.0 │ 4KiB blocks ║
|
|
||||||
* ║ Dirty │ 5 │ 25.0 │ 4KiB blocks ║
|
|
||||||
* ╚══════════════════╧══════════╧═══════╧═════════════╝
|
|
||||||
* </pre>
|
|
||||||
*/
|
|
||||||
struct ocf_stats_usage {
|
|
||||||
struct ocf_stat occupancy;
|
|
||||||
struct ocf_stat free;
|
|
||||||
struct ocf_stat clean;
|
|
||||||
struct ocf_stat dirty;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Requests statistcs
|
|
||||||
*
|
|
||||||
* An example of presenting statistics:
|
|
||||||
* <pre>
|
|
||||||
* ╔══════════════════════╤═══════╤═══════╤══════════╗
|
|
||||||
* ║ Request statistics │ Count │ % │ Units ║
|
|
||||||
* ╠══════════════════════╪═══════╪═══════╪══════════╣
|
|
||||||
* ║ Read hits │ 10 │ 4.5 │ Requests ║
|
|
||||||
* ║ Read partial misses │ 1 │ 0.5 │ Requests ║
|
|
||||||
* ║ Read full misses │ 211 │ 95.0 │ Requests ║
|
|
||||||
* ║ Read total │ 222 │ 100.0 │ Requests ║
|
|
||||||
* ╟──────────────────────┼───────┼───────┼──────────╢
|
|
||||||
* ║ Write hits │ 0 │ 0.0 │ Requests ║
|
|
||||||
* ║ Write partial misses │ 0 │ 0.0 │ Requests ║
|
|
||||||
* ║ Write full misses │ 0 │ 0.0 │ Requests ║
|
|
||||||
* ║ Write total │ 0 │ 0.0 │ Requests ║
|
|
||||||
* ╟──────────────────────┼───────┼───────┼──────────╢
|
|
||||||
* ║ Pass-Through reads │ 0 │ 0.0 │ Requests ║
|
|
||||||
* ║ Pass-Through writes │ 0 │ 0.0 │ Requests ║
|
|
||||||
* ║ Serviced requests │ 222 │ 100.0 │ Requests ║
|
|
||||||
* ╟──────────────────────┼───────┼───────┼──────────╢
|
|
||||||
* ║ Total requests │ 222 │ 100.0 │ Requests ║
|
|
||||||
* ╚══════════════════════╧═══════╧═══════╧══════════╝
|
|
||||||
* </pre>
|
|
||||||
*/
|
|
||||||
struct ocf_stats_requests {
|
|
||||||
struct ocf_stat rd_hits;
|
|
||||||
struct ocf_stat rd_partial_misses;
|
|
||||||
struct ocf_stat rd_full_misses;
|
|
||||||
struct ocf_stat rd_total;
|
|
||||||
struct ocf_stat wr_hits;
|
|
||||||
struct ocf_stat wr_partial_misses;
|
|
||||||
struct ocf_stat wr_full_misses;
|
|
||||||
struct ocf_stat wr_total;
|
|
||||||
struct ocf_stat rd_pt;
|
|
||||||
struct ocf_stat wr_pt;
|
|
||||||
struct ocf_stat serviced;
|
|
||||||
struct ocf_stat total;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Block statistics
|
|
||||||
*
|
|
||||||
* An example of presenting statistics:
|
|
||||||
* <pre>
|
|
||||||
* ╔════════════════════════════════════╤═══════╤═══════╤═════════════╗
|
|
||||||
* ║ Block statistics │ Count │ % │ Units ║
|
|
||||||
* ╠════════════════════════════════════╪═══════╪═══════╪═════════════╣
|
|
||||||
* ║ Reads from core volume(s) │ 426 │ 100.0 │ 4KiB blocks ║
|
|
||||||
* ║ Writes to core volume(s) │ 0 │ 0.0 │ 4KiB blocks ║
|
|
||||||
* ║ Total to/from core volume (s) │ 426 │ 100.0 │ 4KiB blocks ║
|
|
||||||
* ╟────────────────────────────────────┼───────┼───────┼─────────────╢
|
|
||||||
* ║ Reads from cache volume │ 13 │ 3.0 │ 4KiB blocks ║
|
|
||||||
* ║ Writes to cache volume │ 426 │ 97.0 │ 4KiB blocks ║
|
|
||||||
* ║ Total to/from cache volume │ 439 │ 100.0 │ 4KiB blocks ║
|
|
||||||
* ╟────────────────────────────────────┼───────┼───────┼─────────────╢
|
|
||||||
* ║ Reads from core(s) │ 439 │ 100.0 │ 4KiB blocks ║
|
|
||||||
* ║ Writes to core(s) │ 0 │ 0.0 │ 4KiB blocks ║
|
|
||||||
* ║ Total to/from core(s) │ 439 │ 100.0 │ 4KiB blocks ║
|
|
||||||
* ╚════════════════════════════════════╧═══════╧═══════╧═════════════╝
|
|
||||||
* </pre>
|
|
||||||
*/
|
|
||||||
struct ocf_stats_blocks {
|
|
||||||
struct ocf_stat core_volume_rd;
|
|
||||||
struct ocf_stat core_volume_wr;
|
|
||||||
struct ocf_stat core_volume_total;
|
|
||||||
struct ocf_stat cache_volume_rd;
|
|
||||||
struct ocf_stat cache_volume_wr;
|
|
||||||
struct ocf_stat cache_volume_total;
|
|
||||||
struct ocf_stat volume_rd;
|
|
||||||
struct ocf_stat volume_wr;
|
|
||||||
struct ocf_stat volume_total;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Errors statistics
|
|
||||||
*
|
|
||||||
* An example of presenting statistics:
|
|
||||||
* <pre>
|
|
||||||
* ╔════════════════════╤═══════╤═════╤══════════╗
|
|
||||||
* ║ Error statistics │ Count │ % │ Units ║
|
|
||||||
* ╠════════════════════╪═══════╪═════╪══════════╣
|
|
||||||
* ║ Cache read errors │ 0 │ 0.0 │ Requests ║
|
|
||||||
* ║ Cache write errors │ 0 │ 0.0 │ Requests ║
|
|
||||||
* ║ Cache total errors │ 0 │ 0.0 │ Requests ║
|
|
||||||
* ╟────────────────────┼───────┼─────┼──────────╢
|
|
||||||
* ║ Core read errors │ 0 │ 0.0 │ Requests ║
|
|
||||||
* ║ Core write errors │ 0 │ 0.0 │ Requests ║
|
|
||||||
* ║ Core total errors │ 0 │ 0.0 │ Requests ║
|
|
||||||
* ╟────────────────────┼───────┼─────┼──────────╢
|
|
||||||
* ║ Total errors │ 0 │ 0.0 │ Requests ║
|
|
||||||
* ╚════════════════════╧═══════╧═════╧══════════╝
|
|
||||||
* </pre>
|
|
||||||
*/
|
|
||||||
struct ocf_stats_errors {
|
|
||||||
struct ocf_stat core_volume_rd;
|
|
||||||
struct ocf_stat core_volume_wr;
|
|
||||||
struct ocf_stat core_volume_total;
|
|
||||||
struct ocf_stat cache_volume_rd;
|
|
||||||
struct ocf_stat cache_volume_wr;
|
|
||||||
struct ocf_stat cache_volume_total;
|
|
||||||
struct ocf_stat total;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Collect statistics for given cache
|
|
||||||
*
|
|
||||||
* @param cache Cache instance for each statistics will be collected
|
|
||||||
* @param usage Usage statistics
|
|
||||||
* @param req Request statistics
|
|
||||||
* @param blocks Blocks statistics
|
|
||||||
* @param errors Errors statistics
|
|
||||||
*
|
|
||||||
* @retval 0 Success
|
|
||||||
* @retval Non-zero Error
|
|
||||||
*/
|
|
||||||
int ocf_stats_collect_cache(ocf_cache_t cache,
|
|
||||||
struct ocf_stats_usage *usage,
|
|
||||||
struct ocf_stats_requests *req,
|
|
||||||
struct ocf_stats_blocks *blocks,
|
|
||||||
struct ocf_stats_errors *errors);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Collect statistics for given core
|
|
||||||
*
|
|
||||||
* @param cache Core for each statistics will be collected
|
|
||||||
* @param usage Usage statistics
|
|
||||||
* @param req Request statistics
|
|
||||||
* @param blocks Blocks statistics
|
|
||||||
* @param errors Errors statistics
|
|
||||||
*
|
|
||||||
* @retval 0 Success
|
|
||||||
* @retval Non-zero Error
|
|
||||||
*/
|
|
||||||
int ocf_stats_collect_core(ocf_core_t core,
|
|
||||||
struct ocf_stats_usage *usage,
|
|
||||||
struct ocf_stats_requests *req,
|
|
||||||
struct ocf_stats_blocks *blocks,
|
|
||||||
struct ocf_stats_errors *errors);
|
|
||||||
|
|
||||||
#endif /* __OCF_STATS_BUILDER_H__ */
|
|
@ -61,7 +61,7 @@ static void _ocf_backfill_complete(struct ocf_request *req, int error)
|
|||||||
req->data = NULL;
|
req->data = NULL;
|
||||||
|
|
||||||
if (req->error) {
|
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);
|
ocf_engine_invalidate(req);
|
||||||
} else {
|
} else {
|
||||||
ocf_req_unlock(req);
|
ocf_req_unlock(req);
|
||||||
|
@ -446,42 +446,14 @@ void ocf_engine_clean(struct ocf_request *req)
|
|||||||
|
|
||||||
void ocf_engine_update_block_stats(struct ocf_request *req)
|
void ocf_engine_update_block_stats(struct ocf_request *req)
|
||||||
{
|
{
|
||||||
ocf_part_id_t part_id = req->part_id;
|
ocf_core_stats_vol_block_update(req->core, req->part_id, req->rw,
|
||||||
struct ocf_counters_block *blocks;
|
req->byte_length);
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ocf_engine_update_request_stats(struct ocf_request *req)
|
void ocf_engine_update_request_stats(struct ocf_request *req)
|
||||||
{
|
{
|
||||||
ocf_part_id_t part_id = req->part_id;
|
ocf_core_stats_request_update(req->core, req->part_id, req->rw,
|
||||||
struct ocf_counters_req *reqs;
|
req->info.hit_no, req->core_line_count);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ocf_engine_push_req_back(struct ocf_request *req, bool allow_sync)
|
void ocf_engine_push_req_back(struct ocf_request *req, bool allow_sync)
|
||||||
|
@ -16,17 +16,13 @@
|
|||||||
|
|
||||||
static void _ocf_d2c_completion(struct ocf_request *req, int error)
|
static void _ocf_d2c_completion(struct ocf_request *req, int error)
|
||||||
{
|
{
|
||||||
ocf_core_t core = req->core;
|
|
||||||
req->error = error;
|
req->error = error;
|
||||||
|
|
||||||
OCF_DEBUG_RQ(req, "Completion");
|
OCF_DEBUG_RQ(req, "Completion");
|
||||||
|
|
||||||
if (req->error) {
|
if (req->error) {
|
||||||
req->info.core_error = 1;
|
req->info.core_error = 1;
|
||||||
if (req->rw == OCF_READ)
|
ocf_core_stats_core_error_update(req->core, req->rw);
|
||||||
env_atomic_inc(&core->counters->core_errors.read);
|
|
||||||
else
|
|
||||||
env_atomic_inc(&core->counters->core_errors.write);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Complete request */
|
/* Complete request */
|
||||||
@ -51,13 +47,8 @@ int ocf_io_d2c(struct ocf_request *req)
|
|||||||
|
|
||||||
ocf_engine_update_block_stats(req);
|
ocf_engine_update_block_stats(req);
|
||||||
|
|
||||||
if (req->rw == OCF_READ) {
|
ocf_core_stats_request_pt_update(req->core, req->part_id, req->rw,
|
||||||
env_atomic64_inc(&core->counters->
|
req->info.hit_no, req->core_line_count);
|
||||||
part_counters[req->part_id].read_reqs.pass_through);
|
|
||||||
} else {
|
|
||||||
env_atomic64_inc(&core->counters->
|
|
||||||
part_counters[req->part_id].write_reqs.pass_through);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Put OCF request - decrease reference counter */
|
/* Put OCF request - decrease reference counter */
|
||||||
ocf_req_put(req);
|
ocf_req_put(req);
|
||||||
|
@ -43,7 +43,7 @@ static void _ocf_read_fast_complete(struct ocf_request *req, int error)
|
|||||||
if (req->error) {
|
if (req->error) {
|
||||||
OCF_DEBUG_RQ(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);
|
ocf_engine_push_req_front_pt(req);
|
||||||
} else {
|
} else {
|
||||||
ocf_req_unlock(req);
|
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);
|
ocf_engine_io_count(req), _ocf_read_fast_complete);
|
||||||
|
|
||||||
|
|
||||||
/* Updata statistics */
|
/* Update statistics */
|
||||||
ocf_engine_update_request_stats(req);
|
ocf_engine_update_request_stats(req);
|
||||||
ocf_engine_update_block_stats(req);
|
ocf_engine_update_block_stats(req);
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ static void _ocf_invalidate_req(struct ocf_request *req, int error)
|
|||||||
{
|
{
|
||||||
if (error) {
|
if (error) {
|
||||||
req->error = 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))
|
if (env_atomic_dec_return(&req->req_remaining))
|
||||||
|
@ -28,7 +28,7 @@ static void _ocf_read_pt_complete(struct ocf_request *req, int error)
|
|||||||
|
|
||||||
if (req->error) {
|
if (req->error) {
|
||||||
req->info.core_error = 1;
|
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 */
|
/* Complete request */
|
||||||
@ -87,8 +87,8 @@ int ocf_read_pt_do(struct ocf_request *req)
|
|||||||
|
|
||||||
/* Update statistics */
|
/* Update statistics */
|
||||||
ocf_engine_update_block_stats(req);
|
ocf_engine_update_block_stats(req);
|
||||||
env_atomic64_inc(&req->core->counters->
|
ocf_core_stats_request_pt_update(req->core, req->part_id, req->rw,
|
||||||
part_counters[req->part_id].read_reqs.pass_through);
|
req->info.hit_no, req->core_line_count);
|
||||||
|
|
||||||
/* Put OCF request - decrease reference counter */
|
/* Put OCF request - decrease reference counter */
|
||||||
ocf_req_put(req);
|
ocf_req_put(req);
|
||||||
|
@ -38,7 +38,7 @@ static void _ocf_read_generic_hit_complete(struct ocf_request *req, int error)
|
|||||||
OCF_DEBUG_RQ(req, "HIT completion");
|
OCF_DEBUG_RQ(req, "HIT completion");
|
||||||
|
|
||||||
if (req->error) {
|
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);
|
ocf_engine_push_req_front_pt(req);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
@ -77,7 +77,7 @@ static void _ocf_read_generic_miss_complete(struct ocf_request *req, int error)
|
|||||||
req->complete(req, req->error);
|
req->complete(req, req->error);
|
||||||
|
|
||||||
req->info.core_error = 1;
|
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);
|
ctx_data_free(cache->owner, req->cp_data);
|
||||||
req->cp_data = NULL;
|
req->cp_data = NULL;
|
||||||
|
@ -24,7 +24,7 @@ static void _ocf_read_wa_complete(struct ocf_request *req, int error)
|
|||||||
|
|
||||||
if (req->error) {
|
if (req->error) {
|
||||||
req->info.core_error = 1;
|
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 */
|
/* Complete request */
|
||||||
@ -76,8 +76,8 @@ int ocf_write_wa(struct ocf_request *req)
|
|||||||
|
|
||||||
/* Update statistics */
|
/* Update statistics */
|
||||||
ocf_engine_update_block_stats(req);
|
ocf_engine_update_block_stats(req);
|
||||||
env_atomic64_inc(&req->core->counters->
|
ocf_core_stats_request_pt_update(req->core, req->part_id, req->rw,
|
||||||
part_counters[req->part_id].write_reqs.pass_through);
|
req->info.hit_no, req->core_line_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Put OCF request - decrease reference counter */
|
/* Put OCF request - decrease reference counter */
|
||||||
|
@ -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)
|
static void _ocf_write_wb_complete(struct ocf_request *req, int error)
|
||||||
{
|
{
|
||||||
if (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;
|
req->error |= error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,13 +150,13 @@ int ocf_write_wb_do(struct ocf_request *req)
|
|||||||
/* Get OCF request - increase reference counter */
|
/* Get OCF request - increase reference counter */
|
||||||
ocf_req_get(req);
|
ocf_req_get(req);
|
||||||
|
|
||||||
/* Updata status bits */
|
/* Update status bits */
|
||||||
_ocf_write_wb_update_bits(req);
|
_ocf_write_wb_update_bits(req);
|
||||||
|
|
||||||
/* Submit IO */
|
/* Submit IO */
|
||||||
_ocf_write_wb_submit(req);
|
_ocf_write_wb_submit(req);
|
||||||
|
|
||||||
/* Updata statistics */
|
/* Update statistics */
|
||||||
ocf_engine_update_request_stats(req);
|
ocf_engine_update_request_stats(req);
|
||||||
ocf_engine_update_block_stats(req);
|
ocf_engine_update_block_stats(req);
|
||||||
|
|
||||||
|
@ -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)
|
static void _ocf_write_wi_io_flush_metadata(struct ocf_request *req, int error)
|
||||||
{
|
{
|
||||||
if (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;
|
req->error |= error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,7 +77,7 @@ static void _ocf_write_wi_core_complete(struct ocf_request *req, int error)
|
|||||||
if (error) {
|
if (error) {
|
||||||
req->error = error;
|
req->error = error;
|
||||||
req->info.core_error = 1;
|
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))
|
if (env_atomic_dec_return(&req->req_remaining))
|
||||||
@ -112,8 +112,8 @@ static int _ocf_write_wi_do(struct ocf_request *req)
|
|||||||
|
|
||||||
/* Update statistics */
|
/* Update statistics */
|
||||||
ocf_engine_update_block_stats(req);
|
ocf_engine_update_block_stats(req);
|
||||||
env_atomic64_inc(&req->core->counters->
|
ocf_core_stats_request_pt_update(req->core, req->part_id, req->rw,
|
||||||
part_counters[req->part_id].write_reqs.pass_through);
|
req->info.hit_no, req->core_line_count);
|
||||||
|
|
||||||
/* Put OCF request - decrease reference counter */
|
/* Put OCF request - decrease reference counter */
|
||||||
ocf_req_put(req);
|
ocf_req_put(req);
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
static void ocf_read_wo_cache_complete(struct ocf_request *req, int error)
|
static void ocf_read_wo_cache_complete(struct ocf_request *req, int error)
|
||||||
{
|
{
|
||||||
if (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;
|
req->error |= error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,7 +148,7 @@ static void _ocf_read_wo_core_complete(struct ocf_request *req, int error)
|
|||||||
if (error) {
|
if (error) {
|
||||||
req->error |= error;
|
req->error |= error;
|
||||||
req->info.core_error = 1;
|
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
|
/* if all mapped cachelines are clean, the data we've read from core
|
||||||
|
@ -48,7 +48,7 @@ static void _ocf_write_wt_cache_complete(struct ocf_request *req, int error)
|
|||||||
{
|
{
|
||||||
if (error) {
|
if (error) {
|
||||||
req->error = req->error ?: 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)
|
if (req->error)
|
||||||
inc_fallback_pt_error_counter(req->cache);
|
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) {
|
if (error) {
|
||||||
req->error = error;
|
req->error = error;
|
||||||
req->info.core_error = 1;
|
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);
|
_ocf_write_wt_req_complete(req);
|
||||||
|
@ -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)
|
static void _ocf_zero_io_flush_metadata(struct ocf_request *req, int error)
|
||||||
{
|
{
|
||||||
if (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;
|
req->error = error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,6 +143,13 @@ int ocf_core_visit(ocf_cache_t cache, ocf_core_visitor_t visitor, void *cntx,
|
|||||||
|
|
||||||
/* *** HELPER FUNCTIONS *** */
|
/* *** 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)
|
static inline struct ocf_request *ocf_io_to_req(struct ocf_io *io)
|
||||||
{
|
{
|
||||||
struct ocf_io_internal *ioi;
|
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_properties,
|
||||||
&ocf_core_volume_extended);
|
&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;
|
||||||
|
}
|
||||||
|
152
src/ocf_stats.c
152
src/ocf_stats.c
@ -47,6 +47,8 @@ static void ocf_stats_part_init(struct ocf_counters_part *stats)
|
|||||||
ocf_stats_req_init(&stats->write_reqs);
|
ocf_stats_req_init(&stats->write_reqs);
|
||||||
|
|
||||||
ocf_stats_block_init(&stats->blocks);
|
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)
|
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);
|
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.
|
* 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;
|
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->cache_errors);
|
||||||
ocf_stats_error_init(&exp_obj_stats->core_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_req_stats(&stats->write_reqs, &part_stat->write_reqs);
|
||||||
|
|
||||||
copy_block_stats(&stats->blocks, &part_stat->blocks);
|
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;
|
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)
|
int ocf_core_get_stats(ocf_core_t core, struct ocf_stats_core *stats)
|
||||||
{
|
{
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
ocf_core_id_t core_id;
|
|
||||||
ocf_cache_t cache;
|
|
||||||
struct ocf_counters_core *core_stats = NULL;
|
struct ocf_counters_core *core_stats = NULL;
|
||||||
struct ocf_counters_part *curr = NULL;
|
struct ocf_counters_part *curr = NULL;
|
||||||
|
|
||||||
OCF_CHECK_NULL(core);
|
OCF_CHECK_NULL(core);
|
||||||
|
|
||||||
core_id = ocf_core_get_id(core);
|
|
||||||
cache = ocf_core_get_cache(core);
|
|
||||||
|
|
||||||
if (!stats)
|
if (!stats)
|
||||||
return -OCF_ERR_INVAL;
|
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));
|
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,
|
copy_error_stats(&stats->core_errors,
|
||||||
&core_stats->core_errors);
|
&core_stats->core_errors);
|
||||||
copy_error_stats(&stats->cache_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);
|
&curr->write_reqs);
|
||||||
|
|
||||||
accum_block_stats(&stats->core, &curr->blocks);
|
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->
|
stats->cache_occupancy += env_atomic_read(&core->runtime_meta->
|
||||||
part_counters[i].cached_clines);
|
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);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,11 +18,11 @@
|
|||||||
} \
|
} \
|
||||||
} while (0)
|
} 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;
|
uint64_t result;
|
||||||
if (denominator) {
|
if (denominator) {
|
||||||
result = 1000 * numerator / denominator;
|
result = 10000 * numerator / denominator;
|
||||||
} else {
|
} else {
|
||||||
result = 0;
|
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)
|
static void _set(struct ocf_stat *stat, uint64_t value, uint64_t denominator)
|
||||||
{
|
{
|
||||||
stat->value = value;
|
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)
|
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);
|
_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,
|
static void _fill_blocks(struct ocf_stats_blocks *blocks,
|
||||||
struct ocf_stats_core *s)
|
struct ocf_stats_core *s)
|
||||||
{
|
{
|
||||||
@ -112,6 +145,36 @@ static void _fill_blocks(struct ocf_stats_blocks *blocks,
|
|||||||
_set(&blocks->volume_total, total, total);
|
_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,
|
static void _fill_errors(struct ocf_stats_errors *errors,
|
||||||
struct ocf_stats_core *s)
|
struct ocf_stats_core *s)
|
||||||
{
|
{
|
||||||
@ -137,6 +200,152 @@ static void _fill_errors(struct ocf_stats_errors *errors,
|
|||||||
_set(&errors->total, total, total);
|
_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,
|
int ocf_stats_collect_core(ocf_core_t core,
|
||||||
struct ocf_stats_usage *usage,
|
struct ocf_stats_usage *usage,
|
||||||
struct ocf_stats_requests *req,
|
struct ocf_stats_requests *req,
|
||||||
@ -194,29 +403,6 @@ int ocf_stats_collect_core(ocf_core_t core,
|
|||||||
return 0;
|
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)
|
static int _accumulate_stats(ocf_core_t core, void *cntx)
|
||||||
{
|
{
|
||||||
struct ocf_stats_core stats, *total = cntx;
|
struct ocf_stats_core stats, *total = cntx;
|
||||||
|
@ -23,6 +23,132 @@ struct ocf_counters_req {
|
|||||||
env_atomic64 pass_through;
|
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.
|
* statistics appropriate for given io class.
|
||||||
*/
|
*/
|
||||||
@ -31,6 +157,9 @@ struct ocf_counters_part {
|
|||||||
struct ocf_counters_req write_reqs;
|
struct ocf_counters_req write_reqs;
|
||||||
|
|
||||||
struct ocf_counters_block blocks;
|
struct ocf_counters_block blocks;
|
||||||
|
|
||||||
|
struct ocf_counters_block core_blocks;
|
||||||
|
struct ocf_counters_block cache_blocks;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef OCF_DEBUG_STATS
|
#ifdef OCF_DEBUG_STATS
|
||||||
@ -44,9 +173,6 @@ struct ocf_counters_debug {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct ocf_counters_core {
|
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 core_errors;
|
||||||
struct ocf_counters_error cache_errors;
|
struct ocf_counters_error cache_errors;
|
||||||
|
|
||||||
@ -56,4 +182,60 @@ struct ocf_counters_core {
|
|||||||
#endif
|
#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
|
#endif
|
||||||
|
@ -465,8 +465,7 @@ static void _ocf_cleaner_core_io_cmpl(struct ocf_io *io, int error)
|
|||||||
if (error) {
|
if (error) {
|
||||||
map->invalid |= 1;
|
map->invalid |= 1;
|
||||||
_ocf_cleaner_set_error(req);
|
_ocf_cleaner_set_error(req);
|
||||||
env_atomic_inc(&req->cache->core[map->core_id].counters->
|
ocf_core_stats_core_error_update(req->core, OCF_WRITE);
|
||||||
core_errors.write);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_ocf_cleaner_core_io_end(req);
|
_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;
|
uint64_t addr, offset;
|
||||||
int err;
|
int err;
|
||||||
ocf_cache_t cache = req->cache;
|
ocf_cache_t cache = req->cache;
|
||||||
ocf_core_t core = ocf_cache_get_core(cache, iter->core_id);
|
|
||||||
struct ocf_io *io;
|
struct ocf_io *io;
|
||||||
struct ocf_counters_block *core_stats =
|
ocf_core_t core = ocf_cache_get_core(cache, iter->core_id);
|
||||||
&cache->core[iter->core_id].counters->core_blocks;
|
|
||||||
ocf_part_id_t part_id = ocf_metadata_get_partition_id(cache,
|
ocf_part_id_t part_id = ocf_metadata_get_partition_id(cache,
|
||||||
iter->coll_idx);
|
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);
|
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, "
|
OCF_DEBUG_PARAM(req->cache, "Core write, line = %llu, "
|
||||||
"sector = %llu, count = %llu", iter->core_line, begin,
|
"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) {
|
if (error) {
|
||||||
map->invalid |= 1;
|
map->invalid |= 1;
|
||||||
_ocf_cleaner_set_error(req);
|
_ocf_cleaner_set_error(req);
|
||||||
env_atomic_inc(&req->cache->core[map->core_id].counters->
|
ocf_core_stats_cache_error_update(req->core, OCF_READ);
|
||||||
cache_errors.read);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_ocf_cleaner_cache_io_end(req);
|
_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)
|
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;
|
uint32_t i;
|
||||||
struct ocf_map_info *iter = req->map;
|
struct ocf_map_info *iter = req->map;
|
||||||
uint64_t addr, offset;
|
uint64_t addr, offset;
|
||||||
ocf_part_id_t part_id;
|
ocf_part_id_t part_id;
|
||||||
struct ocf_io *io;
|
struct ocf_io *io;
|
||||||
int err;
|
int err;
|
||||||
struct ocf_counters_block *cache_stats;
|
|
||||||
|
|
||||||
/* Protect IO completion race */
|
/* Protect IO completion race */
|
||||||
env_atomic_inc(&req->req_remaining);
|
env_atomic_inc(&req->req_remaining);
|
||||||
|
|
||||||
for (i = 0; i < req->core_line_count; i++, iter++) {
|
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;
|
continue;
|
||||||
if (iter->status == LOOKUP_MISS)
|
if (iter->status == LOOKUP_MISS)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
cache_stats = &cache->core[iter->core_id].
|
|
||||||
counters->cache_blocks;
|
|
||||||
|
|
||||||
OCF_DEBUG_PARAM(req->cache, "Cache read, line = %u",
|
OCF_DEBUG_PARAM(req->cache, "Cache read, line = %u",
|
||||||
iter->coll_idx);
|
iter->coll_idx);
|
||||||
|
|
||||||
@ -689,7 +684,8 @@ static int _ocf_cleaner_fire_cache(struct ocf_request *req)
|
|||||||
continue;
|
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);
|
ocf_volume_submit_io(io);
|
||||||
}
|
}
|
||||||
|
@ -227,9 +227,8 @@ void ocf_submit_cache_reqs(struct ocf_cache *cache,
|
|||||||
struct ocf_request *req, int dir, uint64_t offset,
|
struct ocf_request *req, int dir, uint64_t offset,
|
||||||
uint64_t size, unsigned int reqs, ocf_req_end_t callback)
|
uint64_t size, unsigned int reqs, ocf_req_end_t callback)
|
||||||
{
|
{
|
||||||
struct ocf_counters_block *cache_stats;
|
|
||||||
uint64_t flags = req->ioi.io.flags;
|
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;
|
uint64_t addr, bytes, total_bytes = 0;
|
||||||
struct ocf_io *io;
|
struct ocf_io *io;
|
||||||
int err;
|
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(req->byte_length < offset + size);
|
||||||
ENV_BUG_ON(first_cl + reqs > req->core_line_count);
|
ENV_BUG_ON(first_cl + reqs > req->core_line_count);
|
||||||
|
|
||||||
cache_stats = &req->core->counters->cache_blocks;
|
|
||||||
|
|
||||||
if (reqs == 1) {
|
if (reqs == 1) {
|
||||||
addr = ocf_metadata_map_lg2phy(cache,
|
addr = ocf_metadata_map_lg2phy(cache,
|
||||||
req->map[first_cl].coll_idx);
|
req->map[first_cl].coll_idx);
|
||||||
@ -251,7 +248,7 @@ void ocf_submit_cache_reqs(struct ocf_cache *cache,
|
|||||||
bytes = size;
|
bytes = size;
|
||||||
|
|
||||||
io = ocf_new_cache_io(cache, req->io_queue,
|
io = ocf_new_cache_io(cache, req->io_queue,
|
||||||
addr, bytes, dir, class, flags);
|
addr, bytes, dir, io_class, flags);
|
||||||
if (!io) {
|
if (!io) {
|
||||||
callback(req, -OCF_ERR_NO_MEM);
|
callback(req, -OCF_ERR_NO_MEM);
|
||||||
goto update_stats;
|
goto update_stats;
|
||||||
@ -298,7 +295,7 @@ void ocf_submit_cache_reqs(struct ocf_cache *cache,
|
|||||||
ENV_BUG_ON(bytes == 0);
|
ENV_BUG_ON(bytes == 0);
|
||||||
|
|
||||||
io = ocf_new_cache_io(cache, req->io_queue,
|
io = ocf_new_cache_io(cache, req->io_queue,
|
||||||
addr, bytes, dir, class, flags);
|
addr, bytes, dir, io_class, flags);
|
||||||
if (!io) {
|
if (!io) {
|
||||||
/* Finish all IOs which left with ERROR */
|
/* Finish all IOs which left with ERROR */
|
||||||
for (; i < reqs; i++)
|
for (; i < reqs; i++)
|
||||||
@ -323,30 +320,23 @@ void ocf_submit_cache_reqs(struct ocf_cache *cache,
|
|||||||
ENV_BUG_ON(total_bytes != size);
|
ENV_BUG_ON(total_bytes != size);
|
||||||
|
|
||||||
update_stats:
|
update_stats:
|
||||||
if (dir == OCF_WRITE)
|
ocf_core_stats_cache_block_update(req->core, io_class, dir, total_bytes);
|
||||||
env_atomic64_add(total_bytes, &cache_stats->write_bytes);
|
|
||||||
else if (dir == OCF_READ)
|
|
||||||
env_atomic64_add(total_bytes, &cache_stats->read_bytes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ocf_submit_volume_req(ocf_volume_t volume, struct ocf_request *req,
|
void ocf_submit_volume_req(ocf_volume_t volume, struct ocf_request *req,
|
||||||
ocf_req_end_t callback)
|
ocf_req_end_t callback)
|
||||||
{
|
{
|
||||||
struct ocf_counters_block *core_stats;
|
|
||||||
uint64_t flags = req->ioi.io.flags;
|
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;
|
int dir = req->rw;
|
||||||
struct ocf_io *io;
|
struct ocf_io *io;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
core_stats = &req->core->counters->core_blocks;
|
ocf_core_stats_core_block_update(req->core, io_class, dir,
|
||||||
if (dir == OCF_WRITE)
|
req->byte_length);
|
||||||
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);
|
|
||||||
|
|
||||||
io = ocf_volume_new_io(volume, req->io_queue, req->byte_position,
|
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) {
|
if (!io) {
|
||||||
callback(req, -OCF_ERR_NO_MEM);
|
callback(req, -OCF_ERR_NO_MEM);
|
||||||
return;
|
return;
|
||||||
|
@ -25,7 +25,7 @@ from .data import Data
|
|||||||
from .io import Io, IoDir
|
from .io import Io, IoDir
|
||||||
from .queue import Queue
|
from .queue import Queue
|
||||||
from .shared import Uuid, OcfCompletion, OcfError, SeqCutOffPolicy
|
from .shared import Uuid, OcfCompletion, OcfError, SeqCutOffPolicy
|
||||||
from .stats.core import CoreStats
|
from .stats.core import CoreInfo
|
||||||
from .stats.shared import UsageStats, RequestsStats, BlocksStats, ErrorsStats
|
from .stats.shared import UsageStats, RequestsStats, BlocksStats, ErrorsStats
|
||||||
from .volume import Volume
|
from .volume import Volume
|
||||||
from ..ocf import OcfLib
|
from ..ocf import OcfLib
|
||||||
@ -111,7 +111,7 @@ class Core:
|
|||||||
return Io.from_pointer(io)
|
return Io.from_pointer(io)
|
||||||
|
|
||||||
def get_stats(self):
|
def get_stats(self):
|
||||||
core_stats = CoreStats()
|
core_info = CoreInfo()
|
||||||
usage = UsageStats()
|
usage = UsageStats()
|
||||||
req = RequestsStats()
|
req = RequestsStats()
|
||||||
blocks = BlocksStats()
|
blocks = BlocksStats()
|
||||||
@ -125,8 +125,8 @@ class Core:
|
|||||||
self.cache.read_unlock()
|
self.cache.read_unlock()
|
||||||
raise OcfError("Failed collecting core stats", status)
|
raise OcfError("Failed collecting core stats", status)
|
||||||
|
|
||||||
status = self.cache.owner.lib.ocf_core_get_stats(
|
status = self.cache.owner.lib.ocf_core_get_info(
|
||||||
self.handle, byref(core_stats)
|
self.handle, byref(core_info)
|
||||||
)
|
)
|
||||||
if status:
|
if status:
|
||||||
self.cache.read_unlock()
|
self.cache.read_unlock()
|
||||||
@ -134,10 +134,10 @@ class Core:
|
|||||||
|
|
||||||
self.cache.read_unlock()
|
self.cache.read_unlock()
|
||||||
return {
|
return {
|
||||||
"size": Size(core_stats.core_size_bytes),
|
"size": Size(core_info.core_size_bytes),
|
||||||
"dirty_for": timedelta(seconds=core_stats.dirty_for),
|
"dirty_for": timedelta(seconds=core_info.dirty_for),
|
||||||
"seq_cutoff_policy": SeqCutOffPolicy(core_stats.seq_cutoff_policy),
|
"seq_cutoff_policy": SeqCutOffPolicy(core_info.seq_cutoff_policy),
|
||||||
"seq_cutoff_threshold": core_stats.seq_cutoff_threshold,
|
"seq_cutoff_threshold": core_info.seq_cutoff_threshold,
|
||||||
"usage": struct_to_dict(usage),
|
"usage": struct_to_dict(usage),
|
||||||
"req": struct_to_dict(req),
|
"req": struct_to_dict(req),
|
||||||
"blocks": struct_to_dict(blocks),
|
"blocks": struct_to_dict(blocks),
|
||||||
@ -207,8 +207,8 @@ lib.ocf_mngt_core_set_seq_cutoff_policy.argtypes = [c_void_p, c_uint32]
|
|||||||
lib.ocf_mngt_core_set_seq_cutoff_policy.restype = c_int
|
lib.ocf_mngt_core_set_seq_cutoff_policy.restype = c_int
|
||||||
lib.ocf_stats_collect_core.argtypes = [c_void_p, c_void_p, c_void_p, c_void_p, c_void_p]
|
lib.ocf_stats_collect_core.argtypes = [c_void_p, c_void_p, c_void_p, c_void_p, c_void_p]
|
||||||
lib.ocf_stats_collect_core.restype = c_int
|
lib.ocf_stats_collect_core.restype = c_int
|
||||||
lib.ocf_core_get_stats.argtypes = [c_void_p, c_void_p]
|
lib.ocf_core_get_info.argtypes = [c_void_p, c_void_p]
|
||||||
lib.ocf_core_get_stats.restype = c_int
|
lib.ocf_core_get_info.restype = c_int
|
||||||
lib.ocf_core_new_io_wrapper.argtypes = [
|
lib.ocf_core_new_io_wrapper.argtypes = [
|
||||||
c_void_p,
|
c_void_p,
|
||||||
c_void_p,
|
c_void_p,
|
||||||
|
@ -9,22 +9,13 @@ from ctypes import c_uint32, c_uint64, Structure
|
|||||||
from .shared import OcfStatsReq, OcfStatsBlock, OcfStatsDebug, OcfStatsError
|
from .shared import OcfStatsReq, OcfStatsBlock, OcfStatsDebug, OcfStatsError
|
||||||
|
|
||||||
|
|
||||||
class CoreStats(Structure):
|
class CoreInfo(Structure):
|
||||||
_fields_ = [
|
_fields_ = [
|
||||||
("core_size", c_uint64),
|
("core_size", c_uint64),
|
||||||
("core_size_bytes", c_uint64),
|
("core_size_bytes", c_uint64),
|
||||||
("cache_occupancy", c_uint32),
|
|
||||||
("dirty", c_uint32),
|
("dirty", c_uint32),
|
||||||
("flushed", c_uint32),
|
("flushed", c_uint32),
|
||||||
("dirty_for", c_uint32),
|
("dirty_for", c_uint32),
|
||||||
("read_reqs", OcfStatsReq),
|
|
||||||
("write_reqs", OcfStatsReq),
|
|
||||||
("cache_volume", OcfStatsBlock),
|
|
||||||
("core_volume", OcfStatsBlock),
|
|
||||||
("core", OcfStatsBlock),
|
|
||||||
("cache_errors", OcfStatsError),
|
|
||||||
("core_errors", OcfStatsError),
|
|
||||||
("debug_stat", OcfStatsDebug),
|
|
||||||
("seq_cutoff_threshold", c_uint32),
|
("seq_cutoff_threshold", c_uint32),
|
||||||
("seq_cutoff_policy", c_uint32),
|
("seq_cutoff_policy", c_uint32),
|
||||||
]
|
]
|
||||||
|
Loading…
Reference in New Issue
Block a user