Merge pull request #406 from arutk/flush2
Propagate I/O flags (e.g. FUA) to metadata flush I/O
This commit is contained in:
commit
9a23787c6b
@ -223,7 +223,7 @@ static int metadata_io_restart_req(struct ocf_request *req)
|
|||||||
io = ocf_new_cache_io(cache, req->io_queue,
|
io = ocf_new_cache_io(cache, req->io_queue,
|
||||||
PAGES_TO_BYTES(m_req->page),
|
PAGES_TO_BYTES(m_req->page),
|
||||||
PAGES_TO_BYTES(m_req->count),
|
PAGES_TO_BYTES(m_req->count),
|
||||||
m_req->req.rw, 0, 0);
|
m_req->req.rw, 0, m_req->asynch->flags);
|
||||||
if (!io) {
|
if (!io) {
|
||||||
metadata_io_io_end(m_req, -OCF_ERR_NO_MEM);
|
metadata_io_io_end(m_req, -OCF_ERR_NO_MEM);
|
||||||
return 0;
|
return 0;
|
||||||
@ -361,7 +361,7 @@ void metadata_io_req_complete(struct metadata_io_request *m_req)
|
|||||||
* Iterative write request asynchronously
|
* Iterative write request asynchronously
|
||||||
*/
|
*/
|
||||||
static int metadata_io_i_asynch(ocf_cache_t cache, ocf_queue_t queue, int dir,
|
static int metadata_io_i_asynch(ocf_cache_t cache, ocf_queue_t queue, int dir,
|
||||||
void *context, uint32_t page, uint32_t count,
|
void *context, uint32_t page, uint32_t count, int flags,
|
||||||
ocf_metadata_io_event_t io_hndl,
|
ocf_metadata_io_event_t io_hndl,
|
||||||
ocf_metadata_io_end_t compl_hndl)
|
ocf_metadata_io_end_t compl_hndl)
|
||||||
{
|
{
|
||||||
@ -386,6 +386,7 @@ static int metadata_io_i_asynch(ocf_cache_t cache, ocf_queue_t queue, int dir,
|
|||||||
a_req->context = context;
|
a_req->context = context;
|
||||||
a_req->page = page;
|
a_req->page = page;
|
||||||
a_req->count = count;
|
a_req->count = count;
|
||||||
|
a_req->flags = flags;
|
||||||
|
|
||||||
/* IO Requests initialization */
|
/* IO Requests initialization */
|
||||||
for (i = 0; i < req_count; i++) {
|
for (i = 0; i < req_count; i++) {
|
||||||
@ -435,21 +436,21 @@ err:
|
|||||||
}
|
}
|
||||||
|
|
||||||
int metadata_io_write_i_asynch(ocf_cache_t cache, ocf_queue_t queue,
|
int metadata_io_write_i_asynch(ocf_cache_t cache, ocf_queue_t queue,
|
||||||
void *context, uint32_t page, uint32_t count,
|
void *context, uint32_t page, uint32_t count, int flags,
|
||||||
ocf_metadata_io_event_t fill_hndl,
|
ocf_metadata_io_event_t fill_hndl,
|
||||||
ocf_metadata_io_end_t compl_hndl)
|
ocf_metadata_io_end_t compl_hndl)
|
||||||
{
|
{
|
||||||
return metadata_io_i_asynch(cache, queue, OCF_WRITE, context,
|
return metadata_io_i_asynch(cache, queue, OCF_WRITE, context,
|
||||||
page, count, fill_hndl, compl_hndl);
|
page, count, flags, fill_hndl, compl_hndl);
|
||||||
}
|
}
|
||||||
|
|
||||||
int metadata_io_read_i_asynch(ocf_cache_t cache, ocf_queue_t queue,
|
int metadata_io_read_i_asynch(ocf_cache_t cache, ocf_queue_t queue,
|
||||||
void *context, uint32_t page, uint32_t count,
|
void *context, uint32_t page, uint32_t count, int flags,
|
||||||
ocf_metadata_io_event_t drain_hndl,
|
ocf_metadata_io_event_t drain_hndl,
|
||||||
ocf_metadata_io_end_t compl_hndl)
|
ocf_metadata_io_end_t compl_hndl)
|
||||||
{
|
{
|
||||||
return metadata_io_i_asynch(cache, queue, OCF_READ, context,
|
return metadata_io_i_asynch(cache, queue, OCF_READ, context,
|
||||||
page, count, drain_hndl, compl_hndl);
|
page, count, flags, drain_hndl, compl_hndl);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ocf_metadata_io_init(ocf_cache_t cache)
|
int ocf_metadata_io_init(ocf_cache_t cache)
|
||||||
|
@ -74,6 +74,7 @@ struct metadata_io_request_asynch {
|
|||||||
env_atomic req_current;
|
env_atomic req_current;
|
||||||
uint32_t page;
|
uint32_t page;
|
||||||
uint32_t count;
|
uint32_t count;
|
||||||
|
int flags;
|
||||||
ocf_metadata_io_end_t on_complete;
|
ocf_metadata_io_end_t on_complete;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -122,7 +123,7 @@ int metadata_io_read_i_atomic(ocf_cache_t cache, ocf_queue_t queue,
|
|||||||
* @return 0 - No errors, otherwise error occurred
|
* @return 0 - No errors, otherwise error occurred
|
||||||
*/
|
*/
|
||||||
int metadata_io_write_i_asynch(ocf_cache_t cache, ocf_queue_t queue,
|
int metadata_io_write_i_asynch(ocf_cache_t cache, ocf_queue_t queue,
|
||||||
void *context, uint32_t page, uint32_t count,
|
void *context, uint32_t page, uint32_t count, int flags,
|
||||||
ocf_metadata_io_event_t fill_hndl,
|
ocf_metadata_io_event_t fill_hndl,
|
||||||
ocf_metadata_io_end_t compl_hndl);
|
ocf_metadata_io_end_t compl_hndl);
|
||||||
|
|
||||||
@ -140,7 +141,7 @@ int metadata_io_write_i_asynch(ocf_cache_t cache, ocf_queue_t queue,
|
|||||||
* @return 0 - No errors, otherwise error occurred
|
* @return 0 - No errors, otherwise error occurred
|
||||||
*/
|
*/
|
||||||
int metadata_io_read_i_asynch(ocf_cache_t cache, ocf_queue_t queue,
|
int metadata_io_read_i_asynch(ocf_cache_t cache, ocf_queue_t queue,
|
||||||
void *context, uint32_t page, uint32_t count,
|
void *context, uint32_t page, uint32_t count, int flags,
|
||||||
ocf_metadata_io_event_t drain_hndl,
|
ocf_metadata_io_event_t drain_hndl,
|
||||||
ocf_metadata_io_end_t compl_hndl);
|
ocf_metadata_io_end_t compl_hndl);
|
||||||
|
|
||||||
|
@ -259,7 +259,7 @@ static void _raw_ram_load_all(ocf_cache_t cache, struct ocf_metadata_raw *raw,
|
|||||||
context->priv = priv;
|
context->priv = priv;
|
||||||
|
|
||||||
result = metadata_io_read_i_asynch(cache, cache->mngt_queue, context,
|
result = metadata_io_read_i_asynch(cache, cache->mngt_queue, context,
|
||||||
raw->ssd_pages_offset, raw->ssd_pages,
|
raw->ssd_pages_offset, raw->ssd_pages, 0,
|
||||||
_raw_ram_load_all_drain, _raw_ram_load_all_complete);
|
_raw_ram_load_all_drain, _raw_ram_load_all_complete);
|
||||||
if (result)
|
if (result)
|
||||||
_raw_ram_load_all_complete(cache, context, result);
|
_raw_ram_load_all_complete(cache, context, result);
|
||||||
@ -331,7 +331,7 @@ static void _raw_ram_flush_all(ocf_cache_t cache, struct ocf_metadata_raw *raw,
|
|||||||
context->priv = priv;
|
context->priv = priv;
|
||||||
|
|
||||||
result = metadata_io_write_i_asynch(cache, cache->mngt_queue, context,
|
result = metadata_io_write_i_asynch(cache, cache->mngt_queue, context,
|
||||||
raw->ssd_pages_offset, raw->ssd_pages,
|
raw->ssd_pages_offset, raw->ssd_pages, 0,
|
||||||
_raw_ram_flush_all_fill, _raw_ram_flush_all_complete);
|
_raw_ram_flush_all_fill, _raw_ram_flush_all_complete);
|
||||||
if (result)
|
if (result)
|
||||||
_raw_ram_flush_all_complete(cache, context, result);
|
_raw_ram_flush_all_complete(cache, context, result);
|
||||||
@ -536,6 +536,7 @@ static int _raw_ram_flush_do_asynch(ocf_cache_t cache,
|
|||||||
|
|
||||||
result |= metadata_io_write_i_asynch(cache, req->io_queue, ctx,
|
result |= metadata_io_write_i_asynch(cache, req->io_queue, ctx,
|
||||||
raw->ssd_pages_offset + start_page, count,
|
raw->ssd_pages_offset + start_page, count,
|
||||||
|
req->ioi.io.flags,
|
||||||
_raw_ram_flush_do_asynch_fill,
|
_raw_ram_flush_do_asynch_fill,
|
||||||
_raw_ram_flush_do_asynch_io_complete);
|
_raw_ram_flush_do_asynch_io_complete);
|
||||||
|
|
||||||
|
@ -550,7 +550,7 @@ void raw_dynamic_flush_all(ocf_cache_t cache, struct ocf_metadata_raw *raw,
|
|||||||
context->priv = priv;
|
context->priv = priv;
|
||||||
|
|
||||||
result = metadata_io_write_i_asynch(cache, cache->mngt_queue, context,
|
result = metadata_io_write_i_asynch(cache, cache->mngt_queue, context,
|
||||||
raw->ssd_pages_offset, raw->ssd_pages,
|
raw->ssd_pages_offset, raw->ssd_pages, 0,
|
||||||
raw_dynamic_flush_all_fill,
|
raw_dynamic_flush_all_fill,
|
||||||
raw_dynamic_flush_all_complete);
|
raw_dynamic_flush_all_complete);
|
||||||
if (result)
|
if (result)
|
||||||
|
126
tests/functional/tests/engine/test_io_flags.py
Normal file
126
tests/functional/tests/engine/test_io_flags.py
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
#
|
||||||
|
# Copyright(c) 2020 Intel Corporation
|
||||||
|
# SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||||
|
#
|
||||||
|
|
||||||
|
from ctypes import c_int, memmove, cast, c_void_p
|
||||||
|
from enum import IntEnum
|
||||||
|
from itertools import product
|
||||||
|
import random
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from pyocf.types.cache import Cache, CacheMode
|
||||||
|
from pyocf.types.core import Core
|
||||||
|
from pyocf.types.volume import Volume
|
||||||
|
from pyocf.types.data import Data
|
||||||
|
from pyocf.types.io import IoDir
|
||||||
|
from pyocf.utils import Size
|
||||||
|
from pyocf.types.shared import OcfCompletion
|
||||||
|
|
||||||
|
|
||||||
|
def __io(io, queue, address, size, data, direction):
|
||||||
|
io.set_data(data, 0)
|
||||||
|
completion = OcfCompletion([("err", c_int)])
|
||||||
|
io.callback = completion.callback
|
||||||
|
io.submit()
|
||||||
|
completion.wait()
|
||||||
|
return int(completion.results["err"])
|
||||||
|
|
||||||
|
|
||||||
|
def _io(new_io, queue, address, size, data, offset, direction, flags):
|
||||||
|
io = new_io(queue, address, size, direction, 0, flags)
|
||||||
|
if direction == IoDir.READ:
|
||||||
|
_data = Data.from_bytes(bytes(size))
|
||||||
|
else:
|
||||||
|
_data = Data.from_bytes(data, offset, size)
|
||||||
|
ret = __io(io, queue, address, size, _data, direction)
|
||||||
|
if not ret and direction == IoDir.READ:
|
||||||
|
memmove(cast(data, c_void_p).value + offset, _data.handle, size)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
def io_to_exp_obj(core, address, size, data, offset, direction, flags):
|
||||||
|
return _io(
|
||||||
|
core.new_io,
|
||||||
|
core.cache.get_default_queue(),
|
||||||
|
address,
|
||||||
|
size,
|
||||||
|
data,
|
||||||
|
offset,
|
||||||
|
direction,
|
||||||
|
flags,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class FlagsValVolume(Volume):
|
||||||
|
def __init__(self, size, flags):
|
||||||
|
self.flags = flags
|
||||||
|
self.check = False
|
||||||
|
self.fail = False
|
||||||
|
super().__init__(size)
|
||||||
|
|
||||||
|
def set_check(self, check):
|
||||||
|
self.check = check
|
||||||
|
|
||||||
|
def submit_io(self, io):
|
||||||
|
if self.check:
|
||||||
|
flags = io.contents._flags
|
||||||
|
if flags != self.flags:
|
||||||
|
self.fail = True
|
||||||
|
super().submit_io(io)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("cache_mode", CacheMode)
|
||||||
|
def test_io_flags(pyocf_ctx, cache_mode):
|
||||||
|
"""
|
||||||
|
Verify that I/O flags provided at the top volume interface
|
||||||
|
are propagated down to bottom volumes for all associated
|
||||||
|
I/Os (including metadata writes to cache volume).
|
||||||
|
"""
|
||||||
|
|
||||||
|
flags = 0x239482
|
||||||
|
block_size = 4096
|
||||||
|
|
||||||
|
data = bytes(block_size)
|
||||||
|
|
||||||
|
cache_device = FlagsValVolume(Size.from_MiB(30), flags)
|
||||||
|
core_device = FlagsValVolume(Size.from_MiB(30), flags)
|
||||||
|
|
||||||
|
cache = Cache.start_on_device(cache_device, cache_mode=cache_mode)
|
||||||
|
core = Core.using_device(core_device)
|
||||||
|
|
||||||
|
cache.add_core(core)
|
||||||
|
|
||||||
|
cache_device.set_check(True)
|
||||||
|
core_device.set_check(True)
|
||||||
|
|
||||||
|
# write miss
|
||||||
|
io_to_exp_obj(core, block_size * 0, block_size, data, 0, IoDir.WRITE, flags)
|
||||||
|
assert not cache_device.fail
|
||||||
|
assert not core_device.fail
|
||||||
|
|
||||||
|
# read miss
|
||||||
|
io_to_exp_obj(core, block_size * 1, block_size, data, 0, IoDir.READ, flags)
|
||||||
|
assert not cache_device.fail
|
||||||
|
assert not core_device.fail
|
||||||
|
|
||||||
|
# "dirty" read hit
|
||||||
|
io_to_exp_obj(core, block_size * 0, block_size, data, 0, IoDir.READ, flags)
|
||||||
|
assert not cache_device.fail
|
||||||
|
assert not core_device.fail
|
||||||
|
|
||||||
|
# "clean" read hit
|
||||||
|
io_to_exp_obj(core, block_size * 1, block_size, data, 0, IoDir.READ, flags)
|
||||||
|
assert not cache_device.fail
|
||||||
|
assert not core_device.fail
|
||||||
|
|
||||||
|
# "dirty" write hit
|
||||||
|
io_to_exp_obj(core, block_size * 0, block_size, data, 0, IoDir.WRITE, flags)
|
||||||
|
assert not cache_device.fail
|
||||||
|
assert not core_device.fail
|
||||||
|
|
||||||
|
# "clean" write hit
|
||||||
|
io_to_exp_obj(core, block_size * 1, block_size, data, 0, IoDir.WRITE, flags)
|
||||||
|
assert not cache_device.fail
|
||||||
|
assert not core_device.fail
|
Loading…
Reference in New Issue
Block a user