99 lines
2.6 KiB
C
99 lines
2.6 KiB
C
/*
|
|
* Copyright(c) 2012-2022 Intel Corporation
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
#include "ocf/ocf.h"
|
|
#include "../ocf_cache_priv.h"
|
|
#include "../ocf_ctx_priv.h"
|
|
#include "engine_bf.h"
|
|
#include "engine_inv.h"
|
|
#include "engine_common.h"
|
|
#include "cache_engine.h"
|
|
#include "../ocf_request.h"
|
|
#include "../utils/utils_io.h"
|
|
#include "../concurrency/ocf_concurrency.h"
|
|
|
|
#define OCF_ENGINE_DEBUG_IO_NAME "bf"
|
|
#include "engine_debug.h"
|
|
|
|
/* Decrements and checks if queue may be unblocked again */
|
|
static inline void backfill_queue_dec_unblock(struct ocf_cache *cache)
|
|
{
|
|
env_atomic_dec(&cache->pending_read_misses_list_count);
|
|
|
|
if (!env_atomic_read(&cache->pending_read_misses_list_blocked))
|
|
return;
|
|
|
|
if (env_atomic_read(&cache->pending_read_misses_list_count)
|
|
< cache->backfill.queue_unblock_size)
|
|
env_atomic_set(&cache->pending_read_misses_list_blocked, 0);
|
|
}
|
|
|
|
static inline void backfill_queue_inc_block(struct ocf_cache *cache)
|
|
{
|
|
if (env_atomic_inc_return(&cache->pending_read_misses_list_count)
|
|
>= cache->backfill.max_queue_size)
|
|
env_atomic_set(&cache->pending_read_misses_list_blocked, 1);
|
|
}
|
|
|
|
static void _ocf_backfill_complete(struct ocf_request *req, int error)
|
|
{
|
|
struct ocf_cache *cache = req->cache;
|
|
|
|
if (error) {
|
|
req->error = error;
|
|
ocf_core_stats_cache_error_update(req->core, OCF_WRITE);
|
|
}
|
|
|
|
if (req->error)
|
|
inc_fallback_pt_error_counter(req->cache);
|
|
|
|
/* Handle callback-caller race to let only one of the two complete the
|
|
* request. Also, complete original request only if this is the last
|
|
* sub-request to complete
|
|
*/
|
|
if (env_atomic_dec_return(&req->req_remaining))
|
|
return;
|
|
|
|
backfill_queue_dec_unblock(req->cache);
|
|
|
|
/* We must free the pages we have allocated */
|
|
ctx_data_secure_erase(cache->owner, req->data);
|
|
ctx_data_munlock(cache->owner, req->data);
|
|
ctx_data_free(cache->owner, req->data);
|
|
req->data = NULL;
|
|
|
|
if (req->error) {
|
|
ocf_engine_invalidate(req);
|
|
} else {
|
|
ocf_req_unlock(ocf_cache_line_concurrency(cache), req);
|
|
|
|
/* put the request at the last point of the completion path */
|
|
ocf_req_put(req);
|
|
}
|
|
}
|
|
|
|
static int _ocf_backfill_do(struct ocf_request *req)
|
|
{
|
|
unsigned int reqs_to_issue;
|
|
|
|
reqs_to_issue = ocf_engine_io_count(req);
|
|
|
|
/* There will be #reqs_to_issue completions */
|
|
env_atomic_set(&req->req_remaining, reqs_to_issue);
|
|
|
|
req->data = req->cp_data;
|
|
|
|
ocf_submit_cache_reqs(req->cache, req, OCF_WRITE, 0, req->byte_length,
|
|
reqs_to_issue, _ocf_backfill_complete);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void ocf_engine_backfill(struct ocf_request *req)
|
|
{
|
|
backfill_queue_inc_block(req->cache);
|
|
ocf_engine_push_req_front_cb(req, _ocf_backfill_do, true);
|
|
}
|