2 * Copyright(c) 2012-2018 Intel Corporation
3 * SPDX-License-Identifier: BSD-3-Clause-Clear
7 #include "metadata_hash.h"
8 #include "metadata_raw.h"
9 #include "metadata_raw_dynamic.h"
10 #include "metadata_io.h"
11 #include "../engine/cache_engine.h"
12 #include "../engine/engine_common.h"
13 #include "../utils/utils_io.h"
14 #include "../utils/utils_req.h"
15 #include "../ocf_def_priv.h"
17 #define OCF_METADATA_RAW_DEBUG 0
19 #if 1 == OCF_METADATA_RAW_DEBUG
20 #define OCF_DEBUG_TRACE(cache) \
21 ocf_cache_log(cache, log_info, "[Metadata][Volatile] %s\n", __func__)
23 #define OCF_DEBUG_PARAM(cache, format, ...) \
24 ocf_cache_log(cache, log_info, "[Metadata][Volatile] %s - "format"\n", \
25 __func__, ##__VA_ARGS__)
27 #define OCF_DEBUG_TRACE(cache)
28 #define OCF_DEBUG_PARAM(cache, format, ...)
31 /*******************************************************************************
32 * Common RAW Implementation
33 ******************************************************************************/
36 * Check if page is valid for specified RAW descriptor
38 static bool _raw_ssd_page_is_valid(struct ocf_metadata_raw
*raw
, uint32_t page
)
40 ENV_BUG_ON(page
< raw
->ssd_pages_offset
);
41 ENV_BUG_ON(page
>= (raw
->ssd_pages_offset
+ raw
->ssd_pages
));
46 /*******************************************************************************
47 * RAW dynamic Implementation
48 ******************************************************************************/
50 #define _RAW_DYNAMIC_PAGE(raw, line) \
51 ((line) / raw->entries_in_page)
53 #define _RAW_DYNAMIC_PAGE_OFFSET(raw, line) \
54 ((line % raw->entries_in_page) * raw->entry_size)
57 * RAW DYNAMIC control structure
65 static void *_raw_dynamic_get_item(ocf_cache_t cache
,
66 struct ocf_metadata_raw
*raw
, ocf_cache_line_t line
, uint32_t size
)
69 struct _raw_ctrl
*ctrl
= (struct _raw_ctrl
*)raw
->priv
;
70 uint32_t page
= _RAW_DYNAMIC_PAGE(raw
, line
);
72 ENV_BUG_ON(!_raw_is_valid(raw
, line
, size
));
74 OCF_DEBUG_PARAM(cache
, "Accessing item %u on page %u", line
, page
);
76 if (!ctrl
->pages
[page
]) {
77 /* No page, allocate one, and set*/
79 /* This RAW container has some restrictions and need to check
81 * 1. no atomic context when allocation
82 * 2. Only one allocator in time
85 ENV_BUG_ON(env_in_interrupt());
87 env_mutex_lock(&ctrl
->lock
);
89 if (ctrl
->pages
[page
]) {
90 /* Page has been already allocated, skip allocation */
91 goto _raw_dynamic_get_item_SKIP
;
94 OCF_DEBUG_PARAM(cache
, "New page allocation - %u", page
);
96 new = env_secure_alloc(PAGE_SIZE
);
98 ENV_BUG_ON(env_memset(new, PAGE_SIZE
, 0));
99 ctrl
->pages
[page
] = new;
100 env_atomic_inc(&ctrl
->count
);
103 _raw_dynamic_get_item_SKIP
:
105 env_mutex_unlock(&ctrl
->lock
);
108 if (ctrl
->pages
[page
])
109 return ctrl
->pages
[page
] + _RAW_DYNAMIC_PAGE_OFFSET(raw
, line
);
115 * RAM DYNAMIC Implementation - De-Initialize
117 int raw_dynamic_deinit(ocf_cache_t cache
,
118 struct ocf_metadata_raw
*raw
)
121 struct _raw_ctrl
*ctrl
= (struct _raw_ctrl
*)raw
->priv
;
126 OCF_DEBUG_TRACE(cache
);
128 for (i
= 0; i
< raw
->ssd_pages
; i
++)
129 env_secure_free(ctrl
->pages
[i
], PAGE_SIZE
);
138 * RAM DYNAMIC Implementation - Initialize
140 int raw_dynamic_init(ocf_cache_t cache
,
141 struct ocf_metadata_raw
*raw
)
143 struct _raw_ctrl
*ctrl
;
144 size_t size
= sizeof(*ctrl
) + (sizeof(ctrl
->pages
[0]) * raw
->ssd_pages
);
146 OCF_DEBUG_TRACE(cache
);
148 if (raw
->entry_size
> PAGE_SIZE
)
151 ctrl
= env_vmalloc(size
);
155 ENV_BUG_ON(env_memset(ctrl
, size
, 0));
157 if (env_mutex_init(&ctrl
->lock
)) {
168 * RAW DYNAMIC Implementation - Size of
170 size_t raw_dynamic_size_of(ocf_cache_t cache
,
171 struct ocf_metadata_raw
*raw
)
173 struct _raw_ctrl
*ctrl
= (struct _raw_ctrl
*)raw
->priv
;
176 /* Size of allocated items */
177 size
= env_atomic_read(&ctrl
->count
);
180 /* Size of control structure */
181 size
+= sizeof(*ctrl
) + (sizeof(ctrl
->pages
[0]) * raw
->ssd_pages
);
183 OCF_DEBUG_PARAM(cache
, "Count = %d, Size = %lu",
184 env_atomic_read(&ctrl
->count
), size
);
190 * RAW DYNAMIC Implementation - Size on SSD
192 uint32_t raw_dynamic_size_on_ssd(struct ocf_metadata_raw
*raw
)
194 const size_t alignment
= 128 * KiB
/ PAGE_SIZE
;
196 return OCF_DIV_ROUND_UP(raw
->ssd_pages
, alignment
) * alignment
;
200 * RAM DYNAMIC Implementation - Checksum
202 uint32_t raw_dynamic_checksum(ocf_cache_t cache
,
203 struct ocf_metadata_raw
*raw
)
205 struct _raw_ctrl
*ctrl
= (struct _raw_ctrl
*)raw
->priv
;
210 for (i
= 0; i
< raw
->ssd_pages
; i
++) {
212 crc
= env_crc32(crc
, ctrl
->pages
[i
], PAGE_SIZE
);
213 OCF_COND_RESCHED(step
, 10000);
220 * RAM DYNAMIC Implementation - Get
222 int raw_dynamic_get(ocf_cache_t cache
,
223 struct ocf_metadata_raw
*raw
, ocf_cache_line_t line
,
224 void *data
, uint32_t size
)
226 void *item
= _raw_dynamic_get_item(cache
, raw
, line
, size
);
229 ENV_BUG_ON(env_memset(data
, size
, 0));
230 ocf_metadata_error(cache
);
234 return env_memcpy(data
, size
, item
, size
);
238 * RAM DYNAMIC Implementation - Set
240 int raw_dynamic_set(ocf_cache_t cache
,
241 struct ocf_metadata_raw
*raw
, ocf_cache_line_t line
,
242 void *data
, uint32_t size
)
244 void *item
= _raw_dynamic_get_item(cache
, raw
, line
, size
);
247 ocf_metadata_error(cache
);
251 return env_memcpy(item
, size
, data
, size
);
255 * RAM DYNAMIC Implementation - access
257 const void *raw_dynamic_rd_access(ocf_cache_t cache
,
258 struct ocf_metadata_raw
*raw
, ocf_cache_line_t line
,
261 return _raw_dynamic_get_item(cache
, raw
, line
, size
);
265 * RAM DYNAMIC Implementation - access
267 void *raw_dynamic_wr_access(ocf_cache_t cache
,
268 struct ocf_metadata_raw
*raw
, ocf_cache_line_t line
,
271 return _raw_dynamic_get_item(cache
, raw
, line
, size
);
275 * RAM DYNAMIC Implementation - Load all
277 #define RAW_DYNAMIC_LOAD_PAGES 128
279 struct raw_dynamic_load_all_context
{
280 struct ocf_metadata_raw
*raw
;
281 struct ocf_request
*req
;
290 ocf_metadata_end_t cmpl
;
294 static void raw_dynamic_load_all_complete(
295 struct raw_dynamic_load_all_context
*context
, int error
)
297 context
->cmpl(context
->priv
, error
);
299 ocf_req_put(context
->req
);
300 env_secure_free(context
->page
, PAGE_SIZE
);
301 env_free(context
->zpage
);
302 ctx_data_free(context
->cache
->owner
, context
->data
);
306 static int raw_dynamic_load_all_update(struct ocf_request
*req
);
308 static const struct ocf_io_if _io_if_raw_dynamic_load_all_update
= {
309 .read
= raw_dynamic_load_all_update
,
310 .write
= raw_dynamic_load_all_update
,
313 static void raw_dynamic_load_all_read_end(struct ocf_io
*io
, int error
)
315 struct raw_dynamic_load_all_context
*context
= io
->priv1
;
320 raw_dynamic_load_all_complete(context
, error
);
324 context
->req
->io_if
= &_io_if_raw_dynamic_load_all_update
;
325 ocf_engine_push_req_front(context
->req
, true);
328 static int raw_dynamic_load_all_read(struct ocf_request
*req
)
330 struct raw_dynamic_load_all_context
*context
= req
->priv
;
331 struct ocf_metadata_raw
*raw
= context
->raw
;
335 count
= OCF_MIN(RAW_DYNAMIC_LOAD_PAGES
, raw
->ssd_pages
- context
->i
);
338 context
->io
= ocf_new_cache_io(context
->cache
);
340 raw_dynamic_load_all_complete(context
, -OCF_ERR_NO_MEM
);
345 result
= ocf_io_set_data(context
->io
, context
->data
, 0);
347 ocf_io_put(context
->io
);
348 raw_dynamic_load_all_complete(context
, result
);
351 ocf_io_configure(context
->io
,
352 PAGES_TO_BYTES(raw
->ssd_pages_offset
+ context
->i
),
353 PAGES_TO_BYTES(count
), OCF_READ
, 0, 0);
355 ocf_io_set_queue(context
->io
, req
->io_queue
);
356 ocf_io_set_cmpl(context
->io
, context
, NULL
,
357 raw_dynamic_load_all_read_end
);
360 ocf_volume_submit_io(context
->io
);
365 static const struct ocf_io_if _io_if_raw_dynamic_load_all_read
= {
366 .read
= raw_dynamic_load_all_read
,
367 .write
= raw_dynamic_load_all_read
,
370 static int raw_dynamic_load_all_update(struct ocf_request
*req
)
372 struct raw_dynamic_load_all_context
*context
= req
->priv
;
373 struct ocf_metadata_raw
*raw
= context
->raw
;
374 struct _raw_ctrl
*ctrl
= (struct _raw_ctrl
*)raw
->priv
;
375 ocf_cache_t cache
= context
->cache
;
376 uint64_t count
= BYTES_TO_PAGES(context
->io
->bytes
);
381 /* Reset head of data buffer */
382 ctx_data_seek_check(context
->cache
->owner
, context
->data
,
383 ctx_data_seek_begin
, 0);
385 for (i_page
= 0; i_page
< count
; i_page
++, context
->i
++) {
386 if (!context
->page
) {
387 context
->page
= env_secure_alloc(PAGE_SIZE
);
388 if (!context
->page
) {
389 /* Allocation error */
390 result
= -OCF_ERR_NO_MEM
;
395 ctx_data_rd_check(cache
->owner
, context
->page
,
396 context
->data
, PAGE_SIZE
);
398 result
= env_memcmp(context
->zpage
, PAGE_SIZE
, context
->page
,
403 /* When page is zero set, no need to allocate space for it */
405 OCF_DEBUG_PARAM(cache
, "Zero loaded %llu", i
);
409 OCF_DEBUG_PARAM(cache
, "Non-zero loaded %llu", i
);
411 ctrl
->pages
[context
->i
] = context
->page
;
412 context
->page
= NULL
;
414 env_atomic_inc(&ctrl
->count
);
417 if (result
|| context
->i
>= raw
->ssd_pages
) {
418 raw_dynamic_load_all_complete(context
, result
);
422 context
->req
->io_if
= &_io_if_raw_dynamic_load_all_read
;
423 ocf_engine_push_req_front(context
->req
, true);
428 void raw_dynamic_load_all(ocf_cache_t cache
, struct ocf_metadata_raw
*raw
,
429 ocf_metadata_end_t cmpl
, void *priv
)
431 struct raw_dynamic_load_all_context
*context
;
434 OCF_DEBUG_TRACE(cache
);
436 context
= env_vzalloc(sizeof(*context
));
438 cmpl(priv
, -OCF_ERR_NO_MEM
);
443 context
->cache
= cache
;
444 context
->cmpl
= cmpl
;
445 context
->priv
= priv
;
447 context
->data
= ctx_data_alloc(cache
->owner
, RAW_DYNAMIC_LOAD_PAGES
);
448 if (!context
->data
) {
449 result
= -OCF_ERR_NO_MEM
;
453 context
->zpage
= env_zalloc(PAGE_SIZE
, ENV_MEM_NORMAL
);
454 if (!context
->zpage
) {
455 result
= -OCF_ERR_NO_MEM
;
459 context
->req
= ocf_req_new(cache
->mngt_queue
, NULL
, 0, 0, 0);
461 result
= -OCF_ERR_NO_MEM
;
465 context
->req
->info
.internal
= true;
466 context
->req
->priv
= context
;
467 context
->req
->io_if
= &_io_if_raw_dynamic_load_all_read
;
469 ocf_engine_push_req_front(context
->req
, true);
473 env_free(context
->zpage
);
475 ctx_data_free(cache
->owner
, context
->data
);
482 * RAM DYNAMIC Implementation - Flush all
485 struct raw_dynamic_flush_all_context
{
486 struct ocf_metadata_raw
*raw
;
487 ocf_metadata_end_t cmpl
;
492 * RAM Implementation - Flush IO callback - Fill page
494 static int raw_dynamic_flush_all_fill(ocf_cache_t cache
,
495 ctx_data_t
*data
, uint32_t page
, void *priv
)
497 struct raw_dynamic_flush_all_context
*context
= priv
;
498 struct ocf_metadata_raw
*raw
= context
->raw
;
499 struct _raw_ctrl
*ctrl
= (struct _raw_ctrl
*)raw
->priv
;
502 ENV_BUG_ON(!_raw_ssd_page_is_valid(raw
, page
));
504 raw_page
= page
- raw
->ssd_pages_offset
;
506 if (ctrl
->pages
[raw_page
]) {
507 OCF_DEBUG_PARAM(cache
, "Page = %u", raw_page
);
508 ctx_data_wr_check(cache
->owner
, data
, ctrl
->pages
[raw_page
],
511 OCF_DEBUG_PARAM(cache
, "Zero fill, Page = %u", raw_page
);
512 /* Page was not allocated before set only zeros */
513 ctx_data_zero_check(cache
->owner
, data
, PAGE_SIZE
);
519 static void raw_dynamic_flush_all_complete(ocf_cache_t cache
,
520 void *priv
, int error
)
522 struct raw_dynamic_flush_all_context
*context
= priv
;
524 context
->cmpl(context
->priv
, error
);
528 void raw_dynamic_flush_all(ocf_cache_t cache
, struct ocf_metadata_raw
*raw
,
529 ocf_metadata_end_t cmpl
, void *priv
)
531 struct raw_dynamic_flush_all_context
*context
;
534 OCF_DEBUG_TRACE(cache
);
536 context
= env_vmalloc(sizeof(*context
));
538 cmpl(priv
, -OCF_ERR_NO_MEM
);
543 context
->cmpl
= cmpl
;
544 context
->priv
= priv
;
546 result
= metadata_io_write_i_asynch(cache
, cache
->mngt_queue
, context
,
547 raw
->ssd_pages_offset
, raw
->ssd_pages
,
548 raw_dynamic_flush_all_fill
,
549 raw_dynamic_flush_all_complete
);
555 * RAM DYNAMIC Implementation - Mark to Flush
557 void raw_dynamic_flush_mark(ocf_cache_t cache
, struct ocf_request
*req
,
558 uint32_t map_idx
, int to_state
, uint8_t start
, uint8_t stop
)
564 * RAM DYNAMIC Implementation - Do flushing asynchronously
566 int raw_dynamic_flush_do_asynch(ocf_cache_t cache
, struct ocf_request
*req
,
567 struct ocf_metadata_raw
*raw
, ocf_req_end_t complete
)