]> git.proxmox.com Git - ceph.git/blob - ceph/src/spdk/ocf/src/ocf_stats.c
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / spdk / ocf / src / ocf_stats.c
1 /*
2 * Copyright(c) 2012-2018 Intel Corporation
3 * SPDX-License-Identifier: BSD-3-Clause-Clear
4 */
5
6 #include "ocf/ocf.h"
7 #include "ocf_priv.h"
8 #include "metadata/metadata.h"
9 #include "engine/cache_engine.h"
10 #include "utils/utils_part.h"
11 #include "utils/utils_cache_line.h"
12
13 #ifdef OCF_DEBUG_STATS
14 static void ocf_stats_debug_init(struct ocf_counters_debug *stats)
15 {
16 int i;
17
18 for (i = 0; i < IO_PACKET_NO; i++) {
19 env_atomic64_set(&stats->read_size[i], 0);
20 env_atomic64_set(&stats->write_size[i], 0);
21 }
22
23 for (i = 0; i < IO_ALIGN_NO; i++) {
24 env_atomic64_set(&stats->read_align[i], 0);
25 env_atomic64_set(&stats->write_align[i], 0);
26 }
27 }
28 #endif
29
30 static void ocf_stats_req_init(struct ocf_counters_req *stats)
31 {
32 env_atomic64_set(&stats->full_miss, 0);
33 env_atomic64_set(&stats->partial_miss, 0);
34 env_atomic64_set(&stats->total, 0);
35 env_atomic64_set(&stats->pass_through, 0);
36 }
37
38 static void ocf_stats_block_init(struct ocf_counters_block *stats)
39 {
40 env_atomic64_set(&stats->read_bytes, 0);
41 env_atomic64_set(&stats->write_bytes, 0);
42 }
43
44 static void ocf_stats_part_init(struct ocf_counters_part *stats)
45 {
46 ocf_stats_req_init(&stats->read_reqs);
47 ocf_stats_req_init(&stats->write_reqs);
48
49 ocf_stats_block_init(&stats->blocks);
50 ocf_stats_block_init(&stats->core_blocks);
51 ocf_stats_block_init(&stats->cache_blocks);
52 }
53
54 static void ocf_stats_error_init(struct ocf_counters_error *stats)
55 {
56 env_atomic_set(&stats->read, 0);
57 env_atomic_set(&stats->write, 0);
58 }
59
60 static void _ocf_stats_block_update(struct ocf_counters_block *counters, int dir,
61 uint64_t bytes)
62 {
63 switch (dir) {
64 case OCF_READ:
65 env_atomic64_add(bytes, &counters->read_bytes);
66 break;
67 case OCF_WRITE:
68 env_atomic64_add(bytes, &counters->write_bytes);
69 break;
70 default:
71 ENV_BUG();
72 }
73 }
74
75 void ocf_core_stats_vol_block_update(ocf_core_t core, ocf_part_id_t part_id,
76 int dir, uint64_t bytes)
77 {
78 struct ocf_counters_block *counters =
79 &core->counters->part_counters[part_id].blocks;
80
81 _ocf_stats_block_update(counters, dir, bytes);
82 }
83
84 void ocf_core_stats_cache_block_update(ocf_core_t core, ocf_part_id_t part_id,
85 int dir, uint64_t bytes)
86 {
87 struct ocf_counters_block *counters =
88 &core->counters->part_counters[part_id].cache_blocks;
89
90 _ocf_stats_block_update(counters, dir, bytes);
91 }
92
93 void ocf_core_stats_core_block_update(ocf_core_t core, ocf_part_id_t part_id,
94 int dir, uint64_t bytes)
95 {
96 struct ocf_counters_block *counters =
97 &core->counters->part_counters[part_id].core_blocks;
98
99 _ocf_stats_block_update(counters, dir, bytes);
100 }
101
102 void ocf_core_stats_request_update(ocf_core_t core, ocf_part_id_t part_id,
103 uint8_t dir, uint64_t hit_no, uint64_t core_line_count)
104 {
105 struct ocf_counters_req *counters;
106
107 switch (dir) {
108 case OCF_READ:
109 counters = &core->counters->part_counters[part_id].read_reqs;
110 break;
111 case OCF_WRITE:
112 counters = &core->counters->part_counters[part_id].write_reqs;
113 break;
114 default:
115 ENV_BUG();
116 }
117
118 env_atomic64_inc(&counters->total);
119
120 if (hit_no == 0)
121 env_atomic64_inc(&counters->full_miss);
122 else if (hit_no < core_line_count)
123 env_atomic64_inc(&counters->partial_miss);
124 }
125
126 void ocf_core_stats_request_pt_update(ocf_core_t core, ocf_part_id_t part_id,
127 uint8_t dir, uint64_t hit_no, uint64_t core_line_count)
128 {
129 struct ocf_counters_req *counters;
130
131 switch (dir) {
132 case OCF_READ:
133 counters = &core->counters->part_counters[part_id].read_reqs;
134 break;
135 case OCF_WRITE:
136 counters = &core->counters->part_counters[part_id].write_reqs;
137 break;
138 default:
139 ENV_BUG();
140 }
141
142 env_atomic64_inc(&counters->pass_through);
143 }
144
145 static void _ocf_core_stats_error_update(struct ocf_counters_error *counters,
146 uint8_t dir)
147 {
148 switch (dir) {
149 case OCF_READ:
150 env_atomic_inc(&counters->read);
151 break;
152 case OCF_WRITE:
153 env_atomic_inc(&counters->write);
154 break;
155 default:
156 ENV_BUG();
157 }
158 }
159
160 void ocf_core_stats_core_error_update(ocf_core_t core, uint8_t dir)
161 {
162 struct ocf_counters_error *counters = &core->counters->core_errors;
163
164 _ocf_core_stats_error_update(counters, dir);
165 }
166
167 void ocf_core_stats_cache_error_update(ocf_core_t core, uint8_t dir)
168 {
169 struct ocf_counters_error *counters = &core->counters->cache_errors;
170
171 _ocf_core_stats_error_update(counters, dir);
172 }
173
174 /********************************************************************
175 * Function that resets stats, debug and breakdown counters.
176 * If reset is set the following stats won't be reset:
177 * - cache_occupancy
178 * - queue_length
179 * - debug_counters_read_reqs_issued_seq_hits
180 * - debug_counters_read_reqs_issued_not_seq_hits
181 * - debug_counters_read_reqs_issued_read_miss_schedule
182 * - debug_counters_write_reqs_thread
183 * - debug_counters_write_reqs_issued_only_hdd
184 * - debug_counters_write_reqs_issued_both_devs
185 *********************************************************************/
186 void ocf_core_stats_initialize(ocf_core_t core)
187 {
188 struct ocf_counters_core *exp_obj_stats;
189 int i;
190
191 OCF_CHECK_NULL(core);
192
193 exp_obj_stats = core->counters;
194
195 ocf_stats_error_init(&exp_obj_stats->cache_errors);
196 ocf_stats_error_init(&exp_obj_stats->core_errors);
197
198 for (i = 0; i != OCF_IO_CLASS_MAX; i++)
199 ocf_stats_part_init(&exp_obj_stats->part_counters[i]);
200
201 #ifdef OCF_DEBUG_STATS
202 ocf_stats_debug_init(&exp_obj_stats->debug_stats);
203 #endif
204 }
205
206 void ocf_core_stats_initialize_all(ocf_cache_t cache)
207 {
208 ocf_core_id_t id;
209
210 for (id = 0; id < OCF_CORE_MAX; id++) {
211 if (!env_bit_test(id, cache->conf_meta->valid_core_bitmap))
212 continue;
213
214 ocf_core_stats_initialize(&cache->core[id]);
215 }
216 }
217
218 static void copy_req_stats(struct ocf_stats_req *dest,
219 const struct ocf_counters_req *from)
220 {
221 dest->partial_miss = env_atomic64_read(&from->partial_miss);
222 dest->full_miss = env_atomic64_read(&from->full_miss);
223 dest->total = env_atomic64_read(&from->total);
224 dest->pass_through = env_atomic64_read(&from->pass_through);
225 }
226
227 static void accum_req_stats(struct ocf_stats_req *dest,
228 const struct ocf_counters_req *from)
229 {
230 dest->partial_miss += env_atomic64_read(&from->partial_miss);
231 dest->full_miss += env_atomic64_read(&from->full_miss);
232 dest->total += env_atomic64_read(&from->total);
233 dest->pass_through += env_atomic64_read(&from->pass_through);
234 }
235
236 static void copy_block_stats(struct ocf_stats_block *dest,
237 const struct ocf_counters_block *from)
238 {
239 dest->read = env_atomic64_read(&from->read_bytes);
240 dest->write = env_atomic64_read(&from->write_bytes);
241 }
242
243 static void accum_block_stats(struct ocf_stats_block *dest,
244 const struct ocf_counters_block *from)
245 {
246 dest->read += env_atomic64_read(&from->read_bytes);
247 dest->write += env_atomic64_read(&from->write_bytes);
248 }
249
250 static void copy_error_stats(struct ocf_stats_error *dest,
251 const struct ocf_counters_error *from)
252 {
253 dest->read = env_atomic_read(&from->read);
254 dest->write = env_atomic_read(&from->write);
255 }
256
257 #ifdef OCF_DEBUG_STATS
258 static void copy_debug_stats(struct ocf_stats_core_debug *dest,
259 const struct ocf_counters_debug *from)
260 {
261 int i;
262
263 for (i = 0; i < IO_PACKET_NO; i++) {
264 dest->read_size[i] = env_atomic64_read(&from->read_size[i]);
265 dest->write_size[i] = env_atomic64_read(&from->write_size[i]);
266 }
267
268 for (i = 0; i < IO_ALIGN_NO; i++) {
269 dest->read_align[i] = env_atomic64_read(&from->read_align[i]);
270 dest->write_align[i] = env_atomic64_read(&from->write_align[i]);
271 }
272 }
273 #endif
274
275 int ocf_core_io_class_get_stats(ocf_core_t core, ocf_part_id_t part_id,
276 struct ocf_stats_io_class *stats)
277 {
278 ocf_cache_t cache;
279 uint32_t cache_occupancy_total = 0;
280 struct ocf_counters_part *part_stat;
281 ocf_core_t i_core;
282 ocf_core_id_t i_core_id;
283
284 OCF_CHECK_NULL(core);
285 OCF_CHECK_NULL(stats);
286
287 if (part_id > OCF_IO_CLASS_ID_MAX)
288 return -OCF_ERR_INVAL;
289
290 cache = ocf_core_get_cache(core);
291
292 if (!ocf_part_is_valid(&cache->user_parts[part_id]))
293 return -OCF_ERR_IO_CLASS_NOT_EXIST;
294
295 for_each_core(cache, i_core, i_core_id) {
296 cache_occupancy_total += env_atomic_read(
297 &i_core->runtime_meta->cached_clines);
298 }
299
300 part_stat = &core->counters->part_counters[part_id];
301
302 stats->occupancy_clines = env_atomic_read(&core->runtime_meta->
303 part_counters[part_id].cached_clines);
304 stats->dirty_clines = env_atomic_read(&core->runtime_meta->
305 part_counters[part_id].dirty_clines);
306
307 stats->free_clines = cache->conf_meta->cachelines -
308 cache_occupancy_total;
309
310 copy_req_stats(&stats->read_reqs, &part_stat->read_reqs);
311 copy_req_stats(&stats->write_reqs, &part_stat->write_reqs);
312
313 copy_block_stats(&stats->blocks, &part_stat->blocks);
314 copy_block_stats(&stats->cache_blocks, &part_stat->cache_blocks);
315 copy_block_stats(&stats->core_blocks, &part_stat->core_blocks);
316
317 return 0;
318 }
319
320 int ocf_core_get_stats(ocf_core_t core, struct ocf_stats_core *stats)
321 {
322 uint32_t i;
323 struct ocf_counters_core *core_stats = NULL;
324 struct ocf_counters_part *curr = NULL;
325
326 OCF_CHECK_NULL(core);
327
328 if (!stats)
329 return -OCF_ERR_INVAL;
330
331 core_stats = core->counters;
332
333 ENV_BUG_ON(env_memset(stats, sizeof(*stats), 0));
334
335 copy_error_stats(&stats->core_errors,
336 &core_stats->core_errors);
337 copy_error_stats(&stats->cache_errors,
338 &core_stats->cache_errors);
339
340 #ifdef OCF_DEBUG_STATS
341 copy_debug_stats(&stats->debug_stat,
342 &core_stats->debug_stats);
343 #endif
344
345 for (i = 0; i != OCF_IO_CLASS_MAX; i++) {
346 curr = &core_stats->part_counters[i];
347
348 accum_req_stats(&stats->read_reqs,
349 &curr->read_reqs);
350 accum_req_stats(&stats->write_reqs,
351 &curr->write_reqs);
352
353 accum_block_stats(&stats->core, &curr->blocks);
354 accum_block_stats(&stats->core_volume, &curr->core_blocks);
355 accum_block_stats(&stats->cache_volume, &curr->cache_blocks);
356
357 stats->cache_occupancy += env_atomic_read(&core->runtime_meta->
358 part_counters[i].cached_clines);
359 stats->dirty += env_atomic_read(&core->runtime_meta->
360 part_counters[i].dirty_clines);
361 }
362
363 return 0;
364 }
365
366 #ifdef OCF_DEBUG_STATS
367
368 #define IO_ALIGNMENT_SIZE (IO_ALIGN_NO)
369 #define IO_PACKET_SIZE ((IO_PACKET_NO) - 1)
370
371 static uint32_t io_alignment[IO_ALIGNMENT_SIZE] = {
372 512, 1 * KiB, 2 * KiB, 4 * KiB
373 };
374
375 static int to_align_idx(uint64_t off)
376 {
377 int i;
378
379 for (i = IO_ALIGNMENT_SIZE - 1; i >= 0; i--) {
380 if (off % io_alignment[i] == 0)
381 return i;
382 }
383
384 return IO_ALIGNMENT_SIZE;
385 }
386
387 static uint32_t io_packet_size[IO_PACKET_SIZE] = {
388 512, 1 * KiB, 2 * KiB, 4 * KiB, 8 * KiB,
389 16 * KiB, 32 * KiB, 64 * KiB, 128 * KiB,
390 256 * KiB, 512 * KiB
391 };
392
393
394 static int to_packet_idx(uint32_t len)
395 {
396 int i = 0;
397
398 for (i = 0; i < IO_PACKET_SIZE; i++) {
399 if (len == io_packet_size[i])
400 return i;
401 }
402
403 return IO_PACKET_SIZE;
404 }
405
406 void ocf_core_update_stats(ocf_core_t core, struct ocf_io *io)
407 {
408 struct ocf_counters_debug *stats;
409 int idx;
410
411 OCF_CHECK_NULL(core);
412 OCF_CHECK_NULL(io);
413
414 core_id = ocf_core_get_id(core);
415 cache = ocf_core_get_cache(core);
416
417 stats = &core->counters->debug_stats;
418
419 idx = to_packet_idx(io->bytes);
420 if (io->dir == OCF_WRITE)
421 env_atomic64_inc(&stats->write_size[idx]);
422 else
423 env_atomic64_inc(&stats->read_size[idx]);
424
425 idx = to_align_idx(io->addr);
426 if (io->dir == OCF_WRITE)
427 env_atomic64_inc(&stats->write_align[idx]);
428 else
429 env_atomic64_inc(&stats->read_align[idx]);
430 }
431
432 #else
433
434 void ocf_core_update_stats(ocf_core_t core, struct ocf_io *io) {}
435
436 #endif