Merge pull request #406 from arutk/flush2

Propagate I/O flags (e.g. FUA) to metadata flush I/O
This commit is contained in:
Robert Baldyga 2020-10-06 12:49:22 +02:00 committed by GitHub
commit 9a23787c6b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 140 additions and 11 deletions

View File

@ -223,7 +223,7 @@ static int metadata_io_restart_req(struct ocf_request *req)
io = ocf_new_cache_io(cache, req->io_queue,
PAGES_TO_BYTES(m_req->page),
PAGES_TO_BYTES(m_req->count),
m_req->req.rw, 0, 0);
m_req->req.rw, 0, m_req->asynch->flags);
if (!io) {
metadata_io_io_end(m_req, -OCF_ERR_NO_MEM);
return 0;
@ -361,7 +361,7 @@ void metadata_io_req_complete(struct metadata_io_request *m_req)
* Iterative write request asynchronously
*/
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_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->page = page;
a_req->count = count;
a_req->flags = flags;
/* IO Requests initialization */
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,
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_end_t compl_hndl)
{
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,
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_end_t compl_hndl)
{
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)

View File

@ -74,6 +74,7 @@ struct metadata_io_request_asynch {
env_atomic req_current;
uint32_t page;
uint32_t count;
int flags;
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
*/
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_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
*/
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_end_t compl_hndl);

View File

@ -259,7 +259,7 @@ static void _raw_ram_load_all(ocf_cache_t cache, struct ocf_metadata_raw *raw,
context->priv = priv;
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);
if (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;
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);
if (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,
raw->ssd_pages_offset + start_page, count,
req->ioi.io.flags,
_raw_ram_flush_do_asynch_fill,
_raw_ram_flush_do_asynch_io_complete);

View File

@ -550,7 +550,7 @@ void raw_dynamic_flush_all(ocf_cache_t cache, struct ocf_metadata_raw *raw,
context->priv = priv;
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_complete);
if (result)

View 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