Merge pull request #351 from micrakow/seq_cutoff_pt_fix
Fix seq_cutoff respecting in pt read
This commit is contained in:
commit
ed91895f70
@ -153,14 +153,6 @@ static inline struct ocf_io *ocf_core_new_io(ocf_core_t core, ocf_queue_t queue,
|
|||||||
io_class, flags);
|
io_class, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Submit ocf_io
|
|
||||||
*
|
|
||||||
* @param[in] io IO to be submitted
|
|
||||||
* @param[in] mode Cache mode to be enforced
|
|
||||||
*/
|
|
||||||
void ocf_core_submit_io_mode(struct ocf_io *io, ocf_cache_mode_t cache_mode);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Submit ocf_io
|
* @brief Submit ocf_io
|
||||||
*
|
*
|
||||||
@ -178,7 +170,7 @@ static inline void ocf_core_submit_io(struct ocf_io *io)
|
|||||||
* @param[in] io IO to be submitted
|
* @param[in] io IO to be submitted
|
||||||
*
|
*
|
||||||
* @retval 0 IO has been submitted successfully
|
* @retval 0 IO has been submitted successfully
|
||||||
* @retval Non-zero Fast submit failed. Try to submit IO with ocf_submit_io()
|
* @retval Non-zero Fast submit failed. Try to submit IO with ocf_core_submit_io()
|
||||||
*/
|
*/
|
||||||
int ocf_core_submit_io_fast(struct ocf_io *io);
|
int ocf_core_submit_io_fast(struct ocf_io *io);
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@ static const struct ocf_io_if IO_IFS[OCF_IO_PRIV_MAX_IF] = {
|
|||||||
.write = ocf_discard,
|
.write = ocf_discard,
|
||||||
.name = "Discard",
|
.name = "Discard",
|
||||||
},
|
},
|
||||||
[OCF_IO_D2C_IF] = {
|
[OCF_IO_D2C_IF] = {
|
||||||
.read = ocf_io_d2c,
|
.read = ocf_io_d2c,
|
||||||
.write = ocf_io_d2c,
|
.write = ocf_io_d2c,
|
||||||
.name = "Direct to core",
|
.name = "Direct to core",
|
||||||
@ -223,36 +223,51 @@ void ocf_seq_cutoff_update(ocf_core_t core, struct ocf_request *req)
|
|||||||
core->seq_cutoff.bytes += req->byte_length;
|
core->seq_cutoff.bytes += req->byte_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
ocf_cache_mode_t ocf_get_effective_cache_mode(ocf_cache_t cache,
|
void ocf_resolve_effective_cache_mode(ocf_cache_t cache,
|
||||||
ocf_core_t core, struct ocf_io *io)
|
ocf_core_t core, struct ocf_request *req)
|
||||||
{
|
{
|
||||||
ocf_cache_mode_t mode;
|
if (req->d2c) {
|
||||||
|
req->cache_mode = ocf_req_cache_mode_d2c;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (cache->pt_unaligned_io && !ocf_req_is_4k(io->addr, io->bytes))
|
if (ocf_fallback_pt_is_on(cache)){
|
||||||
return ocf_cache_mode_pt;
|
req->cache_mode = ocf_req_cache_mode_pt;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
mode = ocf_part_get_cache_mode(cache,
|
if (cache->pt_unaligned_io && !ocf_req_is_4k(req->byte_position,
|
||||||
ocf_part_class2id(cache, io->io_class));
|
req->byte_length)) {
|
||||||
if (!ocf_cache_mode_is_valid(mode))
|
req->cache_mode = ocf_req_cache_mode_pt;
|
||||||
mode = cache->conf_meta->cache_mode;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (ocf_seq_cutoff_check(core, io->dir, io->addr, io->bytes))
|
if (ocf_seq_cutoff_check(core, req->rw, req->byte_position,
|
||||||
mode = ocf_cache_mode_pt;
|
req->byte_length)) {
|
||||||
|
req->cache_mode = ocf_req_cache_mode_pt;
|
||||||
|
req->seq_cutoff = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (ocf_fallback_pt_is_on(cache))
|
req->cache_mode = ocf_part_get_cache_mode(cache,
|
||||||
mode = ocf_cache_mode_pt;
|
ocf_part_class2id(cache, req->part_id));
|
||||||
|
if (!ocf_cache_mode_is_valid(req->cache_mode))
|
||||||
|
req->cache_mode = cache->conf_meta->cache_mode;
|
||||||
|
|
||||||
return mode;
|
if (req->rw == OCF_WRITE &&
|
||||||
|
ocf_req_cache_mode_has_lazy_write(req->cache_mode) &&
|
||||||
|
ocf_req_set_dirty(req)) {
|
||||||
|
req->cache_mode = ocf_req_cache_mode_wt;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int ocf_engine_hndl_req(struct ocf_request *req,
|
int ocf_engine_hndl_req(struct ocf_request *req)
|
||||||
ocf_req_cache_mode_t req_cache_mode)
|
|
||||||
{
|
{
|
||||||
ocf_cache_t cache = req->cache;
|
ocf_cache_t cache = req->cache;
|
||||||
|
|
||||||
OCF_CHECK_NULL(cache);
|
OCF_CHECK_NULL(cache);
|
||||||
|
|
||||||
req->io_if = ocf_get_io_if(req_cache_mode);
|
req->io_if = ocf_get_io_if(req->cache_mode);
|
||||||
if (!req->io_if)
|
if (!req->io_if)
|
||||||
return -OCF_ERR_INVAL;
|
return -OCF_ERR_INVAL;
|
||||||
|
|
||||||
@ -267,13 +282,12 @@ int ocf_engine_hndl_req(struct ocf_request *req,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ocf_engine_hndl_fast_req(struct ocf_request *req,
|
int ocf_engine_hndl_fast_req(struct ocf_request *req)
|
||||||
ocf_req_cache_mode_t req_cache_mode)
|
|
||||||
{
|
{
|
||||||
const struct ocf_io_if *io_if;
|
const struct ocf_io_if *io_if;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
io_if = ocf_get_io_if(req_cache_mode);
|
io_if = ocf_get_io_if(req->cache_mode);
|
||||||
if (!io_if)
|
if (!io_if)
|
||||||
return -OCF_ERR_INVAL;
|
return -OCF_ERR_INVAL;
|
||||||
|
|
||||||
|
@ -40,8 +40,8 @@ struct ocf_io_if {
|
|||||||
const char *name;
|
const char *name;
|
||||||
};
|
};
|
||||||
|
|
||||||
ocf_cache_mode_t ocf_get_effective_cache_mode(ocf_cache_t cache,
|
void ocf_resolve_effective_cache_mode(ocf_cache_t cache,
|
||||||
ocf_core_t core, struct ocf_io *io);
|
ocf_core_t core, struct ocf_request *req);
|
||||||
|
|
||||||
const struct ocf_io_if *ocf_get_io_if(ocf_req_cache_mode_t cache_mode);
|
const struct ocf_io_if *ocf_get_io_if(ocf_req_cache_mode_t cache_mode);
|
||||||
|
|
||||||
@ -74,14 +74,12 @@ bool ocf_seq_cutoff_check(ocf_core_t core, uint32_t dir, uint64_t addr,
|
|||||||
struct ocf_request *ocf_engine_pop_req(struct ocf_cache *cache,
|
struct ocf_request *ocf_engine_pop_req(struct ocf_cache *cache,
|
||||||
struct ocf_queue *q);
|
struct ocf_queue *q);
|
||||||
|
|
||||||
int ocf_engine_hndl_req(struct ocf_request *req,
|
int ocf_engine_hndl_req(struct ocf_request *req);
|
||||||
ocf_req_cache_mode_t req_cache_mode);
|
|
||||||
|
|
||||||
#define OCF_FAST_PATH_YES 7
|
#define OCF_FAST_PATH_YES 7
|
||||||
#define OCF_FAST_PATH_NO 13
|
#define OCF_FAST_PATH_NO 13
|
||||||
|
|
||||||
int ocf_engine_hndl_fast_req(struct ocf_request *req,
|
int ocf_engine_hndl_fast_req(struct ocf_request *req);
|
||||||
ocf_req_cache_mode_t req_cache_mode);
|
|
||||||
|
|
||||||
void ocf_engine_hndl_discard_req(struct ocf_request *req);
|
void ocf_engine_hndl_discard_req(struct ocf_request *req);
|
||||||
|
|
||||||
|
@ -405,7 +405,7 @@ static void _ocf_engine_clean_end(void *private_data, int error)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ocf_engine_evict(struct ocf_request *req)
|
static int ocf_engine_evict(struct ocf_request *req)
|
||||||
{
|
{
|
||||||
if (!ocf_engine_unmapped_count(req))
|
if (!ocf_engine_unmapped_count(req))
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -120,7 +120,7 @@ int ocf_read_pt(struct ocf_request *req)
|
|||||||
/* Traverse request to check if there are mapped cache lines */
|
/* Traverse request to check if there are mapped cache lines */
|
||||||
ocf_engine_traverse(req);
|
ocf_engine_traverse(req);
|
||||||
|
|
||||||
if (req->info.seq_cutoff && ocf_engine_is_dirty_all(req)) {
|
if (req->seq_cutoff && ocf_engine_is_dirty_all(req)) {
|
||||||
use_cache = true;
|
use_cache = true;
|
||||||
} else {
|
} else {
|
||||||
if (ocf_engine_mapped_count(req)) {
|
if (ocf_engine_mapped_count(req)) {
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
#include "ocf_io_priv.h"
|
#include "ocf_io_priv.h"
|
||||||
#include "metadata/metadata.h"
|
#include "metadata/metadata.h"
|
||||||
#include "engine/cache_engine.h"
|
#include "engine/cache_engine.h"
|
||||||
#include "ocf_request.h"
|
|
||||||
#include "utils/utils_part.h"
|
#include "utils/utils_part.h"
|
||||||
#include "ocf_request.h"
|
#include "ocf_request.h"
|
||||||
#include "ocf_trace_priv.h"
|
#include "ocf_trace_priv.h"
|
||||||
@ -165,12 +164,6 @@ static inline ocf_core_t ocf_volume_to_core(ocf_volume_t volume)
|
|||||||
return core_volume->core;
|
return core_volume->core;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int ocf_io_set_dirty(struct ocf_request *req)
|
|
||||||
{
|
|
||||||
req->dirty = !!ocf_refcnt_inc(&req->cache->refcnt.dirty);
|
|
||||||
return req->dirty ? 0 : -EBUSY;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void dec_counter_if_req_was_dirty(struct ocf_request *req)
|
static inline void dec_counter_if_req_was_dirty(struct ocf_request *req)
|
||||||
{
|
{
|
||||||
if (!req->dirty)
|
if (!req->dirty)
|
||||||
@ -223,10 +216,9 @@ static void ocf_req_complete(struct ocf_request *req, int error)
|
|||||||
ocf_io_put(&req->ioi.io);
|
ocf_io_put(&req->ioi.io);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ocf_core_submit_io_mode(struct ocf_io *io, ocf_cache_mode_t cache_mode)
|
void ocf_core_volume_submit_io(struct ocf_io *io)
|
||||||
{
|
{
|
||||||
struct ocf_request *req;
|
struct ocf_request *req;
|
||||||
ocf_req_cache_mode_t req_cache_mode;
|
|
||||||
ocf_core_t core;
|
ocf_core_t core;
|
||||||
ocf_cache_t cache;
|
ocf_cache_t cache;
|
||||||
int ret;
|
int ret;
|
||||||
@ -251,25 +243,11 @@ void ocf_core_submit_io_mode(struct ocf_io *io, ocf_cache_mode_t cache_mode)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: instead of casting ocf_cache_mode_t to ocf_req_cache_mode_t
|
req->part_id = ocf_part_class2id(cache, io->io_class);
|
||||||
we can resolve IO interface here and get rid of the latter. */
|
|
||||||
req_cache_mode = cache_mode;
|
|
||||||
|
|
||||||
if (cache_mode == ocf_cache_mode_none)
|
|
||||||
req_cache_mode = ocf_get_effective_cache_mode(cache, core, io);
|
|
||||||
|
|
||||||
if (io->dir == OCF_WRITE &&
|
|
||||||
ocf_req_cache_mode_has_lazy_write(req_cache_mode) &&
|
|
||||||
ocf_io_set_dirty(req)) {
|
|
||||||
req_cache_mode = ocf_req_cache_mode_wt;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (req->d2c)
|
|
||||||
req_cache_mode = ocf_req_cache_mode_d2c;
|
|
||||||
|
|
||||||
req->core = core;
|
req->core = core;
|
||||||
req->complete = ocf_req_complete;
|
req->complete = ocf_req_complete;
|
||||||
req->part_id = ocf_part_class2id(cache, io->io_class);
|
|
||||||
|
ocf_resolve_effective_cache_mode(cache, core, req);
|
||||||
|
|
||||||
ocf_seq_cutoff_update(core, req);
|
ocf_seq_cutoff_update(core, req);
|
||||||
|
|
||||||
@ -282,7 +260,7 @@ void ocf_core_submit_io_mode(struct ocf_io *io, ocf_cache_mode_t cache_mode)
|
|||||||
|
|
||||||
ocf_io_get(io);
|
ocf_io_get(io);
|
||||||
|
|
||||||
ret = ocf_engine_hndl_req(req, req_cache_mode);
|
ret = ocf_engine_hndl_req(req);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dec_counter_if_req_was_dirty(req);
|
dec_counter_if_req_was_dirty(req);
|
||||||
ocf_io_end(io, ret);
|
ocf_io_end(io, ret);
|
||||||
@ -292,7 +270,6 @@ void ocf_core_submit_io_mode(struct ocf_io *io, ocf_cache_mode_t cache_mode)
|
|||||||
int ocf_core_submit_io_fast(struct ocf_io *io)
|
int ocf_core_submit_io_fast(struct ocf_io *io)
|
||||||
{
|
{
|
||||||
struct ocf_request *req;
|
struct ocf_request *req;
|
||||||
ocf_req_cache_mode_t req_cache_mode;
|
|
||||||
struct ocf_event_io trace_event;
|
struct ocf_event_io trace_event;
|
||||||
ocf_core_t core;
|
ocf_core_t core;
|
||||||
ocf_cache_t cache;
|
ocf_cache_t cache;
|
||||||
@ -315,26 +292,29 @@ int ocf_core_submit_io_fast(struct ocf_io *io)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (req->d2c) {
|
||||||
|
dec_counter_if_req_was_dirty(req);
|
||||||
|
return -OCF_ERR_IO;
|
||||||
|
}
|
||||||
|
|
||||||
ret = ocf_req_alloc_map(req);
|
ret = ocf_req_alloc_map(req);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
ocf_io_end(io, -OCF_ERR_NO_MEM);
|
ocf_io_end(io, -OCF_ERR_NO_MEM);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
req_cache_mode = ocf_get_effective_cache_mode(cache, core, io);
|
req->core = core;
|
||||||
|
req->complete = ocf_req_complete;
|
||||||
|
req->part_id = ocf_part_class2id(cache, io->io_class);
|
||||||
|
|
||||||
if (io->dir == OCF_WRITE &&
|
ocf_resolve_effective_cache_mode(cache, core, req);
|
||||||
ocf_req_cache_mode_has_lazy_write(req_cache_mode) &&
|
|
||||||
ocf_io_set_dirty(req)) {
|
|
||||||
req_cache_mode = ocf_req_cache_mode_wt;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (req_cache_mode) {
|
switch (req->cache_mode) {
|
||||||
case ocf_req_cache_mode_pt:
|
case ocf_req_cache_mode_pt:
|
||||||
return -OCF_ERR_IO;
|
return -OCF_ERR_IO;
|
||||||
case ocf_req_cache_mode_wb:
|
case ocf_req_cache_mode_wb:
|
||||||
case ocf_req_cache_mode_wo:
|
case ocf_req_cache_mode_wo:
|
||||||
req_cache_mode = ocf_req_cache_mode_fast;
|
req->cache_mode = ocf_req_cache_mode_fast;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (cache->use_submit_io_fast)
|
if (cache->use_submit_io_fast)
|
||||||
@ -342,18 +322,9 @@ int ocf_core_submit_io_fast(struct ocf_io *io)
|
|||||||
if (io->dir == OCF_WRITE)
|
if (io->dir == OCF_WRITE)
|
||||||
return -OCF_ERR_IO;
|
return -OCF_ERR_IO;
|
||||||
|
|
||||||
req_cache_mode = ocf_req_cache_mode_fast;
|
req->cache_mode = ocf_req_cache_mode_fast;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req->d2c) {
|
|
||||||
dec_counter_if_req_was_dirty(req);
|
|
||||||
return -OCF_ERR_IO;
|
|
||||||
}
|
|
||||||
|
|
||||||
req->core = core;
|
|
||||||
req->complete = ocf_req_complete;
|
|
||||||
req->part_id = ocf_part_class2id(cache, io->io_class);
|
|
||||||
|
|
||||||
ocf_core_update_stats(core, io);
|
ocf_core_update_stats(core, io);
|
||||||
|
|
||||||
if (cache->trace.trace_callback) {
|
if (cache->trace.trace_callback) {
|
||||||
@ -365,7 +336,7 @@ int ocf_core_submit_io_fast(struct ocf_io *io)
|
|||||||
|
|
||||||
ocf_io_get(io);
|
ocf_io_get(io);
|
||||||
|
|
||||||
fast = ocf_engine_hndl_fast_req(req, req_cache_mode);
|
fast = ocf_engine_hndl_fast_req(req);
|
||||||
if (fast != OCF_FAST_PATH_NO) {
|
if (fast != OCF_FAST_PATH_NO) {
|
||||||
ocf_trace_push(io->io_queue, &trace_event, sizeof(trace_event));
|
ocf_trace_push(io->io_queue, &trace_event, sizeof(trace_event));
|
||||||
ocf_seq_cutoff_update(core, req);
|
ocf_seq_cutoff_update(core, req);
|
||||||
@ -378,11 +349,6 @@ int ocf_core_submit_io_fast(struct ocf_io *io)
|
|||||||
return -OCF_ERR_IO;
|
return -OCF_ERR_IO;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ocf_core_volume_submit_io(struct ocf_io *io)
|
|
||||||
{
|
|
||||||
ocf_core_submit_io_mode(io, ocf_cache_mode_none);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ocf_core_volume_submit_flush(struct ocf_io *io)
|
static void ocf_core_volume_submit_flush(struct ocf_io *io)
|
||||||
{
|
{
|
||||||
struct ocf_request *req;
|
struct ocf_request *req;
|
||||||
|
@ -303,6 +303,12 @@ void ocf_req_put(struct ocf_request *req)
|
|||||||
ocf_queue_put(queue);
|
ocf_queue_put(queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ocf_req_set_dirty(struct ocf_request *req)
|
||||||
|
{
|
||||||
|
req->dirty = !!ocf_refcnt_inc(&req->cache->refcnt.dirty);
|
||||||
|
return req->dirty ? 0 : -OCF_ERR_AGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
void ocf_req_clear_info(struct ocf_request *req)
|
void ocf_req_clear_info(struct ocf_request *req)
|
||||||
{
|
{
|
||||||
ENV_BUG_ON(env_memset(&req->info, sizeof(req->info), 0));
|
ENV_BUG_ON(env_memset(&req->info, sizeof(req->info), 0));
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include "ocf_env.h"
|
#include "ocf_env.h"
|
||||||
#include "ocf_io_priv.h"
|
#include "ocf_io_priv.h"
|
||||||
|
#include "engine/cache_engine.h"
|
||||||
|
|
||||||
struct ocf_req_allocator;
|
struct ocf_req_allocator;
|
||||||
|
|
||||||
@ -25,9 +26,6 @@ struct ocf_req_info {
|
|||||||
uint32_t seq_req : 1;
|
uint32_t seq_req : 1;
|
||||||
/*!< Sequential cache request flag. */
|
/*!< Sequential cache request flag. */
|
||||||
|
|
||||||
uint32_t seq_cutoff : 1;
|
|
||||||
/*!< Sequential cut off set for this request */
|
|
||||||
|
|
||||||
uint32_t flush_metadata : 1;
|
uint32_t flush_metadata : 1;
|
||||||
/*!< This bit tells if metadata flushing is required */
|
/*!< This bit tells if metadata flushing is required */
|
||||||
|
|
||||||
@ -149,6 +147,8 @@ struct ocf_request {
|
|||||||
ctx_data_t *cp_data;
|
ctx_data_t *cp_data;
|
||||||
/*!< Copy of request data */
|
/*!< Copy of request data */
|
||||||
|
|
||||||
|
ocf_req_cache_mode_t cache_mode;
|
||||||
|
|
||||||
uint64_t byte_position;
|
uint64_t byte_position;
|
||||||
/*!< LBA byte position of request in core domain */
|
/*!< LBA byte position of request in core domain */
|
||||||
|
|
||||||
@ -185,6 +185,9 @@ struct ocf_request {
|
|||||||
uint8_t master_io_req_type : 2;
|
uint8_t master_io_req_type : 2;
|
||||||
/*!< Core device request context type */
|
/*!< Core device request context type */
|
||||||
|
|
||||||
|
uint8_t seq_cutoff : 1;
|
||||||
|
/*!< Sequential cut off set for this request */
|
||||||
|
|
||||||
log_sid_t sid;
|
log_sid_t sid;
|
||||||
/*!< Tracing sequence ID */
|
/*!< Tracing sequence ID */
|
||||||
|
|
||||||
@ -326,6 +329,8 @@ void ocf_req_clear_map(struct ocf_request *req);
|
|||||||
*/
|
*/
|
||||||
void ocf_req_hash(struct ocf_request *req);
|
void ocf_req_hash(struct ocf_request *req);
|
||||||
|
|
||||||
|
int ocf_req_set_dirty(struct ocf_request *req);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Clear OCF request
|
* @brief Clear OCF request
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user